@Test
  public void testExistsRestrictedRange() throws SolverException, InterruptedException {
    BooleanFormula f;

    BooleanFormula _exists_10_20_bx_0 =
        qfm.exists(_x, ifm.makeNumber(10), ifm.makeNumber(20), _b_at_x_eq_0);

    BooleanFormula _exists_10_20_bx_1 =
        qfm.exists(_x, ifm.makeNumber(10), ifm.makeNumber(20), _b_at_x_eq_1);

    // (exists x in [10..20] . b[x] = 0) AND (forall x . b[x] = 0) is SAT
    f = bfm.and(_exists_10_20_bx_0, _forall_x_bx_0);
    assertThat(solver.isUnsat(f)).isFalse();

    // (exists x in [10..20] . b[x] = 1) AND (forall x . b[x] = 0) is UNSAT
    f = bfm.and(_exists_10_20_bx_1, _forall_x_bx_0);
    assertThat(solver.isUnsat(f)).isTrue();

    // (exists x in [10..20] . b[x] = 1) AND (forall x . b[x] = 1) is SAT
    f = bfm.and(_exists_10_20_bx_1, _forall_x_bx_1);
    assertThat(solver.isUnsat(f)).isFalse();

    // (exists x in [10..20] . b[x] = 1) AND (b[10] = 0) is SAT
    f =
        bfm.and(
            _exists_10_20_bx_1, ifm.equal(afm.select(_b, ifm.makeNumber(10)), ifm.makeNumber(0)));
    assertThat(solver.isUnsat(f)).isFalse();

    // (exists x in [10..20] . b[x] = 1) AND (b[1000] = 0) is SAT
    f =
        bfm.and(
            _exists_10_20_bx_1, ifm.equal(afm.select(_b, ifm.makeNumber(1000)), ifm.makeNumber(0)));
    assertThat(solver.isUnsat(f)).isFalse();
  }
  @Test
  public void testNotExistsArrayConjunct() throws SolverException, InterruptedException {
    BooleanFormula f;

    // (not exists x . not b[x] = 0) AND (b[123] = 1) is UNSAT
    f =
        bfm.and(
            Lists.newArrayList(
                bfm.not(qfm.exists(_x, bfm.not(_b_at_x_eq_0))),
                ifm.equal(afm.select(_b, ifm.makeNumber(123)), ifm.makeNumber(1))));
    assertThat(solver.isUnsat(f)).isTrue();

    // (not exists x . not b[x] = 0) AND (b[123] = 0) is SAT
    f =
        bfm.and(
            bfm.not(qfm.exists(_x, bfm.not(_b_at_x_eq_0))),
            ifm.equal(afm.select(_b, ifm.makeNumber(123)), ifm.makeNumber(0)));
    assertThat(solver.isUnsat(f)).isFalse();

    // (not exists x . b[x] = 0) AND (b[123] = 0) is UNSAT
    f =
        bfm.and(
            bfm.not(qfm.exists(_x, _b_at_x_eq_0)),
            ifm.equal(afm.select(_b, ifm.makeNumber(123)), ifm.makeNumber(0)));
    assertThat(solver.isUnsat(f)).isTrue();
  }
  @Test
  public void testEquals() {
    BooleanFormula f1 =
        qfm.exists(ifm.makeVariable("x"), ifm.makeNumber(1), ifm.makeNumber(2), _b_at_x_eq_1);
    BooleanFormula f2 =
        qfm.exists(ifm.makeVariable("x"), ifm.makeNumber(1), ifm.makeNumber(2), _b_at_x_eq_1);

    assertThat(f1).isEqualTo(f2);
  }
  @Test
  public void testContradiction() throws SolverException, InterruptedException {

    // forall x . x = x+1  is UNSAT

    BooleanFormula f = qfm.forall(_x, ifm.equal(_x, ifm.add(_x, ifm.makeNumber(1))));
    assertThat(solver.isUnsat(f)).isTrue();

    BooleanFormula g = qfm.exists(_x, ifm.equal(_x, ifm.add(_x, ifm.makeNumber(1))));
    assertThat(solver.isUnsat(g)).isTrue();
  }
  @Test
  public void testExistsArrayDisjunct() throws SolverException, InterruptedException {
    BooleanFormula f;

    // (exists x . b[x] = 0) OR  (forall x . b[x] = 1) is SAT
    f = bfm.or(qfm.exists(_x, _b_at_x_eq_0), qfm.forall(_x, _b_at_x_eq_1));
    assertThat(solver.isUnsat(f)).isFalse();

    // (exists x . b[x] = 1) OR (exists x . b[x] = 1) is SAT
    f = bfm.or(qfm.exists(_x, _b_at_x_eq_1), qfm.exists(_x, _b_at_x_eq_1));
    assertThat(solver.isUnsat(f)).isFalse();
  }
  @Test
  public void testExistsArrayConjunct() throws SolverException, InterruptedException {
    BooleanFormula f;

    // (exists x . b[x] = 0) AND (b[123] = 1) is SAT
    f =
        bfm.and(
            qfm.exists(_x, _b_at_x_eq_0),
            ifm.equal(afm.select(_b, ifm.makeNumber(123)), ifm.makeNumber(1)));
    assertThat(solver.isUnsat(f)).isFalse();

    // (exists x . b[x] = 1) AND  (forall x . b[x] = 0) is UNSAT
    f = bfm.and(qfm.exists(_x, _b_at_x_eq_1), _forall_x_bx_0);
    assertThat(solver.isUnsat(f)).isTrue();

    // (exists x . b[x] = 0) AND  (forall x . b[x] = 0) is SAT
    f = bfm.and(qfm.exists(_x, _b_at_x_eq_0), _forall_x_bx_0);
    assertThat(solver.isUnsat(f)).isFalse();
  }
  @Test
  public void testSimple() throws SolverException, InterruptedException {

    // forall x . x+2 = x+1+1  is SAT
    BooleanFormula f =
        qfm.forall(
            _x,
            ifm.equal(
                ifm.add(_x, ifm.makeNumber(2)),
                ifm.add(ifm.add(_x, ifm.makeNumber(1)), ifm.makeNumber(1))));
    assertThat(solver.isUnsat(f)).isFalse();
  }
  @Test
  public void testForallArrayDisjunct() throws SolverException, InterruptedException {
    BooleanFormula f;

    // (forall x . b[x] = 0) AND (b[123] = 1 OR b[123] = 0) is SAT
    f =
        bfm.and(
            qfm.forall(_x, _b_at_x_eq_0),
            bfm.or(
                ifm.equal(afm.select(_b, ifm.makeNumber(123)), ifm.makeNumber(1)),
                ifm.equal(afm.select(_b, ifm.makeNumber(123)), ifm.makeNumber(0))));

    assertThat(solver.isUnsat(f)).isFalse();

    // (forall x . b[x] = 0) OR (b[123] = 1) is SAT
    f =
        bfm.or(
            qfm.forall(_x, _b_at_x_eq_0),
            ifm.equal(afm.select(_b, ifm.makeNumber(123)), ifm.makeNumber(1)));
    assertThat(solver.isUnsat(f)).isFalse();
  }
  @Test
  public void testForallRestrictedRange() throws SolverException, InterruptedException {
    BooleanFormula f;

    BooleanFormula _forall_10_20_bx_0 =
        qfm.forall(_x, ifm.makeNumber(10), ifm.makeNumber(20), _b_at_x_eq_0);

    BooleanFormula _forall_10_20_bx_1 =
        qfm.forall(_x, ifm.makeNumber(10), ifm.makeNumber(20), _b_at_x_eq_1);

    // (forall x in [10..20] . b[x] = 0) AND (forall x . b[x] = 0) is SAT
    f = bfm.and(_forall_10_20_bx_0, qfm.forall(_x, _b_at_x_eq_0));
    assert_().about(BooleanFormula()).that(f).isSatisfiable();

    // (forall x in [10..20] . b[x] = 1) AND (exits x in [15..17] . b[x] = 0) is UNSAT
    f =
        bfm.and(
            _forall_10_20_bx_1,
            qfm.exists(_x, ifm.makeNumber(15), ifm.makeNumber(17), _b_at_x_eq_0));
    assertThat(solver.isUnsat(f)).isTrue();

    // (forall x in [10..20] . b[x] = 1) AND b[10] = 0 is UNSAT
    f =
        bfm.and(
            _forall_10_20_bx_1, ifm.equal(afm.select(_b, ifm.makeNumber(10)), ifm.makeNumber(0)));
    assertThat(solver.isUnsat(f)).isTrue();

    // (forall x in [10..20] . b[x] = 1) AND b[20] = 0 is UNSAT
    f =
        bfm.and(
            _forall_10_20_bx_1, ifm.equal(afm.select(_b, ifm.makeNumber(20)), ifm.makeNumber(0)));
    assertThat(solver.isUnsat(f)).isTrue();

    // (forall x in [10..20] . b[x] = 1) AND b[9] = 0 is SAT
    f =
        bfm.and(
            _forall_10_20_bx_1, ifm.equal(afm.select(_b, ifm.makeNumber(9)), ifm.makeNumber(0)));
    assertThat(solver.isUnsat(f)).isFalse();

    // (forall x in [10..20] . b[x] = 1) AND b[21] = 0 is SAT
    f =
        bfm.and(
            _forall_10_20_bx_1, ifm.equal(afm.select(_b, ifm.makeNumber(21)), ifm.makeNumber(0)));
    assertThat(solver.isUnsat(f)).isFalse();

    // (forall x in [10..20] . b[x] = 1) AND (forall x in [0..20] . b[x] = 0) is UNSAT
    f =
        bfm.and(
            _forall_10_20_bx_1,
            qfm.forall(_x, ifm.makeNumber(0), ifm.makeNumber(20), _b_at_x_eq_0));
    assertThat(solver.isUnsat(f)).isTrue();

    // (forall x in [10..20] . b[x] = 1) AND (forall x in [0..9] . b[x] = 0) is SAT
    f =
        bfm.and(
            _forall_10_20_bx_1, qfm.forall(_x, ifm.makeNumber(0), ifm.makeNumber(9), _b_at_x_eq_0));
    assertThat(solver.isUnsat(f)).isFalse();
  }
  @Before
  public void setUp() throws Exception {
    requireArrays();
    requireQuantifiers();

    this.mgrv = new FormulaManagerView(factory, config, TestLogManager.getInstance());
    this.solver = new Solver(mgrv, factory, config, TestLogManager.getInstance());
    this.afm = mgrv.getArrayFormulaManager();
    this.bfm = mgrv.getBooleanFormulaManager();
    this.ifm = mgrv.getIntegerFormulaManager();
    this.qfm = mgrv.getQuantifiedFormulaManager();

    _x = ifm.makeVariable("x");
    _b = afm.makeArray("b", FormulaType.IntegerType, FormulaType.IntegerType);

    _b_at_x_eq_1 = ifm.equal(afm.select(_b, _x), ifm.makeNumber(1));
    _b_at_x_eq_0 = ifm.equal(afm.select(_b, _x), ifm.makeNumber(0));

    _forall_x_bx_1 = qfm.forall(_x, _b_at_x_eq_1);
    _forall_x_bx_0 = qfm.forall(_x, _b_at_x_eq_0);
  }