package jayhorn.solver.princess;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.StringReader;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Stack;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import com.google.common.base.Verify;
import ap.DialogUtil$;
import ap.SimpleAPI;
import ap.SimpleAPI.ProverStatus$;
import ap.basetypes.IdealInt$;
import ap.parser.ConstantSubstVisitor$;
import ap.parser.IAtom;
import ap.parser.IAtom$;
import ap.parser.IBinFormula;
import ap.parser.IBinJunctor;
import ap.parser.IBoolLit;
import ap.parser.IConstant;
import ap.parser.IConstant$;
import ap.parser.IExpression;
import ap.parser.IExpression$;
import ap.parser.IFormula;
import ap.parser.IFormulaITE;
import ap.parser.IFunApp;
import ap.parser.IIntLit;
import ap.parser.INot;
import ap.parser.IPlus;
import ap.parser.ITerm;
import ap.parser.ITermITE;
import ap.parser.IVariable;
import ap.parser.PredicateSubstVisitor$;
import ap.parser.SymbolCollector$;
import ap.terfor.ConstantTerm;
import ap.terfor.preds.Predicate;
import jayhorn.Log;
import jayhorn.Options;
import jayhorn.solver.ArrayType;
import jayhorn.solver.BoolType;
import jayhorn.solver.IntType;
import jayhorn.solver.Prover;
import jayhorn.solver.ProverExpr;
import jayhorn.solver.ProverFun;
import jayhorn.solver.ProverHornClause;
import jayhorn.solver.ProverListener;
import jayhorn.solver.ProverResult;
import jayhorn.solver.ProverTupleExpr;
import jayhorn.solver.ProverTupleType;
import jayhorn.solver.ProverType;
import lazabs.horn.bottomup.HornClauses;
import lazabs.horn.bottomup.HornClauses.Clause;
import lazabs.horn.bottomup.SimpleWrapper;
import lazabs.horn.bottomup.Util.Dag;
import scala.Tuple2;
import scala.collection.Iterator;
import scala.collection.Seq;
import scala.collection.immutable.List;
import scala.collection.immutable.Map;
import scala.collection.immutable.Set;
import scala.collection.mutable.ArrayBuffer;
import scala.util.Either;
public class PrincessProver implements Prover {
private SimpleAPI api;
public PrincessProver() {
ap.util.Debug.enableAllAssertions(false);
api = SimpleAPI.spawn();
// api = SimpleAPI.spawnWithScalaLog();
// api = SimpleAPI.spawnWithAssertions();
}
public PrincessProver(String basename) {
ap.util.Debug.enableAllAssertions(false);
api = SimpleAPI.spawnWithLog(basename);
}
public String solverName(){
return "eldarica";
}
public ProverType getBooleanType() {
return BoolType.INSTANCE;
}
public ProverType getIntType() {
return IntType.INSTANCE;
}
public ProverType getArrayType(ProverType[] argTypes, ProverType resType) {
return new ArrayType(argTypes.length);
}
public ProverType getTupleType(ProverType[] subTypes) {
return new ProverTupleType(Arrays.copyOf(subTypes, subTypes.length));
}
public ProverExpr mkBoundVariable(int deBruijnIndex, ProverType type) {
// TODO: handle tuples
assert(!(type instanceof ProverTupleType));
if (type.equals(getBooleanType())) {
return mkEq(new TermExpr(new IVariable(deBruijnIndex), getIntType()), mkLiteral(0));
} else {
return new TermExpr(new IVariable(deBruijnIndex), type);
}
}
public ProverExpr mkVariable(String name, ProverType type) {
if (type.equals(getIntType())) {
return new TermExpr(api.createConstant(name), type);
} else if (type.equals(getBooleanType())) {
return new FormulaExpr(api.createBooleanVariable(name));
} else if (type instanceof ProverTupleType) {
final ProverTupleType tt = (ProverTupleType)type;
final ProverExpr[] res = new ProverExpr[tt.getArity()];
for (int i = 0; i < tt.getArity(); ++i)
res[i] = mkVariable(name + "_" + i, tt.getSubType(i));
return mkTuple(res);
} else if (type instanceof ArrayType) {
return new TermExpr(api.createConstant(name), type);
}
throw new IllegalArgumentException();
}
public ProverFun mkUnintFunction(String name, ProverType[] argTypes, ProverType resType) {
// TODO: handle tuples
return new PrincessFun(api.createFunction(name, argTypes.length), resType);
}
/**
* Define a new interpreted function. The body is supposed to contain bound
* variables with indexes <code>0, 1, ..., (n-1)</code> representing the
* arguments of the function.
*/
public ProverFun mkDefinedFunction(String name, ProverType[] argTypes, final ProverExpr body) {
// TODO: handle tuples
return new ProverFun() {
public ProverExpr mkExpr(ProverExpr[] args) {
final ArrayBuffer<ITerm> argsBuf = new ArrayBuffer<ITerm>();
for (int i = 0; i < args.length; ++i) {
argsBuf.$plus$eq(((PrincessProverExpr) args[i]).toTerm());
}
final List<ITerm> argsList = argsBuf.toList();
if (body instanceof TermExpr)
return new TermExpr(IExpression$.MODULE$.subst(((TermExpr) body).term, argsList, 0),
body.getType());
else
return new FormulaExpr(IExpression$.MODULE$.subst(((FormulaExpr) body).formula, argsList, 0));
}
};
}
public ProverExpr mkAll(ProverExpr body, ProverType type) {
// TODO: handle tuples
return new FormulaExpr(IExpression$.MODULE$.all(((PrincessProverExpr) body).toFormula()));
}
public ProverExpr mkEx(ProverExpr body, ProverType type) {
// TODO: handle tuples
return new FormulaExpr(IExpression$.MODULE$.ex(((PrincessProverExpr) body).toFormula()));
}
public ProverExpr mkTrigger(ProverExpr body, ProverExpr[] triggers) {
final ArrayBuffer<IExpression> triggerExprs = new ArrayBuffer<IExpression>();
for (int i = 0; i < triggers.length; ++i) {
triggerExprs.$plus$eq(((PrincessProverExpr) triggers[i]).toExpression());
}
return new FormulaExpr(IExpression.trig(((FormulaExpr) body).formula, triggerExprs));
}
public ProverExpr mkEq(ProverExpr left, ProverExpr right) {
if (left instanceof ProverTupleExpr) {
ProverTupleExpr tLeft = (ProverTupleExpr)left;
ProverTupleExpr tRight = (ProverTupleExpr)right;
Verify.verify(tLeft.getArity() == tRight.getArity(), tLeft.getArity()+"!="+ tRight.getArity()+ " for " +left + " and " + right);
ProverExpr[] conjuncts = new ProverExpr[tLeft.getArity()];
for (int i = 0; i < tLeft.getArity(); ++i)
conjuncts[i] = mkEq(tLeft.getSubExpr(i),
tRight.getSubExpr(i));
return mkAnd(conjuncts);
}
PrincessProverExpr pLeft = (PrincessProverExpr) left;
PrincessProverExpr pRight = (PrincessProverExpr) right;
if (pLeft.isBoolean() && pRight.isBoolean())
return new FormulaExpr(pLeft.toFormula().$less$eq$greater(pRight.toFormula()));
else
return new FormulaExpr(pLeft.toTerm().$eq$eq$eq(pRight.toTerm()));
}
public ProverExpr mkLiteral(boolean value) {
return new FormulaExpr(new IBoolLit(value));
}
public ProverExpr mkNot(ProverExpr body) {
return new FormulaExpr(new INot(((PrincessProverExpr) body).toFormula()));
}
public ProverExpr mkAnd(ProverExpr left, ProverExpr right) {
return new FormulaExpr(new IBinFormula(IBinJunctor.And(), ((PrincessProverExpr) left).toFormula(),
((PrincessProverExpr) right).toFormula()));
}
public ProverExpr mkAnd(ProverExpr[] args) {
final ArrayBuffer<IFormula> argsBuf = new ArrayBuffer<IFormula>();
for (int i = 0; i < args.length; ++i)
argsBuf.$plus$eq(((PrincessProverExpr) args[i]).toFormula());
return new FormulaExpr(IExpression$.MODULE$.and(argsBuf));
}
public ProverExpr mkOr(ProverExpr left, ProverExpr right) {
return new FormulaExpr(new IBinFormula(IBinJunctor.Or(), ((PrincessProverExpr) left).toFormula(),
((PrincessProverExpr) right).toFormula()));
}
public ProverExpr mkOr(ProverExpr[] args) {
final ArrayBuffer<IFormula> argsBuf = new ArrayBuffer<IFormula>();
for (int i = 0; i < args.length; ++i)
argsBuf.$plus$eq(((PrincessProverExpr) args[i]).toFormula());
return new FormulaExpr(IExpression$.MODULE$.or(argsBuf));
}
public ProverExpr mkImplies(ProverExpr left, ProverExpr right) {
return mkOr(mkNot(left), right);
}
public ProverExpr mkIte(ProverExpr cond, ProverExpr thenExpr, ProverExpr elseExpr) {
if (thenExpr instanceof TermExpr)
return new TermExpr(new ITermITE(((PrincessProverExpr) cond).toFormula(),
((PrincessProverExpr) thenExpr).toTerm(), ((PrincessProverExpr) elseExpr).toTerm()),
thenExpr.getType());
else
return new FormulaExpr(new IFormulaITE(((PrincessProverExpr) cond).toFormula(),
((PrincessProverExpr) thenExpr).toFormula(), ((PrincessProverExpr) elseExpr).toFormula()));
}
public ProverExpr mkLiteral(int value) {
return new TermExpr(new IIntLit(IdealInt$.MODULE$.apply(value)), getIntType());
}
public ProverExpr mkLiteral(BigInteger value) {
return new TermExpr(new IIntLit(IdealInt$.MODULE$.apply(value.toString())), getIntType());
}
public ProverExpr mkPlus(ProverExpr left, ProverExpr right) {
return new TermExpr(new IPlus(((TermExpr) left).term, ((TermExpr) right).term), getIntType());
}
public ProverExpr mkPlus(ProverExpr[] args) {
final ArrayBuffer<ITerm> argsBuf = new ArrayBuffer<ITerm>();
for (int i = 0; i < args.length; ++i)
argsBuf.$plus$eq(((TermExpr) args[i]).term);
return new TermExpr(IExpression$.MODULE$.sum(argsBuf), getIntType());
}
public ProverExpr mkMinus(ProverExpr left, ProverExpr right) {
return new TermExpr(new IPlus(((TermExpr) left).term, ((TermExpr) right).term.unary_$minus()), getIntType());
}
public ProverExpr mkNeg(ProverExpr arg) {
return new TermExpr(((TermExpr) arg).term.unary_$minus(), getIntType());
}
public ProverExpr mkMult(ProverExpr left, ProverExpr right) {
return new TermExpr(api.mult(((TermExpr) left).term, ((TermExpr) right).term), getIntType());
}
public ProverExpr mkEDiv(ProverExpr num, ProverExpr denom) {
return new TermExpr(api.mulTheory().eDiv(((TermExpr) num).term, ((TermExpr) denom).term), getIntType());
}
public ProverExpr mkEMod(ProverExpr num, ProverExpr denom) {
return new TermExpr(api.mulTheory().eMod(((TermExpr) num).term, ((TermExpr) denom).term), getIntType());
}
public ProverExpr mkTDiv(ProverExpr num, ProverExpr denom) {
return new TermExpr(api.mulTheory().tDiv(((TermExpr) num).term, ((TermExpr) denom).term), getIntType());
}
public ProverExpr mkTMod(ProverExpr num, ProverExpr denom) {
return new TermExpr(api.mulTheory().tMod(((TermExpr) num).term, ((TermExpr) denom).term), getIntType());
}
public ProverExpr mkGeq(ProverExpr left, ProverExpr right) {
return new FormulaExpr(((TermExpr) left).term.$greater$eq(((TermExpr) right).term));
}
public ProverExpr mkGt(ProverExpr left, ProverExpr right) {
return new FormulaExpr(((TermExpr) left).term.$greater(((TermExpr) right).term));
}
public ProverExpr mkLeq(ProverExpr left, ProverExpr right) {
return new FormulaExpr(((TermExpr) left).term.$less$eq(((TermExpr) right).term));
}
public ProverExpr mkLt(ProverExpr left, ProverExpr right) {
return new FormulaExpr(((TermExpr) left).term.$less(((TermExpr) right).term));
}
public ProverExpr mkSelect(ProverExpr ar, ProverExpr[] indexes) {
final ArrayBuffer<ITerm> args = new ArrayBuffer<ITerm>();
args.$plus$eq(((TermExpr) ar).term);
for (int i = 0; i < indexes.length; ++i)
args.$plus$eq(((TermExpr) indexes[i]).term);
return new TermExpr(new IFunApp(api.selectFun(indexes.length), args.toSeq()), getIntType());
}
public ProverExpr mkStore(ProverExpr ar, ProverExpr[] indexes, ProverExpr value) {
final ArrayBuffer<ITerm> args = new ArrayBuffer<ITerm>();
args.$plus$eq(((TermExpr) ar).term);
for (int i = 0; i < indexes.length; ++i)
args.$plus$eq(((TermExpr) indexes[i]).term);
args.$plus$eq(((TermExpr) value).term);
return new TermExpr(new IFunApp(api.storeFun(indexes.length), args.toSeq()), getIntType());
}
////////////////////////////////////////////////////////////////////////////
public ProverExpr mkTuple(ProverExpr[] subExprs) {
return new ProverTupleExpr(Arrays.copyOf(subExprs, subExprs.length));
}
public ProverExpr mkTupleSelect(ProverExpr tuple, int index) {
ProverTupleExpr ttuple = (ProverTupleExpr)tuple;
return ttuple.getSubExpr(index);
}
////////////////////////////////////////////////////////////////////////////
public void push() {
api.push();
assertedClausesStack.push(assertedClauses.size());
}
public void pop() {
api.pop();
int n = assertedClausesStack.pop();
while (assertedClauses.size() > n)
assertedClauses.remove(assertedClauses.size() - 1);
}
public void addAssertion(ProverExpr assertion) {
if (assertion instanceof HornExpr)
assertedClauses.add((HornExpr) assertion);
else
api.addAssertion(((PrincessProverExpr) assertion).toFormula());
}
// ////////////////////////////////////////////////////////////////////////////
private ExecutorService executor = null;
private Future<?> future = null;
private PrincessSolverThread thread = null;
private java.util.Map<String, String> lastSolution;
public java.util.Map<String, String> getLastSolution() {
return lastSolution;
}
public ProverResult checkSat(boolean block) {
if (assertedClauses.isEmpty()) {
return translateRes(api.checkSat(block));
} else {
if (block) {
final ArrayBuffer<HornClauses.Clause> clauses = new ArrayBuffer<HornClauses.Clause>();
for (HornExpr clause : assertedClauses)
clauses.$plus$eq(clause.clause);
lazabs.GlobalParameters$.MODULE$.get().assertions_$eq(false);
if (Options.v().solution) {
final Either<Map<Predicate, IFormula>, Dag<Tuple2<IAtom, Clause>>> result = SimpleWrapper.solve(clauses,
scala.collection.immutable.Map$.MODULE$.<Predicate, Seq<IFormula>> empty(),
Options.v().getSolverOptions().contains("abstract"),
Options.v().getSolverOptions().contains("debug"),
Options.v().dotCEX);
if (result.isLeft()) {
StringBuffer sol = new StringBuffer();
sol.append("Solution:\n");
List<Tuple2<Predicate, IFormula>> ar = result.left().get().toList();
lastSolution = new HashMap<String, String>();
while (!ar.isEmpty()) {
Tuple2<Predicate, IFormula> p = ar.head();
ar = (List<Tuple2<Predicate, IFormula>>) ar.tail();
sol.append("" + p._1() + ": " + api.pp(p._2()) + "\n");
lastSolution.put(p._1().toString(), api.pp(p._2()));
}
Log.info(sol.toString());
return ProverResult.Sat;
} else {
Log.info("Counterexample:\n"
+ DialogUtil$.MODULE$.asString(new scala.runtime.AbstractFunction0<Integer>() {
public Integer apply() {
Dag<IAtom> simpDag = result.right().get()
.map(new scala.runtime.AbstractFunction1<Tuple2<IAtom, Clause>, IAtom>() {
public IAtom apply(Tuple2<IAtom, Clause> p) {
return p._1();
}
});
simpDag.prettyPrint();
return 0;
}
}));
return ProverResult.Unsat;
}
} else {
if (SimpleWrapper.isSat(clauses,
scala.collection.immutable.Map$.MODULE$.<Predicate, Seq<IFormula>> empty(),
Options.v().getSolverOptions().contains("abstract"),
Options.v().getSolverOptions().contains("debug")))
return ProverResult.Sat;
else
return ProverResult.Unsat;
}
} else {
this.executor = Executors.newSingleThreadExecutor();
this.thread = new PrincessSolverThread(assertedClauses);
this.future = executor.submit(this.thread);
return ProverResult.Running;
}
}
}
static class PrincessSolverThread implements Runnable {
private final ArrayList<HornExpr> hornClauses;
private ProverResult status;
public PrincessSolverThread(ArrayList<HornExpr> clauses) {
this.hornClauses = clauses;
}
@Override
public void run() {
status = ProverResult.Running;
final ArrayBuffer<HornClauses.Clause> clauses = new ArrayBuffer<HornClauses.Clause>();
for (HornExpr clause : hornClauses)
clauses.$plus$eq(clause.clause);
lazabs.GlobalParameters$.MODULE$.get().assertions_$eq(false);
final boolean res = SimpleWrapper.isSat(clauses,
scala.collection.immutable.Map$.MODULE$.<Predicate, Seq<IFormula>> empty(),
Options.v().getSolverOptions().contains("abstract"),
Options.v().getSolverOptions().contains("debug"));
if (res)
this.status = ProverResult.Sat;
else
this.status = ProverResult.Unsat;
}
public ProverResult getStatus() {
return this.status;
}
}
private void killThread() {
if (this.future != null && !this.future.isDone()) {
this.future.cancel(true);
}
if (this.executor != null) {
this.executor.shutdown();
}
this.executor = null;
this.future = null;
this.thread = null;
}
private ProverResult translateRes(scala.Enumeration.Value result) {
if (result == ProverStatus$.MODULE$.Sat() || result == ProverStatus$.MODULE$.Invalid())
return ProverResult.Sat;
else if (result == ProverStatus$.MODULE$.Unsat() || result == ProverStatus$.MODULE$.Valid())
return ProverResult.Unsat;
else if (result == ProverStatus$.MODULE$.Unknown())
return ProverResult.Unknown;
else if (result == ProverStatus$.MODULE$.Running())
return ProverResult.Running;
else
return ProverResult.Error;
}
public ProverResult getResult(boolean block) {
return translateRes(api.getStatus(block));
}
public ProverResult getResult(long timeout) {
ProverResult result;
if (future != null) {
try {
future.get(timeout, TimeUnit.MILLISECONDS);
result = this.thread.getStatus();
} catch ( ExecutionException e) {
e.printStackTrace();
throw new RuntimeException("solver failed");
} catch (TimeoutException | InterruptedException e) {
result = ProverResult.Unknown;
}
killThread();
} else {
throw new RuntimeException("Start query with checkSat(false) first.");
}
return result;
// return translateRes(api.getStatus(timeout));
}
public ProverResult nextModel(boolean block) {
return translateRes(api.nextModel(block));
}
public ProverResult stop() {
return translateRes(api.stop());
}
public void setConstructProofs(boolean b) {
api.setConstructProofs(b);
}
public void setPartitionNumber(int num) {
api.setPartitionNumber(num);
}
public ProverExpr[] interpolate(int[][] partitionSeq) {
final ArrayBuffer<Set<Object>> args = new ArrayBuffer<Set<Object>>();
for (int i = 0; i < partitionSeq.length; ++i) {
final ArrayBuffer<Object> indexes = new ArrayBuffer<Object>();
for (int j = 0; j < partitionSeq[i].length; ++j)
indexes.$plus$eq(Integer.valueOf(partitionSeq[i][j]));
args.$plus$eq(indexes.toSet());
}
final Seq<IFormula> ints = api.getInterpolants(args.toSeq(), Long.MAX_VALUE);
final ProverExpr[] res = new ProverExpr[partitionSeq.length - 1];
for (int i = 0; i < partitionSeq.length - 1; ++i)
res[i] = new FormulaExpr(ints.apply(i));
return res;
}
public void addListener(ProverListener listener) {
throw new RuntimeException();
}
public ProverExpr evaluate(ProverExpr expr) {
if (((PrincessProverExpr) expr).isBoolean())
return new FormulaExpr(new IBoolLit(api.eval(((PrincessProverExpr) expr).toFormula())));
else
return new TermExpr(new IIntLit(api.eval(((PrincessProverExpr) expr).toTerm())),
((TermExpr) expr).getType());
}
public ProverExpr[] freeVariables(ProverExpr expr) {
final ArrayList<ProverExpr> res = new ArrayList<ProverExpr>();
final scala.Tuple3<scala.collection.Set<IVariable>, scala.collection.Set<ConstantTerm>, scala.collection.Set<Predicate>> symTriple;
if (expr instanceof TermExpr)
symTriple = SymbolCollector$.MODULE$.varsConstsPreds(((TermExpr) expr).term);
else
symTriple = SymbolCollector$.MODULE$.varsConstsPreds(((FormulaExpr) expr).formula);
final Iterator<IVariable> it1 = symTriple._1().iterator();
while (it1.hasNext())
res.add(new TermExpr(it1.next(), getIntType()));
final Iterator<ConstantTerm> it2 = symTriple._2().iterator();
while (it2.hasNext())
res.add(new TermExpr(IConstant$.MODULE$.apply(it2.next()), getIntType()));
final Iterator<Predicate> it3 = symTriple._3().iterator();
final List<ITerm> emptyArgs = (new ArrayBuffer<ITerm>()).toList();
while (it3.hasNext())
res.add(new FormulaExpr(IAtom$.MODULE$.apply(it3.next(), emptyArgs)));
return res.toArray(new ProverExpr[0]);
}
/**
* Simultaneously substitute <code>from</code> with <code>to</code> in
* <code>target</code>. <code>from</code> has to be an array of free or
* bound variables.
*/
public ProverExpr substitute(ProverExpr target, ProverExpr[] from, ProverExpr[] to) {
assert (from.length == to.length);
final scala.collection.mutable.HashMap<ConstantTerm, ITerm> constantSubst = new scala.collection.mutable.HashMap<ConstantTerm, ITerm>();
final scala.collection.mutable.HashMap<Predicate, IFormula> predicateSubst = new scala.collection.mutable.HashMap<Predicate, IFormula>();
for (int i = 0; i < from.length; ++i) {
if (from[i] instanceof TermExpr) {
final ConstantTerm c = ((IConstant) ((TermExpr) from[i]).term).c();
final ITerm t = ((TermExpr) to[i]).term;
constantSubst.put(c, t);
} else {
final Predicate p = ((IAtom) ((FormulaExpr) from[i]).formula).pred();
assert (p.arity() == 0);
final IFormula f = ((FormulaExpr) to[i]).formula;
predicateSubst.put(p, f);
}
}
// We currently just assume that there are no clashes between
// substituted
// terms and predicates/formulae, and that the substitutions can be
// carried out in sequence
if (target instanceof TermExpr) {
final ITerm t1 = ((TermExpr) target).term;
final ITerm t2 = ConstantSubstVisitor$.MODULE$.apply(t1, constantSubst);
final ITerm t3 = PredicateSubstVisitor$.MODULE$.apply(t2, predicateSubst);
return new TermExpr(t3, target.getType());
} else {
final IFormula f1 = ((FormulaExpr) target).formula;
final IFormula f2 = ConstantSubstVisitor$.MODULE$.apply(f1, constantSubst);
final IFormula f3 = PredicateSubstVisitor$.MODULE$.apply(f2, predicateSubst);
return new FormulaExpr(f3);
}
}
public void shutdown() {
api.shutDown();
}
public void reset() {
api.reset();
}
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "DM_DEFAULT_ENCODING")
public String proverExprToSMT(ProverExpr exp) {
PrintStream originalOut = scala.Console.out();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream newOut = new PrintStream(baos);
scala.Console.setOut(newOut);
ap.parser.SMTLineariser.apply(((FormulaExpr) exp).formula);
scala.Console.flush();
scala.Console.setOut(originalOut);
return baos.toString();
}
////////////////////////////////////////////////////////////////////////////
// Horn clause interface
private final ArrayList<HornExpr> assertedClauses = new ArrayList<HornExpr>();
private final Stack<Integer> assertedClausesStack = new Stack<Integer>();
public ProverExpr mkHornVariable(String name, ProverType type) {
if (type instanceof ProverTupleType) {
final ProverTupleType tt = (ProverTupleType)type;
final ProverExpr[] res = new ProverExpr[tt.getArity()];
for (int i = 0; i < tt.getArity(); ++i)
res[i] = mkHornVariable(name + "_" + i, tt.getSubType(i));
return mkTuple(res);
} else {
// always use terms as Horn variables/arguments
return new TermExpr(api.createConstant(name), type);
}
}
public ProverFun mkHornPredicate(String name, ProverType[] argTypes) {
ProverType[] flatTypes = ProverTupleType.flatten(argTypes);
return new PredicateFun(api.createRelation(name, flatTypes.length),
Arrays.copyOf(argTypes, argTypes.length));
}
/**
* The head literal can either be constructed using
* <code>mkHornPredicate</code>, or be the formula <code>false</code>.
*/
public ProverHornClause mkHornClause(ProverExpr head, ProverExpr[] body, ProverExpr constraint) {
IFormula rawHead = ((FormulaExpr) head).formula;
if ((rawHead instanceof IBoolLit) && !((IBoolLit) rawHead).value())
rawHead = SimpleWrapper.FALSEAtom();
final ArrayBuffer<IAtom> rawBody = new ArrayBuffer<IAtom>();
for (int i = 0; i < body.length; ++i)
rawBody.$plus$eq((IAtom) ((FormulaExpr) body[i]).formula);
final HornClauses.Clause clause = SimpleWrapper.clause((IAtom) rawHead, rawBody.toList(),
((FormulaExpr) constraint).formula);
return new HornExpr(clause);
}
@Override
public void setHornLogic(boolean b) {
// ignore
}
@Override
public String toString() {
return "Princess";
}
public void printRules(){}
////////////////////////////////////////////////////////////////////////////
// Some functions for outputing SMT-LIB
public String toSMTLIBDeclaration(ProverFun fun) {
if (fun instanceof PredicateFun) {
final PredicateFun predFun = (PredicateFun) fun;
return predFun.toSMTLIBDeclaration();
} else {
throw new UnsupportedOperationException();
}
}
public String toSMTLIBFormula(ProverHornClause clause) {
return ((HornExpr) clause).toSMTLIBFormula();
}
public void parseSMTLIBFormula(final String formula) {
// Tuple3<Seq<IFormula>, scala.collection.immutable.Map<IFunction, SMTFunctionType>, scala.collection.immutable.Map<ConstantTerm, SMTType>> triple =
api.execSMTLIB(new StringReader(formula));
// api.extractSMTLIBAssertionsSymbols(new StringReader(formula));
}
@Override
public ProverResult query(ProverExpr relation) {
// TODO Auto-generated method stub
return null;
}
@Override
public void addRule(ProverExpr hornRule) {
// TODO Auto-generated method stub
}
@Override
public ProverExpr getCex() {
// TODO Auto-generated method stub
return null;
}
}