Files
cvc5/test/unit/api/java/SolverTest.java

2534 lines
94 KiB
Java

/******************************************************************************
* Top contributors (to current version):
* Mudathir Mohamed, Andrew Reynolds, Aina Niemetz
*
* This file is part of the cvc5 project.
*
* Copyright (c) 2009-2025 by the authors listed in the file AUTHORS
* in the top-level source directory and their institutional affiliations.
* All rights reserved. See the file COPYING in the top-level source
* directory for licensing information.
* ****************************************************************************
*
* Black box testing of the Solver class of the Java API.
*/
package tests;
import static io.github.cvc5.Kind.*;
import static io.github.cvc5.RoundingMode.*;
import static io.github.cvc5.SortKind.*;
import static org.junit.jupiter.api.Assertions.*;
import io.github.cvc5.*;
import io.github.cvc5.modes.BlockModelsMode;
import io.github.cvc5.modes.FindSynthTarget;
import io.github.cvc5.modes.LearnedLitType;
import io.github.cvc5.modes.OptionCategory;
import io.github.cvc5.modes.ProofComponent;
import io.github.cvc5.modes.ProofFormat;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.function.Executable;
class SolverTest
{
private TermManager d_tm;
private Solver d_solver;
@BeforeEach
void setUp()
{
d_tm = new TermManager();
d_solver = new Solver(d_tm);
}
@AfterEach
void tearDown()
{
Context.deletePointers();
}
@Test
void recoverableException() throws CVC5ApiException
{
d_solver.setOption("produce-models", "true");
Term x = d_tm.mkConst(d_tm.getBooleanSort(), "x");
d_solver.assertFormula(x.eqTerm(x).notTerm());
assertThrows(CVC5ApiRecoverableException.class, () -> d_solver.getValue(x));
}
@Test
void declareFunFresh()
{
Sort boolSort = d_solver.getBooleanSort();
Sort intSort = d_solver.getIntegerSort();
Term t1 = d_solver.declareFun("b", new Sort[] {}, boolSort, true);
Term t2 = d_solver.declareFun("b", new Sort[] {}, boolSort, false);
Term t3 = d_solver.declareFun("b", new Sort[] {}, boolSort, false);
assertNotEquals(t1, t2);
assertNotEquals(t1, t3);
assertEquals(t2, t3);
Term t4 = d_solver.declareFun("c", new Sort[] {}, boolSort, false);
assertNotEquals(t2, t4);
Term t5 = d_solver.declareFun("b", new Sort[] {}, intSort, false);
assertNotEquals(t2, t5);
}
@Test
void declareDatatype()
{
DatatypeConstructorDecl nil = d_solver.mkDatatypeConstructorDecl("nil");
DatatypeConstructorDecl[] ctors1 = new DatatypeConstructorDecl[] {nil};
assertDoesNotThrow(() -> d_solver.declareDatatype(("a"), ctors1));
DatatypeConstructorDecl cons = d_solver.mkDatatypeConstructorDecl("cons");
DatatypeConstructorDecl nil2 = d_solver.mkDatatypeConstructorDecl("nil");
DatatypeConstructorDecl[] ctors2 = new DatatypeConstructorDecl[] {cons, nil2};
assertDoesNotThrow(() -> d_solver.declareDatatype(("b"), ctors2));
DatatypeConstructorDecl cons2 = d_solver.mkDatatypeConstructorDecl("cons");
DatatypeConstructorDecl nil3 = d_solver.mkDatatypeConstructorDecl("nil");
DatatypeConstructorDecl[] ctors3 = new DatatypeConstructorDecl[] {cons2, nil3};
assertDoesNotThrow(() -> d_solver.declareDatatype((""), ctors3));
DatatypeConstructorDecl[] ctors4 = new DatatypeConstructorDecl[0];
assertThrows(CVC5ApiException.class, () -> d_solver.declareDatatype(("c"), ctors4));
assertThrows(CVC5ApiException.class, () -> d_solver.declareDatatype((""), ctors4));
Solver slv = new Solver();
assertThrows(CVC5ApiException.class, () -> slv.declareDatatype(("a"), ctors1));
}
@Test
void declareFun() throws CVC5ApiException
{
Sort bvSort = d_solver.mkBitVectorSort(32);
Sort funSort =
d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"), d_solver.getIntegerSort());
assertDoesNotThrow(() -> d_solver.declareFun("f1", new Sort[] {}, bvSort));
assertDoesNotThrow(
() -> d_solver.declareFun("f3", new Sort[] {bvSort, d_solver.getIntegerSort()}, bvSort));
assertThrows(CVC5ApiException.class, () -> d_solver.declareFun("f2", new Sort[] {}, funSort));
// functions as arguments is allowed
assertDoesNotThrow(() -> d_solver.declareFun("f4", new Sort[] {bvSort, funSort}, bvSort));
assertThrows(CVC5ApiException.class,
() -> d_solver.declareFun("f5", new Sort[] {bvSort, bvSort}, funSort));
Solver slv = new Solver();
assertThrows(CVC5ApiException.class, () -> slv.declareFun("f1", new Sort[] {}, bvSort));
}
@Test
void declareSort()
{
assertDoesNotThrow(() -> d_solver.declareSort("s", 0));
assertDoesNotThrow(() -> d_solver.declareSort("s", 2));
assertDoesNotThrow(() -> d_solver.declareSort("", 2));
}
@Test
void declareSortFresh() throws CVC5ApiException
{
Sort t1 = d_solver.declareSort("b", 0, true);
Sort t2 = d_solver.declareSort("b", 0, false);
Sort t3 = d_solver.declareSort("b", 0, false);
assertNotEquals(t1, t2);
assertNotEquals(t1, t3);
assertEquals(t2, t3);
Sort t4 = d_solver.declareSort("c", 0, false);
assertNotEquals(t2, t4);
Sort t5 = d_solver.declareSort("b", 1, false);
assertNotEquals(t2, t5);
}
@Test
void defineFun() throws CVC5ApiException
{
Sort bvSort = d_solver.mkBitVectorSort(32);
Sort funSort =
d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"), d_solver.getIntegerSort());
Term b1 = d_solver.mkVar(bvSort, "b1");
Term b2 = d_solver.mkVar(d_solver.getIntegerSort(), "b2");
Term b3 = d_solver.mkVar(funSort, "b3");
Term v1 = d_solver.mkConst(bvSort, "v1");
Term v2 = d_solver.mkConst(funSort, "v2");
assertDoesNotThrow(() -> d_solver.defineFun("f", new Term[] {}, bvSort, v1));
assertDoesNotThrow(() -> d_solver.defineFun("ff", new Term[] {b1, b2}, bvSort, v1));
assertThrows(
CVC5ApiException.class, () -> d_solver.defineFun("ff", new Term[] {v1, b2}, bvSort, v1));
assertThrows(
CVC5ApiException.class, () -> d_solver.defineFun("fff", new Term[] {b1}, bvSort, v2));
assertThrows(
CVC5ApiException.class, () -> d_solver.defineFun("ffff", new Term[] {b1}, funSort, v2));
// b3 has function sort, which is allowed as an argument
assertDoesNotThrow(() -> d_solver.defineFun("fffff", new Term[] {b1, b3}, bvSort, v1));
Solver slv = new Solver();
Sort bvSort2 = slv.mkBitVectorSort(32);
Term v12 = slv.mkConst(bvSort2, "v1");
Term b12 = slv.mkVar(bvSort2, "b1");
Term b22 = slv.mkVar(slv.getIntegerSort(), "b2");
assertThrows(CVC5ApiException.class, () -> slv.defineFun("f", new Term[] {}, bvSort, v12));
assertThrows(CVC5ApiException.class, () -> slv.defineFun("f", new Term[] {}, bvSort2, v1));
assertThrows(
CVC5ApiException.class, () -> slv.defineFun("ff", new Term[] {b1, b22}, bvSort2, v12));
assertThrows(
CVC5ApiException.class, () -> slv.defineFun("ff", new Term[] {b12, b2}, bvSort2, v12));
assertThrows(
CVC5ApiException.class, () -> slv.defineFun("ff", new Term[] {b12, b22}, bvSort, v12));
assertThrows(
CVC5ApiException.class, () -> slv.defineFun("ff", new Term[] {b12, b22}, bvSort2, v1));
}
@Test
void defineFunGlobal()
{
Sort bSort = d_solver.getBooleanSort();
Term bTrue = d_solver.mkBoolean(true);
// (define-fun f () Bool true)
Term f = d_solver.defineFun("f", new Term[] {}, bSort, bTrue, true);
Term b = d_solver.mkVar(bSort, "b");
// (define-fun g (b Bool) Bool b)
Term g = d_solver.defineFun("g", new Term[] {b}, bSort, b, true);
// (assert (or (not f) (not (g true))))
d_solver.assertFormula(
d_solver.mkTerm(OR, f.notTerm(), d_solver.mkTerm(APPLY_UF, g, bTrue).notTerm()));
assertTrue(d_solver.checkSat().isUnsat());
d_solver.resetAssertions();
// (assert (or (not f) (not (g true))))
d_solver.assertFormula(
d_solver.mkTerm(OR, f.notTerm(), d_solver.mkTerm(APPLY_UF, g, bTrue).notTerm()));
assertTrue(d_solver.checkSat().isUnsat());
}
@Test
void defineFunRec() throws CVC5ApiException
{
Sort bvSort = d_solver.mkBitVectorSort(32);
Sort funSort1 = d_solver.mkFunctionSort(new Sort[] {bvSort, bvSort}, bvSort);
Sort funSort2 =
d_solver.mkFunctionSort(d_solver.mkUninterpretedSort("u"), d_solver.getIntegerSort());
Term b1 = d_solver.mkVar(bvSort, "b1");
Term b11 = d_solver.mkVar(bvSort, "b1");
Term b2 = d_solver.mkVar(d_solver.getIntegerSort(), "b2");
Term b3 = d_solver.mkVar(funSort2, "b3");
Term v1 = d_solver.mkConst(bvSort, "v1");
Term v2 = d_solver.mkConst(d_solver.getIntegerSort(), "v2");
Term v3 = d_solver.mkConst(funSort2, "v3");
Term f1 = d_solver.mkConst(funSort1, "f1");
Term f2 = d_solver.mkConst(funSort2, "f2");
Term f3 = d_solver.mkConst(bvSort, "f3");
assertDoesNotThrow(() -> d_solver.defineFunRec("f", new Term[] {}, bvSort, v1));
assertDoesNotThrow(() -> d_solver.defineFunRec("ff", new Term[] {b1, b2}, bvSort, v1));
assertDoesNotThrow(() -> d_solver.defineFunRec(f1, new Term[] {b1, b11}, v1));
assertThrows(
CVC5ApiException.class, () -> d_solver.defineFunRec("fff", new Term[] {b1}, bvSort, v3));
assertThrows(
CVC5ApiException.class, () -> d_solver.defineFunRec("ff", new Term[] {b1, v2}, bvSort, v1));
assertThrows(
CVC5ApiException.class, () -> d_solver.defineFunRec("ffff", new Term[] {b1}, funSort2, v3));
// b3 has function sort, which is allowed as an argument
assertDoesNotThrow(() -> d_solver.defineFunRec("fffff", new Term[] {b1, b3}, bvSort, v1));
assertThrows(CVC5ApiException.class, () -> d_solver.defineFunRec(f1, new Term[] {b1}, v1));
assertThrows(CVC5ApiException.class, () -> d_solver.defineFunRec(f1, new Term[] {b1, b11}, v2));
assertThrows(CVC5ApiException.class, () -> d_solver.defineFunRec(f1, new Term[] {b1, b11}, v3));
assertThrows(CVC5ApiException.class, () -> d_solver.defineFunRec(f2, new Term[] {b1}, v2));
assertThrows(CVC5ApiException.class, () -> d_solver.defineFunRec(f3, new Term[] {b1}, v1));
Solver slv = new Solver();
Sort bvSort2 = slv.mkBitVectorSort(32);
Term v12 = slv.mkConst(bvSort2, "v1");
Term b12 = slv.mkVar(bvSort2, "b1");
Term b22 = slv.mkVar(slv.getIntegerSort(), "b2");
assertDoesNotThrow(() -> slv.defineFunRec("f", new Term[] {}, bvSort2, v12));
assertDoesNotThrow(() -> slv.defineFunRec("ff", new Term[] {b12, b22}, bvSort2, v12));
assertThrows(CVC5ApiException.class, () -> slv.defineFunRec("f", new Term[] {}, bvSort, v12));
assertThrows(CVC5ApiException.class, () -> slv.defineFunRec("f", new Term[] {}, bvSort2, v1));
assertThrows(
CVC5ApiException.class, () -> slv.defineFunRec("ff", new Term[] {b1, b22}, bvSort2, v12));
assertThrows(
CVC5ApiException.class, () -> slv.defineFunRec("ff", new Term[] {b12, b2}, bvSort2, v12));
assertThrows(
CVC5ApiException.class, () -> slv.defineFunRec("ff", new Term[] {b12, b22}, bvSort, v12));
assertThrows(
CVC5ApiException.class, () -> slv.defineFunRec("ff", new Term[] {b12, b22}, bvSort2, v1));
}
@Test
void defineFunRecWrongLogic() throws CVC5ApiException
{
d_solver.setLogic("QF_BV");
Sort bvSort = d_solver.mkBitVectorSort(32);
Sort funSort = d_solver.mkFunctionSort(new Sort[] {bvSort, bvSort}, bvSort);
Term b = d_solver.mkVar(bvSort, "b");
Term v = d_solver.mkConst(bvSort, "v");
Term f = d_solver.mkConst(funSort, "f");
assertThrows(
CVC5ApiException.class, () -> d_solver.defineFunRec("f", new Term[] {}, bvSort, v));
assertThrows(CVC5ApiException.class, () -> d_solver.defineFunRec(f, new Term[] {b, b}, v));
}
@Test
void defineFunRecGlobal() throws CVC5ApiException
{
Sort bSort = d_solver.getBooleanSort();
Sort fSort = d_solver.mkFunctionSort(bSort, bSort);
d_solver.push();
Term bTrue = d_solver.mkBoolean(true);
// (define-fun f () Bool true)
Term f = d_solver.defineFunRec("f", new Term[] {}, bSort, bTrue, true);
Term b = d_solver.mkVar(bSort, "b");
Term gSym = d_solver.mkConst(fSort, "g");
// (define-fun g (b Bool) Bool b)
Term g = d_solver.defineFunRec(gSym, new Term[] {b}, b, true);
// (assert (or (not f) (not (g true))))
d_solver.assertFormula(
d_solver.mkTerm(OR, f.notTerm(), d_solver.mkTerm(APPLY_UF, g, bTrue).notTerm()));
assertTrue(d_solver.checkSat().isUnsat());
d_solver.pop();
// (assert (or (not f) (not (g true))))
d_solver.assertFormula(
d_solver.mkTerm(OR, f.notTerm(), d_solver.mkTerm(APPLY_UF, g, bTrue).notTerm()));
assertTrue(d_solver.checkSat().isUnsat());
}
@Test
void defineFunsRec() throws CVC5ApiException
{
Sort uSort = d_solver.mkUninterpretedSort("u");
Sort bvSort = d_solver.mkBitVectorSort(32);
Sort funSort1 = d_solver.mkFunctionSort(new Sort[] {bvSort, bvSort}, bvSort);
Sort funSort2 = d_solver.mkFunctionSort(uSort, d_solver.getIntegerSort());
Term b1 = d_solver.mkVar(bvSort, "b1");
Term b11 = d_solver.mkVar(bvSort, "b1");
Term b2 = d_solver.mkVar(d_solver.getIntegerSort(), "b2");
Term b3 = d_solver.mkVar(funSort2, "b3");
Term b4 = d_solver.mkVar(uSort, "b4");
Term v1 = d_solver.mkConst(bvSort, "v1");
Term v2 = d_solver.mkConst(d_solver.getIntegerSort(), "v2");
Term v3 = d_solver.mkConst(funSort2, "v3");
Term v4 = d_solver.mkConst(uSort, "v4");
Term f1 = d_solver.mkConst(funSort1, "f1");
Term f2 = d_solver.mkConst(funSort2, "f2");
Term f3 = d_solver.mkConst(bvSort, "f3");
assertDoesNotThrow(
()
-> d_solver.defineFunsRec(
new Term[] {f1, f2}, new Term[][] {{b1, b11}, {b4}}, new Term[] {v1, v2}));
assertThrows(CVC5ApiException.class,
()
-> d_solver.defineFunsRec(
new Term[] {f1, f2}, new Term[][] {{v1, b11}, {b4}}, new Term[] {v1, v2}));
assertThrows(CVC5ApiException.class,
()
-> d_solver.defineFunsRec(
new Term[] {f1, f3}, new Term[][] {{b1, b11}, {b4}}, new Term[] {v1, v2}));
assertThrows(CVC5ApiException.class,
()
-> d_solver.defineFunsRec(
new Term[] {f1, f2}, new Term[][] {{b1}, {b4}}, new Term[] {v1, v2}));
assertThrows(CVC5ApiException.class,
()
-> d_solver.defineFunsRec(
new Term[] {f1, f2}, new Term[][] {{b1, b2}, {b4}}, new Term[] {v1, v2}));
assertThrows(CVC5ApiException.class,
()
-> d_solver.defineFunsRec(
new Term[] {f1, f2}, new Term[][] {{b1, b11}, {b4}}, new Term[] {v1, v4}));
Solver slv = new Solver();
Sort uSort2 = slv.mkUninterpretedSort("u");
Sort bvSort2 = slv.mkBitVectorSort(32);
Sort funSort12 = slv.mkFunctionSort(new Sort[] {bvSort2, bvSort2}, bvSort2);
Sort funSort22 = slv.mkFunctionSort(uSort2, slv.getIntegerSort());
Term b12 = slv.mkVar(bvSort2, "b1");
Term b112 = slv.mkVar(bvSort2, "b1");
Term b42 = slv.mkVar(uSort2, "b4");
Term v12 = slv.mkConst(bvSort2, "v1");
Term v22 = slv.mkConst(slv.getIntegerSort(), "v2");
Term f12 = slv.mkConst(funSort12, "f1");
Term f22 = slv.mkConst(funSort22, "f2");
assertDoesNotThrow(
()
-> slv.defineFunsRec(
new Term[] {f12, f22}, new Term[][] {{b12, b112}, {b42}}, new Term[] {v12, v22}));
assertThrows(CVC5ApiException.class,
()
-> slv.defineFunsRec(
new Term[] {f1, f22}, new Term[][] {{b12, b112}, {b42}}, new Term[] {v12, v22}));
assertThrows(CVC5ApiException.class,
()
-> slv.defineFunsRec(
new Term[] {f12, f2}, new Term[][] {{b12, b112}, {b42}}, new Term[] {v12, v22}));
assertThrows(CVC5ApiException.class,
()
-> slv.defineFunsRec(
new Term[] {f12, f22}, new Term[][] {{b1, b112}, {b42}}, new Term[] {v12, v22}));
assertThrows(CVC5ApiException.class,
()
-> slv.defineFunsRec(
new Term[] {f12, f22}, new Term[][] {{b12, b11}, {b42}}, new Term[] {v12, v22}));
assertThrows(CVC5ApiException.class,
()
-> slv.defineFunsRec(
new Term[] {f12, f22}, new Term[][] {{b12, b112}, {b4}}, new Term[] {v12, v22}));
assertThrows(CVC5ApiException.class,
()
-> slv.defineFunsRec(
new Term[] {f12, f22}, new Term[][] {{b12, b112}, {b42}}, new Term[] {v1, v22}));
assertThrows(CVC5ApiException.class,
()
-> slv.defineFunsRec(
new Term[] {f12, f22}, new Term[][] {{b12, b112}, {b42}}, new Term[] {v12, v2}));
}
@Test
void defineFunsRecWrongLogic() throws CVC5ApiException
{
d_solver.setLogic("QF_BV");
Sort uSort = d_solver.mkUninterpretedSort("u");
Sort bvSort = d_solver.mkBitVectorSort(32);
Sort funSort1 = d_solver.mkFunctionSort(new Sort[] {bvSort, bvSort}, bvSort);
Sort funSort2 = d_solver.mkFunctionSort(uSort, d_solver.getIntegerSort());
Term b = d_solver.mkVar(bvSort, "b");
Term u = d_solver.mkVar(uSort, "u");
Term v1 = d_solver.mkConst(bvSort, "v1");
Term v2 = d_solver.mkConst(d_solver.getIntegerSort(), "v2");
Term f1 = d_solver.mkConst(funSort1, "f1");
Term f2 = d_solver.mkConst(funSort2, "f2");
assertThrows(CVC5ApiException.class,
()
-> d_solver.defineFunsRec(
new Term[] {f1, f2}, new Term[][] {{b, b}, {u}}, new Term[] {v1, v2}));
}
@Test
void defineFunsRecGlobal() throws CVC5ApiException
{
Sort bSort = d_solver.getBooleanSort();
Sort fSort = d_solver.mkFunctionSort(bSort, bSort);
d_solver.push();
Term bTrue = d_solver.mkBoolean(true);
Term b = d_solver.mkVar(bSort, "b");
Term gSym = d_solver.mkConst(fSort, "g");
// (define-funs-rec ((g ((b Bool)) Bool)) (b))
d_solver.defineFunsRec(new Term[] {gSym}, new Term[][] {{b}}, new Term[] {b}, true);
// (assert (not (g true)))
d_solver.assertFormula(d_solver.mkTerm(APPLY_UF, gSym, bTrue).notTerm());
assertTrue(d_solver.checkSat().isUnsat());
d_solver.pop();
// (assert (not (g true)))
d_solver.assertFormula(d_solver.mkTerm(APPLY_UF, gSym, bTrue).notTerm());
assertTrue(d_solver.checkSat().isUnsat());
}
@Test
void getAssertions()
{
Term a = d_solver.mkConst(d_solver.getBooleanSort(), "a");
Term b = d_solver.mkConst(d_solver.getBooleanSort(), "b");
d_solver.assertFormula(a);
d_solver.assertFormula(b);
Term[] asserts = d_solver.getAssertions();
assertEquals(asserts[0], a);
assertEquals(asserts[1], b);
}
@Test
void getInfo()
{
assertDoesNotThrow(() -> d_solver.getInfo("name"));
assertThrows(CVC5ApiException.class, () -> d_solver.getInfo("asdf"));
}
@Test
void getAbduct() throws CVC5ApiException
{
d_solver.setLogic("QF_LIA");
d_solver.setOption("produce-abducts", "true");
d_solver.setOption("incremental", "false");
Sort intSort = d_solver.getIntegerSort();
Term zero = d_solver.mkInteger(0);
Term x = d_solver.mkConst(intSort, "x");
Term y = d_solver.mkConst(intSort, "y");
// Assumptions for abduction: x > 0
d_solver.assertFormula(d_solver.mkTerm(GT, x, zero));
// Conjecture for abduction: y > 0
Term conj = d_solver.mkTerm(GT, y, zero);
Term output = new Term();
// Call the abduction api, while the resulting abduct is the output
output = d_solver.getAbduct(conj);
// We expect the resulting output to be a boolean formula
assertTrue(!output.isNull() && output.getSort().isBoolean());
// try with a grammar, a simple grammar admitting true
Sort bsort = d_solver.getBooleanSort();
Term truen = d_solver.mkBoolean(true);
Term start = d_solver.mkVar(bsort);
Term output2 = new Term();
Grammar g = d_solver.mkGrammar(new Term[] {}, new Term[] {start});
Term conj2 = d_solver.mkTerm(GT, x, zero);
assertDoesNotThrow(() -> g.addRule(start, truen));
// Call the abduction api, while the resulting abduct is the output
output2 = d_solver.getAbduct(conj2, g);
// abduct must be true
assertEquals(output2, truen);
}
@Test
void getAbduct2() throws CVC5ApiException
{
d_solver.setLogic("QF_LIA");
d_solver.setOption("incremental", "false");
Sort intSort = d_solver.getIntegerSort();
Term zero = d_solver.mkInteger(0);
Term x = d_solver.mkConst(intSort, "x");
Term y = d_solver.mkConst(intSort, "y");
// Assumptions for abduction: x > 0
d_solver.assertFormula(d_solver.mkTerm(GT, x, zero));
// Conjecture for abduction: y > 0
Term conj = d_solver.mkTerm(GT, y, zero);
Term output = new Term();
// Fails due to option not set
assertThrows(CVC5ApiException.class, () -> d_solver.getAbduct(conj));
}
@Test
void getAbductNext() throws CVC5ApiException
{
d_solver.setLogic("QF_LIA");
d_solver.setOption("produce-abducts", "true");
d_solver.setOption("incremental", "true");
Sort intSort = d_solver.getIntegerSort();
Term zero = d_solver.mkInteger(0);
Term x = d_solver.mkConst(intSort, "x");
Term y = d_solver.mkConst(intSort, "y");
// Assumptions for abduction: x > 0
d_solver.assertFormula(d_solver.mkTerm(GT, x, zero));
// Conjecture for abduction: y > 0
Term conj = d_solver.mkTerm(GT, y, zero);
// Call the abduction api, while the resulting abduct is the output
Term output = d_solver.getAbduct(conj);
Term output2 = d_solver.getAbductNext();
// should produce a different output
assertNotEquals(output, output2);
}
@Test
void getInterpolant() throws CVC5ApiException
{
d_solver.setLogic("QF_LIA");
d_solver.setOption("produce-interpolants", "true");
d_solver.setOption("incremental", "false");
Sort intSort = d_solver.getIntegerSort();
Term zero = d_solver.mkInteger(0);
Term x = d_solver.mkConst(intSort, "x");
Term y = d_solver.mkConst(intSort, "y");
Term z = d_solver.mkConst(intSort, "z");
// Assumptions for interpolation: x + y > 0 /\ x < 0
d_solver.assertFormula(d_solver.mkTerm(GT, d_solver.mkTerm(ADD, x, y), zero));
d_solver.assertFormula(d_solver.mkTerm(LT, x, zero));
// Conjecture for interpolation: y + z > 0 \/ z < 0
Term conj = d_solver.mkTerm(
OR, d_solver.mkTerm(GT, d_solver.mkTerm(ADD, y, z), zero), d_solver.mkTerm(LT, z, zero));
// Call the interpolation api, while the resulting interpolant is the output
Term output = d_solver.getInterpolant(conj);
// We expect the resulting output to be a boolean formula
assertTrue(output.getSort().isBoolean());
// try with a grammar, a simple grammar admitting true
Sort bsort = d_solver.getBooleanSort();
Term truen = d_solver.mkBoolean(true);
Term start = d_solver.mkVar(bsort);
Grammar g = d_solver.mkGrammar(new Term[] {}, new Term[] {start});
Term conj2 = d_solver.mkTerm(EQUAL, zero, zero);
assertDoesNotThrow(() -> g.addRule(start, truen));
// Call the interpolation api, while the resulting interpolant is the output
Term output2 = d_solver.getInterpolant(conj2, g);
// interpolant must be true
assertEquals(output2, truen);
}
@Test
void getInterpolantNext() throws CVC5ApiException
{
d_solver.setLogic("QF_LIA");
d_solver.setOption("produce-interpolants", "true");
d_solver.setOption("incremental", "true");
Sort intSort = d_solver.getIntegerSort();
Term zero = d_solver.mkInteger(0);
Term x = d_solver.mkConst(intSort, "x");
Term y = d_solver.mkConst(intSort, "y");
Term z = d_solver.mkConst(intSort, "z");
d_solver.assertFormula(d_solver.mkTerm(GT, d_solver.mkTerm(ADD, x, y), zero));
d_solver.assertFormula(d_solver.mkTerm(LT, x, zero));
Term conj = d_solver.mkTerm(
OR, d_solver.mkTerm(GT, d_solver.mkTerm(ADD, y, z), zero), d_solver.mkTerm(LT, z, zero));
Term output = d_solver.getInterpolant(conj);
Term output2 = d_solver.getInterpolantNext();
// We expect the next output to be distinct
assertNotEquals(output, output2);
}
@Test
void declarePool() throws CVC5ApiException
{
Sort intSort = d_solver.getIntegerSort();
Sort setSort = d_solver.mkSetSort(intSort);
Term zero = d_solver.mkInteger(0);
Term x = d_solver.mkConst(intSort, "x");
Term y = d_solver.mkConst(intSort, "y");
// declare a pool with initial value { 0, x, y }
Term p = d_solver.declarePool("p", intSort, new Term[] {zero, x, y});
// pool should have the same sort
assertEquals(p.getSort(), setSort);
}
@Test
void getOp() throws CVC5ApiException
{
Sort bv32 = d_solver.mkBitVectorSort(32);
Term a = d_solver.mkConst(bv32, "a");
Op ext = d_solver.mkOp(BITVECTOR_EXTRACT, 2, 1);
Term exta = d_solver.mkTerm(ext, a);
assertFalse(a.hasOp());
assertThrows(CVC5ApiException.class, () -> a.getOp());
assertTrue(exta.hasOp());
assertEquals(exta.getOp(), ext);
// Test Datatypes -- more complicated
DatatypeDecl consListSpec = d_solver.mkDatatypeDecl("list");
DatatypeConstructorDecl cons = d_solver.mkDatatypeConstructorDecl("cons");
cons.addSelector("head", d_solver.getIntegerSort());
cons.addSelectorSelf("tail");
consListSpec.addConstructor(cons);
DatatypeConstructorDecl nil = d_solver.mkDatatypeConstructorDecl("nil");
consListSpec.addConstructor(nil);
Sort consListSort = d_solver.mkDatatypeSort(consListSpec);
Datatype consList = consListSort.getDatatype();
Term consTerm = consList.getConstructor("cons").getTerm();
Term nilTerm = consList.getConstructor("nil").getTerm();
Term headTerm = consList.getConstructor("cons").getSelector("head").getTerm();
Term listnil = d_solver.mkTerm(APPLY_CONSTRUCTOR, nilTerm);
Term listcons1 = d_solver.mkTerm(APPLY_CONSTRUCTOR, consTerm, d_solver.mkInteger(1), listnil);
Term listhead = d_solver.mkTerm(APPLY_SELECTOR, headTerm, listcons1);
assertTrue(listnil.hasOp());
assertTrue(listcons1.hasOp());
assertTrue(listhead.hasOp());
}
@Test
void getOption()
{
assertDoesNotThrow(() -> d_solver.getOption("incremental"));
assertThrows(CVC5ApiException.class, () -> d_solver.getOption("asdf"));
}
@Test
void getOptionNames()
{
String[] names = d_solver.getOptionNames();
assertTrue(names.length > 100);
assertTrue(Arrays.asList(names).contains("verbose"));
assertFalse(Arrays.asList(names).contains("foobar"));
}
@Test
void getOptionInfo()
{
List<Executable> assertions = new ArrayList<>();
{
assertions.add(
() -> assertThrows(CVC5ApiException.class, () -> d_solver.getOptionInfo("asdf-invalid")));
}
{
OptionInfo info = d_solver.getOptionInfo("verbose");
assertions.add(() -> assertEquals("verbose", info.getName()));
assertions.add(() -> assertEquals(OptionCategory.COMMON, info.getCategory()));
assertions.add(
() -> assertEquals(Arrays.asList(new String[] {}), Arrays.asList(info.getAliases())));
assertions.add(() -> assertTrue(info.getBaseInfo() instanceof OptionInfo.VoidInfo));
assertions.add(() -> assertEquals(info.toString(), "OptionInfo{ verbose | void }"));
}
{
// bool type with default
OptionInfo info = d_solver.getOptionInfo("print-success");
assertions.add(() -> assertEquals("print-success", info.getName()));
assertions.add(() -> assertEquals(OptionCategory.COMMON, info.getCategory()));
assertions.add(
() -> assertEquals(Arrays.asList(new String[] {}), Arrays.asList(info.getAliases())));
assertions.add(() -> assertTrue(info.getBaseInfo().getClass() == OptionInfo.ValueInfo.class));
OptionInfo.ValueInfo<Boolean> valInfo = (OptionInfo.ValueInfo<Boolean>) info.getBaseInfo();
assertions.add(() -> assertEquals(false, valInfo.getDefaultValue().booleanValue()));
assertions.add(() -> assertEquals(false, valInfo.getCurrentValue().booleanValue()));
assertions.add(() -> assertEquals(info.booleanValue(), false));
assertions.add(()
-> assertEquals(info.toString(),
"OptionInfo{ print-success | bool | false | default false }"));
}
{
// int64 type with default
OptionInfo info = d_solver.getOptionInfo("verbosity");
assertions.add(() -> assertEquals("verbosity", info.getName()));
assertions.add(() -> assertEquals(OptionCategory.COMMON, info.getCategory()));
assertions.add(
() -> assertEquals(Arrays.asList(new String[] {}), Arrays.asList(info.getAliases())));
assertions.add(
() -> assertTrue(info.getBaseInfo().getClass() == OptionInfo.NumberInfo.class));
OptionInfo.NumberInfo<BigInteger> numInfo =
(OptionInfo.NumberInfo<BigInteger>) info.getBaseInfo();
assertions.add(() -> assertEquals(0, numInfo.getDefaultValue().intValue()));
assertions.add(() -> assertEquals(0, numInfo.getCurrentValue().intValue()));
assertions.add(
() -> assertTrue(numInfo.getMinimum() == null && numInfo.getMaximum() == null));
assertions.add(() -> assertEquals(info.intValue().intValue(), 0));
assertions.add(
() -> assertEquals(info.toString(), "OptionInfo{ verbosity | int64_t | 0 | default 0 }"));
}
assertAll(assertions);
{
OptionInfo info = d_solver.getOptionInfo("rlimit");
assertEquals(info.getName(), "rlimit");
assertions.add(() -> assertEquals(OptionCategory.COMMON, info.getCategory()));
assertEquals(Arrays.asList(info.getAliases()), Arrays.asList(new String[] {}));
assertTrue(info.getBaseInfo().getClass() == OptionInfo.NumberInfo.class);
OptionInfo.NumberInfo<BigInteger> ni = (OptionInfo.NumberInfo<BigInteger>) info.getBaseInfo();
assertEquals(ni.getCurrentValue().intValue(), 0);
assertEquals(ni.getDefaultValue().intValue(), 0);
assertTrue(ni.getMinimum() == null && ni.getMaximum() == null);
assertEquals(info.intValue().intValue(), 0);
assertEquals(info.toString(), "OptionInfo{ rlimit | uint64_t | 0 | default 0 }");
}
{
OptionInfo info = d_solver.getOptionInfo("random-freq");
assertEquals(info.getName(), "random-freq");
assertEquals(OptionCategory.EXPERT, info.getCategory());
assertEquals(
Arrays.asList(info.getAliases()), Arrays.asList(new String[] {"random-frequency"}));
assertTrue(info.getBaseInfo().getClass() == OptionInfo.NumberInfo.class);
OptionInfo.NumberInfo<Double> ni = (OptionInfo.NumberInfo<Double>) info.getBaseInfo();
assertEquals(ni.getCurrentValue(), 0.0);
assertEquals(ni.getDefaultValue(), 0.0);
assertTrue(ni.getMinimum() != null && ni.getMaximum() != null);
assertEquals(ni.getMinimum(), 0.0);
assertEquals(ni.getMaximum(), 1.0);
assertEquals(info.doubleValue(), 0.0);
assertEquals(info.toString(),
"OptionInfo{ random-freq, random-frequency | double | 0 | default 0 | 0 <= x <= 1 }");
}
{
OptionInfo info = d_solver.getOptionInfo("force-logic");
assertEquals(info.getName(), "force-logic");
assertEquals(OptionCategory.COMMON, info.getCategory());
assertEquals(Arrays.asList(info.getAliases()), Arrays.asList(new String[] {}));
assertTrue(info.getBaseInfo().getClass() == OptionInfo.ValueInfo.class);
OptionInfo.ValueInfo<String> ni = (OptionInfo.ValueInfo<String>) info.getBaseInfo();
assertEquals(ni.getCurrentValue(), "");
assertEquals(ni.getDefaultValue(), "");
assertEquals(info.stringValue(), "");
assertEquals(info.toString(), "OptionInfo{ force-logic | string | \"\" | default \"\" }");
}
{
// mode option
OptionInfo info = d_solver.getOptionInfo("simplification");
assertions.clear();
assertions.add(() -> assertEquals("simplification", info.getName()));
assertions.add(() -> assertEquals(OptionCategory.REGULAR, info.getCategory()));
assertions.add(()
-> assertEquals(Arrays.asList(new String[] {"simplification-mode"}),
Arrays.asList(info.getAliases())));
assertions.add(() -> assertTrue(info.getBaseInfo().getClass() == OptionInfo.ModeInfo.class));
OptionInfo.ModeInfo modeInfo = (OptionInfo.ModeInfo) info.getBaseInfo();
assertions.add(() -> assertEquals("batch", modeInfo.getDefaultValue()));
assertions.add(() -> assertEquals("batch", modeInfo.getCurrentValue()));
assertions.add(() -> assertEquals(2, modeInfo.getModes().length));
assertions.add(() -> assertTrue(Arrays.asList(modeInfo.getModes()).contains("batch")));
assertions.add(() -> assertTrue(Arrays.asList(modeInfo.getModes()).contains("none")));
assertEquals(info.toString(),
"OptionInfo{ simplification, simplification-mode | mode | batch | default batch | modes: batch, none }");
}
assertAll(assertions);
}
@Test
void getStatistics()
{
// do some array reasoning to make sure we have a double statistics
{
Sort s1 = d_tm.getIntegerSort();
Sort s2 = d_tm.mkArraySort(s1, s1);
Term t1 = d_tm.mkConst(s1, "i");
Term t2 = d_tm.mkVar(s2, "a");
Term t3 = d_tm.mkTerm(Kind.SELECT, t2, t1);
d_solver.checkSat();
}
Statistics stats = d_solver.getStatistics();
stats.toString();
{
Stat s = stats.get("global::totalTime");
assertFalse(s.isInternal());
assertFalse(s.isDefault());
assertTrue(s.isString());
assertTrue(s.getString().endsWith("ms"));
s = stats.get("resource::resourceUnitsUsed");
s.toString();
assertTrue(s.isInternal());
assertFalse(s.isDefault());
assertTrue(s.isInt());
assertTrue(s.getInt() >= 0);
s.toString();
}
for (Map.Entry<String, Stat> s : stats)
{
assertFalse(s.getKey().isEmpty());
}
for (Statistics.ConstIterator it = stats.iterator(true, true); it.hasNext();)
{
Map.Entry<String, Stat> elem = it.next();
if (elem.getKey().equals("theory::arrays::avgIndexListLength"))
{
assertTrue(elem.getValue().isInternal());
assertTrue(elem.getValue().isDouble());
assertTrue(Double.isNaN(elem.getValue().getDouble()));
elem.getValue().toString();
}
}
}
@Test
void getUnsatAssumptions1()
{
d_solver.setOption("incremental", "false");
d_solver.checkSatAssuming(d_solver.mkFalse());
assertThrows(CVC5ApiException.class, () -> d_solver.getUnsatAssumptions());
}
@Test
void getUnsatAssumptions2()
{
d_solver.setOption("incremental", "true");
d_solver.setOption("produce-unsat-assumptions", "false");
d_solver.checkSatAssuming(d_solver.mkFalse());
assertThrows(CVC5ApiException.class, () -> d_solver.getUnsatAssumptions());
}
@Test
void getUnsatAssumptions3()
{
d_solver.setOption("incremental", "true");
d_solver.setOption("produce-unsat-assumptions", "true");
d_solver.checkSatAssuming(d_solver.mkFalse());
assertDoesNotThrow(() -> d_solver.getUnsatAssumptions());
d_solver.checkSatAssuming(d_solver.mkTrue());
assertThrows(CVC5ApiException.class, () -> d_solver.getUnsatAssumptions());
}
@Test
void getUnsatCore1()
{
d_solver.setOption("incremental", "false");
d_solver.assertFormula(d_solver.mkFalse());
d_solver.checkSat();
assertThrows(CVC5ApiException.class, () -> d_solver.getUnsatCore());
}
@Test
void getUnsatCore2()
{
d_solver.setOption("incremental", "false");
d_solver.setOption("produce-unsat-cores", "false");
d_solver.assertFormula(d_solver.mkFalse());
d_solver.checkSat();
assertThrows(CVC5ApiException.class, () -> d_solver.getUnsatCore());
}
@Test
void getUnsatCoreAndProof()
{
d_solver.setOption("incremental", "true");
d_solver.setOption("produce-unsat-cores", "true");
d_solver.setOption("produce-proofs", "true");
Sort uSort = d_solver.mkUninterpretedSort("u");
Sort intSort = d_solver.getIntegerSort();
Sort boolSort = d_solver.getBooleanSort();
Sort uToIntSort = d_solver.mkFunctionSort(uSort, intSort);
Sort intPredSort = d_solver.mkFunctionSort(intSort, boolSort);
Term x = d_solver.mkConst(uSort, "x");
Term y = d_solver.mkConst(uSort, "y");
Term f = d_solver.mkConst(uToIntSort, "f");
Term p = d_solver.mkConst(intPredSort, "p");
Term zero = d_solver.mkInteger(0);
Term one = d_solver.mkInteger(1);
Term f_x = d_solver.mkTerm(Kind.APPLY_UF, f, x);
Term f_y = d_solver.mkTerm(Kind.APPLY_UF, f, y);
Term sum = d_solver.mkTerm(Kind.ADD, f_x, f_y);
Term p_0 = d_solver.mkTerm(Kind.APPLY_UF, p, zero);
Term p_f_y = d_solver.mkTerm(APPLY_UF, p, f_y);
d_solver.assertFormula(d_solver.mkTerm(Kind.GT, zero, f_x));
d_solver.assertFormula(d_solver.mkTerm(Kind.GT, zero, f_y));
d_solver.assertFormula(d_solver.mkTerm(Kind.GT, sum, one));
d_solver.assertFormula(p_0);
d_solver.assertFormula(p_f_y.notTerm());
assertTrue(d_solver.checkSat().isUnsat());
Term[] unsat_core = d_solver.getUnsatCore();
assertDoesNotThrow(() -> d_solver.getProof());
assertDoesNotThrow(() -> d_solver.getProof(ProofComponent.SAT));
d_solver.resetAssertions();
for (Term t : unsat_core)
{
d_solver.assertFormula(t);
}
Result res = d_solver.checkSat();
assertTrue(res.isUnsat());
assertDoesNotThrow(() -> d_solver.getProof());
}
@Test
void getProofAndProofToString()
{
d_solver.setOption("produce-proofs", "true");
Sort uSort = d_solver.mkUninterpretedSort("u");
Sort intSort = d_solver.getIntegerSort();
Sort boolSort = d_solver.getBooleanSort();
Sort uToIntSort = d_solver.mkFunctionSort(uSort, intSort);
Sort intPredSort = d_solver.mkFunctionSort(intSort, boolSort);
Term x = d_solver.mkConst(uSort, "x");
Term y = d_solver.mkConst(uSort, "y");
Term f = d_solver.mkConst(uToIntSort, "f");
Term p = d_solver.mkConst(intPredSort, "p");
Term zero = d_solver.mkInteger(0);
Term one = d_solver.mkInteger(1);
Term f_x = d_solver.mkTerm(Kind.APPLY_UF, f, x);
Term f_y = d_solver.mkTerm(Kind.APPLY_UF, f, y);
Term sum = d_solver.mkTerm(Kind.ADD, f_x, f_y);
Term p_0 = d_solver.mkTerm(Kind.APPLY_UF, p, zero);
Term p_f_y = d_solver.mkTerm(APPLY_UF, p, f_y);
d_solver.assertFormula(d_solver.mkTerm(Kind.GT, zero, f_x));
d_solver.assertFormula(d_solver.mkTerm(Kind.GT, zero, f_y));
d_solver.assertFormula(d_solver.mkTerm(Kind.GT, sum, one));
d_solver.assertFormula(p_0);
d_solver.assertFormula(p_f_y.notTerm());
assertTrue(d_solver.checkSat().isUnsat());
Proof[] proofs = d_solver.getProof();
assertNotEquals(0, proofs.length);
String printedProof = d_solver.proofToString(proofs[0]);
assertFalse(printedProof.isEmpty());
printedProof = d_solver.proofToString(proofs[0], ProofFormat.ALETHE);
assertFalse(printedProof.isEmpty());
proofs = d_solver.getProof(ProofComponent.SAT);
assertNotEquals(0, proofs.length);
printedProof = d_solver.proofToString(proofs[0], ProofFormat.NONE);
assertFalse(printedProof.isEmpty());
}
@Test
void proofToStringAssertionNames()
{
d_solver.setOption("produce-proofs", "true");
Sort uSort = d_solver.mkUninterpretedSort("u");
Term x = d_solver.mkConst(uSort, "x");
Term y = d_solver.mkConst(uSort, "y");
Term x_eq_y = d_solver.mkTerm(Kind.EQUAL, x, y);
Term not_x_eq_y = d_solver.mkTerm(Kind.NOT, x_eq_y);
Map<Term, String> assertionNames = new HashMap();
assertionNames.put(x_eq_y, "as1");
assertionNames.put(not_x_eq_y, "as2");
d_solver.assertFormula(x_eq_y);
d_solver.assertFormula(not_x_eq_y);
assertTrue(d_solver.checkSat().isUnsat());
Proof[] proofs = d_solver.getProof();
assertNotEquals(0, proofs.length);
String printedProof = d_solver.proofToString(proofs[0], ProofFormat.ALETHE, assertionNames);
assertFalse(printedProof.isEmpty());
assertTrue(printedProof.contains("as1"));
assertTrue(printedProof.contains("as2"));
}
@Test
void getUnsatCoreLemmas1()
{
d_solver.assertFormula(d_solver.mkFalse());
assertTrue(d_solver.checkSat().isUnsat());
assertThrows(CVC5ApiException.class, () -> d_solver.getUnsatCoreLemmas());
}
@Test
void getUnsatCoreLemmas2()
{
d_solver.setOption("produce-unsat-cores", "true");
d_solver.setOption("unsat-cores-mode", "sat-proof");
Sort uSort = d_solver.mkUninterpretedSort("u");
Sort intSort = d_solver.getIntegerSort();
Sort boolSort = d_solver.getBooleanSort();
Sort uToIntSort = d_solver.mkFunctionSort(uSort, intSort);
Sort intPredSort = d_solver.mkFunctionSort(intSort, boolSort);
Term x = d_solver.mkConst(uSort, "x");
Term y = d_solver.mkConst(uSort, "y");
Term f = d_solver.mkConst(uToIntSort, "f");
Term p = d_solver.mkConst(intPredSort, "p");
Term zero = d_solver.mkInteger(0);
Term one = d_solver.mkInteger(1);
Term f_x = d_solver.mkTerm(Kind.APPLY_UF, f, x);
Term f_y = d_solver.mkTerm(Kind.APPLY_UF, f, y);
Term sum = d_solver.mkTerm(Kind.ADD, f_x, f_y);
Term p_0 = d_solver.mkTerm(Kind.APPLY_UF, p, zero);
Term p_f_y = d_solver.mkTerm(APPLY_UF, p, f_y);
d_solver.assertFormula(d_solver.mkTerm(Kind.GT, zero, f_x));
d_solver.assertFormula(d_solver.mkTerm(Kind.GT, zero, f_y));
d_solver.assertFormula(d_solver.mkTerm(Kind.GT, sum, one));
d_solver.assertFormula(p_0);
d_solver.assertFormula(p_f_y.notTerm());
assertTrue(d_solver.checkSat().isUnsat());
d_solver.getUnsatCoreLemmas();
}
@Test
void getDifficulty()
{
d_solver.setOption("produce-difficulty", "true");
// cannot ask before a check sat
assertThrows(CVC5ApiException.class, () -> d_solver.getDifficulty());
d_solver.checkSat();
assertDoesNotThrow(() -> d_solver.getDifficulty());
}
@Test
void getDifficulty2()
{
d_solver.checkSat();
// option is not set
assertThrows(CVC5ApiException.class, () -> d_solver.getDifficulty());
}
@Test
void getDifficulty3() throws CVC5ApiException
{
d_solver.setOption("produce-difficulty", "true");
Sort intSort = d_solver.getIntegerSort();
Term x = d_solver.mkConst(intSort, "x");
Term zero = d_solver.mkInteger(0);
Term ten = d_solver.mkInteger(10);
Term f0 = d_solver.mkTerm(GEQ, x, ten);
Term f1 = d_solver.mkTerm(GEQ, zero, x);
d_solver.assertFormula(f0);
d_solver.assertFormula(f1);
d_solver.checkSat();
Map<Term, Term> dmap = d_solver.getDifficulty();
// difficulty should map assertions to integer values
for (Map.Entry<Term, Term> t : dmap.entrySet())
{
assertTrue(t.getKey().equals(f0) || t.getKey().equals(f1));
assertTrue(t.getValue().getKind() == Kind.CONST_INTEGER);
}
}
@Test
void getLearnedLiterals()
{
d_solver.setOption("produce-learned-literals", "true");
// cannot ask before a check sat
assertThrows(CVC5ApiException.class, () -> d_solver.getLearnedLiterals());
d_solver.checkSat();
assertDoesNotThrow(() -> d_solver.getLearnedLiterals());
assertDoesNotThrow(() -> d_solver.getLearnedLiterals(LearnedLitType.PREPROCESS));
}
@Test
void getLearnedLiterals2()
{
d_solver.setOption("produce-learned-literals", "true");
Sort intSort = d_solver.getIntegerSort();
Term x = d_solver.mkConst(intSort, "x");
Term y = d_solver.mkConst(intSort, "y");
Term zero = d_solver.mkInteger(0);
Term ten = d_solver.mkInteger(10);
Term f0 = d_solver.mkTerm(GEQ, x, ten);
Term f1 = d_solver.mkTerm(OR, d_solver.mkTerm(GEQ, zero, x), d_solver.mkTerm(GEQ, y, zero));
d_solver.assertFormula(f0);
d_solver.assertFormula(f1);
d_solver.checkSat();
assertDoesNotThrow(() -> d_solver.getLearnedLiterals(LearnedLitType.INPUT));
}
@Test
void getTimeoutCoreUnsat() throws CVC5ApiException
{
d_solver.setOption("timeout-core-timeout", "100");
d_solver.setOption("produce-unsat-cores", "true");
Sort intSort = d_solver.getIntegerSort();
Term x = d_solver.mkConst(intSort, "x");
Term tt = d_solver.mkBoolean(true);
Term hard = d_solver.mkTerm(EQUAL,
new Term[] {d_solver.mkTerm(MULT, new Term[] {x, x}),
d_solver.mkInteger("501240912901901249014210220059591")});
d_solver.assertFormula(tt);
d_solver.assertFormula(hard);
Pair<Result, Term[]> res = d_solver.getTimeoutCore();
assertTrue(res.first.isUnknown());
assertTrue(res.second.length == 1);
assertEquals(res.second[0], hard);
}
@Test
void getTimeoutCore() throws CVC5ApiException
{
d_solver.setOption("produce-unsat-cores", "true");
Term ff = d_solver.mkBoolean(false);
Term tt = d_solver.mkBoolean(true);
d_solver.assertFormula(tt);
d_solver.assertFormula(ff);
d_solver.assertFormula(tt);
Pair<Result, Term[]> res = d_solver.getTimeoutCore();
assertTrue(res.first.isUnsat());
assertTrue(res.second.length == 1);
assertEquals(res.second[0], ff);
}
@Test
void getTimeoutCoreAssuming() throws CVC5ApiException
{
d_solver.setOption("produce-unsat-cores", "true");
Term ff = d_solver.mkBoolean(false);
Term tt = d_solver.mkBoolean(true);
d_solver.assertFormula(tt);
Pair<Result, Term[]> res = d_solver.getTimeoutCoreAssuming(new Term[] {ff, tt});
assertTrue(res.first.isUnsat());
assertTrue(res.second.length == 1);
assertEquals(res.second[0], ff);
}
@Test
void getTimeoutCoreAssumingEmpty() throws CVC5ApiException
{
d_solver.setOption("produce-unsat-cores", "true");
assertThrows(CVC5ApiException.class, () -> d_solver.getTimeoutCoreAssuming(new Term[] {}));
}
@Test
void getValue1()
{
d_solver.setOption("produce-models", "false");
Term t = d_solver.mkTrue();
d_solver.assertFormula(t);
d_solver.checkSat();
assertThrows(CVC5ApiException.class, () -> d_solver.getValue(t));
}
@Test
void getValue2()
{
d_solver.setOption("produce-models", "true");
Term t = d_solver.mkFalse();
d_solver.assertFormula(t);
d_solver.checkSat();
assertThrows(CVC5ApiException.class, () -> d_solver.getValue(t));
}
@Test
void getValue3()
{
d_solver.setOption("produce-models", "true");
Sort uSort = d_solver.mkUninterpretedSort("u");
Sort intSort = d_solver.getIntegerSort();
Sort boolSort = d_solver.getBooleanSort();
Sort uToIntSort = d_solver.mkFunctionSort(uSort, intSort);
Sort intPredSort = d_solver.mkFunctionSort(intSort, boolSort);
Term[] unsat_core;
Term x = d_solver.mkConst(uSort, "x");
Term y = d_solver.mkConst(uSort, "y");
Term z = d_solver.mkConst(uSort, "z");
Term f = d_solver.mkConst(uToIntSort, "f");
Term p = d_solver.mkConst(intPredSort, "p");
Term zero = d_solver.mkInteger(0);
Term one = d_solver.mkInteger(1);
Term f_x = d_solver.mkTerm(APPLY_UF, f, x);
Term f_y = d_solver.mkTerm(APPLY_UF, f, y);
Term sum = d_solver.mkTerm(ADD, f_x, f_y);
Term p_0 = d_solver.mkTerm(APPLY_UF, p, zero);
Term p_f_y = d_solver.mkTerm(APPLY_UF, p, f_y);
d_solver.assertFormula(d_solver.mkTerm(LEQ, zero, f_x));
d_solver.assertFormula(d_solver.mkTerm(LEQ, zero, f_y));
d_solver.assertFormula(d_solver.mkTerm(LEQ, sum, one));
d_solver.assertFormula(p_0.notTerm());
d_solver.assertFormula(p_f_y);
assertTrue(d_solver.checkSat().isSat());
assertDoesNotThrow(() -> d_solver.getValue(x));
assertDoesNotThrow(() -> d_solver.getValue(y));
assertDoesNotThrow(() -> d_solver.getValue(z));
assertDoesNotThrow(() -> d_solver.getValue(sum));
assertDoesNotThrow(() -> d_solver.getValue(p_f_y));
Term[] b = d_solver.getValue(new Term[] {x, y, z});
Solver slv = new Solver();
assertThrows(CVC5ApiException.class, () -> slv.getValue(x));
}
@Test
void getModelDomainElements()
{
d_solver.setOption("produce-models", "true");
Sort uSort = d_solver.mkUninterpretedSort("u");
Sort intSort = d_solver.getIntegerSort();
Term x = d_solver.mkConst(uSort, "x");
Term y = d_solver.mkConst(uSort, "y");
Term z = d_solver.mkConst(uSort, "z");
Term f = d_solver.mkTerm(DISTINCT, x, y, z);
d_solver.assertFormula(f);
d_solver.checkSat();
assertDoesNotThrow(() -> d_solver.getModelDomainElements(uSort));
assertTrue(d_solver.getModelDomainElements(uSort).length >= 3);
assertThrows(CVC5ApiException.class, () -> d_solver.getModelDomainElements(intSort));
}
@Test
void getModelDomainElements2()
{
d_solver.setOption("produce-models", "true");
d_solver.setOption("finite-model-find", "true");
Sort uSort = d_solver.mkUninterpretedSort("u");
Term x = d_solver.mkVar(uSort, "x");
Term y = d_solver.mkVar(uSort, "y");
Term eq = d_solver.mkTerm(EQUAL, x, y);
Term bvl = d_solver.mkTerm(VARIABLE_LIST, x, y);
Term f = d_solver.mkTerm(FORALL, bvl, eq);
d_solver.assertFormula(f);
d_solver.checkSat();
assertDoesNotThrow(() -> d_solver.getModelDomainElements(uSort));
// a model for the above must interpret u as size 1
assertTrue(d_solver.getModelDomainElements(uSort).length == 1);
}
@Test
void isModelCoreSymbol()
{
d_solver.setOption("produce-models", "true");
d_solver.setOption("model-cores", "simple");
Sort uSort = d_solver.mkUninterpretedSort("u");
Term x = d_solver.mkConst(uSort, "x");
Term y = d_solver.mkConst(uSort, "y");
Term z = d_solver.mkConst(uSort, "z");
Term zero = d_solver.mkInteger(0);
Term f = d_solver.mkTerm(NOT, d_solver.mkTerm(EQUAL, x, y));
d_solver.assertFormula(f);
d_solver.checkSat();
assertTrue(d_solver.isModelCoreSymbol(x));
assertTrue(d_solver.isModelCoreSymbol(y));
assertFalse(d_solver.isModelCoreSymbol(z));
assertThrows(CVC5ApiException.class, () -> d_solver.isModelCoreSymbol(zero));
}
@Test
void getModel()
{
d_solver.setOption("produce-models", "true");
Sort uSort = d_solver.mkUninterpretedSort("u");
Term x = d_solver.mkConst(uSort, "x");
Term y = d_solver.mkConst(uSort, "y");
Term z = d_solver.mkConst(uSort, "z");
Term f = d_solver.mkTerm(NOT, d_solver.mkTerm(EQUAL, x, y));
d_solver.assertFormula(f);
d_solver.checkSat();
Sort[] sorts = new Sort[] {uSort};
Term[] terms = new Term[] {x, y};
assertDoesNotThrow(() -> d_solver.getModel(sorts, terms));
Term nullTerm = new Term();
Term[] terms2 = new Term[] {x, y, nullTerm};
assertThrows(CVC5ApiException.class, () -> d_solver.getModel(sorts, terms2));
}
@Test
void getModel2()
{
d_solver.setOption("produce-models", "true");
Sort[] sorts = new Sort[] {};
Term[] terms = new Term[] {};
assertThrows(CVC5ApiException.class, () -> d_solver.getModel(sorts, terms));
}
@Test
void getModel3()
{
d_solver.setOption("produce-models", "true");
Sort[] sorts = new Sort[] {};
final Term[] terms = new Term[] {};
d_solver.checkSat();
assertDoesNotThrow(() -> d_solver.getModel(sorts, terms));
Sort integer = d_solver.getIntegerSort();
Sort[] sorts2 = new Sort[] {integer};
assertThrows(CVC5ApiException.class, () -> d_solver.getModel(sorts2, terms));
}
@Test
void getQuantifierElimination()
{
Term x = d_solver.mkVar(d_solver.getBooleanSort(), "x");
Term forall = d_solver.mkTerm(
FORALL, d_solver.mkTerm(VARIABLE_LIST, x), d_solver.mkTerm(OR, x, d_solver.mkTerm(NOT, x)));
assertThrows(CVC5ApiException.class, () -> d_solver.getQuantifierElimination(new Term()));
Solver slv = new Solver();
assertThrows(
CVC5ApiException.class, () -> d_solver.getQuantifierElimination(slv.mkBoolean(false)));
assertDoesNotThrow(() -> d_solver.getQuantifierElimination(forall));
}
@Test
void getQuantifierEliminationDisjunct()
{
Term x = d_solver.mkVar(d_solver.getBooleanSort(), "x");
Term forall = d_solver.mkTerm(
FORALL, d_solver.mkTerm(VARIABLE_LIST, x), d_solver.mkTerm(OR, x, d_solver.mkTerm(NOT, x)));
assertThrows(
CVC5ApiException.class, () -> d_solver.getQuantifierEliminationDisjunct(new Term()));
Solver slv = new Solver();
assertThrows(CVC5ApiException.class,
() -> d_solver.getQuantifierEliminationDisjunct(slv.mkBoolean(false)));
assertDoesNotThrow(() -> d_solver.getQuantifierEliminationDisjunct(forall));
}
@Test
void declareSepHeap() throws CVC5ApiException
{
d_solver.setLogic("ALL");
d_solver.setOption("incremental", "false");
Sort integer = d_solver.getIntegerSort();
assertDoesNotThrow(() -> d_solver.declareSepHeap(integer, integer));
// cannot declare separation logic heap more than once
assertThrows(CVC5ApiException.class, () -> d_solver.declareSepHeap(integer, integer));
}
/**
* Helper function for testGetSeparation{Heap,Nil}TermX. Asserts and checks
* some simple separation logic constraints.
*/
void checkSimpleSeparationConstraints(Solver solver)
{
Sort integer = solver.getIntegerSort();
// declare the separation heap
solver.declareSepHeap(integer, integer);
Term x = solver.mkConst(integer, "x");
Term p = solver.mkConst(integer, "p");
Term heap = solver.mkTerm(SEP_PTO, p, x);
solver.assertFormula(heap);
Term nil = solver.mkSepNil(integer);
solver.assertFormula(nil.eqTerm(solver.mkInteger(5)));
solver.checkSat();
}
@Test
void getValueSepHeap1() throws CVC5ApiException
{
d_solver.setLogic("QF_BV");
d_solver.setOption("incremental", "false");
d_solver.setOption("produce-models", "true");
Term t = d_solver.mkTrue();
d_solver.assertFormula(t);
assertThrows(CVC5ApiException.class, () -> d_solver.getValueSepHeap());
}
@Test
void getValueSepHeap2() throws CVC5ApiException
{
d_solver.setLogic("ALL");
d_solver.setOption("incremental", "false");
d_solver.setOption("produce-models", "false");
checkSimpleSeparationConstraints(d_solver);
assertThrows(CVC5ApiException.class, () -> d_solver.getValueSepHeap());
}
@Test
void getValueSepHeap3() throws CVC5ApiException
{
d_solver.setLogic("ALL");
d_solver.setOption("incremental", "false");
d_solver.setOption("produce-models", "true");
Term t = d_solver.mkFalse();
d_solver.assertFormula(t);
d_solver.checkSat();
assertThrows(CVC5ApiException.class, () -> d_solver.getValueSepHeap());
}
@Test
void getValueSepHeap4() throws CVC5ApiException
{
d_solver.setLogic("ALL");
d_solver.setOption("incremental", "false");
d_solver.setOption("produce-models", "true");
Term t = d_solver.mkTrue();
d_solver.assertFormula(t);
d_solver.checkSat();
assertThrows(CVC5ApiException.class, () -> d_solver.getValueSepHeap());
}
@Test
void getValueSepHeap5() throws CVC5ApiException
{
d_solver.setLogic("ALL");
d_solver.setOption("incremental", "false");
d_solver.setOption("produce-models", "true");
checkSimpleSeparationConstraints(d_solver);
assertDoesNotThrow(() -> d_solver.getValueSepHeap());
}
@Test
void getValueSepNil1() throws CVC5ApiException
{
d_solver.setLogic("QF_BV");
d_solver.setOption("incremental", "false");
d_solver.setOption("produce-models", "true");
Term t = d_solver.mkTrue();
d_solver.assertFormula(t);
assertThrows(CVC5ApiException.class, () -> d_solver.getValueSepNil());
}
@Test
void getValueSepNil2() throws CVC5ApiException
{
d_solver.setLogic("ALL");
d_solver.setOption("incremental", "false");
d_solver.setOption("produce-models", "false");
checkSimpleSeparationConstraints(d_solver);
assertThrows(CVC5ApiException.class, () -> d_solver.getValueSepNil());
}
@Test
void getValueSepNil3() throws CVC5ApiException
{
d_solver.setLogic("ALL");
d_solver.setOption("incremental", "false");
d_solver.setOption("produce-models", "true");
Term t = d_solver.mkFalse();
d_solver.assertFormula(t);
d_solver.checkSat();
assertThrows(CVC5ApiException.class, () -> d_solver.getValueSepNil());
}
@Test
void getValueSepNil4() throws CVC5ApiException
{
d_solver.setLogic("ALL");
d_solver.setOption("incremental", "false");
d_solver.setOption("produce-models", "true");
Term t = d_solver.mkTrue();
d_solver.assertFormula(t);
d_solver.checkSat();
assertThrows(CVC5ApiException.class, () -> d_solver.getValueSepNil());
}
@Test
void getValueSepNil5() throws CVC5ApiException
{
d_solver.setLogic("ALL");
d_solver.setOption("incremental", "false");
d_solver.setOption("produce-models", "true");
checkSimpleSeparationConstraints(d_solver);
assertDoesNotThrow(() -> d_solver.getValueSepNil());
}
@Test
void push1()
{
d_solver.setOption("incremental", "true");
assertDoesNotThrow(() -> d_solver.push(1));
assertThrows(CVC5ApiException.class, () -> d_solver.setOption("incremental", "false"));
assertThrows(CVC5ApiException.class, () -> d_solver.setOption("incremental", "true"));
}
@Test
void push2()
{
d_solver.setOption("incremental", "false");
assertThrows(CVC5ApiException.class, () -> d_solver.push(1));
}
@Test
void pop1()
{
d_solver.setOption("incremental", "false");
assertThrows(CVC5ApiException.class, () -> d_solver.pop(1));
}
@Test
void pop2()
{
d_solver.setOption("incremental", "true");
assertThrows(CVC5ApiException.class, () -> d_solver.pop(1));
}
@Test
void pop3()
{
d_solver.setOption("incremental", "true");
assertDoesNotThrow(() -> d_solver.push(1));
assertDoesNotThrow(() -> d_solver.pop(1));
assertThrows(CVC5ApiException.class, () -> d_solver.pop(1));
}
@Test
void blockModel1()
{
Term x = d_solver.mkConst(d_solver.getBooleanSort(), "x");
d_solver.assertFormula(x.eqTerm(x));
d_solver.checkSat();
assertThrows(CVC5ApiException.class, () -> d_solver.blockModel(BlockModelsMode.LITERALS));
}
@Test
void blockModel2() throws CVC5ApiException
{
d_solver.setOption("produce-models", "true");
Term x = d_solver.mkConst(d_solver.getBooleanSort(), "x");
d_solver.assertFormula(x.eqTerm(x));
assertThrows(CVC5ApiException.class, () -> d_solver.blockModel(BlockModelsMode.LITERALS));
}
@Test
void blockModel3() throws CVC5ApiException
{
d_solver.setOption("produce-models", "true");
Term x = d_solver.mkConst(d_solver.getBooleanSort(), "x");
d_solver.assertFormula(x.eqTerm(x));
d_solver.checkSat();
assertDoesNotThrow(() -> d_solver.blockModel(BlockModelsMode.LITERALS));
}
@Test
void blockModelValues1() throws CVC5ApiException
{
d_solver.setOption("produce-models", "true");
Term x = d_solver.mkConst(d_solver.getBooleanSort(), "x");
d_solver.assertFormula(x.eqTerm(x));
d_solver.checkSat();
assertThrows(CVC5ApiException.class, () -> d_solver.blockModelValues(new Term[] {}));
assertThrows(CVC5ApiException.class, () -> d_solver.blockModelValues(new Term[] {new Term()}));
Solver slv = new Solver();
assertThrows(
CVC5ApiException.class, () -> d_solver.blockModelValues(new Term[] {slv.mkBoolean(false)}));
}
@Test
void blockModelValues2() throws CVC5ApiException
{
d_solver.setOption("produce-models", "true");
Term x = d_solver.mkConst(d_solver.getBooleanSort(), "x");
d_solver.assertFormula(x.eqTerm(x));
d_solver.checkSat();
assertDoesNotThrow(() -> d_solver.blockModelValues(new Term[] {x}));
}
@Test
void blockModelValues3() throws CVC5ApiException
{
Term x = d_solver.mkConst(d_solver.getBooleanSort(), "x");
d_solver.assertFormula(x.eqTerm(x));
d_solver.checkSat();
assertThrows(CVC5ApiException.class, () -> d_solver.blockModelValues(new Term[] {x}));
}
@Test
void blockModelValues4() throws CVC5ApiException
{
d_solver.setOption("produce-models", "true");
Term x = d_solver.mkConst(d_solver.getBooleanSort(), "x");
d_solver.assertFormula(x.eqTerm(x));
assertThrows(CVC5ApiException.class, () -> d_solver.blockModelValues(new Term[] {x}));
}
@Test
void blockModelValues5() throws CVC5ApiException
{
d_solver.setOption("produce-models", "true");
Term x = d_solver.mkConst(d_solver.getBooleanSort(), "x");
d_solver.assertFormula(x.eqTerm(x));
d_solver.checkSat();
assertDoesNotThrow(() -> d_solver.blockModelValues(new Term[] {x}));
}
@Test
void getInstantiations() throws CVC5ApiException
{
Sort iSort = d_solver.getIntegerSort();
Sort boolSort = d_solver.getBooleanSort();
Term p = d_solver.declareFun("p", new Sort[] {iSort}, boolSort);
Term x = d_solver.mkVar(iSort, "x");
Term bvl = d_solver.mkTerm(VARIABLE_LIST, new Term[] {x});
Term app = d_solver.mkTerm(APPLY_UF, new Term[] {p, x});
Term q = d_solver.mkTerm(FORALL, new Term[] {bvl, app});
d_solver.assertFormula(q);
Term five = d_solver.mkInteger(5);
Term app2 = d_solver.mkTerm(NOT, new Term[] {d_solver.mkTerm(APPLY_UF, new Term[] {p, five})});
d_solver.assertFormula(app2);
assertThrows(CVC5ApiException.class, () -> d_solver.getInstantiations());
d_solver.checkSat();
assertDoesNotThrow(() -> d_solver.getInstantiations());
}
@Test
void setInfo() throws CVC5ApiException
{
assertThrows(CVC5ApiException.class, () -> d_solver.setInfo("cvc4-lagic", "QF_BV"));
assertThrows(CVC5ApiException.class, () -> d_solver.setInfo("cvc2-logic", "QF_BV"));
assertThrows(CVC5ApiException.class, () -> d_solver.setInfo("cvc4-logic", "asdf"));
assertDoesNotThrow(() -> d_solver.setInfo("source", "asdf"));
assertDoesNotThrow(() -> d_solver.setInfo("category", "asdf"));
assertDoesNotThrow(() -> d_solver.setInfo("difficulty", "asdf"));
assertDoesNotThrow(() -> d_solver.setInfo("filename", "asdf"));
assertDoesNotThrow(() -> d_solver.setInfo("license", "asdf"));
assertDoesNotThrow(() -> d_solver.setInfo("name", "asdf"));
assertDoesNotThrow(() -> d_solver.setInfo("notes", "asdf"));
assertDoesNotThrow(() -> d_solver.setInfo("smt-lib-version", "2"));
assertDoesNotThrow(() -> d_solver.setInfo("smt-lib-version", "2.0"));
assertDoesNotThrow(() -> d_solver.setInfo("smt-lib-version", "2.5"));
assertDoesNotThrow(() -> d_solver.setInfo("smt-lib-version", "2.6"));
assertThrows(CVC5ApiException.class, () -> d_solver.setInfo("smt-lib-version", ".0"));
assertDoesNotThrow(() -> d_solver.setInfo("status", "sat"));
assertDoesNotThrow(() -> d_solver.setInfo("status", "unsat"));
assertDoesNotThrow(() -> d_solver.setInfo("status", "unknown"));
assertThrows(CVC5ApiException.class, () -> d_solver.setInfo("status", "asdf"));
}
@Test
void simplifyApplySubs() throws CVC5ApiException
{
d_solver.setOption("incremental", "true");
Sort intSort = d_tm.getIntegerSort();
Term x = d_solver.mkConst(intSort, "x");
Term zero = d_solver.mkInteger(0);
Term eq = d_solver.mkTerm(EQUAL, x, zero);
d_solver.assertFormula(eq);
assertDoesNotThrow(() -> d_solver.checkSat());
assertEquals(d_solver.simplify(x, false), x);
assertEquals(d_solver.simplify(x, true), zero);
}
@Test
void simplify() throws CVC5ApiException
{
assertThrows(CVC5ApiException.class, () -> d_solver.simplify(new Term()));
Sort bvSort = d_solver.mkBitVectorSort(32);
Sort uSort = d_solver.mkUninterpretedSort("u");
Sort funSort1 = d_solver.mkFunctionSort(new Sort[] {bvSort, bvSort}, bvSort);
Sort funSort2 = d_solver.mkFunctionSort(uSort, d_solver.getIntegerSort());
DatatypeDecl consListSpec = d_solver.mkDatatypeDecl("list");
DatatypeConstructorDecl cons = d_solver.mkDatatypeConstructorDecl("cons");
cons.addSelector("head", d_solver.getIntegerSort());
cons.addSelectorSelf("tail");
consListSpec.addConstructor(cons);
DatatypeConstructorDecl nil = d_solver.mkDatatypeConstructorDecl("nil");
consListSpec.addConstructor(nil);
Sort consListSort = d_solver.mkDatatypeSort(consListSpec);
Term x = d_solver.mkConst(bvSort, "x");
assertDoesNotThrow(() -> d_solver.simplify(x));
Term a = d_solver.mkConst(bvSort, "a");
assertDoesNotThrow(() -> d_solver.simplify(a));
Term b = d_solver.mkConst(bvSort, "b");
assertDoesNotThrow(() -> d_solver.simplify(b));
Term x_eq_x = d_solver.mkTerm(EQUAL, x, x);
assertDoesNotThrow(() -> d_solver.simplify(x_eq_x));
assertNotEquals(d_solver.mkTrue(), x_eq_x);
assertEquals(d_solver.mkTrue(), d_solver.simplify(x_eq_x));
Term x_eq_b = d_solver.mkTerm(EQUAL, x, b);
assertDoesNotThrow(() -> d_solver.simplify(x_eq_b));
assertNotEquals(d_solver.mkTrue(), x_eq_b);
assertNotEquals(d_solver.mkTrue(), d_solver.simplify(x_eq_b));
Solver slv = new Solver();
assertThrows(CVC5ApiException.class, () -> slv.simplify(x));
Term i1 = d_solver.mkConst(d_solver.getIntegerSort(), "i1");
assertDoesNotThrow(() -> d_solver.simplify(i1));
Term i2 = d_solver.mkTerm(MULT, i1, d_solver.mkInteger("23"));
assertDoesNotThrow(() -> d_solver.simplify(i2));
assertNotEquals(i1, i2);
assertNotEquals(i1, d_solver.simplify(i2));
Term i3 = d_solver.mkTerm(ADD, i1, d_solver.mkInteger(0));
assertDoesNotThrow(() -> d_solver.simplify(i3));
assertNotEquals(i1, i3);
assertEquals(i1, d_solver.simplify(i3));
Datatype consList = consListSort.getDatatype();
Term dt1 = d_solver.mkTerm(APPLY_CONSTRUCTOR,
consList.getConstructor("cons").getTerm(),
d_solver.mkInteger(0),
d_solver.mkTerm(APPLY_CONSTRUCTOR, consList.getConstructor("nil").getTerm()));
assertDoesNotThrow(() -> d_solver.simplify(dt1));
Term dt2 = d_solver.mkTerm(
APPLY_SELECTOR, consList.getConstructor("cons").getSelector("head").getTerm(), dt1);
assertDoesNotThrow(() -> d_solver.simplify(dt2));
Term b1 = d_solver.mkVar(bvSort, "b1");
assertDoesNotThrow(() -> d_solver.simplify(b1));
Term b2 = d_solver.mkVar(bvSort, "b1");
assertDoesNotThrow(() -> d_solver.simplify(b2));
Term b3 = d_solver.mkVar(uSort, "b3");
assertDoesNotThrow(() -> d_solver.simplify(b3));
Term v1 = d_solver.mkConst(bvSort, "v1");
assertDoesNotThrow(() -> d_solver.simplify(v1));
Term v2 = d_solver.mkConst(d_solver.getIntegerSort(), "v2");
assertDoesNotThrow(() -> d_solver.simplify(v2));
Term f1 = d_solver.mkConst(funSort1, "f1");
assertDoesNotThrow(() -> d_solver.simplify(f1));
Term f2 = d_solver.mkConst(funSort2, "f2");
assertDoesNotThrow(() -> d_solver.simplify(f2));
d_solver.defineFunsRec(new Term[] {f1, f2}, new Term[][] {{b1, b2}, {b3}}, new Term[] {v1, v2});
assertDoesNotThrow(() -> d_solver.simplify(f1));
assertDoesNotThrow(() -> d_solver.simplify(f2));
}
@Test
void assertFormula()
{
assertDoesNotThrow(() -> d_solver.assertFormula(d_solver.mkTrue()));
assertThrows(CVC5ApiException.class, () -> d_solver.assertFormula(new Term()));
Solver slv = new Solver();
assertThrows(CVC5ApiException.class, () -> slv.assertFormula(d_solver.mkTrue()));
}
@Test
void checkSat() throws CVC5ApiException
{
d_solver.setOption("incremental", "false");
assertDoesNotThrow(() -> d_solver.checkSat());
assertThrows(CVC5ApiException.class, () -> d_solver.checkSat());
}
@Test
void checkSatAssuming() throws CVC5ApiException
{
d_solver.setOption("incremental", "false");
assertDoesNotThrow(() -> d_solver.checkSatAssuming(d_solver.mkTrue()));
assertThrows(CVC5ApiException.class, () -> d_solver.checkSatAssuming(d_solver.mkTrue()));
Solver slv = new Solver();
assertThrows(CVC5ApiException.class, () -> slv.checkSatAssuming(d_solver.mkTrue()));
}
@Test
void checkSatAssuming1() throws CVC5ApiException
{
Sort boolSort = d_solver.getBooleanSort();
Term x = d_solver.mkConst(boolSort, "x");
Term y = d_solver.mkConst(boolSort, "y");
Term z = d_solver.mkTerm(AND, x, y);
d_solver.setOption("incremental", "true");
assertDoesNotThrow(() -> d_solver.checkSatAssuming(d_solver.mkTrue()));
assertThrows(CVC5ApiException.class, () -> d_solver.checkSatAssuming(new Term()));
assertDoesNotThrow(() -> d_solver.checkSatAssuming(d_solver.mkTrue()));
assertDoesNotThrow(() -> d_solver.checkSatAssuming(z));
Solver slv = new Solver();
assertThrows(CVC5ApiException.class, () -> slv.checkSatAssuming(d_solver.mkTrue()));
}
@Test
void checkSatAssuming2() throws CVC5ApiException
{
d_solver.setOption("incremental", "true");
Sort uSort = d_solver.mkUninterpretedSort("u");
Sort intSort = d_solver.getIntegerSort();
Sort boolSort = d_solver.getBooleanSort();
Sort uToIntSort = d_solver.mkFunctionSort(uSort, intSort);
Sort intPredSort = d_solver.mkFunctionSort(intSort, boolSort);
Term n = new Term();
// Constants
Term x = d_solver.mkConst(uSort, "x");
Term y = d_solver.mkConst(uSort, "y");
// Functions
Term f = d_solver.mkConst(uToIntSort, "f");
Term p = d_solver.mkConst(intPredSort, "p");
// Values
Term zero = d_solver.mkInteger(0);
Term one = d_solver.mkInteger(1);
// Terms
Term f_x = d_solver.mkTerm(APPLY_UF, f, x);
Term f_y = d_solver.mkTerm(APPLY_UF, f, y);
Term sum = d_solver.mkTerm(ADD, f_x, f_y);
Term p_0 = d_solver.mkTerm(APPLY_UF, p, zero);
Term p_f_y = d_solver.mkTerm(APPLY_UF, p, f_y);
// Assertions
Term assertions = d_solver.mkTerm(AND,
new Term[] {
d_solver.mkTerm(LEQ, zero, f_x), // 0 <= f(x)
d_solver.mkTerm(LEQ, zero, f_y), // 0 <= f(y)
d_solver.mkTerm(LEQ, sum, one), // f(x) + f(y) <= 1
p_0.notTerm(), // not p(0)
p_f_y // p(f(y))
});
assertDoesNotThrow(() -> d_solver.checkSatAssuming(d_solver.mkTrue()));
d_solver.assertFormula(assertions);
assertDoesNotThrow(() -> d_solver.checkSatAssuming(d_solver.mkTerm(DISTINCT, x, y)));
assertDoesNotThrow(()
-> d_solver.checkSatAssuming(
new Term[] {d_solver.mkFalse(), d_solver.mkTerm(DISTINCT, x, y)}));
assertThrows(CVC5ApiException.class, () -> d_solver.checkSatAssuming(n));
assertThrows(CVC5ApiException.class,
() -> d_solver.checkSatAssuming(new Term[] {n, d_solver.mkTerm(DISTINCT, x, y)}));
Solver slv = new Solver();
assertThrows(CVC5ApiException.class, () -> slv.checkSatAssuming(d_solver.mkTrue()));
}
@Test
void setLogic() throws CVC5ApiException
{
assertDoesNotThrow(() -> d_solver.setLogic("AUFLIRA"));
assertThrows(CVC5ApiException.class, () -> d_solver.setLogic("AF_BV"));
d_solver.assertFormula(d_solver.mkTrue());
assertThrows(CVC5ApiException.class, () -> d_solver.setLogic("AUFLIRA"));
}
@Test
void isLogicSet() throws CVC5ApiException
{
assertFalse(d_solver.isLogicSet());
assertDoesNotThrow(() -> d_solver.setLogic("QF_BV"));
assertTrue(d_solver.isLogicSet());
}
@Test
void getLogic() throws CVC5ApiException
{
assertThrows(CVC5ApiException.class, () -> d_solver.getLogic());
assertDoesNotThrow(() -> d_solver.setLogic("QF_BV"));
assertEquals(d_solver.getLogic(), "QF_BV");
}
@Test
void setOption() throws CVC5ApiException
{
assertDoesNotThrow(() -> d_solver.setOption("bv-sat-solver", "minisat"));
assertThrows(CVC5ApiException.class, () -> d_solver.setOption("bv-sat-solver", "1"));
d_solver.assertFormula(d_solver.mkTrue());
assertThrows(CVC5ApiException.class, () -> d_solver.setOption("bv-sat-solver", "minisat"));
}
@Test
void resetAssertions() throws CVC5ApiException
{
d_solver.setOption("incremental", "true");
Sort bvSort = d_solver.mkBitVectorSort(4);
Term one = d_solver.mkBitVector(4, 1);
Term x = d_solver.mkConst(bvSort, "x");
Term ule = d_solver.mkTerm(BITVECTOR_ULE, x, one);
Term srem = d_solver.mkTerm(BITVECTOR_SREM, one, x);
d_solver.push(4);
Term slt = d_solver.mkTerm(BITVECTOR_SLT, srem, one);
d_solver.resetAssertions();
d_solver.checkSatAssuming(new Term[] {slt, ule});
}
@Test
void declareSygusVar() throws CVC5ApiException
{
d_solver.setOption("sygus", "true");
Sort boolSort = d_solver.getBooleanSort();
Sort intSort = d_solver.getIntegerSort();
Sort funSort = d_solver.mkFunctionSort(intSort, boolSort);
assertDoesNotThrow(() -> d_solver.declareSygusVar("", boolSort));
assertDoesNotThrow(() -> d_solver.declareSygusVar("", funSort));
assertDoesNotThrow(() -> d_solver.declareSygusVar(("b"), boolSort));
assertThrows(CVC5ApiException.class, () -> d_solver.declareSygusVar("", new Sort()));
assertThrows(CVC5ApiException.class, () -> d_solver.declareSygusVar("a", new Sort()));
Solver slv = new Solver();
slv.setOption("sygus", "true");
assertThrows(CVC5ApiException.class, () -> slv.declareSygusVar("", boolSort));
}
@Test
void mkGrammar() throws CVC5ApiException
{
Term nullTerm = new Term();
Term boolTerm = d_solver.mkBoolean(true);
Term boolVar = d_solver.mkVar(d_solver.getBooleanSort());
Term intVar = d_solver.mkVar(d_solver.getIntegerSort());
assertDoesNotThrow(() -> d_solver.mkGrammar(new Term[] {}, new Term[] {intVar}));
assertDoesNotThrow(() -> d_solver.mkGrammar(new Term[] {boolVar}, new Term[] {intVar}));
assertThrows(CVC5ApiException.class, () -> d_solver.mkGrammar(new Term[] {}, new Term[] {}));
assertThrows(
CVC5ApiException.class, () -> d_solver.mkGrammar(new Term[] {}, new Term[] {nullTerm}));
assertThrows(
CVC5ApiException.class, () -> d_solver.mkGrammar(new Term[] {}, new Term[] {boolTerm}));
assertThrows(CVC5ApiException.class,
() -> d_solver.mkGrammar(new Term[] {boolTerm}, new Term[] {intVar}));
Solver slv = new Solver();
slv.setOption("sygus", "true");
Term boolVar2 = slv.mkVar(slv.getBooleanSort());
Term intVar2 = slv.mkVar(slv.getIntegerSort());
assertDoesNotThrow(() -> slv.mkGrammar(new Term[] {boolVar2}, new Term[] {intVar2}));
assertThrows(
CVC5ApiException.class, () -> slv.mkGrammar(new Term[] {boolVar}, new Term[] {intVar2}));
assertThrows(
CVC5ApiException.class, () -> slv.mkGrammar(new Term[] {boolVar2}, new Term[] {intVar}));
}
@Test
void synthFun() throws CVC5ApiException
{
d_solver.setOption("sygus", "true");
Sort nullSort = new Sort();
Sort bool = d_solver.getBooleanSort();
Sort integer = d_solver.getIntegerSort();
Term nullTerm = new Term();
Term x = d_solver.mkVar(bool);
Term start1 = d_solver.mkVar(bool);
Term start2 = d_solver.mkVar(integer);
Grammar g1 = d_solver.mkGrammar(new Term[] {x}, new Term[] {start1});
g1.addRule(start1, d_solver.mkBoolean(false));
Grammar g2 = d_solver.mkGrammar(new Term[] {x}, new Term[] {start2});
g2.addRule(start2, d_solver.mkInteger(0));
assertDoesNotThrow(() -> d_solver.synthFun("", new Term[] {}, bool));
assertDoesNotThrow(() -> d_solver.synthFun("f1", new Term[] {x}, bool));
assertDoesNotThrow(() -> d_solver.synthFun("f2", new Term[] {x}, bool, g1));
assertThrows(
CVC5ApiException.class, () -> d_solver.synthFun("f3", new Term[] {nullTerm}, bool));
assertThrows(CVC5ApiException.class, () -> d_solver.synthFun("f4", new Term[] {}, nullSort));
assertThrows(CVC5ApiException.class, () -> d_solver.synthFun("f6", new Term[] {x}, bool, g2));
Solver slv = new Solver();
slv.setOption("sygus", "true");
Term x2 = slv.mkVar(slv.getBooleanSort());
assertDoesNotThrow(() -> slv.synthFun("f1", new Term[] {x2}, slv.getBooleanSort()));
assertThrows(
CVC5ApiException.class, () -> slv.synthFun("", new Term[] {}, d_solver.getBooleanSort()));
assertThrows(CVC5ApiException.class,
() -> slv.synthFun("f1", new Term[] {x}, d_solver.getBooleanSort()));
}
@Test
void addSygusConstraint() throws CVC5ApiException
{
d_solver.setOption("sygus", "true");
Term nullTerm = new Term();
Term boolTerm = d_solver.mkBoolean(true);
Term intTerm = d_solver.mkInteger(1);
assertDoesNotThrow(() -> d_solver.addSygusConstraint(boolTerm));
assertThrows(CVC5ApiException.class, () -> d_solver.addSygusConstraint(nullTerm));
assertThrows(CVC5ApiException.class, () -> d_solver.addSygusConstraint(intTerm));
Solver slv = new Solver();
slv.setOption("sygus", "true");
assertThrows(CVC5ApiException.class, () -> slv.addSygusConstraint(boolTerm));
}
@Test
void getSygusConstraints()
{
d_solver.setOption("sygus", "true");
Term trueTerm = d_solver.mkBoolean(true);
Term falseTerm = d_solver.mkBoolean(false);
d_solver.addSygusConstraint(trueTerm);
d_solver.addSygusConstraint(falseTerm);
Term[] constraints = d_solver.getSygusConstraints();
assertEquals(constraints[0], trueTerm);
assertEquals(constraints[1], falseTerm);
}
@Test
void addSygusAssume()
{
d_solver.setOption("sygus", "true");
Term nullTerm = new Term();
Term boolTerm = d_solver.mkBoolean(false);
Term intTerm = d_solver.mkInteger(1);
assertDoesNotThrow(() -> d_solver.addSygusAssume(boolTerm));
assertThrows(CVC5ApiException.class, () -> d_solver.addSygusAssume(nullTerm));
assertThrows(CVC5ApiException.class, () -> d_solver.addSygusAssume(intTerm));
Solver slv = new Solver();
slv.setOption("sygus", "true");
assertThrows(CVC5ApiException.class, () -> slv.addSygusAssume(boolTerm));
}
@Test
void getSygusAssumptions()
{
d_solver.setOption("sygus", "true");
Term trueTerm = d_solver.mkBoolean(true);
Term falseTerm = d_solver.mkBoolean(false);
d_solver.addSygusAssume(trueTerm);
d_solver.addSygusAssume(falseTerm);
Term[] assumptions = d_solver.getSygusAssumptions();
assertEquals(assumptions[0], trueTerm);
assertEquals(assumptions[1], falseTerm);
}
@Test
void addSygusInvConstraint() throws CVC5ApiException
{
d_solver.setOption("sygus", "true");
Sort bool = d_solver.getBooleanSort();
Sort real = d_solver.getRealSort();
Term nullTerm = new Term();
Term intTerm = d_solver.mkInteger(1);
Term inv = d_solver.declareFun("inv", new Sort[] {real}, bool);
Term pre = d_solver.declareFun("pre", new Sort[] {real}, bool);
Term trans = d_solver.declareFun("trans", new Sort[] {real, real}, bool);
Term post = d_solver.declareFun("post", new Sort[] {real}, bool);
Term inv1 = d_solver.declareFun("inv1", new Sort[] {real}, real);
Term trans1 = d_solver.declareFun("trans1", new Sort[] {bool, real}, bool);
Term trans2 = d_solver.declareFun("trans2", new Sort[] {real, bool}, bool);
Term trans3 = d_solver.declareFun("trans3", new Sort[] {real, real}, real);
assertDoesNotThrow(() -> d_solver.addSygusInvConstraint(inv, pre, trans, post));
assertThrows(
CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(nullTerm, pre, trans, post));
assertThrows(
CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(inv, nullTerm, trans, post));
assertThrows(
CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(inv, pre, nullTerm, post));
assertThrows(
CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(inv, pre, trans, nullTerm));
assertThrows(
CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(intTerm, pre, trans, post));
assertThrows(
CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(inv1, pre, trans, post));
assertThrows(
CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(inv, trans, trans, post));
assertThrows(CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(inv, pre, pre, post));
assertThrows(
CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(inv, pre, trans1, post));
assertThrows(
CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(inv, pre, trans2, post));
assertThrows(
CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(inv, pre, trans3, post));
assertThrows(
CVC5ApiException.class, () -> d_solver.addSygusInvConstraint(inv, pre, trans, trans));
Solver slv = new Solver();
slv.setOption("sygus", "true");
Sort boolean2 = slv.getBooleanSort();
Sort real2 = slv.getRealSort();
Term inv22 = slv.declareFun("inv", new Sort[] {real2}, boolean2);
Term pre22 = slv.declareFun("pre", new Sort[] {real2}, boolean2);
Term trans22 = slv.declareFun("trans", new Sort[] {real2, real2}, boolean2);
Term post22 = slv.declareFun("post", new Sort[] {real2}, boolean2);
assertDoesNotThrow(() -> slv.addSygusInvConstraint(inv22, pre22, trans22, post22));
assertThrows(
CVC5ApiException.class, () -> slv.addSygusInvConstraint(inv, pre22, trans22, post22));
assertThrows(
CVC5ApiException.class, () -> slv.addSygusInvConstraint(inv22, pre, trans22, post22));
assertThrows(
CVC5ApiException.class, () -> slv.addSygusInvConstraint(inv22, pre22, trans, post22));
assertThrows(
CVC5ApiException.class, () -> slv.addSygusInvConstraint(inv22, pre22, trans22, post));
}
@Test
void checkSynth() throws CVC5ApiException
{
assertThrows(CVC5ApiException.class, () -> d_solver.checkSynth());
d_solver.setOption("sygus", "true");
assertDoesNotThrow(() -> d_solver.checkSynth());
}
@Test
void getSynthSolution() throws CVC5ApiException
{
d_solver.setOption("sygus", "true");
d_solver.setOption("incremental", "false");
Term nullTerm = new Term();
Term x = d_solver.mkBoolean(false);
Term f = d_solver.synthFun("f", new Term[] {}, d_solver.getBooleanSort());
assertThrows(CVC5ApiException.class, () -> d_solver.getSynthSolution(f));
SynthResult sr = d_solver.checkSynth();
assertEquals(sr.hasSolution(), true);
assertDoesNotThrow(() -> d_solver.getSynthSolution(f));
assertDoesNotThrow(() -> d_solver.getSynthSolution(f));
assertThrows(CVC5ApiException.class, () -> d_solver.getSynthSolution(nullTerm));
assertThrows(CVC5ApiException.class, () -> d_solver.getSynthSolution(x));
Solver slv = new Solver();
assertThrows(CVC5ApiException.class, () -> slv.getSynthSolution(f));
}
@Test
void getSynthSolutions() throws CVC5ApiException
{
d_solver.setOption("sygus", "true");
d_solver.setOption("incremental", "false");
Term nullTerm = new Term();
Term x = d_solver.mkBoolean(false);
Term f = d_solver.synthFun("f", new Term[] {}, d_solver.getBooleanSort());
assertThrows(CVC5ApiException.class, () -> d_solver.getSynthSolutions(new Term[] {}));
assertThrows(CVC5ApiException.class, () -> d_solver.getSynthSolutions(new Term[] {f}));
d_solver.checkSynth();
assertDoesNotThrow(() -> d_solver.getSynthSolutions(new Term[] {f}));
assertDoesNotThrow(() -> d_solver.getSynthSolutions(new Term[] {f, f}));
assertThrows(CVC5ApiException.class, () -> d_solver.getSynthSolutions(new Term[] {}));
assertThrows(CVC5ApiException.class, () -> d_solver.getSynthSolutions(new Term[] {nullTerm}));
assertThrows(CVC5ApiException.class, () -> d_solver.getSynthSolutions(new Term[] {x}));
Solver slv = new Solver();
assertThrows(CVC5ApiException.class, () -> slv.getSynthSolutions(new Term[] {x}));
}
@Test
void checkSynthNext() throws CVC5ApiException
{
d_solver.setOption("sygus", "true");
d_solver.setOption("incremental", "true");
Term f = d_solver.synthFun("f", new Term[] {}, d_solver.getBooleanSort());
SynthResult sr = d_solver.checkSynth();
assertEquals(sr.hasSolution(), true);
assertDoesNotThrow(() -> d_solver.getSynthSolutions(new Term[] {f}));
sr = d_solver.checkSynthNext();
assertEquals(sr.hasSolution(), true);
assertDoesNotThrow(() -> d_solver.getSynthSolutions(new Term[] {f}));
}
@Test
void checkSynthNext2() throws CVC5ApiException
{
d_solver.setOption("sygus", "true");
d_solver.setOption("incremental", "false");
Term f = d_solver.synthFun("f", new Term[] {}, d_solver.getBooleanSort());
d_solver.checkSynth();
assertThrows(CVC5ApiException.class, () -> d_solver.checkSynthNext());
}
@Test
void checkSynthNext3() throws CVC5ApiException
{
d_solver.setOption("sygus", "true");
d_solver.setOption("incremental", "true");
Term f = d_solver.synthFun("f", new Term[] {}, d_solver.getBooleanSort());
assertThrows(CVC5ApiException.class, () -> d_solver.checkSynthNext());
}
@Test
void findSynth() throws CVC5ApiException
{
d_solver.setOption("sygus", "true");
Sort boolSort = d_solver.getBooleanSort();
Term start = d_solver.mkVar(boolSort);
Grammar g = d_solver.mkGrammar(new Term[] {}, new Term[] {start});
Term truen = d_solver.mkBoolean(true);
Term falsen = d_solver.mkBoolean(false);
g.addRule(start, truen);
g.addRule(start, falsen);
Term f = d_solver.synthFun("f", new Term[] {}, d_solver.getBooleanSort(), g);
// should enumerate based on the grammar of the function to synthesize above
Term t = d_solver.findSynth(FindSynthTarget.ENUM);
assertTrue(!t.isNull() && t.getSort().isBoolean());
}
@Test
void findSynth2() throws CVC5ApiException
{
d_solver.setOption("sygus", "true");
d_solver.setOption("incremental", "true");
Sort boolSort = d_solver.getBooleanSort();
Term start = d_solver.mkVar(boolSort);
Grammar g = d_solver.mkGrammar(new Term[] {}, new Term[] {start});
Term truen = d_solver.mkBoolean(true);
Term falsen = d_solver.mkBoolean(false);
g.addRule(start, truen);
g.addRule(start, falsen);
// should enumerate true/false
Term t = d_solver.findSynth(FindSynthTarget.ENUM, g);
assertTrue(!t.isNull() && t.getSort().isBoolean());
t = d_solver.findSynthNext();
assertTrue(!t.isNull() && t.getSort().isBoolean());
}
@Test
void tupleProject() throws CVC5ApiException
{
Term[] elements = new Term[] {d_solver.mkBoolean(true),
d_solver.mkInteger(3),
d_solver.mkString("C"),
d_solver.mkTerm(SET_SINGLETON, d_solver.mkString("Z"))};
Term tuple = d_solver.mkTuple(elements);
int[] indices1 = new int[] {};
int[] indices2 = new int[] {0};
int[] indices3 = new int[] {0, 1};
int[] indices4 = new int[] {0, 0, 2, 2, 3, 3, 0};
int[] indices5 = new int[] {4};
int[] indices6 = new int[] {0, 4};
assertDoesNotThrow(() -> d_solver.mkTerm(d_solver.mkOp(TUPLE_PROJECT, indices1), tuple));
assertDoesNotThrow(() -> d_solver.mkTerm(d_solver.mkOp(TUPLE_PROJECT, indices2), tuple));
assertDoesNotThrow(() -> d_solver.mkTerm(d_solver.mkOp(TUPLE_PROJECT, indices3), tuple));
assertDoesNotThrow(() -> d_solver.mkTerm(d_solver.mkOp(TUPLE_PROJECT, indices4), tuple));
assertThrows(CVC5ApiException.class,
() -> d_solver.mkTerm(d_solver.mkOp(TUPLE_PROJECT, indices5), tuple));
assertThrows(CVC5ApiException.class,
() -> d_solver.mkTerm(d_solver.mkOp(TUPLE_PROJECT, indices6), tuple));
int[] indices = new int[] {0, 3, 2, 0, 1, 2};
Op op = d_solver.mkOp(TUPLE_PROJECT, indices);
Term projection = d_solver.mkTerm(op, tuple);
Datatype datatype = tuple.getSort().getDatatype();
DatatypeConstructor constructor = datatype.getConstructor(0);
for (int i = 0; i < indices.length; i++)
{
Term selectorTerm = constructor.getSelector(indices[i]).getTerm();
Term selectedTerm = d_solver.mkTerm(APPLY_SELECTOR, selectorTerm, tuple);
Term simplifiedTerm = d_solver.simplify(selectedTerm);
assertEquals(elements[indices[i]], simplifiedTerm);
}
assertEquals("((_ tuple.project 0 3 2 0 1 2) (tuple true 3 \"C\" "
+ "(set.singleton \"Z\")))",
projection.toString());
}
@Test
void declareOracleFunError() throws CVC5ApiException
{
Sort iSort = d_solver.getIntegerSort();
// cannot declare without option
assertThrows(CVC5ApiException.class,
()
-> d_solver.declareOracleFun(
"f", new Sort[] {iSort}, iSort, (input) -> d_solver.mkInteger(0)));
d_solver.setOption("oracles", "true");
Sort nullSort = new Sort();
// bad sort
assertThrows(CVC5ApiException.class,
()
-> d_solver.declareOracleFun(
"f", new Sort[] {nullSort}, iSort, (input) -> d_solver.mkInteger(0)));
}
@Test
void declareOracleFunUnsat() throws CVC5ApiException
{
d_solver.setOption("oracles", "true");
Sort iSort = d_solver.getIntegerSort();
// f is the function implementing (lambda ((x Int)) (+ x 1))
Term f = d_solver.declareOracleFun("f", new Sort[] {iSort}, iSort, (input) -> {
if (input[0].getIntegerValue().signum() > -1)
{
return d_solver.mkInteger(input[0].getIntegerValue().add(new BigInteger("1")).toString());
}
return d_solver.mkInteger(0);
});
Term three = d_solver.mkInteger(3);
Term five = d_solver.mkInteger(5);
Term eq =
d_solver.mkTerm(EQUAL, new Term[] {d_solver.mkTerm(APPLY_UF, new Term[] {f, three}), five});
d_solver.assertFormula(eq);
// (f 3) = 5
assertTrue(d_solver.checkSat().isUnsat());
}
@Test
void declareOracleFunSat() throws CVC5ApiException
{
d_solver.setOption("oracles", "true");
d_solver.setOption("produce-models", "true");
Sort iSort = d_solver.getIntegerSort();
// f is the function implementing (lambda ((x Int)) (% x 10))
Term f = d_solver.declareOracleFun("f", new Sort[] {iSort}, iSort, (input) -> {
if (input[0].getIntegerValue().signum() > -1)
{
return d_solver.mkInteger(input[0].getIntegerValue().mod(new BigInteger("10")).toString());
}
return d_solver.mkInteger(0);
});
Term seven = d_solver.mkInteger(7);
Term x = d_solver.mkConst(iSort, "x");
Term lb = d_solver.mkTerm(Kind.GEQ, new Term[] {x, d_solver.mkInteger(0)});
d_solver.assertFormula(lb);
Term ub = d_solver.mkTerm(Kind.LEQ, new Term[] {x, d_solver.mkInteger(100)});
d_solver.assertFormula(ub);
Term eq = d_solver.mkTerm(
Kind.EQUAL, new Term[] {d_solver.mkTerm(APPLY_UF, new Term[] {f, x}), seven});
d_solver.assertFormula(eq);
// x >= 0 ^ x <= 100 ^ (f x) = 7
assertTrue(d_solver.checkSat().isSat());
Term xval = d_solver.getValue(x);
assertTrue(xval.getIntegerValue().signum() > -1);
assertTrue(xval.getIntegerValue().mod(new BigInteger("10")).equals(new BigInteger("7")));
}
@Test
void declareOracleFunSat2() throws CVC5ApiException
{
d_solver.setOption("oracles", "true");
d_solver.setOption("produce-models", "true");
Sort iSort = d_solver.getIntegerSort();
Sort bSort = d_solver.getBooleanSort();
// eq is the function implementing (lambda ((x Int) (y Int)) (= x y))
Term eq = d_solver.declareOracleFun("eq", new Sort[] {iSort, iSort}, bSort, (input) -> {
return d_solver.mkBoolean(input[0].equals(input[1]));
});
Term x = d_solver.mkConst(iSort, "x");
Term y = d_solver.mkConst(iSort, "y");
Term neq = d_solver.mkTerm(
Kind.NOT, new Term[] {d_solver.mkTerm(Kind.APPLY_UF, new Term[] {eq, x, y})});
d_solver.assertFormula(neq);
// (not (eq x y))
assertTrue(d_solver.checkSat().isSat());
Term xval = d_solver.getValue(x);
Term yval = d_solver.getValue(y);
assertFalse(xval.equals(yval));
}
class PluginUnsat extends AbstractPlugin
{
public PluginUnsat(TermManager tm)
{
super(tm);
}
@Override
public Term[] check()
{
// add the "false" lemma.
Term flem = d_tm.mkBoolean(false);
return new Term[] {flem};
}
@Override
public void notifySatClause(Term cl)
{
}
@Override
public void notifyTheoryLemma(Term lem)
{
}
@Override
public String getName()
{
return "PluginUnsat";
}
}
@Test
void pluginUnsat()
{
PluginUnsat pu = new PluginUnsat(d_tm);
d_solver.addPlugin(pu);
assertTrue(pu.getName().equals("PluginUnsat"));
// should be unsat since the plugin above asserts "false" as a lemma
assertTrue(d_solver.checkSat().isUnsat());
}
class PluginListen extends AbstractPlugin
{
public PluginListen(TermManager tm)
{
super(tm);
}
@Override
public Term[] check()
{
return new Term[0];
}
@Override
public void notifySatClause(Term cl)
{
d_hasSeenSatClause = true;
}
public boolean hasSeenSatClause()
{
return d_hasSeenSatClause;
}
@Override
public void notifyTheoryLemma(Term lem)
{
d_hasSeenTheoryLemma = true;
}
public boolean hasSeenTheoryLemma()
{
return d_hasSeenTheoryLemma;
}
@Override
public String getName()
{
return "PluginListen";
}
/** Reference to the term manager */
private TermManager d_tm;
/** have we seen a theory lemma? */
private boolean d_hasSeenTheoryLemma;
/** have we seen a SAT clause? */
private boolean d_hasSeenSatClause;
};
@Test
void pluginListen()
{
// NOTE: this shouldn't be necessary but ensures notifySatClause is called here.
d_solver.setOption("plugin-notify-sat-clause-in-solve", "false");
PluginListen pl = new PluginListen(d_tm);
d_solver.addPlugin(pl);
Sort stringSort = d_tm.getStringSort();
Term x = d_tm.mkConst(stringSort, "x");
Term y = d_tm.mkConst(stringSort, "y");
Term ctn1 = d_tm.mkTerm(Kind.STRING_CONTAINS, new Term[] {x, y});
Term ctn2 = d_tm.mkTerm(Kind.STRING_CONTAINS, new Term[] {y, x});
d_solver.assertFormula(d_tm.mkTerm(Kind.OR, new Term[] {ctn1, ctn2}));
Term lx = d_tm.mkTerm(Kind.STRING_LENGTH, new Term[] {x});
Term ly = d_tm.mkTerm(Kind.STRING_LENGTH, new Term[] {y});
Term lc = d_tm.mkTerm(Kind.GT, new Term[] {lx, ly});
d_solver.assertFormula(lc);
assertTrue(d_solver.checkSat().isSat());
// above input formulas should induce a theory lemma and SAT clause learning
assertTrue(pl.hasSeenTheoryLemma());
assertTrue(pl.hasSeenSatClause());
}
@Test
void getVersion() throws CVC5ApiException
{
System.out.println(d_solver.getVersion());
}
@Test
void verticalBars() throws CVC5ApiException
{
Term a = d_solver.declareFun("|a |", new Sort[] {}, d_solver.getRealSort());
assertEquals("|a |", a.toString());
}
@Test
void multipleSolvers() throws CVC5ApiException
{
Term function1, function2, value1, value2, definedFunction;
Sort integerSort;
Term zero;
{
Solver s1 = new Solver(d_tm);
s1.setLogic("ALL");
s1.setOption("produce-models", "true");
integerSort = s1.getIntegerSort();
function1 = s1.declareFun("f1", new Sort[] {}, s1.getIntegerSort());
Term x = s1.mkVar(integerSort, "x");
zero = s1.mkInteger(0);
definedFunction = s1.defineFun("f", new Term[] {x}, integerSort, zero);
s1.assertFormula(function1.eqTerm(zero));
s1.checkSat();
value1 = s1.getValue(function1);
}
assertEquals(zero, value1);
{
Solver s2 = new Solver(d_tm);
s2.setLogic("ALL");
s2.setOption("produce-models", "true");
function2 = s2.declareFun("function2", new Sort[] {}, integerSort);
s2.assertFormula(function2.eqTerm(value1));
s2.checkSat();
value2 = s2.getValue(function2);
}
assertEquals(value1, value2);
{
Solver s3 = new Solver(d_tm);
s3.setLogic("ALL");
s3.setOption("produce-models", "true");
function2 = s3.declareFun("function3", new Sort[] {}, integerSort);
Term apply = s3.mkTerm(APPLY_UF, new Term[] {definedFunction, zero});
s3.assertFormula(function2.eqTerm(apply));
s3.checkSat();
Term value3 = s3.getValue(function2);
assertEquals(value1, value3);
}
}
}