/*
* Copyright (C) 2009-2012 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.interpolate;
import java.util.Collections;
import java.util.Set;
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.Rational;
import de.uni_freiburg.informatik.ultimate.logic.Sort;
import de.uni_freiburg.informatik.ultimate.logic.Term;
import de.uni_freiburg.informatik.ultimate.logic.TermVariable;
import de.uni_freiburg.informatik.ultimate.smtinterpol.DefaultLogger;
import de.uni_freiburg.informatik.ultimate.smtinterpol.convert.Clausifier;
import de.uni_freiburg.informatik.ultimate.smtinterpol.convert.Clausifier.CCTermBuilder;
import de.uni_freiburg.informatik.ultimate.smtinterpol.convert.EqualityProxy;
import de.uni_freiburg.informatik.ultimate.smtinterpol.convert.SMTAffineTerm;
import de.uni_freiburg.informatik.ultimate.smtinterpol.convert.SharedTerm;
import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Clause;
import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Literal;
import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.LeafNode;
import de.uni_freiburg.informatik.ultimate.smtinterpol.smtlib2.SMTInterpol;
import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.cclosure.CCEquality;
import de.uni_freiburg.informatik.ultimate.smtinterpol.theory.linar.LAEquality;
@RunWith(JUnit4.class)
public class InterpolatorTest {
SMTInterpol mSolver;
Clausifier mClausifier;
Interpolator mInterpolator;
Sort mReal;
Term mA, mB, mS;
public InterpolatorTest() {
mSolver = new SMTInterpol(new DefaultLogger());
mSolver.setLogic("QF_UFLRA");
mReal = mSolver.sort("Real");
mSolver.declareFun("a", new Sort[0], mReal);
mSolver.declareFun("b", new Sort[0], mReal);
mSolver.declareFun("s", new Sort[0], mReal);
mClausifier = mSolver.getClausifier();
mA = mSolver.term("a");
mB = mSolver.term("b");
mS = mSolver.term("s");
}
public void doTestEq(boolean ccswap, boolean abswap,
boolean clauseswap, boolean litswap,
boolean doubleab, boolean addconst, boolean addvar) {
addvar = false;
final Term a = mA;
final Term b = mB;
SharedTerm sa = mClausifier.getSharedTerm(a);
SharedTerm sb = mClausifier.getSharedTerm(b);
if (doubleab || addconst || addvar) {
SMTAffineTerm aterm = SMTAffineTerm.create(a);
SMTAffineTerm bterm = SMTAffineTerm.create(b);
if (doubleab) {
aterm = aterm.mul(Rational.TWO);
bterm = bterm.mul(Rational.TWO);
}
if (addvar) {
aterm = aterm.add(SMTAffineTerm.create(mS));
bterm = bterm.add(SMTAffineTerm.create(mS));
}
if (addconst) {
aterm = aterm.add(Rational.TWO);
bterm = bterm.add(Rational.TWO);
}
sa = mClausifier.getSharedTerm(aterm);
sb = mClausifier.getSharedTerm(bterm);
}
final CCTermBuilder builder = mClausifier.new CCTermBuilder();
sa.shareWithLinAr(); builder.convert(sa.getTerm());
sb.shareWithLinAr(); builder.convert(sb.getTerm());
final EqualityProxy eq = sa.createEquality(sb);
Assert.assertNotSame(EqualityProxy.getFalseProxy(), eq);
Assert.assertNotSame(EqualityProxy.getTrueProxy(), eq);
final CCEquality cceq = ccswap
? eq.createCCEquality(sa, sb) : eq.createCCEquality(sb, sa);
final LAEquality laeq = cceq.getLASharedData();
final Literal[] lits =
clauseswap ? (litswap ? new Literal[] { cceq.negate(), laeq }
: new Literal[] { laeq, cceq.negate() })
: (litswap ? new Literal[] { laeq.negate(), cceq }
: new Literal[] { cceq, laeq.negate() });
final Clause clause = new Clause(lits);
clause.setProof(new LeafNode(LeafNode.EQ, null));
final Set<String> empty = Collections.emptySet();
@SuppressWarnings("unchecked")
final
Set<String>[] partition = new Set[] { empty, empty };
mInterpolator =
new Interpolator(mSolver.getLogger(), mSolver, null,
mSolver.getTheory(),
partition, new int[partition.length]);
if (abswap) {
mInterpolator.addOccurrence(sb, 0);
mInterpolator.addOccurrence(sa, 1);
} else {
mInterpolator.addOccurrence(sa, 0);
mInterpolator.addOccurrence(sb, 1);
}
final Interpolant[] interpolants = mInterpolator.interpolate(clause);
final TermVariable ccVar = mInterpolator.getLiteralInfo(cceq).getMixedVar();
final TermVariable laVar = mInterpolator.getLiteralInfo(laeq).getMixedVar();
Term var;
final InterpolatorAffineTerm summands = new InterpolatorAffineTerm();
if (clauseswap) {
Rational factor = Rational.ONE;
if (doubleab) {
factor = Rational.TWO.inverse();
}
if (abswap) {
factor = factor.negate();
}
summands.add(factor, ccVar);
if (addvar) {
summands.add(factor.negate(), mSolver.term("s"));
}
if (addconst) {
final Rational offset = factor.mul(Rational.TWO).negate();
summands.add(offset);
}
var = laVar;
} else {
Rational factor = Rational.ONE;
if (doubleab) {
factor = Rational.TWO;
}
if (abswap) {
factor = factor.negate();
}
if (addvar) {
summands.add(Rational.ONE, mSolver.term("s"));
}
summands.add(factor, laVar);
if (addconst) {
final Rational offset = Rational.TWO;
summands.add(offset);
}
var = ccVar;
}
final Term rhs = summands.toSMTLib(mSolver.getTheory(), false);
final Term expected = mSolver.term("=", var, rhs);
Assert.assertSame(expected, interpolants[0].mTerm);
}
@Test
public void testEq() {
for (int i = 0; i < 128; i++)
{
doTestEq((i&1) != 0, (i&2) != 0, (i&4) != 0, (i&8) != 0,// NOCHECKSTYLE
(i&16) != 0, (i&32) != 0, (i& 64) != 0);// NOCHECKSTYLE
}
}
}