/*
* Copyright (C) 2015-2016 University of Freiburg
*
* This file is part of SMTInterpol.
*
* SMTInterpol is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SMTInterpol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with SMTInterpol. If not, see <http://www.gnu.org/licenses/>.
*/
package de.uni_freiburg.informatik.ultimate.smtinterpol.smtlib2;
import java.math.BigInteger;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import de.uni_freiburg.informatik.ultimate.logic.Logics;
import de.uni_freiburg.informatik.ultimate.logic.SMTLIBException;
import de.uni_freiburg.informatik.ultimate.logic.Script;
import de.uni_freiburg.informatik.ultimate.logic.Script.LBool;
import de.uni_freiburg.informatik.ultimate.logic.Sort;
import de.uni_freiburg.informatik.ultimate.logic.Term;
import de.uni_freiburg.informatik.ultimate.smtinterpol.Config;
@RunWith(JUnit4.class)
public class AssumptionTest {
/**
* A test that only executes if Config.STRONG_USAGE_CHECKS is set. It
* tests that we correctly complain about bad terms used as assumptions.
*/
@Test
public void badAssumptions() {
if (Config.STRONG_USAGE_CHECKS) {
final SMTInterpol solver = new SMTInterpol();
solver.setLogic(Logics.QF_UFLIA);
final Sort boolsort = solver.sort("Bool");
final Sort intsort = solver.sort("Int");
solver.declareFun("P", Script.EMPTY_SORT_ARRAY, boolsort);
solver.declareFun("Q", Script.EMPTY_SORT_ARRAY, boolsort);
solver.declareFun("f", new Sort[]{intsort}, intsort);
final Term p = solver.term("P");
final Term q = solver.term("Q");
final Term notp = solver.term("not", p);
final Term pandq = solver.term("and", p, q);
final Term zero = solver.numeral(BigInteger.ZERO);
final Term fzero = solver.term("f", zero);
// The actual test
// 1) assume zero?
try {
solver.checkSatAssuming(zero);
Assert.fail("Solver did not complain about assuming a numeral");
} catch (final SMTLIBException expected) {
// This is the expected behaviour!
// Do we want to check the error message?
}
// 2) Assume (and p q)
try {
solver.checkSatAssuming(pandq);
Assert.fail("Solver did not complain about assuming a conjunction");
} catch (final SMTLIBException expected) {
// This is the expected behaviour!
// Do we want to check the error message?
}
// 3) Assume non-Boolean term
try {
solver.checkSatAssuming(fzero);
Assert.fail("Solver did not complain about assuming a non-Boolean term");
} catch (final SMTLIBException expected) {
// This is the expected behaviour!
// Do we want to check the error message?
}
// Make sure Boolean terms are supported
// I omit try-catch here since junit takes care of catching the
// exception and setting the test to failed. I don't want to lose
// the exception
// 4) Assume negation
solver.checkSatAssuming(notp);
// 5) Multiple assumptions
solver.checkSatAssuming(p, q, notp);
}
}
/**
* A test to check that we don't keep assumptions that should be deleted.
*/
@Test
public void clearRepeatedAssumptions() {
final SMTInterpol solver = new SMTInterpol();
solver.setLogic(Logics.QF_UF);
solver.declareFun("P", Script.EMPTY_SORT_ARRAY, solver.sort("Bool"));
final Term p = solver.term("P");
final Term notp = solver.term("not", p);
LBool isSat = solver.checkSatAssuming(p);
Assert.assertSame(LBool.SAT, isSat);
isSat = solver.checkSatAssuming(notp);
Assert.assertSame(LBool.SAT, isSat);
}
/**
* Test that conflicting assumptions are handled correctly
*/
@Test
public void conflictingAssumptions() {
final SMTInterpol solver = new SMTInterpol();
solver.setLogic(Logics.QF_UF);
solver.declareFun("P", Script.EMPTY_SORT_ARRAY, solver.sort("Bool"));
final Term p = solver.term("P");
final Term notp = solver.term("not", p);
LBool isSat = solver.checkSatAssuming(p, notp);
Assert.assertSame(LBool.UNSAT, isSat);
isSat = solver.checkSatAssuming(notp, p);
Assert.assertSame(LBool.UNSAT, isSat);
// But without assumptions we should still be satisfiable
isSat = solver.checkSat();
Assert.assertSame(LBool.SAT, isSat);
}
@Test
public void testAssumptionRemoval() {
final SMTInterpol solver = new SMTInterpol();
solver.setLogic(Logics.QF_UFLIA);
final Sort boolsort = solver.sort("Bool");
final Sort intsort = solver.sort("Int");
solver.declareFun("P", Script.EMPTY_SORT_ARRAY, boolsort);
solver.declareFun("Q", Script.EMPTY_SORT_ARRAY, boolsort);
final Term p = solver.term("P");
final Term q = solver.term("Q");
solver.assertTerm(solver.term("or", p, q));
LBool isSat = solver.checkSatAssuming(solver.term("not", p));
// Model should be (not p) q (not r)
Assert.assertSame(LBool.SAT, isSat);
// Note that q was essentially a unit clause before. Check that is not
// stored as unit clause
solver.assertTerm(solver.term("not", q));
isSat = solver.checkSat();
Assert.assertSame(LBool.SAT, isSat);
}
@Test
public void modelproduction() {
final SMTInterpol solver = new SMTInterpol();
solver.setLogic(Logics.QF_UFLIA);
final Sort boolsort = solver.sort("Bool");
final Sort intsort = solver.sort("Int");
solver.declareFun("P", Script.EMPTY_SORT_ARRAY, boolsort);
solver.declareFun("Q", Script.EMPTY_SORT_ARRAY, boolsort);
final Term p = solver.term("P");
final Term q = solver.term("Q");
solver.assertTerm(solver.term("or", p, q));
// Check value of assumption
LBool isSat = solver.checkSatAssuming(p);
Assert.assertSame(LBool.SAT, isSat);
// q is essentially undefined, so I don't check it. Should be false...
final Term pval = solver.getValue(new Term[] {p}).get(p);
Assert.assertSame(solver.term("true"), pval);
// Check value of assumption and derived values
isSat = solver.checkSatAssuming(solver.term("not", p));
Assert.assertSame(LBool.SAT, isSat);
final Map<Term, Term> vals = solver.getValue(new Term[] {p, q});
Assert.assertSame(solver.term("false"), vals.get(p));
Assert.assertSame(solver.term("true"), vals.get(q));
// Check correct unsatisfiability deduction
isSat = solver.checkSatAssuming(
solver.term("not", p), solver.term("not", q));
Assert.assertSame(LBool.UNSAT, isSat);
}
// More tests are needed that test unsat assumption production, proof production, interpolation
}