From e45b18a7f16637410e7930833a79b75be03228e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 27 Aug 2020 12:45:27 +0200 Subject: [PATCH 01/99] Add solver-smtlib subproject --- subprojects/solver-smtlib/README.md | 1 + subprojects/solver-smtlib/bin/.gitignore | 2 ++ subprojects/solver-smtlib/build.gradle.kts | 9 +++++++++ 3 files changed, 12 insertions(+) create mode 100644 subprojects/solver-smtlib/README.md create mode 100644 subprojects/solver-smtlib/bin/.gitignore create mode 100644 subprojects/solver-smtlib/build.gradle.kts diff --git a/subprojects/solver-smtlib/README.md b/subprojects/solver-smtlib/README.md new file mode 100644 index 0000000000..709f60bec0 --- /dev/null +++ b/subprojects/solver-smtlib/README.md @@ -0,0 +1 @@ +This project wraps a generic solver that supports the SMT-LIB2 interface into our common interfaces for solvers (located in the [solver](../solver) project). \ No newline at end of file diff --git a/subprojects/solver-smtlib/bin/.gitignore b/subprojects/solver-smtlib/bin/.gitignore new file mode 100644 index 0000000000..7eed456bec --- /dev/null +++ b/subprojects/solver-smtlib/bin/.gitignore @@ -0,0 +1,2 @@ +/main/ +/test/ diff --git a/subprojects/solver-smtlib/build.gradle.kts b/subprojects/solver-smtlib/build.gradle.kts new file mode 100644 index 0000000000..046f35169a --- /dev/null +++ b/subprojects/solver-smtlib/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("java-common") +} + +dependencies { + compile(project(":theta-common")) + compile(project(":theta-core")) + compile(project(":theta-solver")) +} From 7ccadf6cbd150ededf1ed12f1d00ddcb2aeb7883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 27 Aug 2020 12:45:56 +0200 Subject: [PATCH 02/99] Add SmtLibSymbolTable --- .../solver/smtlib/SmtLibSymbolTable.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java new file mode 100644 index 0000000000..1cc539a493 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java @@ -0,0 +1,52 @@ +package hu.bme.mit.theta.solver.smtlib; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Maps; +import hu.bme.mit.theta.core.decl.ConstDecl; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public class SmtLibSymbolTable { + private final BiMap, String> constToSymbol; + private final BiMap, String> constToDeclaration; + + public SmtLibSymbolTable() { + constToSymbol = Maps.synchronizedBiMap(HashBiMap.create()); + constToDeclaration = Maps.synchronizedBiMap(HashBiMap.create()); + } + + public boolean definesConst(final ConstDecl constDecl) { + return constToSymbol.containsKey(constDecl); + } + + public boolean definesSymbol(final String symbol) { + return constToSymbol.inverse().containsKey(symbol); + } + + public String getSymbol(final ConstDecl constDecl) { + checkArgument(definesConst(constDecl)); + return constToSymbol.get(constDecl); + } + + public String getDeclaration(final ConstDecl constDecl) { + checkArgument(definesConst(constDecl)); + return constToDeclaration.get(constDecl); + } + + public ConstDecl getConst(final String symbol) { + checkArgument(definesSymbol(symbol)); + return constToSymbol.inverse().get(symbol); + } + + public void put(final ConstDecl constDecl, final String symbol, final String declaration) { + checkNotNull(constDecl); + checkNotNull(symbol); + checkNotNull(declaration); + checkState(!constToSymbol.containsKey(constDecl), "Constant not found."); + constToSymbol.put(constDecl, symbol); + constToDeclaration.put(constDecl, declaration); + } +} From 4178f211c4f0b2ca17e410e61fb1f5a44ff4eb06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 27 Aug 2020 12:47:57 +0200 Subject: [PATCH 03/99] Add Theta to SMT-LIB translation skeleton --- .../solver/smtlib/SmtLibDeclTransformer.java | 95 +++++++++++++++++++ .../solver/smtlib/SmtLibExprTransformer.java | 38 ++++++++ .../smtlib/SmtLibTransformationManager.java | 43 +++++++++ .../solver/smtlib/SmtLibTypeTransformer.java | 66 +++++++++++++ 4 files changed, 242 insertions(+) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java new file mode 100644 index 0000000000..d909b98f28 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java @@ -0,0 +1,95 @@ +package hu.bme.mit.theta.solver.smtlib; + +import com.google.common.collect.ImmutableList; +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.decl.Decl; +import hu.bme.mit.theta.core.type.Type; +import hu.bme.mit.theta.core.type.functype.FuncType; + +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; + +public class SmtLibDeclTransformer { + private final SmtLibTransformationManager transformer; + private final SmtLibSymbolTable symbolTable; + + private int symbolCount; + + public SmtLibDeclTransformer(final SmtLibTransformationManager transformer, final SmtLibSymbolTable symbolTable) { + this.transformer = transformer; + this.symbolTable = symbolTable; + + symbolCount = 0; + } + + public String toSymbol(final Decl decl) { + if (decl instanceof ConstDecl) { + final ConstDecl cdecl = (ConstDecl) decl; + if(!symbolTable.definesConst(cdecl)) { + transformConst(cdecl); + } + return symbolTable.getSymbol(cdecl); + } else { + throw new UnsupportedOperationException("Cannot transform declaration: " + decl); + } + } + + public String toDeclaration(final Decl decl) { + if (decl instanceof ConstDecl) { + final ConstDecl cdecl = (ConstDecl) decl; + if(!symbolTable.definesConst(cdecl)) { + transformConst(cdecl); + } + return symbolTable.getDeclaration(cdecl); + } else { + throw new UnsupportedOperationException("Cannot transform declaration: " + decl); + } + } + + private void transformConst(final ConstDecl decl) { + final Type type = decl.getType(); + + final Tuple2, Type> extractedTypes = extractTypes(type); + final List paramTypes = extractedTypes.get1(); + final Type returnType = extractedTypes.get2(); + + final String returnSort = transformer.toSort(returnType); + final String[] paramSorts = paramTypes.stream().map(transformer::toSort) + .toArray(String[]::new); + + final String symbolName = symbolNameFor(decl); + final String symbolDeclaration = String.format( + "(declare-fun %s (%s) %s)", + symbolName, String.join(" ", paramSorts), returnSort + ); + symbolTable.put(decl, symbolName, symbolDeclaration); + } + + private Tuple2, Type> extractTypes(final Type type) { + if (type instanceof FuncType) { + final FuncType funcType = (FuncType) type; + + final Type paramType = funcType.getParamType(); + final Type resultType = funcType.getResultType(); + + checkArgument(!(paramType instanceof FuncType)); + + final Tuple2, Type> subResult = extractTypes(resultType); + final List paramTypes = subResult.get1(); + final Type newResultType = subResult.get2(); + final List newParamTypes = ImmutableList.builder().add(paramType).addAll(paramTypes).build(); + final Tuple2, Type> result = Tuple2.of(newParamTypes, newResultType); + + return result; + } else { + return Tuple2.of(ImmutableList.of(), type); + } + } + + private String symbolNameFor(final Decl decl) { + return String.format("%s_%d", decl.getName(), symbolCount++); + } + +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java new file mode 100644 index 0000000000..4b7955bb19 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -0,0 +1,38 @@ +package hu.bme.mit.theta.solver.smtlib; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import hu.bme.mit.theta.common.DispatchTable; +import hu.bme.mit.theta.common.dsl.Env; +import hu.bme.mit.theta.core.type.Expr; + +import java.util.concurrent.ExecutionException; + +public class SmtLibExprTransformer { + private static final int CACHE_SIZE = 1000; + + private final SmtLibTransformationManager transformer; + + private final Cache, String> exprToTerm; + private final DispatchTable table; + private final Env env; + + public SmtLibExprTransformer(final SmtLibTransformationManager transformer) { + this.transformer = transformer; + this.env = new Env(); + + this.exprToTerm = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).build(); + + this.table = DispatchTable.builder() + .build(); + } + + public final String toTerm(final Expr expr) { + try { + return exprToTerm.get(expr, () -> table.dispatch(expr)); + } catch (final ExecutionException e) { + throw new AssertionError(); + } + } + +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java new file mode 100644 index 0000000000..38392c2989 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java @@ -0,0 +1,43 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.core.decl.Decl; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.Type; + +public class SmtLibTransformationManager { + private final SmtLibTypeTransformer typeTransformer; + private final SmtLibDeclTransformer declTransformer; + private final SmtLibExprTransformer exprTransformer; + + public SmtLibTransformationManager(final SmtLibSymbolTable symbolTable) { + this.typeTransformer = instantiateTypeTransformer(this); + this.declTransformer = instantiateDeclTransformer(this, symbolTable); + this.exprTransformer = instantiateExprTransformer(this); + } + + public final String toSort(final Type type) { + return typeTransformer.toSort(type); + } + + public final String toSymbol(final Decl decl) { + return declTransformer.toSymbol(decl); + } + + public final String toTerm(final Expr expr) { + return exprTransformer.toTerm(expr); + } + + protected SmtLibTypeTransformer instantiateTypeTransformer(final SmtLibTransformationManager transformer) { + return new SmtLibTypeTransformer(transformer); + } + + protected SmtLibDeclTransformer instantiateDeclTransformer( + final SmtLibTransformationManager transformer, final SmtLibSymbolTable symbolTable + ) { + return new SmtLibDeclTransformer(transformer, symbolTable); + } + + protected SmtLibExprTransformer instantiateExprTransformer(final SmtLibTransformationManager transformer) { + return new SmtLibExprTransformer(transformer); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java new file mode 100644 index 0000000000..38ce0dad63 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java @@ -0,0 +1,66 @@ +package hu.bme.mit.theta.solver.smtlib; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import hu.bme.mit.theta.common.DispatchTable; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.Type; +import hu.bme.mit.theta.core.type.arraytype.ArrayType; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.core.type.bvtype.BvType; +import hu.bme.mit.theta.core.type.inttype.IntType; +import hu.bme.mit.theta.core.type.rattype.RatType; + +import java.util.concurrent.ExecutionException; + +public class SmtLibTypeTransformer { + private static final int CACHE_SIZE = 1000; + + @SuppressWarnings("unused") + private final SmtLibTransformationManager transformer; + + private final Cache typeToSmtLib; + private final DispatchTable table; + + public SmtLibTypeTransformer(final SmtLibTransformationManager transformer) { + this.transformer = transformer; + + typeToSmtLib = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).build(); + + table = DispatchTable.builder() + .addCase(BoolType.class, this::boolType) + .addCase(IntType.class, this::intType) + .addCase(RatType.class, this::ratType) + .addCase(BvType.class, this::bvType) + .addCase(ArrayType.class, this::arrayType) + .build(); + } + + public final String toSort(final Type type) { + try { + return typeToSmtLib.get(type, () -> table.dispatch(type)); + } catch (final ExecutionException e) { + throw new AssertionError(); + } + } + + protected String boolType(final BoolType type) { + return "Bool"; + } + + protected String intType(final IntType type) { + return "Int"; + } + + protected String ratType(final RatType type) { + return "Real"; + } + + protected String bvType(final BvType type) { + return String.format("(_ BitVec %d)", type.getSize()); + } + + protected String arrayType(final ArrayType type) { + return String.format("(Array %s %s)", toSort(type.getIndexType()), toSort(type.getElemType())); + } +} From f3ce7e322fb8b0f821e75b501d157aa97dd78437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 27 Aug 2020 12:48:55 +0200 Subject: [PATCH 04/99] Add general expression translation --- .../solver/smtlib/SmtLibExprTransformer.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index 4b7955bb19..4019795a68 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -4,7 +4,13 @@ import com.google.common.cache.CacheBuilder; import hu.bme.mit.theta.common.DispatchTable; import hu.bme.mit.theta.common.dsl.Env; +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.decl.Decl; +import hu.bme.mit.theta.core.decl.ParamDecl; +import hu.bme.mit.theta.core.dsl.DeclSymbol; import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.anytype.IteExpr; +import hu.bme.mit.theta.core.type.anytype.RefExpr; import java.util.concurrent.ExecutionException; @@ -24,6 +30,13 @@ public SmtLibExprTransformer(final SmtLibTransformationManager transformer) { this.exprToTerm = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).build(); this.table = DispatchTable.builder() + + // General + + .addCase(RefExpr.class, this::transformRef) + + .addCase(IteExpr.class, this::transformIte) + .build(); } @@ -35,4 +48,27 @@ public final String toTerm(final Expr expr) { } } + //// + + /* + * General + */ + + protected String transformRef(final RefExpr expr) { + final Decl decl = expr.getDecl(); + if (decl instanceof ConstDecl) { + return transformer.toSymbol(decl); + } else if (decl instanceof ParamDecl) { + return (String) env.eval(DeclSymbol.of(decl)); + } else { + throw new UnsupportedOperationException("Cannot transform reference for declaration: " + decl); + } + } + + protected String transformIte(final IteExpr expr) { + final String condTerm = toTerm(expr.getCond()); + final String thenTerm = toTerm(expr.getThen()); + final String elzeTerm = toTerm(expr.getElse()); + return String.format("(ite %s %s %s)", condTerm, thenTerm, elzeTerm); + } } From 22925dd26bd67c78886ddc8f489ab69beaca2aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 27 Aug 2020 12:49:16 +0200 Subject: [PATCH 05/99] Add boolean expression translation --- .../solver/smtlib/SmtLibExprTransformer.java | 120 +++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index 4019795a68..d40632102a 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -9,9 +9,22 @@ import hu.bme.mit.theta.core.decl.ParamDecl; import hu.bme.mit.theta.core.dsl.DeclSymbol; import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.Type; import hu.bme.mit.theta.core.type.anytype.IteExpr; import hu.bme.mit.theta.core.type.anytype.RefExpr; - +import hu.bme.mit.theta.core.type.booltype.AndExpr; +import hu.bme.mit.theta.core.type.booltype.ExistsExpr; +import hu.bme.mit.theta.core.type.booltype.FalseExpr; +import hu.bme.mit.theta.core.type.booltype.ForallExpr; +import hu.bme.mit.theta.core.type.booltype.IffExpr; +import hu.bme.mit.theta.core.type.booltype.ImplyExpr; +import hu.bme.mit.theta.core.type.booltype.NotExpr; +import hu.bme.mit.theta.core.type.booltype.OrExpr; +import hu.bme.mit.theta.core.type.booltype.TrueExpr; +import hu.bme.mit.theta.core.type.booltype.XorExpr; +import hu.bme.mit.theta.core.type.functype.FuncType; + +import java.util.List; import java.util.concurrent.ExecutionException; public class SmtLibExprTransformer { @@ -37,6 +50,28 @@ public SmtLibExprTransformer(final SmtLibTransformationManager transformer) { .addCase(IteExpr.class, this::transformIte) + // Boolean + + .addCase(FalseExpr.class, this::transformFalse) + + .addCase(TrueExpr.class, this::transformTrue) + + .addCase(NotExpr.class, this::transformNot) + + .addCase(ImplyExpr.class, this::transformImply) + + .addCase(IffExpr.class, this::transformIff) + + .addCase(XorExpr.class, this::transformXor) + + .addCase(AndExpr.class, this::transformAnd) + + .addCase(OrExpr.class, this::transformOr) + + .addCase(ExistsExpr.class, this::transformExists) + + .addCase(ForallExpr.class, this::transformForall) + .build(); } @@ -71,4 +106,87 @@ protected String transformIte(final IteExpr expr) { final String elzeTerm = toTerm(expr.getElse()); return String.format("(ite %s %s %s)", condTerm, thenTerm, elzeTerm); } + + /* + * Booleans + */ + + protected String transformFalse(final FalseExpr expr) { + return "false"; + } + + protected String transformTrue(final TrueExpr expr) { + return "true"; + } + + protected String transformNot(final NotExpr expr) { + return String.format("(not %s)", toTerm(expr.getOp())); + } + + protected String transformImply(final ImplyExpr expr) { + return String.format("(=> %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIff(final IffExpr expr) { + return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformXor(final XorExpr expr) { + return String.format("(xor %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformAnd(final AndExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(and %s)", String.join(" ", opTerms)); + } + + protected String transformOr(final OrExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(or %s)", String.join(" ", opTerms)); + } + + protected String transformExists(final ExistsExpr expr) { + env.push(); + final String[] paramTerms = transformParamDecls(expr.getParamDecls()); + final String opTerm = toTerm(expr.getOp()); + final String result = String.format("(exists (%s) %s)", String.join(" ", paramTerms), opTerm); + env.pop(); + return result; + } + + protected String transformForall(final ForallExpr expr) { + env.push(); + final String[] paramTerms = transformParamDecls(expr.getParamDecls()); + final String opTerm = toTerm(expr.getOp()); + final String result = String.format("(forall (%s) %s)", String.join(" ", paramTerms), opTerm); + env.pop(); + return result; + } + + private String[] transformParamDecls(final List> paramDecls) { + final String[] paramTerms = new String[paramDecls.size()]; + int i = 0; + for (final ParamDecl paramDecl : paramDecls) { + final String paramSymbol = transformParamDecl(paramDecl); + paramTerms[i] = paramSymbol; + env.define(DeclSymbol.of(paramDecl), paramSymbol); + i++; + } + return paramTerms; + } + + private String transformParamDecl(final ParamDecl paramDecl) { + final Type type = paramDecl.getType(); + if (type instanceof FuncType) { + throw new UnsupportedOperationException("Only simple types are supported"); + } else { + return String.format("(%s %s)", paramDecl.getName(), transformer.toSort(type)); + } + } } From 77bff398009363adeae0a925f23a7729312df42c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 27 Aug 2020 13:00:44 +0200 Subject: [PATCH 06/99] Add rational expression translation --- .../solver/smtlib/SmtLibExprTransformer.java | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index d40632102a..e628218e8c 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -23,6 +23,19 @@ import hu.bme.mit.theta.core.type.booltype.TrueExpr; import hu.bme.mit.theta.core.type.booltype.XorExpr; import hu.bme.mit.theta.core.type.functype.FuncType; +import hu.bme.mit.theta.core.type.rattype.RatAddExpr; +import hu.bme.mit.theta.core.type.rattype.RatDivExpr; +import hu.bme.mit.theta.core.type.rattype.RatEqExpr; +import hu.bme.mit.theta.core.type.rattype.RatGeqExpr; +import hu.bme.mit.theta.core.type.rattype.RatGtExpr; +import hu.bme.mit.theta.core.type.rattype.RatLeqExpr; +import hu.bme.mit.theta.core.type.rattype.RatLitExpr; +import hu.bme.mit.theta.core.type.rattype.RatLtExpr; +import hu.bme.mit.theta.core.type.rattype.RatMulExpr; +import hu.bme.mit.theta.core.type.rattype.RatNegExpr; +import hu.bme.mit.theta.core.type.rattype.RatNeqExpr; +import hu.bme.mit.theta.core.type.rattype.RatPosExpr; +import hu.bme.mit.theta.core.type.rattype.RatSubExpr; import java.util.List; import java.util.concurrent.ExecutionException; @@ -72,6 +85,34 @@ public SmtLibExprTransformer(final SmtLibTransformationManager transformer) { .addCase(ForallExpr.class, this::transformForall) + // Rationals + + .addCase(RatLitExpr.class, this::transformRatLit) + + .addCase(RatAddExpr.class, this::transformRatAdd) + + .addCase(RatSubExpr.class, this::transformRatSub) + + .addCase(RatPosExpr.class, this::transformRatPos) + + .addCase(RatNegExpr.class, this::transformRatNeg) + + .addCase(RatMulExpr.class, this::transformRatMul) + + .addCase(RatDivExpr.class, this::transformRatDiv) + + .addCase(RatEqExpr.class, this::transformRatEq) + + .addCase(RatNeqExpr.class, this::transformRatNeq) + + .addCase(RatGeqExpr.class, this::transformRatGeq) + + .addCase(RatGtExpr.class, this::transformRatGt) + + .addCase(RatLeqExpr.class, this::transformRatLeq) + + .addCase(RatLtExpr.class, this::transformRatLt) + .build(); } @@ -189,4 +230,68 @@ private String transformParamDecl(final ParamDecl paramDecl) { return String.format("(%s %s)", paramDecl.getName(), transformer.toSort(type)); } } + + /* + * Rationals + */ + + protected String transformRatLit(final RatLitExpr expr) { + return String.format("(/ %d.0 %d.0)", expr.getNum(), expr.getDenom()); + } + + protected String transformRatAdd(final RatAddExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(+ %s)", String.join(" ", opTerms)); + } + + protected String transformRatSub(final RatSubExpr expr) { + return String.format("(- %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatPos(final RatPosExpr expr) { + return toTerm(expr.getOp()); + } + + protected String transformRatNeg(final RatNegExpr expr) { + return String.format("(- %s)", toTerm(expr.getOp())); + } + + protected String transformRatMul(final RatMulExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(* %s)", String.join(" ", opTerms)); + } + + protected String transformRatDiv(final RatDivExpr expr) { + return String.format("(/ %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatEq(final RatEqExpr expr) { + return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatNeq(final RatNeqExpr expr) { + return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatGeq(final RatGeqExpr expr) { + return String.format("(>= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatGt(final RatGtExpr expr) { + return String.format("(> %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatLeq(final RatLeqExpr expr) { + return String.format("(<= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatLt(final RatLtExpr expr) { + return String.format("(< %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } } From 5672fbc64204465c4ae7bf398aab82131e763657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 27 Aug 2020 13:14:28 +0200 Subject: [PATCH 07/99] Add integer expression translation --- .../solver/smtlib/SmtLibExprTransformer.java | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index e628218e8c..a9547de169 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -23,6 +23,23 @@ import hu.bme.mit.theta.core.type.booltype.TrueExpr; import hu.bme.mit.theta.core.type.booltype.XorExpr; import hu.bme.mit.theta.core.type.functype.FuncType; +import hu.bme.mit.theta.core.type.inttype.IntAddExpr; +import hu.bme.mit.theta.core.type.inttype.IntDivExpr; +import hu.bme.mit.theta.core.type.inttype.IntEqExpr; +import hu.bme.mit.theta.core.type.inttype.IntGeqExpr; +import hu.bme.mit.theta.core.type.inttype.IntGtExpr; +import hu.bme.mit.theta.core.type.inttype.IntLeqExpr; +import hu.bme.mit.theta.core.type.inttype.IntLitExpr; +import hu.bme.mit.theta.core.type.inttype.IntLtExpr; +import hu.bme.mit.theta.core.type.inttype.IntModExpr; +import hu.bme.mit.theta.core.type.inttype.IntMulExpr; +import hu.bme.mit.theta.core.type.inttype.IntNegExpr; +import hu.bme.mit.theta.core.type.inttype.IntNeqExpr; +import hu.bme.mit.theta.core.type.inttype.IntPosExpr; +import hu.bme.mit.theta.core.type.inttype.IntRemExpr; +import hu.bme.mit.theta.core.type.inttype.IntSubExpr; +import hu.bme.mit.theta.core.type.inttype.IntToBvExpr; +import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; import hu.bme.mit.theta.core.type.rattype.RatAddExpr; import hu.bme.mit.theta.core.type.rattype.RatDivExpr; import hu.bme.mit.theta.core.type.rattype.RatEqExpr; @@ -113,6 +130,42 @@ public SmtLibExprTransformer(final SmtLibTransformationManager transformer) { .addCase(RatLtExpr.class, this::transformRatLt) + // Integers + + .addCase(IntLitExpr.class, this::transformIntLit) + + .addCase(IntAddExpr.class, this::transformIntAdd) + + .addCase(IntSubExpr.class, this::transformIntSub) + + .addCase(IntPosExpr.class, this::transformIntPos) + + .addCase(IntNegExpr.class, this::transformIntNeg) + + .addCase(IntMulExpr.class, this::transformIntMul) + + .addCase(IntDivExpr.class, this::transformIntDiv) + + .addCase(IntModExpr.class, this::transformIntMod) + + .addCase(IntRemExpr.class, this::transformIntRem) + + .addCase(IntEqExpr.class, this::transformIntEq) + + .addCase(IntNeqExpr.class, this::transformIntNeq) + + .addCase(IntGeqExpr.class, this::transformIntGeq) + + .addCase(IntGtExpr.class, this::transformIntGt) + + .addCase(IntLeqExpr.class, this::transformIntLeq) + + .addCase(IntLtExpr.class, this::transformIntLt) + + .addCase(IntToRatExpr.class, this::transformIntToRat) + + .addCase(IntToBvExpr.class, this::transformIntToBv) + .build(); } @@ -294,4 +347,84 @@ protected String transformRatLeq(final RatLeqExpr expr) { protected String transformRatLt(final RatLtExpr expr) { return String.format("(< %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } + + /* + * Integers + */ + + protected String transformIntLit(final IntLitExpr expr) { + return Integer.toString(expr.getValue()); + } + + protected String transformIntAdd(final IntAddExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(+ %s)", String.join(" ", opTerms)); + } + + protected String transformIntSub(final IntSubExpr expr) { + return String.format("(- %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntPos(final IntPosExpr expr) { + return toTerm(expr.getOp()); + } + + protected String transformIntNeg(final IntNegExpr expr) { + return String.format("(- %s)", toTerm(expr.getOp())); + } + + protected String transformIntMul(final IntMulExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(* %s)", String.join(" ", opTerms)); + } + + protected String transformIntDiv(final IntDivExpr expr) { + return String.format("(/ %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntMod(final IntModExpr expr) { + return String.format("(mod %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntRem(final IntRemExpr expr) { + return String.format("(rem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntEq(final IntEqExpr expr) { + return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntNeq(final IntNeqExpr expr) { + return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntGeq(final IntGeqExpr expr) { + return String.format("(>= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntGt(final IntGtExpr expr) { + return String.format("(> %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntLeq(final IntLeqExpr expr) { + return String.format("(<= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntLt(final IntLtExpr expr) { + return String.format("(< %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntToRat(final IntToRatExpr expr) { + return String.format("(to_real %s)", toTerm(expr.getOp())); + } + + protected String transformIntToBv(final IntToBvExpr expr) { + return String.format("((_ int2bv %d) %s)", expr.getType().getSize(), toTerm(expr.getOp())); + } } From c63a3cb8525cbc961227626d428823ad7415719b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 27 Aug 2020 13:43:59 +0200 Subject: [PATCH 08/99] Add bitvector expression translation --- .../solver/smtlib/SmtLibExprTransformer.java | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index a9547de169..712e1ac526 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -22,6 +22,31 @@ import hu.bme.mit.theta.core.type.booltype.OrExpr; import hu.bme.mit.theta.core.type.booltype.TrueExpr; import hu.bme.mit.theta.core.type.booltype.XorExpr; +import hu.bme.mit.theta.core.type.bvtype.BvAddExpr; +import hu.bme.mit.theta.core.type.bvtype.BvAndExpr; +import hu.bme.mit.theta.core.type.bvtype.BvArithShiftRightExpr; +import hu.bme.mit.theta.core.type.bvtype.BvDivExpr; +import hu.bme.mit.theta.core.type.bvtype.BvEqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvGeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvGtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLogicShiftRightExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvModExpr; +import hu.bme.mit.theta.core.type.bvtype.BvMulExpr; +import hu.bme.mit.theta.core.type.bvtype.BvNegExpr; +import hu.bme.mit.theta.core.type.bvtype.BvNeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvNotExpr; +import hu.bme.mit.theta.core.type.bvtype.BvOrExpr; +import hu.bme.mit.theta.core.type.bvtype.BvPosExpr; +import hu.bme.mit.theta.core.type.bvtype.BvRemExpr; +import hu.bme.mit.theta.core.type.bvtype.BvRotateLeftExpr; +import hu.bme.mit.theta.core.type.bvtype.BvRotateRightExpr; +import hu.bme.mit.theta.core.type.bvtype.BvShiftLeftExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; +import hu.bme.mit.theta.core.type.bvtype.BvToIntExpr; +import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.type.inttype.IntAddExpr; import hu.bme.mit.theta.core.type.inttype.IntDivExpr; @@ -54,6 +79,7 @@ import hu.bme.mit.theta.core.type.rattype.RatPosExpr; import hu.bme.mit.theta.core.type.rattype.RatSubExpr; +import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutionException; @@ -166,6 +192,58 @@ public SmtLibExprTransformer(final SmtLibTransformationManager transformer) { .addCase(IntToBvExpr.class, this::transformIntToBv) + // Bitvectors + + .addCase(BvLitExpr.class, this::transformBvLit) + + .addCase(BvAddExpr.class, this::transformBvAdd) + + .addCase(BvSubExpr.class, this::transformBvSub) + + .addCase(BvPosExpr.class, this::transformBvPos) + + .addCase(BvNegExpr.class, this::transformBvNeg) + + .addCase(BvMulExpr.class, this::transformBvMul) + + .addCase(BvDivExpr.class, this::transformBvDiv) + + .addCase(BvModExpr.class, this::transformBvMod) + + .addCase(BvRemExpr.class, this::transformBvRem) + + .addCase(BvAndExpr.class, this::transformBvAnd) + + .addCase(BvOrExpr.class, this::transformBvOr) + + .addCase(BvXorExpr.class, this::transformBvXor) + + .addCase(BvNotExpr.class, this::transformBvNot) + + .addCase(BvShiftLeftExpr.class, this::transformBvShiftLeft) + + .addCase(BvArithShiftRightExpr.class, this::transformBvArithShiftRight) + + .addCase(BvLogicShiftRightExpr.class, this::transformBvLogicShiftRight) + + .addCase(BvRotateLeftExpr.class, this::transformBvRotateLeft) + + .addCase(BvRotateRightExpr.class, this::transformBvRotateRight) + + .addCase(BvEqExpr.class, this::transformBvEq) + + .addCase(BvNeqExpr.class, this::transformBvNeq) + + .addCase(BvGeqExpr.class, this::transformBvGeq) + + .addCase(BvGtExpr.class, this::transformBvGt) + + .addCase(BvLeqExpr.class, this::transformBvLeq) + + .addCase(BvLtExpr.class, this::transformBvLt) + + .addCase(BvToIntExpr.class, this::transformBvToInt) + .build(); } @@ -425,6 +503,189 @@ protected String transformIntToRat(final IntToRatExpr expr) { } protected String transformIntToBv(final IntToBvExpr expr) { + throw new UnsupportedOperationException("SMT-LIB does not have the corresponding operation"); + /* Works with Z3, but it is not standard return String.format("((_ int2bv %d) %s)", expr.getType().getSize(), toTerm(expr.getOp())); + */ + } + + /* + * Bitvectors + */ + + protected String transformBvLit(final BvLitExpr expr) { + final String value = Arrays.toString(expr.getValue()) + .replace("true", "1") + .replace("false", "0") + .replace("[", "") + .replace("]", "") + .replace(",", "") + .replace(" ", ""); + + return String.format("#b%s", value); + } + + protected String transformBvAdd(final BvAddExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(bvadd %s)", String.join(" ", opTerms)); + } + + protected String transformBvSub(final BvSubExpr expr) { + return String.format("(bvsub %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvPos(final BvPosExpr expr) { + return toTerm(expr.getOp()); + } + + protected String transformBvNeg(final BvNegExpr expr) { + return String.format("(bvneg %s)", toTerm(expr.getOp())); + } + + protected String transformBvMul(final BvMulExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(bvmul %s)", String.join(" ", opTerms)); + } + + protected String transformBvDiv(final BvDivExpr expr) { + if(expr.getType().isSigned()) { + return String.format("(bvsdiv %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvudiv %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvMod(final BvModExpr expr) { + if(expr.getType().isSigned()) { + return String.format("(bvsmod %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvurem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvRem(final BvRemExpr expr) { + if(expr.getType().isSigned()) { + return String.format("(bvsrem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvurem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvAnd(final BvAndExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(bvand %s)", String.join(" ", opTerms)); + } + + protected String transformBvOr(final BvOrExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(bvor %s)", String.join(" ", opTerms)); + } + + protected String transformBvXor(final BvXorExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(bvxor %s)", String.join(" ", opTerms)); + } + + protected String transformBvNot(final BvNotExpr expr) { + return String.format("(bvnot %s)", toTerm(expr.getOp())); + } + + protected String transformBvShiftLeft(final BvShiftLeftExpr expr) { + return String.format("(bvshl %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvArithShiftRight(final BvArithShiftRightExpr expr) { + return String.format("(bvashr %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvLogicShiftRight(final BvLogicShiftRightExpr expr) { + return String.format("(bvlshr %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvRotateLeft(final BvRotateLeftExpr expr) { + return String.format("((_ rotate_left %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); + } + + protected String transformBvRotateRight(final BvRotateRightExpr expr) { + return String.format("((_ rotate_right %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); + } + + protected String transformBvEq(final BvEqExpr expr) { + return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvNeq(final BvNeqExpr expr) { + return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvGeq(final BvGeqExpr expr) { + if(expr.getLeftOp().getType().isSigned()) { + return String.format("(bvsge %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvuge %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvGt(final BvGtExpr expr) { + if(expr.getLeftOp().getType().isSigned()) { + return String.format("(bvsgt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvugt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvLeq(final BvLeqExpr expr) { + if(expr.getLeftOp().getType().isSigned()) { + return String.format("(bvsle %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvule %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvLt(final BvLtExpr expr) { + if(expr.getLeftOp().getType().isSigned()) { + return String.format("(bvslt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvult %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvToInt(final BvToIntExpr expr) { + throw new UnsupportedOperationException("SMT-LIB does not have the corresponding operation"); + /* Works with Z3, but not standard + if(expr.getOp().getType().isSigned()) { + final String bv = toTerm(expr.getOp()); + final BigInteger exp = BigInteger.TWO.pow(expr.getOp().getType().getSize()); + return String.format( + "(ite (bvslt %s ((_ int2bv %d) 0)) (- (bv2int %s) %s) (bv2int %s))", + bv, expr.getOp().getType().getSize(), bv, exp.toString(), bv + ); + } + else { + return String.format("(bv2int %s)", toTerm(expr.getOp())); + } + */ } } From e56411574d36bb4539f58964df02c5421fc55659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 27 Aug 2020 15:00:01 +0200 Subject: [PATCH 09/99] Add function expression translation --- .../solver/smtlib/SmtLibExprTransformer.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index 712e1ac526..8784c5d94c 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -2,7 +2,9 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.google.common.collect.ImmutableList; import hu.bme.mit.theta.common.DispatchTable; +import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.common.dsl.Env; import hu.bme.mit.theta.core.decl.ConstDecl; import hu.bme.mit.theta.core.decl.Decl; @@ -47,6 +49,7 @@ import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; import hu.bme.mit.theta.core.type.bvtype.BvToIntExpr; import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; +import hu.bme.mit.theta.core.type.functype.FuncAppExpr; import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.type.inttype.IntAddExpr; import hu.bme.mit.theta.core.type.inttype.IntDivExpr; @@ -243,6 +246,10 @@ public SmtLibExprTransformer(final SmtLibTransformationManager transformer) { .addCase(BvLtExpr.class, this::transformBvLt) .addCase(BvToIntExpr.class, this::transformBvToInt) + + // Functions + + .addCase(FuncAppExpr.class, this::transformFuncApp) .build(); } @@ -688,4 +695,41 @@ protected String transformBvToInt(final BvToIntExpr expr) { } */ } + + /* + * Functions + */ + + protected String transformFuncApp(final FuncAppExpr expr) { + final Tuple2, List>> funcAndArgs = extractFuncAndArgs(expr); + final Expr func = funcAndArgs.get1(); + if (func instanceof RefExpr) { + final RefExpr ref = (RefExpr) func; + final Decl decl = ref.getDecl(); + final String funcDecl = transformer.toSymbol(decl); + final List> args = funcAndArgs.get2(); + final String[] argTerms = args.stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(%s %s)", funcDecl, String.join(" ", argTerms)); + } else { + throw new UnsupportedOperationException("Higher order functions are not supported: " + func); + } + } + + private static Tuple2, List>> extractFuncAndArgs(final FuncAppExpr expr) { + final Expr func = expr.getFunc(); + final Expr arg = expr.getParam(); + if (func instanceof FuncAppExpr) { + final FuncAppExpr funcApp = (FuncAppExpr) func; + final Tuple2, List>> funcAndArgs = extractFuncAndArgs(funcApp); + final Expr resFunc = funcAndArgs.get1(); + final List> args = funcAndArgs.get2(); + final List> resArgs = ImmutableList.>builder().addAll(args).add(arg).build(); + return Tuple2.of(resFunc, resArgs); + } else { + return Tuple2.of(func, ImmutableList.of(arg)); + } + } } From d25336b7afeb23362acfc9dec73df79c90a348e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 27 Aug 2020 15:09:16 +0200 Subject: [PATCH 10/99] Add array expression translation --- .../solver/smtlib/SmtLibExprTransformer.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index 8784c5d94c..884ce13a51 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -14,6 +14,11 @@ import hu.bme.mit.theta.core.type.Type; import hu.bme.mit.theta.core.type.anytype.IteExpr; import hu.bme.mit.theta.core.type.anytype.RefExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayEqExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayLitExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayNeqExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayReadExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayWriteExpr; import hu.bme.mit.theta.core.type.booltype.AndExpr; import hu.bme.mit.theta.core.type.booltype.ExistsExpr; import hu.bme.mit.theta.core.type.booltype.FalseExpr; @@ -251,6 +256,18 @@ public SmtLibExprTransformer(final SmtLibTransformationManager transformer) { .addCase(FuncAppExpr.class, this::transformFuncApp) + // Arrays + + .addCase(ArrayReadExpr.class, this::transformArrayRead) + + .addCase(ArrayWriteExpr.class, this::transformArrayWrite) + + .addCase(ArrayEqExpr.class, this::transformArrayEq) + + .addCase(ArrayNeqExpr.class, this::transformArrayNeq) + + .addCase(ArrayLitExpr.class, this::transformArrayLit) + .build(); } @@ -732,4 +749,32 @@ private static Tuple2, List>> extractFuncAndArgs(final FuncAppEx return Tuple2.of(func, ImmutableList.of(arg)); } } + + /* + * Arrays + */ + + protected String transformArrayRead(final ArrayReadExpr expr) { + return String.format("(select %s %s)", toTerm(expr.getArray()), toTerm(expr.getIndex())); + } + + protected String transformArrayWrite(final ArrayWriteExpr expr) { + return String.format("(store %s %s %s)", toTerm(expr.getArray()), toTerm(expr.getIndex()), toTerm(expr.getElem())); + } + + protected String transformArrayEq(final ArrayEqExpr expr) { + return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformArrayNeq(final ArrayNeqExpr expr) { + return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformArrayLit(final ArrayLitExpr expr) { + String running = String.format("((as const %s) %s)", transformer.toSort(expr.getType()), toTerm(expr.getElseElem())); + for (Tuple2, ? extends Expr> elem : expr.getElements()) { + running = String.format("(store %s %s %s)", running, toTerm(elem.get1()), toTerm(elem.get2())); + } + return running; + } } From 79fd2072d0af5e2a42226c2dc0b9f49222cf4a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 12:58:14 +0200 Subject: [PATCH 11/99] Model (part-of) SMT-LIB response language --- subprojects/solver-smtlib/build.gradle.kts | 1 + .../solver-smtlib/src/main/antlr/SMTLIBv2.g4 | 513 ++++++++++++++++++ 2 files changed, 514 insertions(+) create mode 100644 subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 diff --git a/subprojects/solver-smtlib/build.gradle.kts b/subprojects/solver-smtlib/build.gradle.kts index 046f35169a..e959b56575 100644 --- a/subprojects/solver-smtlib/build.gradle.kts +++ b/subprojects/solver-smtlib/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("java-common") + id("antlr-grammar") } dependencies { diff --git a/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 b/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 new file mode 100644 index 0000000000..d745427763 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 @@ -0,0 +1,513 @@ +/** + * SMT-LIB (v2.6) grammar + * + * Grammar is baesd on the following specification: + * http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Julian Thome + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + +grammar SMTLIBv2; + +// Parser Rules Start + +response + : general_response_success + | general_response_unsupported + | general_response_error + | specific_success_response + ; + +general_response_success + : PS_Success + ; + +general_response_unsupported + : PS_Unsupported + ; + +general_response_error + : reason=PS_Unsupported + | ParOpen PS_Error reason=String ParClose + ; + +specific_success_response + : check_sat_response + ; + +check_sat_response + : value=PS_Sat + | value=PS_Unsat + | value=PS_Unknown + ; + +// Parser Rules End + +// Lexer Rules Start + + +Comment + : Semicolon ~[\r\n]* -> skip + ; + + +ParOpen + : '(' + ; + +ParClose + : ')' + ; + +Semicolon + : ';' + ; + +String + : '"' (PrintableCharNoDquote | WhiteSpaceChar)+ '"' + ; + +QuotedSymbol: + '|' (PrintableCharNoBackslash | WhiteSpaceChar)+ '|' + ; + + +// Predefined Symbols + +PS_Not + : 'not' + ; +PS_Bool + : 'Bool' + ; +PS_ContinuedExecution + : 'continued-execution' + ; +PS_Error + : 'error' + ; +PS_False + : 'false' + ; +PS_ImmediateExit + : 'immediate-exit' + ; +PS_Incomplete + : 'incomplete' + ; +PS_Logic + : 'logic' + ; +PS_Memout + : 'memout' + ; +PS_Sat + : 'sat' + ; +PS_Success + : 'success' + ; +PS_Theory + : 'theory' + ; +PS_True + : 'true' + ; +PS_Unknown + : 'unknown' + ; +PS_Unsupported + : 'unsupported' + ; +PS_Unsat + : 'unsat' + ; + +// RESERVED Words + +// Command names + + +CMD_Assert + : 'assert' + ; +CMD_CheckSat + : 'check-sat' + ; +CMD_CheckSatAssuming + : 'check-sat-assuming' + ; +CMD_DeclareConst + : 'declare-const' + ; +CMD_DeclareDatatype + : 'declare-datatype' + ; +CMD_DeclareDatatypes + : 'declare-datatypes' + ; +CMD_DeclareFun + : 'declare-fun' + ; +CMD_DeclareSort + : 'declare-sort' + ; +CMD_DefineFun + : 'define-fun' + ; +CMD_DefineFunRec + : 'define-fun-rec' + ; +CMD_DefineFunsRec + : 'define-funs-rec' + ; +CMD_DefineSort + : 'define-sort' + ; +CMD_Echo + : 'echo' + ; +CMD_Exit + : 'exit' + ; +CMD_GetAssertions + : 'get-assertions' + ; +CMD_GetAssignment + : 'get-assignment' + ; +CMD_GetInfo + : 'get-info' + ; +CMD_GetModel + : 'get-model' + ; +CMD_GetOption + : 'get-option' + ; +CMD_GetProof + : 'get-proof' + ; +CMD_GetUnsatAssumptions + : 'get-unsat-assumptions' + ; +CMD_GetUnsatCore + : 'get-unsat-core' + ; +CMD_GetValue + : 'get-value' + ; +CMD_Pop + : 'pop' + ; +CMD_Push + : 'push' + ; +CMD_Reset + : 'reset' + ; +CMD_ResetAssertions + : 'reset-assertions' + ; +CMD_SetInfo + : 'set-info' + ; +CMD_SetLogic + : 'set-logic' + ; +CMD_SetOption + : 'set-option' + ; + + + + +// General reserved words + +GRW_Exclamation + : '!' + ; +GRW_Underscore + : '_' + ; +GRW_As + : 'as' + ; +GRW_Binary + : 'BINARY' + ; +GRW_Decimal + : 'DECIMAL' + ; +GRW_Exists + : 'exists' + ; +GRW_Hexadecimal + : 'HEXADECIMAL' + ; +GRW_Forall + : 'forall' + ; +GRW_Let + : 'let' + ; +GRW_Match + : 'match' + ; +GRW_Numeral + : 'NUMERAL' + ; +GRW_Par + : 'par' + ; +GRW_String + : 'string' + ; + +Numeral + : '0' + | [1-9] Digit* + ; + +Binary: + BinaryDigit+ + ; + +HexDecimal + : '#x' HexDigit HexDigit HexDigit HexDigit + ; + +Decimal + : Numeral '.' '0'* Numeral + ; + + + +fragment HexDigit + : '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' + ; + + +Colon + : ':' + ; + +fragment Digit + : [0-9] + ; + +fragment Sym + : 'a'..'z' + | 'A' .. 'Z' + | '+' + | '=' + | '/' + | '*' + | '%' + | '?' + | '!' + | '$' + | '-' + | '_' + | '~' + | '&' + | '^' + | '<' + | '>' + | '@' + | '.' + ; + + + +fragment BinaryDigit + : [01] + ; + +fragment PrintableChar + : '\u0020' .. '\u007E' + | '\u0080' .. '\uffff' + | EscapedSpace + ; + +fragment PrintableCharNoDquote + : '\u0020' .. '\u0021' + | '\u0023' .. '\u007E' + | '\u0080' .. '\uffff' + | EscapedSpace + ; + +fragment PrintableCharNoBackslash + : '\u0020' .. '\u005B' + | '\u005D' .. '\u007B' + | '\u007D' .. '\u007E' + | '\u0080' .. '\uffff' + | EscapedSpace + ; + +fragment EscapedSpace + : '""' + ; + +fragment WhiteSpaceChar + : '\u0009' + | '\u000A' + | '\u000D' + | '\u0020' + ; + +// Lexer Rules End + +// Predefined Keywords + + + +PK_AllStatistics + : ':all-statistics' + ; +PK_AssertionStackLevels + : ':assertion-stack-levels' + ; +PK_Authors + : ':authors' + ; +PK_Category + : ':category' + ; +PK_Chainable + : ':chainable' + ; +PK_Definition + : ':definition' + ; +PK_DiagnosticOutputChannel + : ':diagnostic-output-channel' + ; +PK_ErrorBehaviour + : ':error-behavior' + ; +PK_Extension + : ':extensions' + ; +PK_Funs + : ':funs' + ; +PK_FunsDescription + : ':funs-description' + ; +PK_GlobalDeclarations + : ':global-declarations' + ; +PK_InteractiveMode + : ':interactive-mode' + ; +PK_Language + : ':language' + ; +PK_LeftAssoc + : ':left-assoc' + ; +PK_License + : ':license' + ; +PK_Named + : ':named' + ; +PK_Name + : ':name' + ; +PK_Notes + : ':notes' + ; +PK_Pattern + : ':pattern' + ; +PK_PrintSuccess + : ':print-success' + ; +PK_ProduceAssertions + : ':produce-assertions' + ; +PK_ProduceAssignments + : ':produce-assignments' + ; +PK_ProduceModels + : ':produce-models' + ; +PK_ProduceProofs + : ':produce-proofs' + ; +PK_ProduceUnsatAssumptions + : ':produce-unsat-assumptions' + ; +PK_ProduceUnsatCores + : ':produce-unsat-cores' + ; +PK_RandomSeed + : ':random-seed' + ; +PK_ReasonUnknown + : ':reason-unknown' + ; +PK_RegularOutputChannel + : ':regular-output-channel' + ; +PK_ReproducibleResourceLimit + : ':reproducible-resource-limit' + ; +PK_RightAssoc + : ':right-assoc' + ; +PK_SmtLibVersion + : ':smt-lib-version' + ; +PK_Sorts + : ':sorts' + ; +PK_SortsDescription + : ':sorts-description' + ; +PK_Source + : ':source' + ; +PK_Status + : ':status' + ; +PK_Theories + : ':theories' + ; +PK_Values + : ':values' + ; +PK_Verbosity + : ':verbosity' + ; +PK_Version + : ':version' + ; + +UndefinedSymbol: + Sym (Digit | Sym)*; + +WS : [ \t\r\n]+ -> skip + ; \ No newline at end of file From bb0d072d4733502d21ac94db4650c842de26ccd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 12:58:42 +0200 Subject: [PATCH 12/99] Model (part-of) SMT-LIB response language --- .../smtlib/parser/CheckSatResponse.java | 46 +++++++++++++ .../solver/smtlib/parser/GeneralResponse.java | 66 +++++++++++++++++++ .../smtlib/parser/SpecificResponse.java | 16 +++++ 3 files changed, 128 insertions(+) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java new file mode 100644 index 0000000000..af49c39305 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java @@ -0,0 +1,46 @@ +package hu.bme.mit.theta.solver.smtlib.parser; + +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Check_sat_responseContext; + +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.PS_Sat; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.PS_Unknown; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.PS_Unsat; + +public class CheckSatResponse implements SpecificResponse { + private enum Status { + SAT, UNSAT, UNKNOWN + } + + private final Status status; + + private CheckSatResponse(Status status) { + this.status = status; + } + + public static CheckSatResponse fromContext(final Check_sat_responseContext ctx) { + switch (ctx.value.getType()) { + case PS_Sat: + return new CheckSatResponse(Status.SAT); + case PS_Unsat: + return new CheckSatResponse(Status.UNSAT); + case PS_Unknown: + return new CheckSatResponse(Status.UNKNOWN); + default: + throw new SmtLibSolverException("Invalid interface"); + + } + } + + public boolean isSat() { + return status == Status.SAT; + } + + public boolean isUnsat() { + return status == Status.UNSAT; + } + + public boolean isUnknown() { + return status == Status.UNKNOWN; + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java new file mode 100644 index 0000000000..6973f32822 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java @@ -0,0 +1,66 @@ +package hu.bme.mit.theta.solver.smtlib.parser; + +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.General_response_errorContext; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.General_response_successContext; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.General_response_unsupportedContext; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.ResponseContext; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Specific_success_responseContext; + +public class GeneralResponse { + private final boolean successful; + private final String reason; + private final SpecificResponse specificResponse; + + private GeneralResponse(boolean successful, String reason, SpecificResponse specificResponse) { + this.successful = successful; + this.reason = reason; + this.specificResponse = specificResponse; + } + + public static GeneralResponse fromContext(final ResponseContext ctx) { + return ctx.accept(new SMTLIBv2BaseVisitor<>() { + @Override + public GeneralResponse visitGeneral_response_success(General_response_successContext ctx) { + return new GeneralResponse(true, null, null); + } + + @Override + public GeneralResponse visitGeneral_response_unsupported(General_response_unsupportedContext ctx) { + return new GeneralResponse(false, "Unsupported", null); + } + + @Override + public GeneralResponse visitSpecific_success_response(Specific_success_responseContext ctx) { + return new GeneralResponse(true, null, SpecificResponse.fromContext(ctx)); + } + + @Override + public GeneralResponse visitGeneral_response_error(General_response_errorContext ctx) { + return new GeneralResponse(false, ctx.reason.getText(), null); + } + }); + } + + public boolean isSuccessful() { + return successful && specificResponse == null; + } + + public boolean isError() { + return !successful; + } + + public String getReason() { + return reason; + } + + public boolean isSpecific() { + return successful && specificResponse != null; + } + + @SuppressWarnings("unchecked") + public T asSpecific() { + return (T) specificResponse; + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java new file mode 100644 index 0000000000..9c0b400e9d --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java @@ -0,0 +1,16 @@ +package hu.bme.mit.theta.solver.smtlib.parser; + +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Specific_success_responseContext; + +public interface SpecificResponse { + static SpecificResponse fromContext(final Specific_success_responseContext ctx) { + return ctx.accept(new SMTLIBv2BaseVisitor<>() { + @Override + public SpecificResponse visitCheck_sat_response(SMTLIBv2Parser.Check_sat_responseContext ctx) { + return CheckSatResponse.fromContext(ctx); + } + }); + } +} From b705b102458842a437a641b9843a4e835221dd49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 12:59:27 +0200 Subject: [PATCH 13/99] Add interface to solver binary --- .../smtlib/binary/ContinousSolverBinary.java | 126 ++++++++++++++++++ .../solver/smtlib/binary/SolverBinary.java | 5 + 2 files changed, 131 insertions(+) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinousSolverBinary.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/SolverBinary.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinousSolverBinary.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinousSolverBinary.java new file mode 100644 index 0000000000..6e72446268 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinousSolverBinary.java @@ -0,0 +1,126 @@ +package hu.bme.mit.theta.solver.smtlib.binary; + +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverProcessFailureException; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; + +import static com.google.common.base.Preconditions.checkState; + +public final class ContinousSolverBinary implements SolverBinary { + + private final Process solverProcess; + private final PrintWriter solverInput; + private final Reader solverOutput; + + public ContinousSolverBinary(final Path solverPath, final String[] args) { + final var processCmd = new ArrayList(); + processCmd.add(solverPath.toAbsolutePath().toString()); + processCmd.addAll(Arrays.asList(args)); + try { + solverProcess = new ProcessBuilder(processCmd) + .redirectError(ProcessBuilder.Redirect.INHERIT) + .start(); + solverInput = new PrintWriter(solverProcess.getOutputStream(), true, StandardCharsets.US_ASCII); + solverOutput = new InputStreamReader(solverProcess.getInputStream(), StandardCharsets.US_ASCII); + checkState(solverProcess.isAlive()); + } catch (IOException e) { + throw new SmtLibSolverProcessFailureException(e); + } + } + + @Override + public String issueCommand(final String command) { + checkState(solverProcess.isAlive()); + solverInput.println(command); + return readResponse(solverOutput); + } + + private String readResponse(final Reader solverOutput) { + final var sb = new StringBuilder(256); + final var readProcessor = new ReadProcessor(); + while (sb.length() == 0 || !readProcessor.isReady()) { + Thread.yield(); + if (!solverProcess.isAlive()) { + throw new SmtLibSolverProcessFailureException("Solver process terminated early"); + } + try { + while (solverOutput.ready() && !readProcessor.isReady()) { + readProcessor.step(sb, (char) solverOutput.read()); + } + } catch (IOException e) { + throw new SmtLibSolverProcessFailureException(e); + } + } + return sb.toString().trim(); + } + + private static final class ReadProcessor { + private enum ReadStatus { + INIT, LINE, PARENTHESES, STRING, COMMENT, READY + } + + private ReadProcessor.ReadStatus status = ReadProcessor.ReadStatus.INIT; + private int level = 0; + + public void step(final StringBuilder sb, final char c) { + switch (status) { + case INIT: + if (c == '(') { + level++; + sb.append(c); + status = ReadProcessor.ReadStatus.PARENTHESES; + } else if (c == ';') { + status = ReadProcessor.ReadStatus.COMMENT; + } else if (Character.isAlphabetic(c)) { + sb.append(c); + status = ReadProcessor.ReadStatus.LINE; + } + break; + case LINE: + if (c == '\n') { + status = ReadProcessor.ReadStatus.READY; + } else { + sb.append(c); + } + break; + case PARENTHESES: + sb.append(c); + if (c == '(') { + level++; + } else if (c == ')') { + level--; + if (level == 0) { + status = ReadProcessor.ReadStatus.READY; + } + } else if (c == '"') { + status = ReadProcessor.ReadStatus.STRING; + } + break; + case STRING: + sb.append(c); + if (c == '"') { + status = ReadProcessor.ReadStatus.PARENTHESES; + } + break; + case COMMENT: + if (c == '\n') { + status = ReadProcessor.ReadStatus.INIT; + } + break; + case READY: + throw new AssertionError(); + } + } + + public boolean isReady() { + return status == ReadProcessor.ReadStatus.READY; + } + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/SolverBinary.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/SolverBinary.java new file mode 100644 index 0000000000..b292b36cf0 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/SolverBinary.java @@ -0,0 +1,5 @@ +package hu.bme.mit.theta.solver.smtlib.binary; + +public interface SolverBinary { + String issueCommand(String command); +} From c142af8acbd4b310c823413c0b1dd44e22c9a1a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 13:00:12 +0200 Subject: [PATCH 14/99] Implement simple solver functionalities --- .../bme/mit/theta/core/utils/ExprUtils.java | 54 +++++ .../mit/theta/solver/smtlib/SmtLibSolver.java | 213 ++++++++++++++++++ .../solver/smtlib/SmtLibSolverException.java | 32 +++ .../SmtLibSolverProcessFailureException.java | 28 +++ 4 files changed, 327 insertions(+) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverProcessFailureException.java diff --git a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/ExprUtils.java b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/ExprUtils.java index 0ef4a97117..4e5f8f9907 100644 --- a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/ExprUtils.java +++ b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/ExprUtils.java @@ -26,6 +26,7 @@ import java.util.Set; import java.util.stream.Collectors; +import hu.bme.mit.theta.core.decl.ConstDecl; import hu.bme.mit.theta.core.decl.Decl; import hu.bme.mit.theta.core.decl.ParamDecl; import hu.bme.mit.theta.core.decl.VarDecl; @@ -160,6 +161,59 @@ public static Set> getVars(final Iterable> exprs) { return vars; } + /** + * Collect constants of an expression into a given collection. + * + * @param expr Expression + * @param collectTo Collection where the constants should be put + */ + public static void collectConstants(final Expr expr, final Collection> collectTo) { + if (expr instanceof RefExpr) { + final RefExpr refExpr = (RefExpr) expr; + final Decl decl = refExpr.getDecl(); + if (decl instanceof ConstDecl) { + final ConstDecl constDecl = (ConstDecl) decl; + collectTo.add(constDecl); + return; + } + } + expr.getOps().forEach(op -> collectConstants(op, collectTo)); + } + + /** + * Collect constants from expressions into a given collection. + * + * @param exprs Expressions + * @param collectTo Collection where the constants should be put + */ + public static void collectConstants(final Iterable> exprs, final Collection> collectTo) { + exprs.forEach(e -> collectConstants(e, collectTo)); + } + + /** + * Get constants of an expression. + * + * @param expr Expression + * @return Set of constants appearing in the expression + */ + public static Set> getConstants(final Expr expr) { + final Set> consts = new HashSet<>(); + collectConstants(expr, consts); + return consts; + } + + /** + * Get constants of expressions. + * + * @param exprs Expressions + * @return Set of constants appearing in the expressions + */ + public static Set> getConstants(final Iterable> exprs) { + final Set> consts = new HashSet<>(); + collectConstants(exprs, consts); + return consts; + } + /** * Get indexed variables of an expression. * diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java new file mode 100644 index 0000000000..5fa174f2a5 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java @@ -0,0 +1,213 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.model.Valuation; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.core.utils.ExprUtils; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.Stack; +import hu.bme.mit.theta.solver.UnknownSolverStatusException; +import hu.bme.mit.theta.solver.impl.StackImpl; +import hu.bme.mit.theta.solver.smtlib.binary.ContinousSolverBinary; +import hu.bme.mit.theta.solver.smtlib.binary.SolverBinary; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.parser.CheckSatResponse; +import hu.bme.mit.theta.solver.smtlib.parser.GeneralResponse; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkState; + +public class SmtLibSolver implements Solver { + private final SolverBinary solverBinary; + + private final SmtLibSymbolTable symbolTable; + private final SmtLibTransformationManager transformationManager; + + private final Stack> assertions; + private final Map> assumptions; + private final Set> declarations; + private final Stack>> declarationStack; + + private static final String ASSUMPTION_LABEL = "_LABEL_%d"; + private int labelNum = 0; + + private Valuation model; + private Collection> unsatCore; + private SolverStatus status; + + public SmtLibSolver( + final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, + final Path solverPath, final String[] args + ) { + this.solverBinary = new ContinousSolverBinary(solverPath, args); + + this.symbolTable = symbolTable; + this.transformationManager = transformationManager; + + assertions = new StackImpl<>(); + assumptions = new HashMap<>(); + declarations = new HashSet<>(); + declarationStack = new StackImpl<>(); + + init(); + } + + @Override + public void add(Expr assertion) { + final var consts = ExprUtils.getConstants(assertion); + consts.removeAll(declarations); + declarations.addAll(consts); + declarationStack.add(consts); + + final var term = transformationManager.toTerm(assertion); + + consts.stream().map(symbolTable::getDeclaration).forEach(this::issueGeneralCommand); + issueGeneralCommand(String.format("(assert %s)%n", term)); + + clearState(); + } + + @Override + public void track(Expr assertion) { + final var consts = ExprUtils.getConstants(assertion); + consts.removeAll(declarations); + declarations.addAll(consts); + declarationStack.add(consts); + + final var term = transformationManager.toTerm(assertion); + final var label = String.format(ASSUMPTION_LABEL, labelNum++); + assumptions.put(label, assertion); + + consts.stream().map(symbolTable::getDeclaration).forEach(this::issueGeneralCommand); + issueGeneralCommand(String.format("(assert (! %s :named %s))%n", term, label)); + + clearState(); + } + + @Override + public SolverStatus check() { + var res = parseResponse(solverBinary.issueCommand("(check-sat)")); + if(res.isError()) { + throw new SmtLibSolverException(res.getReason()); + } + else if(res.isSpecific()) { + final CheckSatResponse checkSatResponse = res.asSpecific(); + if(checkSatResponse.isSat()) { + return SolverStatus.SAT; + } + else if(checkSatResponse.isUnsat()) { + return SolverStatus.UNSAT; + } + else { + throw new UnknownSolverStatusException(); + } + } + else { + throw new AssertionError(); + } + } + + @Override + public void push() { + assertions.push(); + declarationStack.push(); + declarations.clear(); + declarations.addAll(declarationStack.toCollection().stream().flatMap(Collection::stream).collect(Collectors.toSet())); + issueGeneralCommand("(push)"); + } + + @Override + public void pop(int n) { + assertions.pop(n); + declarationStack.pop(n); + issueGeneralCommand("(pop)"); + clearState(); + } + + @Override + public void reset() { + issueGeneralCommand("(reset)"); + clearState(); + init(); + } + + @Override + public SolverStatus getStatus() { + checkState(status != null, "Solver status is unknown."); + return status; + } + + @Override + public Valuation getModel() { + checkState(status == SolverStatus.SAT, "Cannot get model if status is not SAT."); + + if (model == null) { + //model = extractModel(); + } + + assert model != null; + return model; + } + + @Override + public Collection> getUnsatCore() { + checkState(status == SolverStatus.UNSAT, "Cannot get unsat core if status is not UNSAT"); + + if (unsatCore == null) { + //unsatCore = extractUnsatCore(); + } + + assert unsatCore != null; + return Collections.unmodifiableCollection(unsatCore); + } + + @Override + public Collection> getAssertions() { + return assertions.toCollection(); + } + + protected void init() { + issueGeneralCommand("(set-option :print-success true)"); + issueGeneralCommand("(set-option :produce-models true)"); + issueGeneralCommand("(set-option :produce-unsat-cores true)"); + issueGeneralCommand("(set-logic ALL)"); + } + + private void clearState() { + status = null; + model = null; + unsatCore = null; + } + + private void issueGeneralCommand(String command) { + var res = parseResponse(solverBinary.issueCommand(command)); + if(res.isError()) { + throw new SmtLibSolverException(res.getReason()); + } + } + + private GeneralResponse parseResponse(final String response) { + try { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(response)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + return GeneralResponse.fromContext(parser.response()); + } + catch (Exception e) { + throw new SmtLibSolverException("Could not parse solver output: " + response, e); + } + } + +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java new file mode 100644 index 0000000000..f02b1f1210 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hu.bme.mit.theta.solver.smtlib; + +public class SmtLibSolverException extends RuntimeException { + private static final long serialVersionUID = -7472824180590829943L; + + public SmtLibSolverException(Exception e) { + super(e); + } + + public SmtLibSolverException(String e) { + super(e); + } + + public SmtLibSolverException(String e, Throwable c) { + super(e, c); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverProcessFailureException.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverProcessFailureException.java new file mode 100644 index 0000000000..5b6638d7cc --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverProcessFailureException.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hu.bme.mit.theta.solver.smtlib; + +public class SmtLibSolverProcessFailureException extends SmtLibSolverException { + private static final long serialVersionUID = -7472824180590829943L; + + public SmtLibSolverProcessFailureException(Exception e) { + super(e); + } + + public SmtLibSolverProcessFailureException(String e) { + super(e); + } +} From 6ec7a204b1c01af7583b775ebb8d5eda865dc510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 13:00:28 +0200 Subject: [PATCH 15/99] Implement solver factory --- .../solver/smtlib/SmtLibSolverFactory.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java new file mode 100644 index 0000000000..741db5de34 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java @@ -0,0 +1,34 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverFactory; + +import java.nio.file.Path; + +public class SmtLibSolverFactory implements SolverFactory { + private final Path solverPath; + private final String[] args; + + private SmtLibSolverFactory(Path solverPath, String[] args) { + this.solverPath = solverPath; + this.args = args; + } + + public static SmtLibSolverFactory create(Path solverPath, String[] args) { + return new SmtLibSolverFactory(solverPath, args); + } + + @Override + public Solver createSolver() { + final var symbolTable = new SmtLibSymbolTable(); + final var transformationManager = new SmtLibTransformationManager(symbolTable); + + return new SmtLibSolver(symbolTable, transformationManager, solverPath, args); + } + + @Override + public ItpSolver createItpSolver() { + throw new UnsupportedOperationException("SmtLibSolver does not support interpolation"); + } +} From 5c880b7faa48083ceb42a47f59ab7d09efed1c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 13:00:44 +0200 Subject: [PATCH 16/99] Add basic tests --- .../solver/smtlib/SmtLibExprTransformer.java | 2 +- .../theta/solver/smtlib/SmtLibSolverTest.java | 94 +++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index 884ce13a51..206f965ab0 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -371,7 +371,7 @@ private String[] transformParamDecls(final List> paramDecls) { for (final ParamDecl paramDecl : paramDecls) { final String paramSymbol = transformParamDecl(paramDecl); paramTerms[i] = paramSymbol; - env.define(DeclSymbol.of(paramDecl), paramSymbol); + env.define(DeclSymbol.of(paramDecl), paramDecl.getName()); i++; } return paramTerms; diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java new file mode 100644 index 0000000000..27894061ee --- /dev/null +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -0,0 +1,94 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.decl.ParamDecl; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolExprs; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.core.type.functype.FuncType; +import hu.bme.mit.theta.core.type.inttype.IntExprs; +import hu.bme.mit.theta.core.type.inttype.IntType; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverStatus; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.nio.file.Path; + +import static com.google.common.collect.ImmutableList.of; +import static hu.bme.mit.theta.core.decl.Decls.Const; +import static hu.bme.mit.theta.core.decl.Decls.Param; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; +import static hu.bme.mit.theta.core.type.functype.FuncExprs.App; +import static hu.bme.mit.theta.core.type.functype.FuncExprs.Func; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; +import static org.junit.Assert.assertTrue; + +public final class SmtLibSolverTest { + private static SmtLibSolverFactory solverFactory; + + @BeforeClass + public static void init() { + solverFactory = SmtLibSolverFactory.create( + Path.of("/home/vagrant/Vagrant/z3-4.8.8-x64-ubuntu-16.04/bin/z3"), + new String[] { "-in", "-smt2" } + ); + } + + @Test + public void testSimple() { + final Solver solver = solverFactory.createSolver(); + + // Create two integer constants x and y + final ConstDecl cx = Const("x", Int()); + final ConstDecl cy = Const("y", Int()); + + // Add x == y + 1 to the solver + solver.add(IntExprs.Eq(cx.getRef(), IntExprs.Add(cy.getRef(), Int(1)))); + + // Check, the expression should be satisfiable + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + // Add x < y to the solver + solver.add(IntExprs.Lt(cx.getRef(), cy.getRef())); + + // Check, the expression should be unsatisfiable + status = solver.check(); + assertTrue(status.isUnsat()); + } + + @Test + public void testTrack() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl ca = Const("a", BoolExprs.Bool()); + final Expr expr = BoolExprs.And(ca.getRef(), True()); + + solver.push(); + solver.track(expr); + + final SolverStatus status = solver.check(); + + assertTrue(status.isSat()); + + solver.pop(); + } + + @Test + public void testFunc() { + // Arrange + final Solver solver = solverFactory.createSolver(); + final ConstDecl> ca = Const("a", Func(Int(), Int())); + final Expr> a = ca.getRef(); + final ParamDecl px = Param("x", Int()); + final Expr x = px.getRef(); + + solver.add(BoolExprs.Forall(of(px), BoolExprs.Imply(IntExprs.Leq(x, Int(0)), IntExprs.Eq(App(a, x), Int(0))))); + solver.add(BoolExprs.Forall(of(px), BoolExprs.Imply(IntExprs.Geq(x, Int(1)), IntExprs.Eq(App(a, x), Int(1))))); + + // Act + final SolverStatus status = solver.check(); + assertTrue(status.isSat()); + } +} From 216dbf1aecc32f95260a35fd7668ebdcd690de5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 13:29:27 +0200 Subject: [PATCH 17/99] Implement unsat core feature in solver --- .../solver-smtlib/src/main/antlr/SMTLIBv2.g4 | 18 +++++++++ .../mit/theta/solver/smtlib/SmtLibSolver.java | 38 +++++++++++++++++-- .../smtlib/parser/GetUnsatCoreResponse.java | 26 +++++++++++++ .../smtlib/parser/SpecificResponse.java | 5 +++ .../theta/solver/smtlib/SmtLibSolverTest.java | 24 ++++++++++++ 5 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java diff --git a/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 b/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 index d745427763..fb8ccdc2f0 100644 --- a/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 +++ b/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 @@ -53,6 +53,7 @@ general_response_error specific_success_response : check_sat_response + | get_unsat_core_response ; check_sat_response @@ -61,6 +62,23 @@ check_sat_response | value=PS_Unknown ; +get_unsat_core_response + : ParOpen symbols+=symbol* ParClose + ; + +symbol + : simpleSymbol + | quotedSymbol + ; + +simpleSymbol + : UndefinedSymbol + ; + +quotedSymbol + : QuotedSymbol + ; + // Parser Rules End // Lexer Rules Start diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java index 5fa174f2a5..5f0bcacaa2 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java @@ -16,6 +16,7 @@ import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; import hu.bme.mit.theta.solver.smtlib.parser.CheckSatResponse; import hu.bme.mit.theta.solver.smtlib.parser.GeneralResponse; +import hu.bme.mit.theta.solver.smtlib.parser.GetUnsatCoreResponse; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; @@ -24,6 +25,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -106,10 +108,10 @@ public SolverStatus check() { else if(res.isSpecific()) { final CheckSatResponse checkSatResponse = res.asSpecific(); if(checkSatResponse.isSat()) { - return SolverStatus.SAT; + status = SolverStatus.SAT; } else if(checkSatResponse.isUnsat()) { - return SolverStatus.UNSAT; + status = SolverStatus.UNSAT; } else { throw new UnknownSolverStatusException(); @@ -118,6 +120,8 @@ else if(checkSatResponse.isUnsat()) { else { throw new AssertionError(); } + + return status; } @Override @@ -167,13 +171,41 @@ public Collection> getUnsatCore() { checkState(status == SolverStatus.UNSAT, "Cannot get unsat core if status is not UNSAT"); if (unsatCore == null) { - //unsatCore = extractUnsatCore(); + unsatCore = extractUnsatCore(); } assert unsatCore != null; return Collections.unmodifiableCollection(unsatCore); } + private Collection> extractUnsatCore() { + assert status == SolverStatus.UNSAT; + assert unsatCore == null; + + final Collection> unsatCore = new LinkedList<>(); + final Collection unsatCoreLabels; + + final var res = parseResponse(solverBinary.issueCommand("(get-unsat-core)")); + if(res.isError()) { + throw new SmtLibSolverException(res.getReason()); + } + else if(res.isSpecific()) { + final GetUnsatCoreResponse getUnsatCoreResponse = res.asSpecific(); + unsatCoreLabels = getUnsatCoreResponse.getLabels(); + } + else { + throw new AssertionError(); + } + + for(final var label : unsatCoreLabels) { + final Expr assumption = assumptions.get(label); + assert assumption != null; + unsatCore.add(assumption); + } + + return unsatCore; + } + @Override public Collection> getAssertions() { return assertions.toCollection(); diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java new file mode 100644 index 0000000000..fb7fde0f07 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java @@ -0,0 +1,26 @@ +package hu.bme.mit.theta.solver.smtlib.parser; + +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Get_unsat_core_responseContext; +import org.antlr.v4.runtime.RuleContext; + +import java.util.Collection; +import java.util.stream.Collectors; + +public class GetUnsatCoreResponse implements SpecificResponse { + private final Collection labels; + + private GetUnsatCoreResponse(Collection labels) { + this.labels = labels; + } + + public static GetUnsatCoreResponse fromContext(Get_unsat_core_responseContext ctx) { + return new GetUnsatCoreResponse( + ctx.symbols.stream().map(RuleContext::getText).collect(Collectors.toUnmodifiableSet()) + ); + } + + public Collection getLabels() { + return labels; + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java index 9c0b400e9d..cda90c8e48 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java @@ -11,6 +11,11 @@ static SpecificResponse fromContext(final Specific_success_responseContext ctx) public SpecificResponse visitCheck_sat_response(SMTLIBv2Parser.Check_sat_responseContext ctx) { return CheckSatResponse.fromContext(ctx); } + + @Override + public SpecificResponse visitGet_unsat_core_response(SMTLIBv2Parser.Get_unsat_core_responseContext ctx) { + return GetUnsatCoreResponse.fromContext(ctx); + } }); } } diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index 27894061ee..5887fcb6d9 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -22,6 +22,7 @@ import static hu.bme.mit.theta.core.type.functype.FuncExprs.App; import static hu.bme.mit.theta.core.type.functype.FuncExprs.Func; import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public final class SmtLibSolverTest { @@ -75,6 +76,29 @@ public void testTrack() { solver.pop(); } + @Test + public void testUnsatCore() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl x = Const("x", IntExprs.Int()); + final ConstDecl y = Const("y", IntExprs.Int()); + final Expr expr1 = IntExprs.Eq(x.getRef(), IntExprs.Int(0)); + final Expr expr2 = IntExprs.Eq(x.getRef(), IntExprs.Int(1)); + final Expr expr3 = IntExprs.Eq(y.getRef(), IntExprs.Int(1)); + + solver.track(expr1); + solver.track(expr2); + solver.track(expr3); + + final SolverStatus status = solver.check(); + assertTrue(status.isUnsat()); + + final var uc = solver.getUnsatCore(); + assertTrue(uc.contains(expr1)); + assertTrue(uc.contains(expr2)); + assertEquals(2, uc.size()); + } + @Test public void testFunc() { // Arrange From f7666037875b86ff47a6f532296d12a1c790f3f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 18:42:18 +0200 Subject: [PATCH 18/99] Replace parametric rotate operations with binary equivalent --- .../theta/solver/smtlib/SmtLibExprTransformer.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index 206f965ab0..b28bd45974 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -86,6 +86,7 @@ import hu.bme.mit.theta.core.type.rattype.RatNeqExpr; import hu.bme.mit.theta.core.type.rattype.RatPosExpr; import hu.bme.mit.theta.core.type.rattype.RatSubExpr; +import hu.bme.mit.theta.core.utils.BvUtils; import java.util.Arrays; import java.util.List; @@ -645,11 +646,19 @@ protected String transformBvLogicShiftRight(final BvLogicShiftRightExpr expr) { } protected String transformBvRotateLeft(final BvRotateLeftExpr expr) { - return String.format("((_ rotate_left %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); + final var toRotate = toTerm(expr.getLeftOp()); + final var rotateWith = toTerm(expr.getRightOp()); + final var size = toTerm(BvUtils.intToBvLitExpr(expr.getType().getSize(), expr.getType().getSize(), expr.getRightOp().getType().isSigned())); + return String.format("(bvor (bvshl %s %s) (bvashr %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); + // return String.format("((_ rotate_left %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); } protected String transformBvRotateRight(final BvRotateRightExpr expr) { - return String.format("((_ rotate_right %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); + final var toRotate = toTerm(expr.getLeftOp()); + final var rotateWith = toTerm(expr.getRightOp()); + final var size = toTerm(BvUtils.intToBvLitExpr(expr.getType().getSize(), expr.getType().getSize(), expr.getRightOp().getType().isSigned())); + return String.format("(bvor (bvashr %s %s) (bvshl %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); + // return String.format("((_ rotate_right %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); } protected String transformBvEq(final BvEqExpr expr) { From e66521f8c2ed1ed0de699bfba3872f0d46b1e9b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 22:41:20 +0200 Subject: [PATCH 19/99] Fix rotate operation --- .../hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index b28bd45974..3a1cbd6333 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -649,7 +649,7 @@ protected String transformBvRotateLeft(final BvRotateLeftExpr expr) { final var toRotate = toTerm(expr.getLeftOp()); final var rotateWith = toTerm(expr.getRightOp()); final var size = toTerm(BvUtils.intToBvLitExpr(expr.getType().getSize(), expr.getType().getSize(), expr.getRightOp().getType().isSigned())); - return String.format("(bvor (bvshl %s %s) (bvashr %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); + return String.format("(bvor (bvshl %s %s) (bvlshr %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); // return String.format("((_ rotate_left %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); } @@ -657,7 +657,7 @@ protected String transformBvRotateRight(final BvRotateRightExpr expr) { final var toRotate = toTerm(expr.getLeftOp()); final var rotateWith = toTerm(expr.getRightOp()); final var size = toTerm(BvUtils.intToBvLitExpr(expr.getType().getSize(), expr.getType().getSize(), expr.getRightOp().getType().isSigned())); - return String.format("(bvor (bvashr %s %s) (bvshl %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); + return String.format("(bvor (bvlshr %s %s) (bvshl %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); // return String.format("((_ rotate_right %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); } From edc8e1b0fc2343b457ec1b1857ad248a44b0a221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 22:42:23 +0200 Subject: [PATCH 20/99] Add model response to grammar --- .../solver-smtlib/src/main/antlr/SMTLIBv2.g4 | 260 +++++++++++++++++- .../smtlib/parser/GetUnsatCoreResponse.java | 2 +- 2 files changed, 249 insertions(+), 13 deletions(-) diff --git a/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 b/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 index fb8ccdc2f0..a8163165c6 100644 --- a/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 +++ b/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 @@ -47,13 +47,13 @@ general_response_unsupported ; general_response_error - : reason=PS_Unsupported - | ParOpen PS_Error reason=String ParClose + : ParOpen PS_Error reason=String ParClose ; specific_success_response : check_sat_response | get_unsat_core_response + | get_model_response ; check_sat_response @@ -63,32 +63,265 @@ check_sat_response ; get_unsat_core_response - : ParOpen symbols+=symbol* ParClose + : ParOpen symbol* ParClose ; -symbol - : simpleSymbol - | quotedSymbol +get_model_response + : ParOpen PS_Model? model_response* ParClose + ; + +model_response + : model_response_fun + | model_response_fun_rec + | model_response_funs_rec + ; + +model_response_fun + : ParOpen CMD_DefineFun function_def ParClose + ; + +model_response_fun_rec + : ParOpen CMD_DefineFunRec function_def ParClose + ; + +model_response_funs_rec + : ParOpen CMD_DefineFunsRec ParOpen function_dec+ ParClose ParOpen term+ ParClose ParClose ; +function_def + : symbol ParOpen sorted_var* ParClose sort term + ; + +function_dec + : ParOpen symbol ParOpen sorted_var* ParClose sort ParClose + ; + +// Parser Rules End + +// Parser Rules Start + +// Starting rule(s) + simpleSymbol - : UndefinedSymbol + : predefSymbol + | UndefinedSymbol ; quotedSymbol : QuotedSymbol ; +predefSymbol + : PS_Not + | PS_Bool + | PS_ContinuedExecution + | PS_Error + | PS_False + | PS_ImmediateExit + | PS_Incomplete + | PS_Logic + | PS_Memout + | PS_Sat + | PS_Success + | PS_Theory + | PS_True + | PS_Unknown + | PS_Unsupported + | PS_Unsat + ; + +predefKeyword + : PK_AllStatistics + | PK_AssertionStackLevels + | PK_Authors + | PK_Category + | PK_Chainable + | PK_Definition + | PK_DiagnosticOutputChannel + | PK_ErrorBehaviour + | PK_Extension + | PK_Funs + | PK_FunsDescription + | PK_GlobalDeclarations + | PK_InteractiveMode + | PK_Language + | PK_LeftAssoc + | PK_License + | PK_Named + | PK_Name + | PK_Notes + | PK_Pattern + | PK_PrintSuccess + | PK_ProduceAssertions + | PK_ProduceAssignments + | PK_ProduceModels + | PK_ProduceProofs + | PK_ProduceUnsatAssumptions + | PK_ProduceUnsatCores + | PK_RandomSeed + | PK_ReasonUnknown + | PK_RegularOutputChannel + | PK_ReproducibleResourceLimit + | PK_RightAssoc + | PK_SmtLibVersion + | PK_Sorts + | PK_SortsDescription + | PK_Source + | PK_Status + | PK_Theories + | PK_Values + | PK_Verbosity + | PK_Version + ; + +symbol + : simpleSymbol + | quotedSymbol + ; + +numeral + : Numeral + ; + +decimal + : Decimal + ; + +hexadecimal + : HexDecimal + ; + +binary + : Binary + ; + +string + : String + ; + +keyword + : predefKeyword + | Colon simpleSymbol + ; + +// S-expression + +spec_constant + : numeral + | decimal + | hexadecimal + | binary + | string + ; + + +s_expr + : spec_constant + | symbol + | keyword + | ParOpen s_expr* ParClose + ; + +// Identifiers + +index + : numeral + | symbol + ; + +identifier + : symbol + | ParOpen GRW_Underscore symbol index+ ParClose + ; + +// Attributes + +attribute_value + : spec_constant + | symbol + | ParOpen s_expr* ParClose + ; + +attribute + : keyword + | keyword attribute_value + ; + +// Sorts + +sort + : identifier + | ParOpen identifier sort+ ParClose + ; + + +// Terms and Formulas + +qual_identifier + : identifier + | ParOpen GRW_As identifier sort ParClose + ; + +var_binding + : ParOpen symbol term ParClose + ; + +sorted_var + : ParOpen symbol sort ParClose + ; + +pattern + : symbol + | ParOpen symbol symbol+ ParClose + ; + +match_case + : ParOpen pattern term ParClose + ; + +term + : spec_constant + | qual_identifier + | generic_term + | let_term + | forall_term + | exists_term + | match_term + | annotate_term + ; + +generic_term + : ParOpen qual_identifier term+ ParClose + ; + +let_term + : ParOpen GRW_Let ParOpen var_binding+ ParClose term ParClose + ; + +forall_term + : ParOpen GRW_Forall ParOpen sorted_var+ ParClose term ParClose + ; + +exists_term + : ParOpen GRW_Exists ParOpen sorted_var+ ParClose term ParClose + ; + +match_term + : ParOpen GRW_Match term ParOpen match_case+ ParClose ParClose + ; + +annotate_term + : ParOpen GRW_Exclamation term attribute+ ParClose + ; + // Parser Rules End // Lexer Rules Start - Comment : Semicolon ~[\r\n]* -> skip ; - ParOpen : '(' ; @@ -139,6 +372,9 @@ PS_Logic PS_Memout : 'memout' ; +PS_Model + : 'model' + ; PS_Sat : 'sat' ; @@ -307,12 +543,12 @@ Numeral | [1-9] Digit* ; -Binary: - BinaryDigit+ +Binary + : '#b' BinaryDigit+ ; HexDecimal - : '#x' HexDigit HexDigit HexDigit HexDigit + : '#x' HexDigit+ ; Decimal diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java index fb7fde0f07..cf704e5fb8 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java @@ -16,7 +16,7 @@ private GetUnsatCoreResponse(Collection labels) { public static GetUnsatCoreResponse fromContext(Get_unsat_core_responseContext ctx) { return new GetUnsatCoreResponse( - ctx.symbols.stream().map(RuleContext::getText).collect(Collectors.toUnmodifiableSet()) + ctx.symbol().stream().map(RuleContext::getText).collect(Collectors.toUnmodifiableSet()) ); } From 906048fa987b30051c5f4c91ffe6a5fa66199acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 22:42:59 +0200 Subject: [PATCH 21/99] Add get-model response processor --- .../smtlib/parser/GetModelResponse.java | 62 +++++++++++++++++++ .../smtlib/parser/SpecificResponse.java | 5 ++ 2 files changed, 67 insertions(+) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java new file mode 100644 index 0000000000..89e15a1c94 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java @@ -0,0 +1,62 @@ +package hu.bme.mit.theta.solver.smtlib.parser; + +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.inttype.IntExprs; +import hu.bme.mit.theta.core.type.rattype.RatExprs; +import hu.bme.mit.theta.core.utils.BvUtils; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.misc.Interval; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Collection; +import java.util.Map; +import java.util.stream.Collectors; + +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.*; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Get_model_responseContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Model_response_funContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Model_response_fun_recContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Model_response_funs_recContext; + +public class GetModelResponse implements SpecificResponse { + private final Map values; + + private GetModelResponse(final Map values) { + this.values = values; + } + + public static GetModelResponse fromContext(final Get_model_responseContext ctx) { + return new GetModelResponse(ctx.model_response().stream().map(member -> member.accept(new SMTLIBv2BaseVisitor>() { + @Override + public Tuple2 visitModel_response_fun(Model_response_funContext ctx) { + return Tuple2.of(extractString(ctx.function_def().symbol()), extractString(ctx.function_def().term())); + } + + @Override + public Tuple2 visitModel_response_fun_rec(Model_response_fun_recContext ctx) { + throw new UnsupportedOperationException(); + } + + @Override + public Tuple2 visitModel_response_funs_rec(Model_response_funs_recContext ctx) { + throw new UnsupportedOperationException(); + } + })).collect(Collectors.toUnmodifiableMap(Tuple2::get1, Tuple2::get2))); + } + + public Collection getDecls() { + return values.keySet(); + } + + public String getTerm(final String symbol) { + return values.get(symbol); + } + + private static String extractString(final ParserRuleContext ctx) { + return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex())); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java index cda90c8e48..0315811f91 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java @@ -16,6 +16,11 @@ public SpecificResponse visitCheck_sat_response(SMTLIBv2Parser.Check_sat_respons public SpecificResponse visitGet_unsat_core_response(SMTLIBv2Parser.Get_unsat_core_responseContext ctx) { return GetUnsatCoreResponse.fromContext(ctx); } + + @Override + public SpecificResponse visitGet_model_response(SMTLIBv2Parser.Get_model_responseContext ctx) { + return GetModelResponse.fromContext(ctx); + } }); } } From 677539569373cdb0fe628d2d25eaa146c3522097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 22:43:34 +0200 Subject: [PATCH 22/99] Add term transformer --- .../mit/theta/solver/smtlib/SmtLibSolver.java | 153 ++++++- .../solver/smtlib/SmtLibSolverFactory.java | 3 +- .../solver/smtlib/SmtLibTermTransformer.java | 430 ++++++++++++++++++ .../parser/ThrowExceptionErrorListener.java | 14 + 4 files changed, 595 insertions(+), 5 deletions(-) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java index 5f0bcacaa2..de7fe34f7e 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java @@ -1,9 +1,16 @@ package hu.bme.mit.theta.solver.smtlib; +import com.google.common.collect.ImmutableList; import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.decl.Decl; import hu.bme.mit.theta.core.model.Valuation; import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.LitExpr; +import hu.bme.mit.theta.core.type.Type; +import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; +import hu.bme.mit.theta.core.type.bvtype.BvType; import hu.bme.mit.theta.core.utils.ExprUtils; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; @@ -16,27 +23,35 @@ import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; import hu.bme.mit.theta.solver.smtlib.parser.CheckSatResponse; import hu.bme.mit.theta.solver.smtlib.parser.GeneralResponse; +import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; import hu.bme.mit.theta.solver.smtlib.parser.GetUnsatCoreResponse; +import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; +import static hu.bme.mit.theta.core.utils.TypeUtils.cast; public class SmtLibSolver implements Solver { private final SolverBinary solverBinary; private final SmtLibSymbolTable symbolTable; private final SmtLibTransformationManager transformationManager; + private final SmtLibTermTransformer termTransformer; private final Stack> assertions; private final Map> assumptions; @@ -52,12 +67,13 @@ public class SmtLibSolver implements Solver { public SmtLibSolver( final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, - final Path solverPath, final String[] args + final SmtLibTermTransformer termTransformer, final Path solverPath, final String[] args ) { this.solverBinary = new ContinousSolverBinary(solverPath, args); this.symbolTable = symbolTable; this.transformationManager = transformationManager; + this.termTransformer = termTransformer; assertions = new StackImpl<>(); assumptions = new HashMap<>(); @@ -159,13 +175,29 @@ public Valuation getModel() { checkState(status == SolverStatus.SAT, "Cannot get model if status is not SAT."); if (model == null) { - //model = extractModel(); + model = extractModel(); } - assert model != null; return model; } + private Valuation extractModel() { + assert status == SolverStatus.SAT; + assert model == null; + + final var res = parseResponse(solverBinary.issueCommand("(get-model)")); + if(res.isError()) { + throw new SmtLibSolverException(res.getReason()); + } + else if(res.isSpecific()) { + final GetModelResponse getModelResponse = res.asSpecific(); + return new SmtLibValuation(getModelResponse); + } + else { + throw new AssertionError(); + } + } + @Override public Collection> getUnsatCore() { checkState(status == SolverStatus.UNSAT, "Cannot get unsat core if status is not UNSAT"); @@ -174,7 +206,6 @@ public Collection> getUnsatCore() { unsatCore = extractUnsatCore(); } - assert unsatCore != null; return Collections.unmodifiableCollection(unsatCore); } @@ -235,6 +266,10 @@ private GeneralResponse parseResponse(final String response) { try { final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(response)); final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); return GeneralResponse.fromContext(parser.response()); } catch (Exception e) { @@ -242,4 +277,114 @@ private GeneralResponse parseResponse(final String response) { } } + private final class SmtLibValuation extends Valuation { + private final GetModelResponse model; + private final Map, LitExpr> constToExpr; + private volatile Collection> constDecls = null; + + public SmtLibValuation(final GetModelResponse model) { + this.model = model; + constToExpr = new HashMap<>(); + } + + @Override + public Collection> getDecls() { + Collection> result = constDecls; + if (result == null) { + result = constDeclsOf(model); + constDecls = result; + } + return result; + } + + @Override + public Optional> eval(Decl decl) { + checkNotNull(decl); + + if (!(decl instanceof ConstDecl)) { + return Optional.empty(); + } + + final ConstDecl constDecl = (ConstDecl) decl; + + LitExpr val = constToExpr.get(constDecl); + if (val == null) { + val = extractLiteral(constDecl); + if (val != null) { + constToExpr.put(constDecl, val); + } + } + + @SuppressWarnings("unchecked") final LitExpr tVal = (LitExpr) val; + return Optional.ofNullable(tVal); + } + + private LitExpr extractLiteral(final ConstDecl decl) { + final String symbol = transformationManager.toSymbol(decl); + final Type type = decl.getType(); + /*if (type instanceof FuncType) { + return extractFuncLiteral(funcDecl); + } else if (type instanceof ArrayType) { + return extractArrayLiteral(funcDecl); + } else if (type instanceof BvType) { + return extractBvConstLiteral(funcDecl, (BvType) type); + } else {*/ + //} + if(type instanceof ArrayType) { + return extractArrayLiteral(symbol, (ArrayType) type); + } + else if (type instanceof BvType) { + return extractBvConstLiteral(symbol, (BvType) type); + } + else { + return extractConstLiteral(symbol, type); + } + } + + private LitExpr extractArrayLiteral(final String symbol, final ArrayType type) { + final String term = model.getTerm(symbol); + if (term == null) { + return null; + } else { + return (LitExpr) ExprUtils.simplify(cast(termTransformer.toArrayLitExpr(term, type, model), type)); + } + } + + private LitExpr extractBvConstLiteral(final String symbol, final BvType type) { + final String term = model.getTerm(symbol); + if (term == null) { + return null; + } else { + BvLitExpr expr = (BvLitExpr) termTransformer.toExpr(term, model); + return Bv(expr.getValue(), type.isSigned()); + } + } + + private LitExpr extractConstLiteral(final String symbol, final Type type) { + final String term = model.getTerm(symbol); + if (term == null) { + return null; + } else { + return (LitExpr) ExprUtils.simplify(cast(termTransformer.toExpr(term, model), type)); + } + } + + @Override + public Map, LitExpr> toMap() { + getDecls().forEach(this::eval); + return Collections.unmodifiableMap(constToExpr); + } + + private Collection> constDeclsOf(final GetModelResponse model) { + final ImmutableList.Builder> builder = ImmutableList.builder(); + for (final var symbol : model.getDecls()) { + if (symbolTable.definesSymbol(symbol)) { + final ConstDecl constDecl = symbolTable.getConst(symbol); + builder.add(constDecl); + } + } + return builder.build(); + } + } + } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java index 741db5de34..2867a0ae05 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java @@ -23,8 +23,9 @@ public static SmtLibSolverFactory create(Path solverPath, String[] args) { public Solver createSolver() { final var symbolTable = new SmtLibSymbolTable(); final var transformationManager = new SmtLibTransformationManager(symbolTable); + final var termTransformer = new SmtLibTermTransformer(symbolTable); - return new SmtLibSolver(symbolTable, transformationManager, solverPath, args); + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverPath, args); } @Override diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java new file mode 100644 index 0000000000..1f2d7f4216 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java @@ -0,0 +1,430 @@ +package hu.bme.mit.theta.solver.smtlib; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import hu.bme.mit.theta.common.TernaryOperator; +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.core.decl.Decl; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.Type; +import hu.bme.mit.theta.core.type.abstracttype.AddExpr; +import hu.bme.mit.theta.core.type.abstracttype.DivExpr; +import hu.bme.mit.theta.core.type.abstracttype.EqExpr; +import hu.bme.mit.theta.core.type.abstracttype.GeqExpr; +import hu.bme.mit.theta.core.type.abstracttype.GtExpr; +import hu.bme.mit.theta.core.type.abstracttype.LeqExpr; +import hu.bme.mit.theta.core.type.abstracttype.LtExpr; +import hu.bme.mit.theta.core.type.abstracttype.ModExpr; +import hu.bme.mit.theta.core.type.abstracttype.MulExpr; +import hu.bme.mit.theta.core.type.abstracttype.NegExpr; +import hu.bme.mit.theta.core.type.abstracttype.RemExpr; +import hu.bme.mit.theta.core.type.abstracttype.SubExpr; +import hu.bme.mit.theta.core.type.anytype.IteExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayExprs; +import hu.bme.mit.theta.core.type.arraytype.ArrayLitExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayReadExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayType; +import hu.bme.mit.theta.core.type.arraytype.ArrayWriteExpr; +import hu.bme.mit.theta.core.type.booltype.AndExpr; +import hu.bme.mit.theta.core.type.booltype.BoolExprs; +import hu.bme.mit.theta.core.type.booltype.IffExpr; +import hu.bme.mit.theta.core.type.booltype.ImplyExpr; +import hu.bme.mit.theta.core.type.booltype.NotExpr; +import hu.bme.mit.theta.core.type.booltype.OrExpr; +import hu.bme.mit.theta.core.type.booltype.XorExpr; +import hu.bme.mit.theta.core.type.bvtype.BvAddExpr; +import hu.bme.mit.theta.core.type.bvtype.BvAndExpr; +import hu.bme.mit.theta.core.type.bvtype.BvArithShiftRightExpr; +import hu.bme.mit.theta.core.type.bvtype.BvDivExpr; +import hu.bme.mit.theta.core.type.bvtype.BvExprs; +import hu.bme.mit.theta.core.type.bvtype.BvGeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvGtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLogicShiftRightExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvModExpr; +import hu.bme.mit.theta.core.type.bvtype.BvNegExpr; +import hu.bme.mit.theta.core.type.bvtype.BvNotExpr; +import hu.bme.mit.theta.core.type.bvtype.BvOrExpr; +import hu.bme.mit.theta.core.type.bvtype.BvRemExpr; +import hu.bme.mit.theta.core.type.bvtype.BvShiftLeftExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; +import hu.bme.mit.theta.core.type.bvtype.BvType; +import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; +import hu.bme.mit.theta.core.type.inttype.IntExprs; +import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; +import hu.bme.mit.theta.core.type.rattype.RatExprs; +import hu.bme.mit.theta.core.utils.BvUtils; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; +import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; +import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.*; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.BinaryContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.DecimalContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Generic_termContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.HexadecimalContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.IndexContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.KeywordContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.NumeralContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.StringContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.SymbolContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.TermContext; + +public class SmtLibTermTransformer { + private static final String PARAM_NAME_FORMAT = "_p%d"; + + private final SmtLibSymbolTable symbolTable; + + public SmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { + this.symbolTable = symbolTable; + } + + public Expr toExpr(final String term, final GetModelResponse model) { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(term)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + + return new TermTransformer(this, model).toExpr(parser.term()); + } + + @SuppressWarnings("unchecked") + public Expr toArrayLitExpr(final String arrayLitImpl, final ArrayType type, final GetModelResponse model) { + final var arrayLitExpr = toExpr(arrayLitImpl, model); + final var entryExprsBuilder = new ImmutableList.Builder, Expr>>(); + + if(arrayLitExpr instanceof IteExpr) { + var iteExpr = (IteExpr) arrayLitExpr; + while (true) { + entryExprsBuilder.add(Tuple2.of((Expr) iteExpr.getCond().getOps().get(1), iteExpr.getThen())); + if (iteExpr.getElse() instanceof IteExpr) { + iteExpr = (IteExpr) iteExpr.getElse(); + } else { + return ArrayExprs.Array(entryExprsBuilder.build(), iteExpr.getElse(), type); + } + } + } + else { + return toExpr(arrayLitImpl, model); + } + } + + protected ImmutableMap.Builder, List, Expr>> configureFunAppTransformer( + final ImmutableMap.Builder, List, Expr>> builder + ) { + return builder; + } + + private static final class TermTransformer extends SMTLIBv2BaseVisitor> { + private final List> vars; + private final GetModelResponse model; + private static Map, List, Expr>> funAppTransformer; + + private final SmtLibTermTransformer that; + + private TermTransformer(final SmtLibTermTransformer that, final GetModelResponse model) { + this.vars = new ArrayList<>(); + this.model = model; + this.that = that; + + if(funAppTransformer == null) { + final var transformer = ImmutableMap., List, Expr>>builder() + // Generic + .put("ite", exprTernaryOperator(IteExpr::create)) + + // Abstract + .put("=", exprBinaryOperator(EqExpr::create2)) + .put("<=", exprBinaryOperator(LeqExpr::create2)) + .put("<", exprBinaryOperator(LtExpr::create2)) + .put(">=", exprBinaryOperator(GeqExpr::create2)) + .put(">", exprBinaryOperator(GtExpr::create2)) + .put("+", exprMultiaryOperator(AddExpr::create2)) + .put("-", exprMinusOperator()) + .put("*", exprMultiaryOperator(MulExpr::create2)) + .put("div", exprBinaryOperator(DivExpr::create2)) + .put("mod", exprBinaryOperator(ModExpr::create2)) + .put("rem", exprBinaryOperator(RemExpr::create2)) + + // Booleal + .put("not", exprUnaryOperator(NotExpr::create)) + .put("or", exprMultiaryOperator(OrExpr::create)) + .put("and", exprMultiaryOperator(AndExpr::create)) + .put("xor", exprBinaryOperator(XorExpr::create)) + .put("iff", exprBinaryOperator(IffExpr::create)) + .put("=>", exprBinaryOperator(ImplyExpr::create)) + + // Integer + .put("to_real", exprUnaryOperator(IntToRatExpr::create)) + + // Rational + + // Bitvector + .put("bvadd", exprMultiaryOperator(BvAddExpr::create)) + .put("bvsub", exprBinaryOperator(BvSubExpr::create)) + .put("bvneg", exprUnaryOperator(BvNegExpr::create)) + .put("bvmul", exprMultiaryOperator(BvAddExpr::create)) + .put("bvudiv", exprBinaryOperator(BvDivExpr::create)) + .put("bvsdiv", exprBinaryOperator(BvDivExpr::create)) + .put("bvsmod", exprBinaryOperator(BvModExpr::create)) + .put("bvsrem", exprBinaryOperator(BvRemExpr::create)) + .put("bvurem", exprBinaryOperator(BvRemExpr::create)) + .put("bvand", exprMultiaryOperator(BvAndExpr::create)) + .put("bvor", exprMultiaryOperator(BvOrExpr::create)) + .put("bvxor", exprMultiaryOperator(BvXorExpr::create)) + .put("bvnot", exprUnaryOperator(BvNotExpr::create)) + .put("bvshl", exprBinaryOperator(BvShiftLeftExpr::create)) + .put("bvashr", exprBinaryOperator(BvArithShiftRightExpr::create)) + .put("bvlshr", exprBinaryOperator(BvLogicShiftRightExpr::create)) + .put("bvult", exprBinaryOperator(BvLtExpr::create)) + .put("bvslt", exprBinaryOperator(BvLtExpr::create)) + .put("bvule", exprBinaryOperator(BvLeqExpr::create)) + .put("bvsle", exprBinaryOperator(BvLeqExpr::create)) + .put("bvugt", exprBinaryOperator(BvGtExpr::create)) + .put("bvsgt", exprBinaryOperator(BvGtExpr::create)) + .put("bvuge", exprBinaryOperator(BvGeqExpr::create)) + .put("bvsge", exprBinaryOperator(BvGeqExpr::create)) + + // Array + .put("select", exprBinaryOperator(ArrayReadExpr::create)) + .put("store", exprTernaryOperator(ArrayWriteExpr::create)); + + funAppTransformer = that.configureFunAppTransformer(transformer).build(); + } + } + + public Expr toExpr(final TermContext ctx) { + return visitTerm(ctx); + } + + @Override + public Expr visitGeneric_term(Generic_termContext ctx) { + final var funName = ctx.qual_identifier().identifier().symbol().getText(); + + final var funParams = ctx.qual_identifier().identifier().index(); + final var funAppParams = ctx.term(); + + if (funName.equals("const")) { // as const construct + final var type = new SortTransformer().visitSort(ctx.qual_identifier().sort()); + final var expr = this.visitTerm(ctx.term().get(0)); + if (type instanceof ArrayType) { + return createArrayLitExpr(expr, (ArrayType) type); + } + else { + throw new UnsupportedOperationException(); + } + } else if (funAppTransformer.containsKey(funName)) { // known function application + return funAppTransformer.get(funName).apply(funParams, funAppParams); + } else { // custom function application + throw new UnsupportedOperationException(); + /*final Expr funcExpr; + if (symbolTable.definesSymbol(operation)) { + funcExpr = symbolTable.getConst(operation).getRef(); + } else { + funcExpr = toFuncLitExpr(funcDecl, model, vars); + } + return transformFuncApp(funcExpr, term.getArgs(), model, vars);*/ + } + } + + @SuppressWarnings("unchecked") + private Expr createArrayLitExpr(final Expr elze, final ArrayType type) { + return ArrayExprs.Array(Collections.emptyList(), (Expr) elze, type); + } + + // identifier + + @Override + public Expr visitIdentifier(IdentifierContext ctx) { + if(ctx.symbol().getText().equals("(as-array)")) { + final var name = ctx.index().get(0).getText(); + return that.toExpr(model.getTerm(name), model); + } + else { + return super.visitIdentifier(ctx); + } + } + + @Override + public Expr visitQual_identifier(Qual_identifierContext ctx) { + if(ctx.identifier().symbol().getText().equals("const")) { + + } + return super.visitQual_identifier(ctx); + } + + // symbol + + @Override + public Expr visitSymbol(SymbolContext ctx) { + final var value = ctx.getText(); + switch (value) { + case "true": + return BoolExprs.True(); + case "false": + return BoolExprs.False(); + default: + throw new UnsupportedOperationException(); + } + } + + // spec_constant + + @Override + public Expr visitNumeral(NumeralContext ctx) { + return IntExprs.Int(Integer.parseInt(ctx.getText())); + } + + @Override + public Expr visitDecimal(DecimalContext ctx) { + final var decimal = new BigDecimal(ctx.getText()); + if(decimal.scale() <= 0) { + return RatExprs.Rat(decimal.unscaledValue().intValue(), BigInteger.ONE.intValue()); + } + else { + return RatExprs.Rat(decimal.unscaledValue().intValue(), BigInteger.TEN.pow(decimal.scale()).intValue()); + } + } + + @Override + public Expr visitHexadecimal(HexadecimalContext ctx) { + final var numStr = ctx.getText().substring(2); + final var num = new BigInteger(numStr, 16); + return BvUtils.bigIntegerToBvLitExpr(num, numStr.length() * 4, false); + } + + @Override + public Expr visitBinary(BinaryContext ctx) { + final var numStr = ctx.getText().substring(2); + final var num = new BigInteger(numStr, 2); + return BvUtils.bigIntegerToBvLitExpr(num, numStr.length(), false); + } + + @Override + public Expr visitString(StringContext ctx) { + throw new UnsupportedOperationException(); + } + + @Override + public Expr visitKeyword(KeywordContext ctx) { + return super.visitKeyword(ctx); + } + + //// + + private BiFunction, List, Expr> exprNullaryOperator( + final Supplier> function + ) { + return (params, ops) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 0); + return function.get(); + }; + } + + private BiFunction, List, Expr> exprUnaryOperator( + final UnaryOperator> function + ) { + return (params, ops) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 1); + final Expr op = visitTerm(ops.get(0)); + return function.apply(op); + }; + } + + private BiFunction, List, Expr> exprBinaryOperator( + final BinaryOperator> function + ) { + return (params, ops) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 2); + final Expr op1 = visitTerm(ops.get(0)); + final Expr op2 = visitTerm(ops.get(1)); + return function.apply(op1, op2); + }; + } + + private BiFunction, List, Expr> exprMinusOperator() { + return (params, ops) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 1 || ops.size() == 2); + if(ops.size() == 2) { + final Expr op1 = visitTerm(ops.get(0)); + final Expr op2 = visitTerm(ops.get(1)); + return SubExpr.create2(op1, op2); + } + else { + final Expr op = visitTerm(ops.get(0)); + return NegExpr.create2(op); + } + }; + } + + private BiFunction, List, Expr> exprTernaryOperator( + final TernaryOperator> function + ) { + return (params, ops) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 3); + final Expr op1 = visitTerm(ops.get(0)); + final Expr op2 = visitTerm(ops.get(1)); + final Expr op3 = visitTerm(ops.get(2)); + return function.apply(op1, op2, op3); + }; + } + + private BiFunction, List, Expr> exprMultiaryOperator( + final Function>, Expr> function + ) { + return (params, ops) -> { + checkArgument(params.size() == 0); + return function.apply(ops.stream().map(this::visitTerm).collect(Collectors.toUnmodifiableList())); + }; + } + } + + private static final class SortTransformer extends SMTLIBv2BaseVisitor { + @Override + public Type visitSort(SortContext ctx) { + final var name = ctx.identifier().symbol().getText(); + switch(name) { + case "Bool": + return BoolExprs.Bool(); + case "Int": + return IntExprs.Int(); + case "Real": + return RatExprs.Rat(); + case "BitVec": + return BvExprs.BvType(Integer.parseInt(ctx.identifier().index().get(0).getText()), false); + case "Array": + return ArrayExprs.Array(this.visitSort(ctx.sort().get(0)), this.visitSort(ctx.sort().get(1))); + default: + throw new UnsupportedOperationException(); + } + } + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java new file mode 100644 index 0000000000..9f69d4c8d7 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java @@ -0,0 +1,14 @@ +package hu.bme.mit.theta.solver.smtlib.parser; + +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverException; +import org.antlr.v4.runtime.ANTLRErrorListener; +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; + +public class ThrowExceptionErrorListener extends BaseErrorListener implements ANTLRErrorListener { + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { + throw new SmtLibSolverException(String.format("Invalid Expression: %s", msg), e); + } +} \ No newline at end of file From 37a1236d5fc8c9f869b459e1d81289e37c67fcc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 22:43:48 +0200 Subject: [PATCH 23/99] Add tests --- .../solver/smtlib/SmtLibSolverBVTest.java | 74 ++++ .../theta/solver/smtlib/SmtLibSolverTest.java | 343 ++++++++++++++++++ 2 files changed, 417 insertions(+) create mode 100644 subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java new file mode 100644 index 0000000000..1e5783dea6 --- /dev/null +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java @@ -0,0 +1,74 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.abstracttype.EqExpr; +import hu.bme.mit.theta.core.utils.BvTestUtils; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverStatus; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class SmtLibSolverBVTest { + @Parameterized.Parameter(0) + public Class exprType; + + @Parameterized.Parameter(1) + public Expr expected; + + @Parameterized.Parameter(2) + public Expr actual; + + @Parameters(name = "expr: {0}, expected: {1}, actual: {2}") + public static Collection operations() { + return Stream.concat( + BvTestUtils.BasicOperations().stream(), + Stream.concat( + BvTestUtils.BitvectorOperations().stream(), + BvTestUtils.RelationalOperations().stream() + ) + ).collect(Collectors.toUnmodifiableList()); + } + + @Test + public void testOperationEquals() { + // Sanity check + assertNotNull(exprType); + assertNotNull(expected); + assertNotNull(actual); + + // Type checks + assertTrue( + "The type of actual is " + actual.getClass().getName() + " instead of " + exprType.getName(), + exprType.isInstance(actual) + ); + assertEquals( + "The type of expected (" + expected.getType() + ") must match the type of actual (" + actual.getType() + ")", + expected.getType(), + actual.getType() + ); + + // Equality check + final Solver solver = SmtLibSolverFactory.create( + Path.of("/home/vagrant/Vagrant/z3-4.8.8-x64-ubuntu-16.04/bin/z3"), + new String[] { "-in", "-smt2" } + ).createSolver(); + solver.push(); + + solver.add(EqExpr.create2(expected, actual)); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + } +} diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index 5887fcb6d9..c1febf9079 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -2,9 +2,18 @@ import hu.bme.mit.theta.core.decl.ConstDecl; import hu.bme.mit.theta.core.decl.ParamDecl; +import hu.bme.mit.theta.core.model.ImmutableValuation; +import hu.bme.mit.theta.core.model.Valuation; import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.LitExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayExprs; +import hu.bme.mit.theta.core.type.arraytype.ArrayLitExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.booltype.BoolExprs; import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.core.type.bvtype.BvExprs; +import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; +import hu.bme.mit.theta.core.type.bvtype.BvType; import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.type.inttype.IntExprs; import hu.bme.mit.theta.core.type.inttype.IntType; @@ -14,15 +23,23 @@ import org.junit.Test; import java.nio.file.Path; +import java.util.List; +import java.util.Optional; import static com.google.common.collect.ImmutableList.of; import static hu.bme.mit.theta.core.decl.Decls.Const; import static hu.bme.mit.theta.core.decl.Decls.Param; +import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; +import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Read; +import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Write; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; +import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; import static hu.bme.mit.theta.core.type.functype.FuncExprs.App; import static hu.bme.mit.theta.core.type.functype.FuncExprs.Func; import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; +import static hu.bme.mit.theta.core.utils.BvUtils.uint16ToBvLitExpr; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; public final class SmtLibSolverTest { @@ -99,6 +116,34 @@ public void testUnsatCore() { assertEquals(2, uc.size()); } + @Test + public void testModel() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl x = Const("x", IntExprs.Int()); + final ConstDecl y = Const("y", IntExprs.Int()); + final ConstDecl z = Const("z", IntExprs.Int()); + final ConstDecl u = Const("u", BoolExprs.Bool()); + final Expr expr1 = IntExprs.Eq(x.getRef(), IntExprs.Int(2)); + final Expr expr2 = IntExprs.Eq(y.getRef(), IntExprs.Int(3)); + final Expr expr3 = IntExprs.Eq(z.getRef(), IntExprs.Add(x.getRef(), y.getRef())); + final Expr expr4 = BoolExprs.Iff(u.getRef(), BoolExprs.True()); + + solver.track(expr1); + solver.track(expr2); + solver.track(expr3); + solver.track(expr4); + + final SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + final var model = solver.getModel(); + assertEquals(IntExprs.Int(2), model.eval(x).orElseThrow()); + assertEquals(IntExprs.Int(3), model.eval(y).orElseThrow()); + assertEquals(IntExprs.Int(5), model.eval(z).orElseThrow()); + assertEquals(BoolExprs.Bool(true), model.eval(u).orElseThrow()); + } + @Test public void testFunc() { // Arrange @@ -115,4 +160,302 @@ public void testFunc() { final SolverStatus status = solver.check(); assertTrue(status.isSat()); } + + @Test + public void testArray() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl> arr = Const("arr", Array(Int(), Int())); + + solver.add(ArrayExprs.Eq(Write(arr.getRef(), Int(0), Int(1)), arr.getRef())); + solver.add(ArrayExprs.Eq(Write(arr.getRef(), Int(1), Int(2)), arr.getRef())); + + // Check, the expression should be satisfiable + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation valuation = solver.getModel(); + final Optional>> optVal = valuation.eval(arr); + final Expr> val = optVal.get(); + assertTrue(val instanceof ArrayLitExpr); + var valLit = (ArrayLitExpr)val; + assertEquals(2, valLit.getElements().size()); + assertEquals(Int(1), Read(valLit, Int(0)).eval(ImmutableValuation.empty())); + assertEquals(Int(2), Read(valLit, Int(1)).eval(ImmutableValuation.empty())); + } + + @Test + public void testBV1() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); + + solver.push(); + + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[]{false, false, true, false}, true))); + solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[]{false, false, true, false}, true))); + solver.add(BvExprs.Eq(cx.getRef(), cy.getRef())); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + solver.pop(); + } + + @Test + public void testBV2() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); + final ConstDecl cz = Const("z", BvExprs.BvType(4, true)); + + solver.push(); + + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[]{false, false, false, false}, true))); + solver.add(BvExprs.Neq(cx.getRef(), cz.getRef())); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation model = solver.getModel(); + assertNotNull(model); + assertNotNull(model.toMap()); + + solver.pop(); + } + + @Test + public void testBV3() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); + + solver.push(); + + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, false, false}, true))); + solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Add(List.of(cx.getRef(), Bv(new boolean[] {false, false, false, true}, true))))); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation model = solver.getModel(); + assertNotNull(model); + assertNotNull(model.toMap()); + + solver.pop(); + } + + @Test + public void testBV4() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); + + solver.push(); + + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, true, false}, true))); + solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Sub(cx.getRef(), Bv(new boolean[] {false, false, false, true}, true)))); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation model = solver.getModel(); + assertNotNull(model); + assertNotNull(model.toMap()); + + solver.pop(); + } + + @Test + public void testBV5() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); + + solver.push(); + + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, true, false}, true))); + solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Neg(cx.getRef()))); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation model = solver.getModel(); + assertNotNull(model); + assertNotNull(model.toMap()); + + solver.pop(); + } + + @Test + public void testBV6() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); + + solver.push(); + + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, true, false}, true))); + solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Mul(List.of(cx.getRef(), Bv(new boolean[] {false, false, true, false}, true))))); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation model = solver.getModel(); + assertNotNull(model); + assertNotNull(model.toMap()); + + solver.pop(); + } + + @Test + public void testBV7() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + + solver.push(); + + solver.add(BvExprs.Lt(cx.getRef(), Bv(new boolean[] {true, true, true, true}, true))); + solver.add(BvExprs.Lt(cy.getRef(), Bv(new boolean[] {true, true, true, true}, false))); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation model = solver.getModel(); + assertNotNull(model); + assertNotNull(model.toMap()); + + solver.pop(); + } + + @Test + public void testBV8() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, false)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + + solver.push(); + + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {true, false, true, false}, false))); + solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Mod(cx.getRef(), Bv(new boolean[] {false, true, false, false}, false)))); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation model = solver.getModel(); + assertNotNull(model); + assertNotNull(model.toMap()); + + solver.pop(); + } + + @Test + public void testBV9() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, false)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + + solver.push(); + + solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}, false))); + solver.add(BvExprs.Eq(BvExprs.Or(List.of(cx.getRef(), cy.getRef())), Bv(new boolean[] {true, true, false, false}, false))); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation model = solver.getModel(); + assertNotNull(model); + assertNotNull(model.toMap()); + + solver.pop(); + } + + @Test + public void testBV10() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, false)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + + solver.push(); + + solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}, false))); + solver.add(BvExprs.Eq(BvExprs.And(List.of(cx.getRef(), cy.getRef())), Bv(new boolean[] {false, true, false, false}, false))); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation model = solver.getModel(); + assertNotNull(model); + assertNotNull(model.toMap()); + + solver.pop(); + } + + @Test + public void testBV11() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, false)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + + solver.push(); + + solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}, false))); + solver.add(BvExprs.Eq(BvExprs.Xor(List.of(cx.getRef(), cy.getRef())), Bv(new boolean[] {false, true, false, false}, false))); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation model = solver.getModel(); + assertNotNull(model); + assertNotNull(model.toMap()); + + solver.pop(); + } + + @Test + public void testBV12() { + final Solver solver = solverFactory.createSolver(); + + final ConstDecl cx = Const("x", BvExprs.BvType(4, false)); + final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + + solver.push(); + + solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}, false))); + solver.add(BvExprs.Eq(BvExprs.ArithShiftRight(cy.getRef(), Bv(new boolean[] {false, false, false, true}, false)), cx.getRef())); + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + + Valuation model = solver.getModel(); + assertNotNull(model); + assertNotNull(model.toMap()); + + solver.pop(); + } + + public void testBV13() { + final Solver solver = solverFactory.createSolver(); + solver.push(); + + solver.add(BvExprs.Eq(uint16ToBvLitExpr(4), BvExprs.Add(List.of(uint16ToBvLitExpr(1), uint16ToBvLitExpr(3))))); + solver.add(BvExprs.Eq(uint16ToBvLitExpr(1), BvExprs.Sub(uint16ToBvLitExpr(4), uint16ToBvLitExpr(3)))); + solver.add(BvExprs.Eq(uint16ToBvLitExpr(12), BvExprs.Mul(List.of(uint16ToBvLitExpr(3), uint16ToBvLitExpr(4))))); + solver.add(BvExprs.Eq(uint16ToBvLitExpr(4), BvExprs.Div(uint16ToBvLitExpr(12), uint16ToBvLitExpr(3)))); + solver.add(BvExprs.Eq(uint16ToBvLitExpr(1), BvExprs.Mod(uint16ToBvLitExpr(13), uint16ToBvLitExpr(3)))); + solver.add(BvExprs.Eq(uint16ToBvLitExpr(1), BvExprs.Rem(uint16ToBvLitExpr(13), uint16ToBvLitExpr(3)))); + + } } From 1a75b6ebf10624fce24459edd2de545a11a3147d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 28 Aug 2020 22:51:11 +0200 Subject: [PATCH 24/99] Update SmtLib solver to handle BigInteger backend of IntLitExpr and RatLitExpr --- .../solver/smtlib/SmtLibExprTransformer.java | 2 +- .../solver/smtlib/SmtLibTermTransformer.java | 22 +++++-------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index 3a1cbd6333..14e2749758 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -456,7 +456,7 @@ protected String transformRatLt(final RatLtExpr expr) { */ protected String transformIntLit(final IntLitExpr expr) { - return Integer.toString(expr.getValue()); + return expr.getValue().toString(); } protected String transformIntAdd(final IntAddExpr expr) { diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java index 1f2d7f4216..4a23d23b80 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java @@ -21,7 +21,6 @@ import hu.bme.mit.theta.core.type.abstracttype.SubExpr; import hu.bme.mit.theta.core.type.anytype.IteExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayExprs; -import hu.bme.mit.theta.core.type.arraytype.ArrayLitExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayReadExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.arraytype.ArrayWriteExpr; @@ -49,7 +48,6 @@ import hu.bme.mit.theta.core.type.bvtype.BvRemExpr; import hu.bme.mit.theta.core.type.bvtype.BvShiftLeftExpr; import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; -import hu.bme.mit.theta.core.type.bvtype.BvType; import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; import hu.bme.mit.theta.core.type.inttype.IntExprs; import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; @@ -77,17 +75,15 @@ import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; -import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; -import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.*; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.BinaryContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.DecimalContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Generic_termContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.HexadecimalContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.IdentifierContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.IndexContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.KeywordContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.NumeralContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.SortContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.StringContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.SymbolContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.TermContext; @@ -268,14 +264,6 @@ public Expr visitIdentifier(IdentifierContext ctx) { } } - @Override - public Expr visitQual_identifier(Qual_identifierContext ctx) { - if(ctx.identifier().symbol().getText().equals("const")) { - - } - return super.visitQual_identifier(ctx); - } - // symbol @Override @@ -295,17 +283,17 @@ public Expr visitSymbol(SymbolContext ctx) { @Override public Expr visitNumeral(NumeralContext ctx) { - return IntExprs.Int(Integer.parseInt(ctx.getText())); + return IntExprs.Int(ctx.getText()); } @Override public Expr visitDecimal(DecimalContext ctx) { final var decimal = new BigDecimal(ctx.getText()); if(decimal.scale() <= 0) { - return RatExprs.Rat(decimal.unscaledValue().intValue(), BigInteger.ONE.intValue()); + return RatExprs.Rat(decimal.unscaledValue(), BigInteger.ONE); } else { - return RatExprs.Rat(decimal.unscaledValue().intValue(), BigInteger.TEN.pow(decimal.scale()).intValue()); + return RatExprs.Rat(decimal.unscaledValue(), BigInteger.TEN.pow(decimal.scale())); } } From 9ba886b561e139c67a4171e8d010fa16745215dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 29 Aug 2020 16:40:32 +0200 Subject: [PATCH 25/99] Implement quantifier term comversion --- .../solver/smtlib/SmtLibTermTransformer.java | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java index 4a23d23b80..a5446f1312 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java @@ -1,10 +1,14 @@ package hu.bme.mit.theta.solver.smtlib; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import hu.bme.mit.theta.common.TernaryOperator; import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.core.decl.Decl; +import hu.bme.mit.theta.core.decl.Decls; +import hu.bme.mit.theta.core.decl.ParamDecl; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.Type; import hu.bme.mit.theta.core.type.abstracttype.AddExpr; @@ -26,6 +30,7 @@ import hu.bme.mit.theta.core.type.arraytype.ArrayWriteExpr; import hu.bme.mit.theta.core.type.booltype.AndExpr; import hu.bme.mit.theta.core.type.booltype.BoolExprs; +import hu.bme.mit.theta.core.type.booltype.BoolType; import hu.bme.mit.theta.core.type.booltype.IffExpr; import hu.bme.mit.theta.core.type.booltype.ImplyExpr; import hu.bme.mit.theta.core.type.booltype.NotExpr; @@ -53,6 +58,7 @@ import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; import hu.bme.mit.theta.core.type.rattype.RatExprs; import hu.bme.mit.theta.core.utils.BvUtils; +import hu.bme.mit.theta.core.utils.TypeUtils; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; @@ -75,6 +81,9 @@ import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Exists; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Forall; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.BinaryContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.DecimalContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Generic_termContext; @@ -136,14 +145,14 @@ protected ImmutableMap.Builder, List> { - private final List> vars; + private final BiMap, String> vars; private final GetModelResponse model; private static Map, List, Expr>> funAppTransformer; private final SmtLibTermTransformer that; private TermTransformer(final SmtLibTermTransformer that, final GetModelResponse model) { - this.vars = new ArrayList<>(); + this.vars = HashBiMap.create(); this.model = model; this.that = that; @@ -251,11 +260,35 @@ private Expr createArrayLitExpr(final Expr) elze, type); } + @Override + public Expr visitForall_term(SMTLIBv2Parser.Forall_termContext ctx) { + final var paramDecls = ctx.sorted_var().stream() + .map(sv -> Decls.Param(sv.symbol().getText(), new SortTransformer().visitSort(sv.sort()))) + .collect(Collectors.toUnmodifiableList()); + + pushParams(paramDecls); + final Expr op = TypeUtils.cast(visitTerm(ctx.term()), Bool()); + popParams(paramDecls); + return Forall(paramDecls, op); + } + + @Override + public Expr visitExists_term(SMTLIBv2Parser.Exists_termContext ctx) { + final var paramDecls = ctx.sorted_var().stream() + .map(sv -> Decls.Param(sv.symbol().getText(), new SortTransformer().visitSort(sv.sort()))) + .collect(Collectors.toUnmodifiableList()); + + pushParams(paramDecls); + final Expr op = TypeUtils.cast(visitTerm(ctx.term()), Bool()); + popParams(paramDecls); + return Exists(paramDecls, op); + } + // identifier @Override public Expr visitIdentifier(IdentifierContext ctx) { - if(ctx.symbol().getText().equals("(as-array)")) { + if(ctx.symbol().getText().equals("as-array")) { final var name = ctx.index().get(0).getText(); return that.toExpr(model.getTerm(name), model); } @@ -323,6 +356,18 @@ public Expr visitKeyword(KeywordContext ctx) { //// + private void pushParams(final List> paramDecls) { + vars.putAll(paramDecls.stream().collect(Collectors.toUnmodifiableMap(Function.identity(), Decl::getName))); + } + + private void popParams(final List> paramDecls) { + for (final var paramDecl : paramDecls) { + vars.remove(paramDecl, paramDecl.getName()); + } + } + + //// + private BiFunction, List, Expr> exprNullaryOperator( final Supplier> function ) { From 6e22b73ae780b8fa34a7b336df20358e37e497df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 29 Aug 2020 17:15:07 +0200 Subject: [PATCH 26/99] Refactor LitExpr creation --- .../mit/theta/solver/smtlib/SmtLibSolver.java | 7 ++-- .../solver/smtlib/SmtLibTermTransformer.java | 38 ++++++++++++++++--- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java index de7fe34f7e..63d3a079ec 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java @@ -346,7 +346,7 @@ private LitExpr extractArrayLiteral(final String symbol, final ArrayType) ExprUtils.simplify(cast(termTransformer.toArrayLitExpr(term, type, model), type)); + return termTransformer.toArrayLitExpr(term, type, model); } } @@ -355,8 +355,7 @@ private LitExpr extractBvConstLiteral(final String symbol, final BvType type) if (term == null) { return null; } else { - BvLitExpr expr = (BvLitExpr) termTransformer.toExpr(term, model); - return Bv(expr.getValue(), type.isSigned()); + return termTransformer.toBvLitExpr(term, type, model); } } @@ -365,7 +364,7 @@ private LitExpr extractConstLiteral(final String symbol, final Type type) { if (term == null) { return null; } else { - return (LitExpr) ExprUtils.simplify(cast(termTransformer.toExpr(term, model), type)); + return termTransformer.toLitExpr(term, type, model); } } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java index a5446f1312..d91f2e2a58 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java @@ -10,6 +10,7 @@ import hu.bme.mit.theta.core.decl.Decls; import hu.bme.mit.theta.core.decl.ParamDecl; import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.LitExpr; import hu.bme.mit.theta.core.type.Type; import hu.bme.mit.theta.core.type.abstracttype.AddExpr; import hu.bme.mit.theta.core.type.abstracttype.DivExpr; @@ -44,6 +45,7 @@ import hu.bme.mit.theta.core.type.bvtype.BvGeqExpr; import hu.bme.mit.theta.core.type.bvtype.BvGtExpr; import hu.bme.mit.theta.core.type.bvtype.BvLeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; import hu.bme.mit.theta.core.type.bvtype.BvLogicShiftRightExpr; import hu.bme.mit.theta.core.type.bvtype.BvLtExpr; import hu.bme.mit.theta.core.type.bvtype.BvModExpr; @@ -53,11 +55,13 @@ import hu.bme.mit.theta.core.type.bvtype.BvRemExpr; import hu.bme.mit.theta.core.type.bvtype.BvShiftLeftExpr; import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; +import hu.bme.mit.theta.core.type.bvtype.BvType; import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; import hu.bme.mit.theta.core.type.inttype.IntExprs; import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; import hu.bme.mit.theta.core.type.rattype.RatExprs; import hu.bme.mit.theta.core.utils.BvUtils; +import hu.bme.mit.theta.core.utils.ExprUtils; import hu.bme.mit.theta.core.utils.TypeUtils; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; @@ -84,6 +88,8 @@ import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Exists; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Forall; +import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; +import static hu.bme.mit.theta.core.utils.TypeUtils.cast; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.BinaryContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.DecimalContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Generic_termContext; @@ -117,12 +123,23 @@ public Expr toExpr(final String term, final GetModelResponse model) { return new TermTransformer(this, model).toExpr(parser.term()); } + public LitExpr toLitExpr(final String litImpl, final T type, final GetModelResponse model) { + final var litExpr = toExpr(litImpl, model); + + if(litExpr instanceof LitExpr) { + return (LitExpr) cast(litExpr, type); + } + else { + return (LitExpr) cast(ExprUtils.simplify(litExpr), type); + } + } + @SuppressWarnings("unchecked") - public Expr toArrayLitExpr(final String arrayLitImpl, final ArrayType type, final GetModelResponse model) { + public LitExpr> toArrayLitExpr(final String arrayLitImpl, final ArrayType type, final GetModelResponse model) { final var arrayLitExpr = toExpr(arrayLitImpl, model); - final var entryExprsBuilder = new ImmutableList.Builder, Expr>>(); if(arrayLitExpr instanceof IteExpr) { + final var entryExprsBuilder = new ImmutableList.Builder, Expr>>(); var iteExpr = (IteExpr) arrayLitExpr; while (true) { entryExprsBuilder.add(Tuple2.of((Expr) iteExpr.getCond().getOps().get(1), iteExpr.getThen())); @@ -134,7 +151,18 @@ public Expr toArrayLitExpr(final String arr } } else { - return toExpr(arrayLitImpl, model); + return (LitExpr>) cast(ExprUtils.simplify(arrayLitExpr), type); + } + } + + public LitExpr toBvLitExpr(final String bvLitImpl, final BvType type, final GetModelResponse model) { + final var bvLitExpr = toExpr(bvLitImpl, model); + + if(bvLitExpr instanceof BvLitExpr) { + return Bv(((BvLitExpr) bvLitExpr).getValue(), type.isSigned()); + } + else { + return (LitExpr) cast(ExprUtils.simplify(bvLitExpr), type); } } @@ -267,7 +295,7 @@ public Expr visitForall_term(SMTLIBv2Parser.Forall_termContext ctx) { .collect(Collectors.toUnmodifiableList()); pushParams(paramDecls); - final Expr op = TypeUtils.cast(visitTerm(ctx.term()), Bool()); + final Expr op = cast(visitTerm(ctx.term()), Bool()); popParams(paramDecls); return Forall(paramDecls, op); } @@ -279,7 +307,7 @@ public Expr visitExists_term(SMTLIBv2Parser.Exists_termContext ctx) { .collect(Collectors.toUnmodifiableList()); pushParams(paramDecls); - final Expr op = TypeUtils.cast(visitTerm(ctx.term()), Bool()); + final Expr op = cast(visitTerm(ctx.term()), Bool()); popParams(paramDecls); return Exists(paramDecls, op); } From 6895dde24e80912a85fe1e3d0306571ff180a7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 29 Aug 2020 18:48:06 +0200 Subject: [PATCH 27/99] Remove ANTLR visitor dependency from SmtLibTermTransformer --- .../hu/bme/mit/theta/common/QuadFunction.java | 16 + .../solver/smtlib/SmtLibTermTransformer.java | 588 +++++++++--------- 2 files changed, 314 insertions(+), 290 deletions(-) create mode 100644 subprojects/common/src/main/java/hu/bme/mit/theta/common/QuadFunction.java diff --git a/subprojects/common/src/main/java/hu/bme/mit/theta/common/QuadFunction.java b/subprojects/common/src/main/java/hu/bme/mit/theta/common/QuadFunction.java new file mode 100644 index 0000000000..416b77bb74 --- /dev/null +++ b/subprojects/common/src/main/java/hu/bme/mit/theta/common/QuadFunction.java @@ -0,0 +1,16 @@ +package hu.bme.mit.theta.common; + +import java.util.function.Function; + +import static com.google.common.base.Preconditions.checkNotNull; + +@FunctionalInterface +public interface QuadFunction { + + R apply(T t, U u, V v, W w); + + default QuadFunction andThen(final Function after) { + checkNotNull(after); + return (final T t, final U u, final V v, final W w) -> after.apply(apply(t, u, v, w)); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java index d91f2e2a58..a72c7e1ff5 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java @@ -3,7 +3,7 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; +import hu.bme.mit.theta.common.QuadFunction; import hu.bme.mit.theta.common.TernaryOperator; import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.core.decl.Decl; @@ -62,8 +62,6 @@ import hu.bme.mit.theta.core.type.rattype.RatExprs; import hu.bme.mit.theta.core.utils.BvUtils; import hu.bme.mit.theta.core.utils.ExprUtils; -import hu.bme.mit.theta.core.utils.TypeUtils; -import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; @@ -73,11 +71,10 @@ import java.math.BigDecimal; import java.math.BigInteger; -import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.function.BiFunction; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; @@ -92,26 +89,91 @@ import static hu.bme.mit.theta.core.utils.TypeUtils.cast; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.BinaryContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.DecimalContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Exists_termContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Forall_termContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Generic_termContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.HexadecimalContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.IdentifierContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.IndexContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.KeywordContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.NumeralContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Qual_identifierContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.SortContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.StringContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Spec_constantContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.SymbolContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.TermContext; public class SmtLibTermTransformer { - private static final String PARAM_NAME_FORMAT = "_p%d"; + protected static final String PARAM_NAME_FORMAT = "_p%d"; - private final SmtLibSymbolTable symbolTable; + protected final SmtLibSymbolTable symbolTable; + protected final Map, List, GetModelResponse, BiMap, String>, Expr>> funAppTransformer; public SmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { this.symbolTable = symbolTable; + this.funAppTransformer = new HashMap<>(); + + // Generic + this.funAppTransformer.put("ite", exprTernaryOperator(IteExpr::create)); + + // Abstract + this.funAppTransformer.put("=", exprBinaryOperator(EqExpr::create2)); + this.funAppTransformer.put("<=", exprBinaryOperator(LeqExpr::create2)); + this.funAppTransformer.put("<", exprBinaryOperator(LtExpr::create2)); + this.funAppTransformer.put(">=", exprBinaryOperator(GeqExpr::create2)); + this.funAppTransformer.put(">", exprBinaryOperator(GtExpr::create2)); + this.funAppTransformer.put("+", exprMultiaryOperator(AddExpr::create2)); + this.funAppTransformer.put("-", exprMinusOperator()); + this.funAppTransformer.put("*", exprMultiaryOperator(MulExpr::create2)); + this.funAppTransformer.put("div", exprBinaryOperator(DivExpr::create2)); + this.funAppTransformer.put("mod", exprBinaryOperator(ModExpr::create2)); + this.funAppTransformer.put("rem", exprBinaryOperator(RemExpr::create2)); + + // Booleal + this.funAppTransformer.put("not", exprUnaryOperator(NotExpr::create)); + this.funAppTransformer.put("or", exprMultiaryOperator(OrExpr::create)); + this.funAppTransformer.put("and", exprMultiaryOperator(AndExpr::create)); + this.funAppTransformer.put("xor", exprBinaryOperator(XorExpr::create)); + this.funAppTransformer.put("iff", exprBinaryOperator(IffExpr::create)); + this.funAppTransformer.put("=>", exprBinaryOperator(ImplyExpr::create)); + + // Integer + this.funAppTransformer.put("to_real", exprUnaryOperator(IntToRatExpr::create)); + + // Rational + + // Bitvector + this.funAppTransformer.put("bvadd", exprMultiaryOperator(BvAddExpr::create)); + this.funAppTransformer.put("bvsub", exprBinaryOperator(BvSubExpr::create)); + this.funAppTransformer.put("bvneg", exprUnaryOperator(BvNegExpr::create)); + this.funAppTransformer.put("bvmul", exprMultiaryOperator(BvAddExpr::create)); + this.funAppTransformer.put("bvudiv", exprBinaryOperator(BvDivExpr::create)); + this.funAppTransformer.put("bvsdiv", exprBinaryOperator(BvDivExpr::create)); + this.funAppTransformer.put("bvsmod", exprBinaryOperator(BvModExpr::create)); + this.funAppTransformer.put("bvsrem", exprBinaryOperator(BvRemExpr::create)); + this.funAppTransformer.put("bvurem", exprBinaryOperator(BvRemExpr::create)); + this.funAppTransformer.put("bvand", exprMultiaryOperator(BvAndExpr::create)); + this.funAppTransformer.put("bvor", exprMultiaryOperator(BvOrExpr::create)); + this.funAppTransformer.put("bvxor", exprMultiaryOperator(BvXorExpr::create)); + this.funAppTransformer.put("bvnot", exprUnaryOperator(BvNotExpr::create)); + this.funAppTransformer.put("bvshl", exprBinaryOperator(BvShiftLeftExpr::create)); + this.funAppTransformer.put("bvashr", exprBinaryOperator(BvArithShiftRightExpr::create)); + this.funAppTransformer.put("bvlshr", exprBinaryOperator(BvLogicShiftRightExpr::create)); + this.funAppTransformer.put("bvult", exprBinaryOperator(BvLtExpr::create)); + this.funAppTransformer.put("bvslt", exprBinaryOperator(BvLtExpr::create)); + this.funAppTransformer.put("bvule", exprBinaryOperator(BvLeqExpr::create)); + this.funAppTransformer.put("bvsle", exprBinaryOperator(BvLeqExpr::create)); + this.funAppTransformer.put("bvugt", exprBinaryOperator(BvGtExpr::create)); + this.funAppTransformer.put("bvsgt", exprBinaryOperator(BvGtExpr::create)); + this.funAppTransformer.put("bvuge", exprBinaryOperator(BvGeqExpr::create)); + this.funAppTransformer.put("bvsge", exprBinaryOperator(BvGeqExpr::create)); + + // Array + this.funAppTransformer.put("select", exprBinaryOperator(ArrayReadExpr::create)); + this.funAppTransformer.put("store", exprTernaryOperator(ArrayWriteExpr::create)); } + /* Public interface */ + public Expr toExpr(final String term, final GetModelResponse model) { final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(term)); final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); @@ -120,7 +182,7 @@ public Expr toExpr(final String term, final GetModelResponse model) { parser.removeErrorListeners(); parser.addErrorListener(new ThrowExceptionErrorListener()); - return new TermTransformer(this, model).toExpr(parser.term()); + return transformTerm(parser.term(), model, HashBiMap.create()); } public LitExpr toLitExpr(final String litImpl, final T type, final GetModelResponse model) { @@ -166,326 +228,272 @@ public LitExpr toBvLitExpr(final String bvLitImpl, final BvType type, fi } } - protected ImmutableMap.Builder, List, Expr>> configureFunAppTransformer( - final ImmutableMap.Builder, List, Expr>> builder - ) { - return builder; - } + /* End of public interface */ - private static final class TermTransformer extends SMTLIBv2BaseVisitor> { - private final BiMap, String> vars; - private final GetModelResponse model; - private static Map, List, Expr>> funAppTransformer; - - private final SmtLibTermTransformer that; - - private TermTransformer(final SmtLibTermTransformer that, final GetModelResponse model) { - this.vars = HashBiMap.create(); - this.model = model; - this.that = that; - - if(funAppTransformer == null) { - final var transformer = ImmutableMap., List, Expr>>builder() - // Generic - .put("ite", exprTernaryOperator(IteExpr::create)) - - // Abstract - .put("=", exprBinaryOperator(EqExpr::create2)) - .put("<=", exprBinaryOperator(LeqExpr::create2)) - .put("<", exprBinaryOperator(LtExpr::create2)) - .put(">=", exprBinaryOperator(GeqExpr::create2)) - .put(">", exprBinaryOperator(GtExpr::create2)) - .put("+", exprMultiaryOperator(AddExpr::create2)) - .put("-", exprMinusOperator()) - .put("*", exprMultiaryOperator(MulExpr::create2)) - .put("div", exprBinaryOperator(DivExpr::create2)) - .put("mod", exprBinaryOperator(ModExpr::create2)) - .put("rem", exprBinaryOperator(RemExpr::create2)) - - // Booleal - .put("not", exprUnaryOperator(NotExpr::create)) - .put("or", exprMultiaryOperator(OrExpr::create)) - .put("and", exprMultiaryOperator(AndExpr::create)) - .put("xor", exprBinaryOperator(XorExpr::create)) - .put("iff", exprBinaryOperator(IffExpr::create)) - .put("=>", exprBinaryOperator(ImplyExpr::create)) - - // Integer - .put("to_real", exprUnaryOperator(IntToRatExpr::create)) - - // Rational - - // Bitvector - .put("bvadd", exprMultiaryOperator(BvAddExpr::create)) - .put("bvsub", exprBinaryOperator(BvSubExpr::create)) - .put("bvneg", exprUnaryOperator(BvNegExpr::create)) - .put("bvmul", exprMultiaryOperator(BvAddExpr::create)) - .put("bvudiv", exprBinaryOperator(BvDivExpr::create)) - .put("bvsdiv", exprBinaryOperator(BvDivExpr::create)) - .put("bvsmod", exprBinaryOperator(BvModExpr::create)) - .put("bvsrem", exprBinaryOperator(BvRemExpr::create)) - .put("bvurem", exprBinaryOperator(BvRemExpr::create)) - .put("bvand", exprMultiaryOperator(BvAndExpr::create)) - .put("bvor", exprMultiaryOperator(BvOrExpr::create)) - .put("bvxor", exprMultiaryOperator(BvXorExpr::create)) - .put("bvnot", exprUnaryOperator(BvNotExpr::create)) - .put("bvshl", exprBinaryOperator(BvShiftLeftExpr::create)) - .put("bvashr", exprBinaryOperator(BvArithShiftRightExpr::create)) - .put("bvlshr", exprBinaryOperator(BvLogicShiftRightExpr::create)) - .put("bvult", exprBinaryOperator(BvLtExpr::create)) - .put("bvslt", exprBinaryOperator(BvLtExpr::create)) - .put("bvule", exprBinaryOperator(BvLeqExpr::create)) - .put("bvsle", exprBinaryOperator(BvLeqExpr::create)) - .put("bvugt", exprBinaryOperator(BvGtExpr::create)) - .put("bvsgt", exprBinaryOperator(BvGtExpr::create)) - .put("bvuge", exprBinaryOperator(BvGeqExpr::create)) - .put("bvsge", exprBinaryOperator(BvGeqExpr::create)) - - // Array - .put("select", exprBinaryOperator(ArrayReadExpr::create)) - .put("store", exprTernaryOperator(ArrayWriteExpr::create)); - - funAppTransformer = that.configureFunAppTransformer(transformer).build(); - } - } + /* Visitor implementation */ - public Expr toExpr(final TermContext ctx) { - return visitTerm(ctx); + protected Expr transformTerm(final TermContext ctx, final GetModelResponse model, final BiMap, String> vars) { + if(ctx.spec_constant() != null) { + return transformSpecConstant(ctx.spec_constant(), model, vars); } - - @Override - public Expr visitGeneric_term(Generic_termContext ctx) { - final var funName = ctx.qual_identifier().identifier().symbol().getText(); - - final var funParams = ctx.qual_identifier().identifier().index(); - final var funAppParams = ctx.term(); - - if (funName.equals("const")) { // as const construct - final var type = new SortTransformer().visitSort(ctx.qual_identifier().sort()); - final var expr = this.visitTerm(ctx.term().get(0)); - if (type instanceof ArrayType) { - return createArrayLitExpr(expr, (ArrayType) type); - } - else { - throw new UnsupportedOperationException(); - } - } else if (funAppTransformer.containsKey(funName)) { // known function application - return funAppTransformer.get(funName).apply(funParams, funAppParams); - } else { // custom function application - throw new UnsupportedOperationException(); - /*final Expr funcExpr; - if (symbolTable.definesSymbol(operation)) { - funcExpr = symbolTable.getConst(operation).getRef(); - } else { - funcExpr = toFuncLitExpr(funcDecl, model, vars); - } - return transformFuncApp(funcExpr, term.getArgs(), model, vars);*/ - } + else if(ctx.qual_identifier() != null) { + return transformQualIdentifier(ctx.qual_identifier(), model, vars); } - - @SuppressWarnings("unchecked") - private Expr createArrayLitExpr(final Expr elze, final ArrayType type) { - return ArrayExprs.Array(Collections.emptyList(), (Expr) elze, type); + else if(ctx.generic_term() != null) { + return transformGenericTerm(ctx.generic_term(), model, vars); } + else if(ctx.let_term() != null) { + throw new UnsupportedOperationException(); + } + else if(ctx.forall_term() != null) { + return transformForallTerm(ctx.forall_term(), model, vars); + } + else if(ctx.exists_term() != null) { + return transformExistsTerm(ctx.exists_term(), model, vars); + } + else if(ctx.match_term() != null) { + throw new UnsupportedOperationException(); + } + else if(ctx.annotate_term() != null) { + throw new UnsupportedOperationException(); + } + else { + throw new SmtLibSolverException("Invalid input"); + } + } - @Override - public Expr visitForall_term(SMTLIBv2Parser.Forall_termContext ctx) { - final var paramDecls = ctx.sorted_var().stream() - .map(sv -> Decls.Param(sv.symbol().getText(), new SortTransformer().visitSort(sv.sort()))) - .collect(Collectors.toUnmodifiableList()); - - pushParams(paramDecls); - final Expr op = cast(visitTerm(ctx.term()), Bool()); - popParams(paramDecls); - return Forall(paramDecls, op); + protected Expr transformSpecConstant(final Spec_constantContext ctx, final GetModelResponse model, final BiMap, String> vars) { + if(ctx.numeral() != null) { + return transformNumeral(ctx.numeral(), model, vars); + } + else if(ctx.decimal() != null) { + return transformDecimal(ctx.decimal(), model, vars); + } + else if(ctx.hexadecimal() != null) { + return transformHexadecimal(ctx.hexadecimal(), model, vars); + } + else if(ctx.binary() != null) { + return transformBinary(ctx.binary(), model, vars); } + else if(ctx.string() != null) { + throw new UnsupportedOperationException(); + } + else { + throw new SmtLibSolverException("Invalid input"); + } + } - @Override - public Expr visitExists_term(SMTLIBv2Parser.Exists_termContext ctx) { - final var paramDecls = ctx.sorted_var().stream() - .map(sv -> Decls.Param(sv.symbol().getText(), new SortTransformer().visitSort(sv.sort()))) - .collect(Collectors.toUnmodifiableList()); + protected Expr transformQualIdentifier(final Qual_identifierContext ctx, final GetModelResponse model, final BiMap, String> vars) { + return transformIdentifier(ctx.identifier(), model, vars); + } - pushParams(paramDecls); - final Expr op = cast(visitTerm(ctx.term()), Bool()); - popParams(paramDecls); - return Exists(paramDecls, op); - } + protected Expr transformGenericTerm(final Generic_termContext ctx, final GetModelResponse model, final BiMap, String> vars) { + final var funName = ctx.qual_identifier().identifier().symbol().getText(); - // identifier + final var funParams = ctx.qual_identifier().identifier().index(); + final var funAppParams = ctx.term(); - @Override - public Expr visitIdentifier(IdentifierContext ctx) { - if(ctx.symbol().getText().equals("as-array")) { - final var name = ctx.index().get(0).getText(); - return that.toExpr(model.getTerm(name), model); + if (funName.equals("const")) { // as const construct + final var type = transformSort(ctx.qual_identifier().sort()); + final var expr = transformTerm(ctx.term().get(0), model, vars); + if (type instanceof ArrayType) { + return createArrayLitExpr(expr, (ArrayType) type); } else { - return super.visitIdentifier(ctx); + throw new UnsupportedOperationException(); } - } - - // symbol - - @Override - public Expr visitSymbol(SymbolContext ctx) { - final var value = ctx.getText(); - switch (value) { - case "true": - return BoolExprs.True(); - case "false": - return BoolExprs.False(); - default: - throw new UnsupportedOperationException(); + } else if (funAppTransformer.containsKey(funName)) { // known function application + return funAppTransformer.get(funName).apply(funParams, funAppParams, model, vars); + } else { // custom function application + throw new UnsupportedOperationException(); + /*final Expr funcExpr; + if (symbolTable.definesSymbol(operation)) { + funcExpr = symbolTable.getConst(operation).getRef(); + } else { + funcExpr = toFuncLitExpr(funcDecl, model, vars); } + return transformFuncApp(funcExpr, term.getArgs(), model, vars);*/ } + } - // spec_constant + @SuppressWarnings("unchecked") + private Expr createArrayLitExpr(final Expr elze, final ArrayType type) { + return ArrayExprs.Array(Collections.emptyList(), (Expr) elze, type); + } - @Override - public Expr visitNumeral(NumeralContext ctx) { - return IntExprs.Int(ctx.getText()); - } + protected Expr transformForallTerm(final Forall_termContext ctx, final GetModelResponse model, final BiMap, String> vars) { + final var paramDecls = ctx.sorted_var().stream() + .map(sv -> Decls.Param(sv.symbol().getText(), transformSort(sv.sort()))) + .collect(Collectors.toUnmodifiableList()); - @Override - public Expr visitDecimal(DecimalContext ctx) { - final var decimal = new BigDecimal(ctx.getText()); - if(decimal.scale() <= 0) { - return RatExprs.Rat(decimal.unscaledValue(), BigInteger.ONE); - } - else { - return RatExprs.Rat(decimal.unscaledValue(), BigInteger.TEN.pow(decimal.scale())); - } - } + pushParams(paramDecls, vars); + final Expr op = cast(transformTerm(ctx.term(), model, vars), Bool()); + popParams(paramDecls, vars); + return Forall(paramDecls, op); + } - @Override - public Expr visitHexadecimal(HexadecimalContext ctx) { - final var numStr = ctx.getText().substring(2); - final var num = new BigInteger(numStr, 16); - return BvUtils.bigIntegerToBvLitExpr(num, numStr.length() * 4, false); - } + protected Expr transformExistsTerm(final Exists_termContext ctx, final GetModelResponse model, final BiMap, String> vars) { + final var paramDecls = ctx.sorted_var().stream() + .map(sv -> Decls.Param(sv.symbol().getText(), transformSort(sv.sort()))) + .collect(Collectors.toUnmodifiableList()); - @Override - public Expr visitBinary(BinaryContext ctx) { - final var numStr = ctx.getText().substring(2); - final var num = new BigInteger(numStr, 2); - return BvUtils.bigIntegerToBvLitExpr(num, numStr.length(), false); - } + pushParams(paramDecls, vars); + final Expr op = cast(transformTerm(ctx.term(), model, vars), Bool()); + popParams(paramDecls, vars); + return Exists(paramDecls, op); + } - @Override - public Expr visitString(StringContext ctx) { - throw new UnsupportedOperationException(); + protected Expr transformIdentifier(final IdentifierContext ctx, final GetModelResponse model, final BiMap, String> vars) { + if(ctx.symbol().getText().equals("as-array")) { + final var name = ctx.index().get(0).getText(); + return toExpr(model.getTerm(name), model); } + else { + return transformSymbol(ctx.symbol(), model, vars); + } + } - @Override - public Expr visitKeyword(KeywordContext ctx) { - return super.visitKeyword(ctx); + protected Expr transformSymbol(final SymbolContext ctx, final GetModelResponse model, final BiMap, String> vars) { + final var value = ctx.getText(); + switch (value) { + case "true": + return BoolExprs.True(); + case "false": + return BoolExprs.False(); + default: + throw new UnsupportedOperationException(); } + } - //// + protected Expr transformNumeral(final NumeralContext ctx, final GetModelResponse model, final BiMap, String> vars) { + return IntExprs.Int(ctx.getText()); + } - private void pushParams(final List> paramDecls) { - vars.putAll(paramDecls.stream().collect(Collectors.toUnmodifiableMap(Function.identity(), Decl::getName))); + protected Expr transformDecimal(final DecimalContext ctx, final GetModelResponse model, final BiMap, String> vars) { + final var decimal = new BigDecimal(ctx.getText()); + if(decimal.scale() <= 0) { + return RatExprs.Rat(decimal.unscaledValue(), BigInteger.ONE); } - - private void popParams(final List> paramDecls) { - for (final var paramDecl : paramDecls) { - vars.remove(paramDecl, paramDecl.getName()); - } + else { + return RatExprs.Rat(decimal.unscaledValue(), BigInteger.TEN.pow(decimal.scale())); } + } - //// + protected Expr transformHexadecimal(final HexadecimalContext ctx, final GetModelResponse model, final BiMap, String> vars) { + final var numStr = ctx.getText().substring(2); + final var num = new BigInteger(numStr, 16); + return BvUtils.bigIntegerToBvLitExpr(num, numStr.length() * 4, false); + } - private BiFunction, List, Expr> exprNullaryOperator( - final Supplier> function - ) { - return (params, ops) -> { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 0); - return function.get(); - }; - } + protected Expr transformBinary(final BinaryContext ctx, final GetModelResponse model, final BiMap, String> vars) { + final var numStr = ctx.getText().substring(2); + final var num = new BigInteger(numStr, 2); + return BvUtils.bigIntegerToBvLitExpr(num, numStr.length(), false); + } - private BiFunction, List, Expr> exprUnaryOperator( - final UnaryOperator> function - ) { - return (params, ops) -> { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 1); - final Expr op = visitTerm(ops.get(0)); - return function.apply(op); - }; + protected Type transformSort(SortContext ctx) { + final var name = ctx.identifier().symbol().getText(); + switch(name) { + case "Bool": + return BoolExprs.Bool(); + case "Int": + return IntExprs.Int(); + case "Real": + return RatExprs.Rat(); + case "BitVec": + return BvExprs.BvType(Integer.parseInt(ctx.identifier().index().get(0).getText()), false); + case "Array": + return ArrayExprs.Array(transformSort(ctx.sort().get(0)), transformSort(ctx.sort().get(1))); + default: + throw new UnsupportedOperationException(); } + } - private BiFunction, List, Expr> exprBinaryOperator( - final BinaryOperator> function - ) { - return (params, ops) -> { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 2); - final Expr op1 = visitTerm(ops.get(0)); - final Expr op2 = visitTerm(ops.get(1)); - return function.apply(op1, op2); - }; - } + /* End of visitor implementation */ - private BiFunction, List, Expr> exprMinusOperator() { - return (params, ops) -> { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 1 || ops.size() == 2); - if(ops.size() == 2) { - final Expr op1 = visitTerm(ops.get(0)); - final Expr op2 = visitTerm(ops.get(1)); - return SubExpr.create2(op1, op2); - } - else { - final Expr op = visitTerm(ops.get(0)); - return NegExpr.create2(op); - } - }; - } + /* Variable scope handling */ - private BiFunction, List, Expr> exprTernaryOperator( - final TernaryOperator> function - ) { - return (params, ops) -> { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 3); - final Expr op1 = visitTerm(ops.get(0)); - final Expr op2 = visitTerm(ops.get(1)); - final Expr op3 = visitTerm(ops.get(2)); - return function.apply(op1, op2, op3); - }; - } + protected void pushParams(final List> paramDecls, BiMap, String> vars) { + vars.putAll(paramDecls.stream().collect(Collectors.toUnmodifiableMap(Function.identity(), Decl::getName))); + } - private BiFunction, List, Expr> exprMultiaryOperator( - final Function>, Expr> function - ) { - return (params, ops) -> { - checkArgument(params.size() == 0); - return function.apply(ops.stream().map(this::visitTerm).collect(Collectors.toUnmodifiableList())); - }; + protected void popParams(final List> paramDecls, BiMap, String> vars) { + for (final var paramDecl : paramDecls) { + vars.remove(paramDecl, paramDecl.getName()); } } - private static final class SortTransformer extends SMTLIBv2BaseVisitor { - @Override - public Type visitSort(SortContext ctx) { - final var name = ctx.identifier().symbol().getText(); - switch(name) { - case "Bool": - return BoolExprs.Bool(); - case "Int": - return IntExprs.Int(); - case "Real": - return RatExprs.Rat(); - case "BitVec": - return BvExprs.BvType(Integer.parseInt(ctx.identifier().index().get(0).getText()), false); - case "Array": - return ArrayExprs.Array(this.visitSort(ctx.sort().get(0)), this.visitSort(ctx.sort().get(1))); - default: - throw new UnsupportedOperationException(); + /* Utilities */ + + private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprNullaryOperator( + final Supplier> function + ) { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 0); + return function.get(); + }; + } + + private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprUnaryOperator( + final UnaryOperator> function + ) { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 1); + final Expr op = transformTerm(ops.get(0), model, vars); + return function.apply(op); + }; + } + + private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprBinaryOperator( + final BinaryOperator> function + ) { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 2); + final Expr op1 = transformTerm(ops.get(0), model, vars); + final Expr op2 = transformTerm(ops.get(1), model, vars); + return function.apply(op1, op2); + }; + } + + private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprMinusOperator() { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 1 || ops.size() == 2); + if(ops.size() == 2) { + final Expr op1 = transformTerm(ops.get(0), model, vars); + final Expr op2 = transformTerm(ops.get(1), model, vars); + return SubExpr.create2(op1, op2); } - } + else { + final Expr op = transformTerm(ops.get(0), model, vars); + return NegExpr.create2(op); + } + }; } + + private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprTernaryOperator( + final TernaryOperator> function + ) { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 3); + final Expr op1 = transformTerm(ops.get(0), model, vars); + final Expr op2 = transformTerm(ops.get(1), model, vars); + final Expr op3 = transformTerm(ops.get(2), model, vars); + return function.apply(op1, op2, op3); + }; + } + + private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprMultiaryOperator( + final Function>, Expr> function + ) { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 0); + return function.apply(ops.stream().map(op -> transformTerm(op, model, vars)).collect(Collectors.toUnmodifiableList())); + }; + } + } From cbadf6376179650f9c0a7f32cbe8f4147091acae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 30 Aug 2020 00:57:01 +0200 Subject: [PATCH 28/99] Add quantifier parameter type deduction support to SmtLibTermTransformer --- .../bme/mit/theta/common/QuintFunction.java | 16 + .../solver/smtlib/SmtLibTermTransformer.java | 646 +++++++++++++----- 2 files changed, 501 insertions(+), 161 deletions(-) create mode 100644 subprojects/common/src/main/java/hu/bme/mit/theta/common/QuintFunction.java diff --git a/subprojects/common/src/main/java/hu/bme/mit/theta/common/QuintFunction.java b/subprojects/common/src/main/java/hu/bme/mit/theta/common/QuintFunction.java new file mode 100644 index 0000000000..548b9fc3e3 --- /dev/null +++ b/subprojects/common/src/main/java/hu/bme/mit/theta/common/QuintFunction.java @@ -0,0 +1,16 @@ +package hu.bme.mit.theta.common; + +import java.util.function.Function; + +import static com.google.common.base.Preconditions.checkNotNull; + +@FunctionalInterface +public interface QuintFunction { + + R apply(T t, U u, V v, W w, X x); + + default QuintFunction andThen(final Function after) { + checkNotNull(after); + return (final T t, final U u, final V v, final W w, final X x) -> after.apply(apply(t, u, v, w, x)); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java index a72c7e1ff5..43184cc0b8 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java @@ -3,7 +3,8 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableList; -import hu.bme.mit.theta.common.QuadFunction; +import hu.bme.mit.theta.common.DispatchTable2; +import hu.bme.mit.theta.common.QuintFunction; import hu.bme.mit.theta.common.TernaryOperator; import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.core.decl.Decl; @@ -14,6 +15,7 @@ import hu.bme.mit.theta.core.type.Type; import hu.bme.mit.theta.core.type.abstracttype.AddExpr; import hu.bme.mit.theta.core.type.abstracttype.DivExpr; +import hu.bme.mit.theta.core.type.abstracttype.Divisible; import hu.bme.mit.theta.core.type.abstracttype.EqExpr; import hu.bme.mit.theta.core.type.abstracttype.GeqExpr; import hu.bme.mit.theta.core.type.abstracttype.GtExpr; @@ -21,11 +23,11 @@ import hu.bme.mit.theta.core.type.abstracttype.LtExpr; import hu.bme.mit.theta.core.type.abstracttype.ModExpr; import hu.bme.mit.theta.core.type.abstracttype.MulExpr; +import hu.bme.mit.theta.core.type.abstracttype.Multiplicative; import hu.bme.mit.theta.core.type.abstracttype.NegExpr; import hu.bme.mit.theta.core.type.abstracttype.RemExpr; import hu.bme.mit.theta.core.type.abstracttype.SubExpr; import hu.bme.mit.theta.core.type.anytype.IteExpr; -import hu.bme.mit.theta.core.type.arraytype.ArrayExprs; import hu.bme.mit.theta.core.type.arraytype.ArrayReadExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.arraytype.ArrayWriteExpr; @@ -57,9 +59,7 @@ import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; import hu.bme.mit.theta.core.type.bvtype.BvType; import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; -import hu.bme.mit.theta.core.type.inttype.IntExprs; import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; -import hu.bme.mit.theta.core.type.rattype.RatExprs; import hu.bme.mit.theta.core.utils.BvUtils; import hu.bme.mit.theta.core.utils.ExprUtils; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; @@ -71,21 +71,29 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.function.UnaryOperator; import java.util.stream.Collectors; +import java.util.stream.IntStream; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Exists; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Forall; import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; +import static hu.bme.mit.theta.core.type.rattype.RatExprs.Rat; import static hu.bme.mit.theta.core.utils.TypeUtils.cast; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.BinaryContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.DecimalContext; @@ -106,75 +114,79 @@ public class SmtLibTermTransformer { protected static final String PARAM_NAME_FORMAT = "_p%d"; protected final SmtLibSymbolTable symbolTable; - protected final Map, List, GetModelResponse, BiMap, String>, Expr>> funAppTransformer; + protected final Map funAppTransformer; + protected final DispatchTable2> typingCorrector; public SmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { this.symbolTable = symbolTable; - this.funAppTransformer = new HashMap<>(); - - // Generic - this.funAppTransformer.put("ite", exprTernaryOperator(IteExpr::create)); - - // Abstract - this.funAppTransformer.put("=", exprBinaryOperator(EqExpr::create2)); - this.funAppTransformer.put("<=", exprBinaryOperator(LeqExpr::create2)); - this.funAppTransformer.put("<", exprBinaryOperator(LtExpr::create2)); - this.funAppTransformer.put(">=", exprBinaryOperator(GeqExpr::create2)); - this.funAppTransformer.put(">", exprBinaryOperator(GtExpr::create2)); - this.funAppTransformer.put("+", exprMultiaryOperator(AddExpr::create2)); - this.funAppTransformer.put("-", exprMinusOperator()); - this.funAppTransformer.put("*", exprMultiaryOperator(MulExpr::create2)); - this.funAppTransformer.put("div", exprBinaryOperator(DivExpr::create2)); - this.funAppTransformer.put("mod", exprBinaryOperator(ModExpr::create2)); - this.funAppTransformer.put("rem", exprBinaryOperator(RemExpr::create2)); - - // Booleal - this.funAppTransformer.put("not", exprUnaryOperator(NotExpr::create)); - this.funAppTransformer.put("or", exprMultiaryOperator(OrExpr::create)); - this.funAppTransformer.put("and", exprMultiaryOperator(AndExpr::create)); - this.funAppTransformer.put("xor", exprBinaryOperator(XorExpr::create)); - this.funAppTransformer.put("iff", exprBinaryOperator(IffExpr::create)); - this.funAppTransformer.put("=>", exprBinaryOperator(ImplyExpr::create)); - - // Integer - this.funAppTransformer.put("to_real", exprUnaryOperator(IntToRatExpr::create)); - - // Rational - - // Bitvector - this.funAppTransformer.put("bvadd", exprMultiaryOperator(BvAddExpr::create)); - this.funAppTransformer.put("bvsub", exprBinaryOperator(BvSubExpr::create)); - this.funAppTransformer.put("bvneg", exprUnaryOperator(BvNegExpr::create)); - this.funAppTransformer.put("bvmul", exprMultiaryOperator(BvAddExpr::create)); - this.funAppTransformer.put("bvudiv", exprBinaryOperator(BvDivExpr::create)); - this.funAppTransformer.put("bvsdiv", exprBinaryOperator(BvDivExpr::create)); - this.funAppTransformer.put("bvsmod", exprBinaryOperator(BvModExpr::create)); - this.funAppTransformer.put("bvsrem", exprBinaryOperator(BvRemExpr::create)); - this.funAppTransformer.put("bvurem", exprBinaryOperator(BvRemExpr::create)); - this.funAppTransformer.put("bvand", exprMultiaryOperator(BvAndExpr::create)); - this.funAppTransformer.put("bvor", exprMultiaryOperator(BvOrExpr::create)); - this.funAppTransformer.put("bvxor", exprMultiaryOperator(BvXorExpr::create)); - this.funAppTransformer.put("bvnot", exprUnaryOperator(BvNotExpr::create)); - this.funAppTransformer.put("bvshl", exprBinaryOperator(BvShiftLeftExpr::create)); - this.funAppTransformer.put("bvashr", exprBinaryOperator(BvArithShiftRightExpr::create)); - this.funAppTransformer.put("bvlshr", exprBinaryOperator(BvLogicShiftRightExpr::create)); - this.funAppTransformer.put("bvult", exprBinaryOperator(BvLtExpr::create)); - this.funAppTransformer.put("bvslt", exprBinaryOperator(BvLtExpr::create)); - this.funAppTransformer.put("bvule", exprBinaryOperator(BvLeqExpr::create)); - this.funAppTransformer.put("bvsle", exprBinaryOperator(BvLeqExpr::create)); - this.funAppTransformer.put("bvugt", exprBinaryOperator(BvGtExpr::create)); - this.funAppTransformer.put("bvsgt", exprBinaryOperator(BvGtExpr::create)); - this.funAppTransformer.put("bvuge", exprBinaryOperator(BvGeqExpr::create)); - this.funAppTransformer.put("bvsge", exprBinaryOperator(BvGeqExpr::create)); - - // Array - this.funAppTransformer.put("select", exprBinaryOperator(ArrayReadExpr::create)); - this.funAppTransformer.put("store", exprTernaryOperator(ArrayWriteExpr::create)); + this.funAppTransformer = new HashMap<>() {{ + // Generic + put("ite", exprIteOperator()); + + // Abstract + put("=", exprRelationalOperator(EqExpr::create2)); + put("<=", exprRelationalOperator(LeqExpr::create2)); + put("<", exprRelationalOperator(LtExpr::create2)); + put(">=", exprRelationalOperator(GeqExpr::create2)); + put(">", exprRelationalOperator(GtExpr::create2)); + put("+", exprMultiaryOperator(AddExpr::create2)); + put("-", exprMinusOperator()); + put("*", exprMultiaryOperator(MulExpr::create2)); + put("div", exprBinaryOperator(DivExpr::create2)); + put("mod", exprBinaryOperator(ModExpr::create2)); + put("rem", exprBinaryOperator(RemExpr::create2)); + + // Booleal + put("not", exprUnaryOperator(NotExpr::create)); + put("or", exprMultiaryOperator(OrExpr::create)); + put("and", exprMultiaryOperator(AndExpr::create)); + put("xor", exprBinaryOperator(XorExpr::create)); + put("iff", exprBinaryOperator(IffExpr::create)); + put("=>", exprBinaryOperator(ImplyExpr::create)); + + // Integer + put("to_real", exprUnaryOperator(IntToRatExpr::create)); + + // Rational + + // Bitvector + put("bvadd", exprMultiaryOperator(BvAddExpr::create)); + put("bvsub", exprBinaryOperator(BvSubExpr::create)); + put("bvneg", exprUnaryOperator(BvNegExpr::create)); + put("bvmul", exprMultiaryOperator(BvAddExpr::create)); + put("bvudiv", exprBinaryOperator(BvDivExpr::create)); + put("bvsdiv", exprBinaryOperator(BvDivExpr::create)); + put("bvsmod", exprBinaryOperator(BvModExpr::create)); + put("bvsrem", exprBinaryOperator(BvRemExpr::create)); + put("bvurem", exprBinaryOperator(BvRemExpr::create)); + put("bvand", exprMultiaryOperator(BvAndExpr::create)); + put("bvor", exprMultiaryOperator(BvOrExpr::create)); + put("bvxor", exprMultiaryOperator(BvXorExpr::create)); + put("bvnot", exprUnaryOperator(BvNotExpr::create)); + put("bvshl", exprBinaryOperator(BvShiftLeftExpr::create)); + put("bvashr", exprBinaryOperator(BvArithShiftRightExpr::create)); + put("bvlshr", exprBinaryOperator(BvLogicShiftRightExpr::create)); + put("bvult", exprBinaryOperator(BvLtExpr::create)); + put("bvslt", exprBinaryOperator(BvLtExpr::create)); + put("bvule", exprBinaryOperator(BvLeqExpr::create)); + put("bvsle", exprBinaryOperator(BvLeqExpr::create)); + put("bvugt", exprBinaryOperator(BvGtExpr::create)); + put("bvsgt", exprBinaryOperator(BvGtExpr::create)); + put("bvuge", exprBinaryOperator(BvGeqExpr::create)); + put("bvsge", exprBinaryOperator(BvGeqExpr::create)); + + // Array + put("select", exprArrayReadOperator()); + put("store", exprArrayWriteOperator()); + }}; + + this.typingCorrector = DispatchTable2.>builder() + .build(); } /* Public interface */ - public Expr toExpr(final String term, final GetModelResponse model) { + public Expr toExpr(final String term, final Type type, final GetModelResponse model) { final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(term)); final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); lexer.removeErrorListeners(); @@ -182,11 +194,11 @@ public Expr toExpr(final String term, final GetModelResponse model) { parser.removeErrorListeners(); parser.addErrorListener(new ThrowExceptionErrorListener()); - return transformTerm(parser.term(), model, HashBiMap.create()); + return cast(transformTerm(parser.term(), type, model, HashBiMap.create()), type); } public LitExpr toLitExpr(final String litImpl, final T type, final GetModelResponse model) { - final var litExpr = toExpr(litImpl, model); + final var litExpr = toExpr(litImpl, type, model); if(litExpr instanceof LitExpr) { return (LitExpr) cast(litExpr, type); @@ -198,7 +210,7 @@ public LitExpr toLitExpr(final String litImpl, final T type, @SuppressWarnings("unchecked") public LitExpr> toArrayLitExpr(final String arrayLitImpl, final ArrayType type, final GetModelResponse model) { - final var arrayLitExpr = toExpr(arrayLitImpl, model); + final var arrayLitExpr = toExpr(arrayLitImpl, type, model); if(arrayLitExpr instanceof IteExpr) { final var entryExprsBuilder = new ImmutableList.Builder, Expr>>(); @@ -208,7 +220,7 @@ public LitExpr> toArrayLitExpr if (iteExpr.getElse() instanceof IteExpr) { iteExpr = (IteExpr) iteExpr.getElse(); } else { - return ArrayExprs.Array(entryExprsBuilder.build(), iteExpr.getElse(), type); + return Array(entryExprsBuilder.build(), iteExpr.getElse(), type); } } } @@ -218,7 +230,7 @@ public LitExpr> toArrayLitExpr } public LitExpr toBvLitExpr(final String bvLitImpl, final BvType type, final GetModelResponse model) { - final var bvLitExpr = toExpr(bvLitImpl, model); + final var bvLitExpr = toExpr(bvLitImpl, type, model); if(bvLitExpr instanceof BvLitExpr) { return Bv(((BvLitExpr) bvLitExpr).getValue(), type.isSigned()); @@ -232,24 +244,27 @@ public LitExpr toBvLitExpr(final String bvLitImpl, final BvType type, fi /* Visitor implementation */ - protected Expr transformTerm(final TermContext ctx, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformTerm(final TermContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert model != null; + assert vars != null; + if(ctx.spec_constant() != null) { - return transformSpecConstant(ctx.spec_constant(), model, vars); + return transformSpecConstant(ctx.spec_constant(), type, model, vars); } else if(ctx.qual_identifier() != null) { - return transformQualIdentifier(ctx.qual_identifier(), model, vars); + return transformQualIdentifier(ctx.qual_identifier(), type, model, vars); } else if(ctx.generic_term() != null) { - return transformGenericTerm(ctx.generic_term(), model, vars); + return transformGenericTerm(ctx.generic_term(), type, model, vars); } else if(ctx.let_term() != null) { throw new UnsupportedOperationException(); } else if(ctx.forall_term() != null) { - return transformForallTerm(ctx.forall_term(), model, vars); + return transformForallTerm(ctx.forall_term(), type, model, vars); } else if(ctx.exists_term() != null) { - return transformExistsTerm(ctx.exists_term(), model, vars); + return transformExistsTerm(ctx.exists_term(), type, model, vars); } else if(ctx.match_term() != null) { throw new UnsupportedOperationException(); @@ -262,18 +277,21 @@ else if(ctx.annotate_term() != null) { } } - protected Expr transformSpecConstant(final Spec_constantContext ctx, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformSpecConstant(final Spec_constantContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert model != null; + assert vars != null; + if(ctx.numeral() != null) { - return transformNumeral(ctx.numeral(), model, vars); + return transformNumeral(ctx.numeral(), type, model, vars); } else if(ctx.decimal() != null) { - return transformDecimal(ctx.decimal(), model, vars); + return transformDecimal(ctx.decimal(), type, model, vars); } else if(ctx.hexadecimal() != null) { - return transformHexadecimal(ctx.hexadecimal(), model, vars); + return transformHexadecimal(ctx.hexadecimal(), type, model, vars); } else if(ctx.binary() != null) { - return transformBinary(ctx.binary(), model, vars); + return transformBinary(ctx.binary(), type, model, vars); } else if(ctx.string() != null) { throw new UnsupportedOperationException(); @@ -283,27 +301,36 @@ else if(ctx.string() != null) { } } - protected Expr transformQualIdentifier(final Qual_identifierContext ctx, final GetModelResponse model, final BiMap, String> vars) { - return transformIdentifier(ctx.identifier(), model, vars); + protected Expr transformQualIdentifier(final Qual_identifierContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert model != null; + assert vars != null; + + return transformIdentifier(ctx.identifier(), type, model, vars); } - protected Expr transformGenericTerm(final Generic_termContext ctx, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformGenericTerm(final Generic_termContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert model != null; + assert vars != null; + final var funName = ctx.qual_identifier().identifier().symbol().getText(); final var funParams = ctx.qual_identifier().identifier().index(); final var funAppParams = ctx.term(); if (funName.equals("const")) { // as const construct - final var type = transformSort(ctx.qual_identifier().sort()); - final var expr = transformTerm(ctx.term().get(0), model, vars); - if (type instanceof ArrayType) { + final var constType = transformSort(ctx.qual_identifier().sort(), type); + if (constType instanceof ArrayType) { + assert type == null || type.equals(constType); + + final var arrayType = (ArrayType) constType; + final var expr = transformTerm(ctx.term().get(0), arrayType.getElemType(), model, vars); return createArrayLitExpr(expr, (ArrayType) type); } else { throw new UnsupportedOperationException(); } } else if (funAppTransformer.containsKey(funName)) { // known function application - return funAppTransformer.get(funName).apply(funParams, funAppParams, model, vars); + return funAppTransformer.get(funName).apply(funParams, funAppParams, type, model, vars); } else { // custom function application throw new UnsupportedOperationException(); /*final Expr funcExpr; @@ -318,42 +345,82 @@ protected Expr transformGenericTerm(final Generic_termContext ctx, final GetM @SuppressWarnings("unchecked") private Expr createArrayLitExpr(final Expr elze, final ArrayType type) { - return ArrayExprs.Array(Collections.emptyList(), (Expr) elze, type); + return Array(Collections.emptyList(), (Expr) elze, type); } - protected Expr transformForallTerm(final Forall_termContext ctx, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformForallTerm(final Forall_termContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert type == null || type.equals(Bool()); + assert model != null; + assert vars != null; + final var paramDecls = ctx.sorted_var().stream() - .map(sv -> Decls.Param(sv.symbol().getText(), transformSort(sv.sort()))) - .collect(Collectors.toUnmodifiableList()); + .map(sv -> Decls.Param(sv.symbol().getText(), transformSort(sv.sort(), null))) + .collect(Collectors.toList()); + + while (paramDecls.stream().anyMatch(p -> p.getType() instanceof DummyType)) { + try { + pushParams(paramDecls, vars); + transformTerm(ctx.term(), type, model, vars); + throw new SmtLibSolverException("Unsupported term: could'nt deduce all types"); + } + catch (ParamTypeDeducedException e) { + popParams(paramDecls, vars); + paramDecls.set(paramDecls.indexOf(e.getDecl()), Decls.Param(e.getDecl().getName(), e.getType())); + } + } pushParams(paramDecls, vars); - final Expr op = cast(transformTerm(ctx.term(), model, vars), Bool()); + final var op = transformTerm(ctx.term(), type, model, vars); popParams(paramDecls, vars); - return Forall(paramDecls, op); + + return Forall(paramDecls, cast(op, Bool())); } - protected Expr transformExistsTerm(final Exists_termContext ctx, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformExistsTerm(final Exists_termContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert type == null || type.equals(Bool()); + assert model != null; + assert vars != null; + final var paramDecls = ctx.sorted_var().stream() - .map(sv -> Decls.Param(sv.symbol().getText(), transformSort(sv.sort()))) - .collect(Collectors.toUnmodifiableList()); + .map(sv -> Decls.Param(sv.symbol().getText(), transformSort(sv.sort(), null))) + .collect(Collectors.toList()); + + while (paramDecls.stream().anyMatch(p -> p.getType() instanceof DummyType)) { + try { + pushParams(paramDecls, vars); + transformTerm(ctx.term(), type, model, vars); + throw new SmtLibSolverException("Unsupported term: could'nt deduce all types"); + } + catch (ParamTypeDeducedException e) { + popParams(paramDecls, vars); + paramDecls.set(paramDecls.indexOf(e.getDecl()), Decls.Param(e.getDecl().getName(), e.getType())); + } + } pushParams(paramDecls, vars); - final Expr op = cast(transformTerm(ctx.term(), model, vars), Bool()); + final var op = transformTerm(ctx.term(), type, model, vars); popParams(paramDecls, vars); - return Exists(paramDecls, op); + + return Exists(paramDecls, cast(op, Bool())); } - protected Expr transformIdentifier(final IdentifierContext ctx, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformIdentifier(final IdentifierContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert model != null; + assert vars != null; + if(ctx.symbol().getText().equals("as-array")) { final var name = ctx.index().get(0).getText(); - return toExpr(model.getTerm(name), model); + return toExpr(model.getTerm(name), type, model); } else { - return transformSymbol(ctx.symbol(), model, vars); + return transformSymbol(ctx.symbol(), type, model, vars); } } - protected Expr transformSymbol(final SymbolContext ctx, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformSymbol(final SymbolContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert model != null; + assert vars != null; + final var value = ctx.getText(); switch (value) { case "true": @@ -361,49 +428,129 @@ protected Expr transformSymbol(final SymbolContext ctx, final GetModelRespons case "false": return BoolExprs.False(); default: - throw new UnsupportedOperationException(); + if(vars.containsValue(value)) { + final var decl = vars.inverse().get(value); + final var ref = decl.getRef(); + if(decl.getType() instanceof DummyType) { + if(type == null) { + return null; + } + else { + throw new ParamTypeDeducedException((ParamDecl) decl, type); + } + } + else { + assert type == null || type.equals(ref.getType()); + return ref; + } + } + else if(symbolTable.definesSymbol(value)) { + final var ref = symbolTable.getConst(value).getRef(); + assert type == null || type.equals(ref.getType()); + return ref; + } + else { + throw new UnsupportedOperationException(); + } } } - protected Expr transformNumeral(final NumeralContext ctx, final GetModelResponse model, final BiMap, String> vars) { - return IntExprs.Int(ctx.getText()); + protected Expr transformNumeral(final NumeralContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert type == null || type.equals(Int()); + assert model != null; + assert vars != null; + + return Int(ctx.getText()); } - protected Expr transformDecimal(final DecimalContext ctx, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformDecimal(final DecimalContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert type == null || type.equals(Rat()); + assert model != null; + assert vars != null; + final var decimal = new BigDecimal(ctx.getText()); if(decimal.scale() <= 0) { - return RatExprs.Rat(decimal.unscaledValue(), BigInteger.ONE); + return Rat(decimal.unscaledValue(), BigInteger.ONE); } else { - return RatExprs.Rat(decimal.unscaledValue(), BigInteger.TEN.pow(decimal.scale())); + return Rat(decimal.unscaledValue(), BigInteger.TEN.pow(decimal.scale())); } } - protected Expr transformHexadecimal(final HexadecimalContext ctx, final GetModelResponse model, final BiMap, String> vars) { - final var numStr = ctx.getText().substring(2); - final var num = new BigInteger(numStr, 16); - return BvUtils.bigIntegerToBvLitExpr(num, numStr.length() * 4, false); + protected Expr transformHexadecimal(final HexadecimalContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert type == null || type instanceof BvType; + assert model != null; + assert vars != null; + + if(type == null) { + return null; + } + else { + final var bvType = (BvType) type; + final var numStr = ctx.getText().substring(2); + final var num = new BigInteger(numStr, 16); + checkState(bvType.getSize() == numStr.length() * 4); + + return BvUtils.bigIntegerToBvLitExpr(num, bvType.getSize(), bvType.isSigned()); + } } - protected Expr transformBinary(final BinaryContext ctx, final GetModelResponse model, final BiMap, String> vars) { - final var numStr = ctx.getText().substring(2); - final var num = new BigInteger(numStr, 2); - return BvUtils.bigIntegerToBvLitExpr(num, numStr.length(), false); + protected Expr transformBinary(final BinaryContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + assert type == null || type instanceof BvType; + assert model != null; + assert vars != null; + + if(type == null) { + return null; + } + else { + final var bvType = (BvType) type; + final var numStr = ctx.getText().substring(2); + final var num = new BigInteger(numStr, 2); + checkState(bvType.getSize() == numStr.length()); + + return BvUtils.bigIntegerToBvLitExpr(num, bvType.getSize(), bvType.isSigned()); + } } - protected Type transformSort(SortContext ctx) { + protected Type transformSort(final SortContext ctx, final Type type) { final var name = ctx.identifier().symbol().getText(); switch(name) { case "Bool": - return BoolExprs.Bool(); + assert type == null || type.equals(Bool()); + return Bool(); case "Int": - return IntExprs.Int(); + assert type == null || type.equals(Int()); + return Int(); case "Real": - return RatExprs.Rat(); + assert type == null || type.equals(Rat()); + return Rat(); case "BitVec": - return BvExprs.BvType(Integer.parseInt(ctx.identifier().index().get(0).getText()), false); + assert type == null || type instanceof BvType; + if(type == null) { + return new DummyType(); + } + else { + final var bvType = (BvType) type; + checkArgument(Integer.parseInt(ctx.identifier().index().get(0).getText()) == bvType.getSize()); + return BvExprs.BvType(bvType.getSize(), bvType.isSigned()); + } case "Array": - return ArrayExprs.Array(transformSort(ctx.sort().get(0)), transformSort(ctx.sort().get(1))); + assert type == null || type instanceof ArrayType; + if(type == null) { + final var indexType = transformSort(ctx.sort().get(0), null); + final var elemType = transformSort(ctx.sort().get(1), null); + if(indexType instanceof DummyType || elemType instanceof DummyType) { + return new DummyType(); + } + else { + return Array(indexType, elemType); + } + } + else { + final var arrayType = (ArrayType) type; + return Array(transformSort(ctx.sort().get(0), arrayType.getIndexType()), transformSort(ctx.sort().get(1), arrayType.getElemType())); + } default: throw new UnsupportedOperationException(); } @@ -413,11 +560,11 @@ protected Type transformSort(SortContext ctx) { /* Variable scope handling */ - protected void pushParams(final List> paramDecls, BiMap, String> vars) { + protected void pushParams(final List> paramDecls, BiMap, String> vars) { vars.putAll(paramDecls.stream().collect(Collectors.toUnmodifiableMap(Function.identity(), Decl::getName))); } - protected void popParams(final List> paramDecls, BiMap, String> vars) { + protected void popParams(final List> paramDecls, BiMap, String> vars) { for (final var paramDecl : paramDecls) { vars.remove(paramDecl, paramDecl.getName()); } @@ -425,75 +572,252 @@ protected void popParams(final List> paramDecls, B /* Utilities */ - private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprNullaryOperator( - final Supplier> function - ) { - return (params, ops, model, vars) -> { + @SuppressWarnings("unused") + private OperatorCreatorFunction exprNullaryOperator(final Supplier> function) { + return (params, ops, type, model, vars) -> { checkArgument(params.size() == 0); checkArgument(ops.size() == 0); return function.get(); }; } - private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprUnaryOperator( - final UnaryOperator> function - ) { - return (params, ops, model, vars) -> { + private OperatorCreatorFunction exprUnaryOperator(final UnaryOperator> function) { + return (params, ops, type, model, vars) -> { checkArgument(params.size() == 0); checkArgument(ops.size() == 1); - final Expr op = transformTerm(ops.get(0), model, vars); - return function.apply(op); + + if(type == null) { + final var op = transformTerm(ops.get(0), type, model, vars); + return function.apply(op); + } + else { + final var op = checkNotNull(transformTerm(ops.get(0), type, model, vars)); + return function.apply(op); + } + }; + } + + private OperatorCreatorFunction exprBinaryOperator(final BinaryOperator> function) { + return (params, ops, type, model, vars) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 2); + + if(type == null) { + var op1 = transformTerm(ops.get(0), null, model, vars); + var op2 = transformTerm(ops.get(1), null, model, vars); + if(op1 == null && op2 == null) { + return null; + } + else if(op1 != null && op2 == null) { + op2 = checkNotNull(transformTerm(ops.get(1), op1.getType(), model, vars)); + } + else if(op1 == null /* && op2 != null */) { + op1 = checkNotNull(transformTerm(ops.get(0), op2.getType(), model, vars)); + } + return function.apply(op1, op2); + } + else { + final var op1 = transformTerm(ops.get(0), type, model, vars); + final var op2 = transformTerm(ops.get(1), type, model, vars); + return function.apply(op1, op2); + } }; } - private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprBinaryOperator( - final BinaryOperator> function - ) { - return (params, ops, model, vars) -> { + private OperatorCreatorFunction exprRelationalOperator(final BinaryOperator> function) { + return (params, ops, type, model, vars) -> { + assert type == null || type.equals(Bool()); checkArgument(params.size() == 0); checkArgument(ops.size() == 2); - final Expr op1 = transformTerm(ops.get(0), model, vars); - final Expr op2 = transformTerm(ops.get(1), model, vars); + + var op1 = transformTerm(ops.get(0), null, model, vars); + var op2 = transformTerm(ops.get(1), null, model, vars); + if(op1 == null && op2 == null) { + return null; + } + else if(op1 != null && op2 == null) { + op2 = checkNotNull(transformTerm(ops.get(1), op1.getType(), model, vars)); + } + else if(op1 == null /* && op2 != null */) { + op1 = checkNotNull(transformTerm(ops.get(0), op2.getType(), model, vars)); + } return function.apply(op1, op2); }; } - private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprMinusOperator() { - return (params, ops, model, vars) -> { + private OperatorCreatorFunction exprArrayReadOperator() { + return (params, ops, type, model, vars) -> { + checkArgument(params.size() == 0); + checkArgument(ops.size() == 2); + + var op1 = transformTerm(ops.get(0), null, model, vars); + var op2 = transformTerm(ops.get(1), null, model, vars); + if(op1 == null && op2 == null) { + return null; + } + else if(op1 != null && op2 == null) { + assert op1.getType() instanceof ArrayType; + final var arrayType = (ArrayType) op1.getType(); + op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars)); + } + else if(op1 == null /* && op2 != null */) { + if(type == null) { + return null; + } + else { + final var arrayType = Array(op2.getType(), type); + op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars)); + } + } + return ArrayReadExpr.create(op1, op2); + }; + } + + private OperatorCreatorFunction exprMinusOperator() { + return (params, ops, type, model, vars) -> { checkArgument(params.size() == 0); checkArgument(ops.size() == 1 || ops.size() == 2); if(ops.size() == 2) { - final Expr op1 = transformTerm(ops.get(0), model, vars); - final Expr op2 = transformTerm(ops.get(1), model, vars); - return SubExpr.create2(op1, op2); + return exprBinaryOperator(SubExpr::create2).apply(params, ops, type, model, vars); } else { - final Expr op = transformTerm(ops.get(0), model, vars); - return NegExpr.create2(op); + return exprUnaryOperator(NegExpr::create2).apply(params, ops, type, model, vars); } }; } - private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprTernaryOperator( - final TernaryOperator> function - ) { - return (params, ops, model, vars) -> { + @SuppressWarnings("unused") + private OperatorCreatorFunction exprTernaryOperator(final TernaryOperator> function) { + return (params, ops, type, model, vars) -> { checkArgument(params.size() == 0); checkArgument(ops.size() == 3); - final Expr op1 = transformTerm(ops.get(0), model, vars); - final Expr op2 = transformTerm(ops.get(1), model, vars); - final Expr op3 = transformTerm(ops.get(2), model, vars); + final Expr op1 = transformTerm(ops.get(0), type, model, vars); + final Expr op2 = transformTerm(ops.get(1), type, model, vars); + final Expr op3 = transformTerm(ops.get(2), type, model, vars); return function.apply(op1, op2, op3); }; } - private QuadFunction, List, GetModelResponse, BiMap, String>, Expr> exprMultiaryOperator( - final Function>, Expr> function - ) { - return (params, ops, model, vars) -> { + private OperatorCreatorFunction exprIteOperator() { + return (params, ops, type, model, vars) -> { checkArgument(params.size() == 0); - return function.apply(ops.stream().map(op -> transformTerm(op, model, vars)).collect(Collectors.toUnmodifiableList())); + checkArgument(ops.size() == 3); + final var op1 = transformTerm(ops.get(0), Bool(), model, vars); + if(type == null) { + var op2 = transformTerm(ops.get(1), type, model, vars); + var op3 = transformTerm(ops.get(2), type, model, vars); + if(op2 == null && op3 == null) { + return null; + } + else if(op2 != null && op3 == null) { + op3 = checkNotNull(transformTerm(ops.get(2), op2.getType(), model, vars)); + } + else if(op2 == null /* && op3 != null */) { + op2 = checkNotNull(transformTerm(ops.get(1), op3.getType(), model, vars)); + } + return IteExpr.create(op1, op2, op3); + } + else { + final var op2 = transformTerm(ops.get(1), type, model, vars); + final var op3 = transformTerm(ops.get(2), type, model, vars); + return IteExpr.create(op1, op2, op3); + } }; } + private OperatorCreatorFunction exprArrayWriteOperator() { + return (params, ops, type, model, vars) -> { + assert type == null || type instanceof ArrayType; + checkArgument(params.size() == 0); + checkArgument(ops.size() == 3); + + if(type == null) { + var op1 = transformTerm(ops.get(0), null, model, vars); + var op2 = transformTerm(ops.get(1), null, model, vars); + var op3 = transformTerm(ops.get(2), null, model, vars); + + if(op1 != null && (op2 == null || op3 == null)) { + final var arrayType = (ArrayType) op1.getType(); + if(op2 == null) { + op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars)); + } + if(op3 == null) { + op3 = checkNotNull(transformTerm(ops.get(2), arrayType.getElemType(), model, vars)); + } + } + else if(op1 == null && op2 != null && op3 != null) { + final var arrayType = Array(op2.getType(), op3.getType()); + op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars)); + } + else { + return null; + } + return ArrayWriteExpr.create(op1, op2, op3); + } + else { + final var arrayType = (ArrayType) type; + final var op1 = transformTerm(ops.get(0), arrayType, model, vars); + final var op2 = transformTerm(ops.get(1), arrayType.getIndexType(), model, vars); + final var op3 = transformTerm(ops.get(2), arrayType.getElemType(), model, vars); + return ArrayWriteExpr.create(op1, op2, op3); + } + }; + } + + private OperatorCreatorFunction exprMultiaryOperator(final Function>, Expr> function) { + return (params, ops, type, model, vars) -> { + checkArgument(params.size() == 0); + if(type == null) { + final var transformedOps = new ArrayList>(); + ops.stream() + .map(op -> transformTerm(op, type, model, vars)) + .forEach(transformedOps::add); + + if(transformedOps.stream().allMatch(Objects::isNull)) { + return null; + } + else { + final var opType = transformedOps.stream().filter(Objects::nonNull).findAny().get().getType(); + return function.apply(IntStream + .range(0, ops.size()) + .mapToObj(i -> transformedOps.get(i) == null ? transformTerm(ops.get(i), opType, model, vars) : transformedOps.get(i)) + .collect(Collectors.toUnmodifiableList()) + ); + } + } + else { + return function.apply(ops.stream().map(op -> transformTerm(op, type, model, vars)).collect(Collectors.toUnmodifiableList())); + } + }; + } + + private interface OperatorCreatorFunction extends QuintFunction< + List, // Parameters + List, // Operands + Type, // Expected type of result + GetModelResponse, // The model + BiMap, String>, // The variable (param) store + Expr // Return type + > {} + + private final static class DummyType implements Type {} + + private final static class ParamTypeDeducedException extends RuntimeException { + private final ParamDecl decl; + private final Type type; + + public ParamTypeDeducedException(ParamDecl decl, Type type) { + this.decl = decl; + this.type = type; + } + + public ParamDecl getDecl() { + return decl; + } + + public Type getType() { + return type; + } + } + } From 9350936b836243903b084ec6b91ac0d6e289f2dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 30 Aug 2020 11:51:24 +0200 Subject: [PATCH 29/99] Refactor parameter type deduction support for SmtLibTermTransformer --- .../theta/solver/smtlib/SmtLibSolverTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index c1febf9079..31f3cf1409 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -6,22 +6,28 @@ import hu.bme.mit.theta.core.model.Valuation; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.LitExpr; +import hu.bme.mit.theta.core.type.abstracttype.EqExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayExprs; import hu.bme.mit.theta.core.type.arraytype.ArrayLitExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.booltype.BoolExprs; import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.core.type.booltype.ExistsExpr; +import hu.bme.mit.theta.core.type.booltype.ForallExpr; import hu.bme.mit.theta.core.type.bvtype.BvExprs; import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; import hu.bme.mit.theta.core.type.bvtype.BvType; import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.type.inttype.IntExprs; import hu.bme.mit.theta.core.type.inttype.IntType; +import hu.bme.mit.theta.core.utils.BvUtils; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; import org.junit.BeforeClass; import org.junit.Test; +import java.math.BigInteger; import java.nio.file.Path; import java.util.List; import java.util.Optional; @@ -32,6 +38,7 @@ import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Read; import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Write; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; import static hu.bme.mit.theta.core.type.functype.FuncExprs.App; @@ -53,6 +60,23 @@ public static void init() { ); } + @Test + public void test() { + final var symbolTable = new SmtLibSymbolTable(); + final var termTransformer = new SmtLibTermTransformer(symbolTable); + + final var x = Const("x", BvExprs.BvType(4, true)); + symbolTable.put(x, "x", "(declare-fun x () (_ BitVec 4))"); + + final var expr = termTransformer.toExpr( + "(forall ((y (Array (_ BitVec 4) Int))) (= (select y x) 0))", + BoolExprs.Bool(), GetModelResponse.empty() + ); + assertNotNull(expr); + assertTrue(expr instanceof ForallExpr); + assertEquals(Array(x.getType(), Int()), ((ForallExpr) expr).getParamDecls().get(0).getType()); + } + @Test public void testSimple() { final Solver solver = solverFactory.createSolver(); From fb24125c50ffa2afa067201db7546ffd555a396b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 30 Aug 2020 13:50:15 +0200 Subject: [PATCH 30/99] Add function literal support to SmtLibTermTransformer --- .../mit/theta/solver/smtlib/SmtLibSolver.java | 34 +- .../solver/smtlib/SmtLibTermTransformer.java | 335 +++++++++++------- .../smtlib/parser/GetModelResponse.java | 14 +- 3 files changed, 238 insertions(+), 145 deletions(-) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java index 63d3a079ec..3fd6b8f9ad 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java @@ -9,8 +9,8 @@ import hu.bme.mit.theta.core.type.Type; import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.booltype.BoolType; -import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; import hu.bme.mit.theta.core.type.bvtype.BvType; +import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.utils.ExprUtils; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; @@ -30,7 +30,6 @@ import org.antlr.v4.runtime.CommonTokenStream; import java.nio.file.Path; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -43,8 +42,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; -import static hu.bme.mit.theta.core.utils.TypeUtils.cast; public class SmtLibSolver implements Solver { private final SolverBinary solverBinary; @@ -322,15 +319,11 @@ public Optional> eval(Decl d private LitExpr extractLiteral(final ConstDecl decl) { final String symbol = transformationManager.toSymbol(decl); final Type type = decl.getType(); - /*if (type instanceof FuncType) { - return extractFuncLiteral(funcDecl); - } else if (type instanceof ArrayType) { - return extractArrayLiteral(funcDecl); - } else if (type instanceof BvType) { - return extractBvConstLiteral(funcDecl, (BvType) type); - } else {*/ - //} - if(type instanceof ArrayType) { + + if(type instanceof FuncType) { + return extractFuncLiteral(symbol, (FuncType) type); + } + else if(type instanceof ArrayType) { return extractArrayLiteral(symbol, (ArrayType) type); } else if (type instanceof BvType) { @@ -341,12 +334,21 @@ else if (type instanceof BvType) { } } + private LitExpr extractFuncLiteral(final String symbol, final FuncType type) { + final String term = model.getTerm(symbol); + if (term == null) { + return null; + } else { + return checkNotNull(termTransformer.toFuncLitExpr(term, type, model)); + } + } + private LitExpr extractArrayLiteral(final String symbol, final ArrayType type) { final String term = model.getTerm(symbol); if (term == null) { return null; } else { - return termTransformer.toArrayLitExpr(term, type, model); + return checkNotNull(termTransformer.toArrayLitExpr(term, type, model)); } } @@ -355,7 +357,7 @@ private LitExpr extractBvConstLiteral(final String symbol, final BvType type) if (term == null) { return null; } else { - return termTransformer.toBvLitExpr(term, type, model); + return checkNotNull(termTransformer.toBvLitExpr(term, type, model)); } } @@ -364,7 +366,7 @@ private LitExpr extractConstLiteral(final String symbol, final Type type) { if (term == null) { return null; } else { - return termTransformer.toLitExpr(term, type, model); + return checkNotNull(termTransformer.toLitExpr(term, type, model)); } } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java index 43184cc0b8..6eba2b2e02 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java @@ -3,11 +3,9 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableList; -import hu.bme.mit.theta.common.DispatchTable2; import hu.bme.mit.theta.common.QuintFunction; import hu.bme.mit.theta.common.TernaryOperator; import hu.bme.mit.theta.common.Tuple2; -import hu.bme.mit.theta.core.decl.Decl; import hu.bme.mit.theta.core.decl.Decls; import hu.bme.mit.theta.core.decl.ParamDecl; import hu.bme.mit.theta.core.type.Expr; @@ -15,7 +13,6 @@ import hu.bme.mit.theta.core.type.Type; import hu.bme.mit.theta.core.type.abstracttype.AddExpr; import hu.bme.mit.theta.core.type.abstracttype.DivExpr; -import hu.bme.mit.theta.core.type.abstracttype.Divisible; import hu.bme.mit.theta.core.type.abstracttype.EqExpr; import hu.bme.mit.theta.core.type.abstracttype.GeqExpr; import hu.bme.mit.theta.core.type.abstracttype.GtExpr; @@ -23,17 +20,16 @@ import hu.bme.mit.theta.core.type.abstracttype.LtExpr; import hu.bme.mit.theta.core.type.abstracttype.ModExpr; import hu.bme.mit.theta.core.type.abstracttype.MulExpr; -import hu.bme.mit.theta.core.type.abstracttype.Multiplicative; import hu.bme.mit.theta.core.type.abstracttype.NegExpr; import hu.bme.mit.theta.core.type.abstracttype.RemExpr; import hu.bme.mit.theta.core.type.abstracttype.SubExpr; import hu.bme.mit.theta.core.type.anytype.IteExpr; +import hu.bme.mit.theta.core.type.anytype.RefExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayReadExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.arraytype.ArrayWriteExpr; import hu.bme.mit.theta.core.type.booltype.AndExpr; import hu.bme.mit.theta.core.type.booltype.BoolExprs; -import hu.bme.mit.theta.core.type.booltype.BoolType; import hu.bme.mit.theta.core.type.booltype.IffExpr; import hu.bme.mit.theta.core.type.booltype.ImplyExpr; import hu.bme.mit.theta.core.type.booltype.NotExpr; @@ -59,6 +55,8 @@ import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; import hu.bme.mit.theta.core.type.bvtype.BvType; import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; +import hu.bme.mit.theta.core.type.functype.FuncExprs; +import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; import hu.bme.mit.theta.core.utils.BvUtils; import hu.bme.mit.theta.core.utils.ExprUtils; @@ -92,6 +90,7 @@ import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Exists; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Forall; import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; +import static hu.bme.mit.theta.core.type.functype.FuncExprs.Func; import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; import static hu.bme.mit.theta.core.type.rattype.RatExprs.Rat; import static hu.bme.mit.theta.core.utils.TypeUtils.cast; @@ -109,13 +108,11 @@ import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Spec_constantContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.SymbolContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.TermContext; +import static java.util.stream.Collectors.toList; public class SmtLibTermTransformer { - protected static final String PARAM_NAME_FORMAT = "_p%d"; - protected final SmtLibSymbolTable symbolTable; protected final Map funAppTransformer; - protected final DispatchTable2> typingCorrector; public SmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { this.symbolTable = symbolTable; @@ -179,13 +176,30 @@ public SmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { put("select", exprArrayReadOperator()); put("store", exprArrayWriteOperator()); }}; - - this.typingCorrector = DispatchTable2.>builder() - .build(); } /* Public interface */ + public

LitExpr> toFuncLitExpr(final String funcLitImpl, final FuncType type, final GetModelResponse model) { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(funcLitImpl)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + + final var litExpr = transformFuncDef(parser.function_def(), type, model, HashBiMap.create()); + if(litExpr == null) { + return null; + } + else if(litExpr instanceof LitExpr) { + return (LitExpr>) cast(litExpr, type); + } + else { + return (LitExpr>) cast(ExprUtils.simplify(litExpr), type); + } + } + public Expr toExpr(final String term, final Type type, final GetModelResponse model) { final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(term)); final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); @@ -194,13 +208,22 @@ public Expr toExpr(final String term, final Type type, final GetModelResponse parser.removeErrorListeners(); parser.addErrorListener(new ThrowExceptionErrorListener()); - return cast(transformTerm(parser.term(), type, model, HashBiMap.create()), type); + final var expr = transformTerm(parser.function_def().term(), type, model, HashBiMap.create()); + if(expr == null) { + return null; + } + else { + return cast(expr, type); + } } public LitExpr toLitExpr(final String litImpl, final T type, final GetModelResponse model) { final var litExpr = toExpr(litImpl, type, model); - if(litExpr instanceof LitExpr) { + if(litExpr == null) { + return null; + } + else if(litExpr instanceof LitExpr) { return (LitExpr) cast(litExpr, type); } else { @@ -212,7 +235,10 @@ public LitExpr toLitExpr(final String litImpl, final T type, public LitExpr> toArrayLitExpr(final String arrayLitImpl, final ArrayType type, final GetModelResponse model) { final var arrayLitExpr = toExpr(arrayLitImpl, type, model); - if(arrayLitExpr instanceof IteExpr) { + if(arrayLitExpr == null) { + return null; + } + else if(arrayLitExpr instanceof IteExpr) { final var entryExprsBuilder = new ImmutableList.Builder, Expr>>(); var iteExpr = (IteExpr) arrayLitExpr; while (true) { @@ -232,7 +258,10 @@ public LitExpr> toArrayLitExpr public LitExpr toBvLitExpr(final String bvLitImpl, final BvType type, final GetModelResponse model) { final var bvLitExpr = toExpr(bvLitImpl, type, model); - if(bvLitExpr instanceof BvLitExpr) { + if(bvLitExpr == null) { + return null; + } + else if(bvLitExpr instanceof BvLitExpr) { return Bv(((BvLitExpr) bvLitExpr).getValue(), type.isSigned()); } else { @@ -244,7 +273,35 @@ public LitExpr toBvLitExpr(final String bvLitImpl, final BvType type, fi /* Visitor implementation */ - protected Expr transformTerm(final TermContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformFuncDef(final SMTLIBv2Parser.Function_defContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { + assert type == null || type instanceof FuncType; + assert model != null; + assert vars != null; + + final var funcType = type != null ? (FuncType) type : null; + + final var paramDecls = ctx.sorted_var().stream() + .map(sv -> new ParamTypeDeducer( + sv.symbol().getText(), transformSort(sv.sort(), + funcType != null ? funcType.getParamType() : null)) + ) + .collect(toList()); + checkArgument(paramDecls.size() == 1, "Only unary functions are supported"); + + pushParams(paramDecls, vars); + final var op = transformTerm(ctx.term(), funcType != null ? funcType.getResultType() : type, model, vars); + popParams(paramDecls, vars); + + if(paramDecls.get(0).isTypeUnknown()) { + return null; + } + else { + assert op != null; + return Func(paramDecls.get(0).getParamDecl(), op); + } + } + + protected Expr transformTerm(final TermContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert model != null; assert vars != null; @@ -277,7 +334,7 @@ else if(ctx.annotate_term() != null) { } } - protected Expr transformSpecConstant(final Spec_constantContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformSpecConstant(final Spec_constantContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert model != null; assert vars != null; @@ -301,14 +358,14 @@ else if(ctx.string() != null) { } } - protected Expr transformQualIdentifier(final Qual_identifierContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformQualIdentifier(final Qual_identifierContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert model != null; assert vars != null; return transformIdentifier(ctx.identifier(), type, model, vars); } - protected Expr transformGenericTerm(final Generic_termContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformGenericTerm(final Generic_termContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert model != null; assert vars != null; @@ -321,9 +378,10 @@ protected Expr transformGenericTerm(final Generic_termContext ctx, final Type final var constType = transformSort(ctx.qual_identifier().sort(), type); if (constType instanceof ArrayType) { assert type == null || type.equals(constType); + checkArgument(funAppParams.size() == 1, "Invalid as const construct"); final var arrayType = (ArrayType) constType; - final var expr = transformTerm(ctx.term().get(0), arrayType.getElemType(), model, vars); + final var expr = transformTerm(funAppParams.get(0), arrayType.getElemType(), model, vars); return createArrayLitExpr(expr, (ArrayType) type); } else { @@ -332,14 +390,10 @@ protected Expr transformGenericTerm(final Generic_termContext ctx, final Type } else if (funAppTransformer.containsKey(funName)) { // known function application return funAppTransformer.get(funName).apply(funParams, funAppParams, type, model, vars); } else { // custom function application - throw new UnsupportedOperationException(); - /*final Expr funcExpr; - if (symbolTable.definesSymbol(operation)) { - funcExpr = symbolTable.getConst(operation).getRef(); - } else { - funcExpr = toFuncLitExpr(funcDecl, model, vars); - } - return transformFuncApp(funcExpr, term.getArgs(), model, vars);*/ + checkArgument(funParams.size() == 0, "Custom unary function application cannot vahe parameter"); + checkArgument(funAppParams.size() == 1, "Only unary functions are supported"); + + return createFuncAppExpr(funName, funAppParams.get(0), type, model, vars); } } @@ -348,63 +402,85 @@ private Expr createArrayLitExpr(final Expr) elze, type); } - protected Expr transformForallTerm(final Forall_termContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + private

Expr createFuncAppExpr(final String funName, final TermContext funAppParam, final Type returnType, final GetModelResponse model, final BiMap vars) { + + var paramExpr = transformTerm(funAppParam, null, model, vars); + final Type paramType = paramExpr != null ? paramExpr.getType() : null; + + final Expr funcExpr; + if (symbolTable.definesSymbol(funName)) { + funcExpr = checkNotNull(symbolTable.getConst(funName).getRef()); + } else { + final var funDefImpl = model.getTerm(funName); + if(paramType == null || returnType == null) { + funcExpr = toFuncLitExpr(funDefImpl, null, model); + if(funcExpr == null) { + return null; + } + } + else { + funcExpr = checkNotNull(toFuncLitExpr(funDefImpl, FuncType.of(paramType, returnType), model), "Unsupported expression: was not able to deduce all types"); + } + } + + assert funcExpr.getType() instanceof FuncType; + @SuppressWarnings("unchecked") final var funType = (FuncType) funcExpr.getType(); + paramExpr = paramExpr == null ? transformTerm(funAppParam, funType.getParamType(), model, vars) : paramExpr; + + return FuncExprs.App(cast(funcExpr, funType), cast(paramExpr, funType.getParamType())); + } + + protected Expr transformForallTerm(final Forall_termContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert type == null || type.equals(Bool()); assert model != null; assert vars != null; final var paramDecls = ctx.sorted_var().stream() - .map(sv -> Decls.Param(sv.symbol().getText(), transformSort(sv.sort(), null))) - .collect(Collectors.toList()); - - while (paramDecls.stream().anyMatch(p -> p.getType() instanceof DummyType)) { - try { - pushParams(paramDecls, vars); - transformTerm(ctx.term(), type, model, vars); - throw new SmtLibSolverException("Unsupported term: could'nt deduce all types"); - } - catch (ParamTypeDeducedException e) { - popParams(paramDecls, vars); - paramDecls.set(paramDecls.indexOf(e.getDecl()), Decls.Param(e.getDecl().getName(), e.getType())); - } - } + .map(sv -> new ParamTypeDeducer(sv.symbol().getText(), transformSort(sv.sort(), null))) + .collect(toList()); pushParams(paramDecls, vars); final var op = transformTerm(ctx.term(), type, model, vars); popParams(paramDecls, vars); - return Forall(paramDecls, cast(op, Bool())); + if(paramDecls.stream().anyMatch(ParamTypeDeducer::isTypeUnknown)) { + return null; + } + else { + assert op != null; + return Forall( + paramDecls.stream().map(ParamTypeDeducer::getParamDecl).collect(Collectors.toUnmodifiableList()), + cast(op, Bool()) + ); + } } - protected Expr transformExistsTerm(final Exists_termContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformExistsTerm(final Exists_termContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert type == null || type.equals(Bool()); assert model != null; assert vars != null; final var paramDecls = ctx.sorted_var().stream() - .map(sv -> Decls.Param(sv.symbol().getText(), transformSort(sv.sort(), null))) - .collect(Collectors.toList()); - - while (paramDecls.stream().anyMatch(p -> p.getType() instanceof DummyType)) { - try { - pushParams(paramDecls, vars); - transformTerm(ctx.term(), type, model, vars); - throw new SmtLibSolverException("Unsupported term: could'nt deduce all types"); - } - catch (ParamTypeDeducedException e) { - popParams(paramDecls, vars); - paramDecls.set(paramDecls.indexOf(e.getDecl()), Decls.Param(e.getDecl().getName(), e.getType())); - } - } + .map(sv -> new ParamTypeDeducer(sv.symbol().getText(), transformSort(sv.sort(), null))) + .collect(toList()); pushParams(paramDecls, vars); final var op = transformTerm(ctx.term(), type, model, vars); popParams(paramDecls, vars); - return Exists(paramDecls, cast(op, Bool())); + if(paramDecls.stream().anyMatch(ParamTypeDeducer::isTypeUnknown)) { + return null; + } + else { + assert op != null; + return Exists( + paramDecls.stream().map(ParamTypeDeducer::getParamDecl).collect(Collectors.toUnmodifiableList()), + cast(op, Bool()) + ); + } } - protected Expr transformIdentifier(final IdentifierContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformIdentifier(final IdentifierContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert model != null; assert vars != null; @@ -417,7 +493,7 @@ protected Expr transformIdentifier(final IdentifierContext ctx, final Type ty } } - protected Expr transformSymbol(final SymbolContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformSymbol(final SymbolContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert model != null; assert vars != null; @@ -430,16 +506,17 @@ protected Expr transformSymbol(final SymbolContext ctx, final Type type, fina default: if(vars.containsValue(value)) { final var decl = vars.inverse().get(value); - final var ref = decl.getRef(); - if(decl.getType() instanceof DummyType) { + if(decl.isTypeUnknown()) { if(type == null) { return null; } else { - throw new ParamTypeDeducedException((ParamDecl) decl, type); + decl.setType(type); + return decl.getRef(); } } else { + final var ref = decl.getRef(); assert type == null || type.equals(ref.getType()); return ref; } @@ -455,7 +532,7 @@ else if(symbolTable.definesSymbol(value)) { } } - protected Expr transformNumeral(final NumeralContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformNumeral(final NumeralContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert type == null || type.equals(Int()); assert model != null; assert vars != null; @@ -463,7 +540,7 @@ protected Expr transformNumeral(final NumeralContext ctx, final Type type, fi return Int(ctx.getText()); } - protected Expr transformDecimal(final DecimalContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformDecimal(final DecimalContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert type == null || type.equals(Rat()); assert model != null; assert vars != null; @@ -477,7 +554,7 @@ protected Expr transformDecimal(final DecimalContext ctx, final Type type, fi } } - protected Expr transformHexadecimal(final HexadecimalContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformHexadecimal(final HexadecimalContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert type == null || type instanceof BvType; assert model != null; assert vars != null; @@ -489,13 +566,13 @@ protected Expr transformHexadecimal(final HexadecimalContext ctx, final Type final var bvType = (BvType) type; final var numStr = ctx.getText().substring(2); final var num = new BigInteger(numStr, 16); - checkState(bvType.getSize() == numStr.length() * 4); + checkState(bvType.getSize() == numStr.length() * 4, "Type mismatch"); return BvUtils.bigIntegerToBvLitExpr(num, bvType.getSize(), bvType.isSigned()); } } - protected Expr transformBinary(final BinaryContext ctx, final Type type, final GetModelResponse model, final BiMap, String> vars) { + protected Expr transformBinary(final BinaryContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { assert type == null || type instanceof BvType; assert model != null; assert vars != null; @@ -507,7 +584,7 @@ protected Expr transformBinary(final BinaryContext ctx, final Type type, fina final var bvType = (BvType) type; final var numStr = ctx.getText().substring(2); final var num = new BigInteger(numStr, 2); - checkState(bvType.getSize() == numStr.length()); + checkState(bvType.getSize() == numStr.length(), "Type mismatch"); return BvUtils.bigIntegerToBvLitExpr(num, bvType.getSize(), bvType.isSigned()); } @@ -528,11 +605,11 @@ protected Type transformSort(final SortContext ctx, final Type type) { case "BitVec": assert type == null || type instanceof BvType; if(type == null) { - return new DummyType(); + return null; } else { final var bvType = (BvType) type; - checkArgument(Integer.parseInt(ctx.identifier().index().get(0).getText()) == bvType.getSize()); + checkArgument(Integer.parseInt(ctx.identifier().index().get(0).getText()) == bvType.getSize(), "Type mismatch"); return BvExprs.BvType(bvType.getSize(), bvType.isSigned()); } case "Array": @@ -540,8 +617,8 @@ protected Type transformSort(final SortContext ctx, final Type type) { if(type == null) { final var indexType = transformSort(ctx.sort().get(0), null); final var elemType = transformSort(ctx.sort().get(1), null); - if(indexType instanceof DummyType || elemType instanceof DummyType) { - return new DummyType(); + if(indexType == null || elemType == null) { + return null; } else { return Array(indexType, elemType); @@ -560,11 +637,11 @@ protected Type transformSort(final SortContext ctx, final Type type) { /* Variable scope handling */ - protected void pushParams(final List> paramDecls, BiMap, String> vars) { - vars.putAll(paramDecls.stream().collect(Collectors.toUnmodifiableMap(Function.identity(), Decl::getName))); + protected void pushParams(final List paramDecls, BiMap vars) { + vars.putAll(paramDecls.stream().collect(Collectors.toUnmodifiableMap(Function.identity(), ParamTypeDeducer::getName))); } - protected void popParams(final List> paramDecls, BiMap, String> vars) { + protected void popParams(final List paramDecls, BiMap vars) { for (final var paramDecl : paramDecls) { vars.remove(paramDecl, paramDecl.getName()); } @@ -575,23 +652,23 @@ protected void popParams(final List> paramDec @SuppressWarnings("unused") private OperatorCreatorFunction exprNullaryOperator(final Supplier> function) { return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 0); + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 0, "Nullary operator expected"); return function.get(); }; } private OperatorCreatorFunction exprUnaryOperator(final UnaryOperator> function) { return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 1); + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 1, "Unary operator expected"); if(type == null) { final var op = transformTerm(ops.get(0), type, model, vars); return function.apply(op); } else { - final var op = checkNotNull(transformTerm(ops.get(0), type, model, vars)); + final var op = checkNotNull(transformTerm(ops.get(0), type, model, vars), "Unsupported expression: was not able to deduce all types"); return function.apply(op); } }; @@ -599,8 +676,8 @@ private OperatorCreatorFunction exprUnaryOperator(final UnaryOperator> f private OperatorCreatorFunction exprBinaryOperator(final BinaryOperator> function) { return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 2); + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 2, "Binary operator expected"); if(type == null) { var op1 = transformTerm(ops.get(0), null, model, vars); @@ -609,10 +686,10 @@ private OperatorCreatorFunction exprBinaryOperator(final BinaryOperator> return null; } else if(op1 != null && op2 == null) { - op2 = checkNotNull(transformTerm(ops.get(1), op1.getType(), model, vars)); + op2 = checkNotNull(transformTerm(ops.get(1), op1.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); } else if(op1 == null /* && op2 != null */) { - op1 = checkNotNull(transformTerm(ops.get(0), op2.getType(), model, vars)); + op1 = checkNotNull(transformTerm(ops.get(0), op2.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); } return function.apply(op1, op2); } @@ -627,8 +704,8 @@ else if(op1 == null /* && op2 != null */) { private OperatorCreatorFunction exprRelationalOperator(final BinaryOperator> function) { return (params, ops, type, model, vars) -> { assert type == null || type.equals(Bool()); - checkArgument(params.size() == 0); - checkArgument(ops.size() == 2); + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 2, "Binary operator expected"); var op1 = transformTerm(ops.get(0), null, model, vars); var op2 = transformTerm(ops.get(1), null, model, vars); @@ -636,10 +713,10 @@ private OperatorCreatorFunction exprRelationalOperator(final BinaryOperator { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 2); + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 2, "Binary operator expected"); var op1 = transformTerm(ops.get(0), null, model, vars); var op2 = transformTerm(ops.get(1), null, model, vars); @@ -658,7 +735,7 @@ private OperatorCreatorFunction exprArrayReadOperator() { else if(op1 != null && op2 == null) { assert op1.getType() instanceof ArrayType; final var arrayType = (ArrayType) op1.getType(); - op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars)); + op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars), "Unsupported expression: was not able to deduce all types"); } else if(op1 == null /* && op2 != null */) { if(type == null) { @@ -666,7 +743,7 @@ else if(op1 == null /* && op2 != null */) { } else { final var arrayType = Array(op2.getType(), type); - op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars)); + op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars), "Unsupported expression: was not able to deduce all types"); } } return ArrayReadExpr.create(op1, op2); @@ -675,8 +752,8 @@ else if(op1 == null /* && op2 != null */) { private OperatorCreatorFunction exprMinusOperator() { return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 1 || ops.size() == 2); + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 1 || ops.size() == 2, "Unary or binary operator expected"); if(ops.size() == 2) { return exprBinaryOperator(SubExpr::create2).apply(params, ops, type, model, vars); } @@ -689,8 +766,8 @@ private OperatorCreatorFunction exprMinusOperator() { @SuppressWarnings("unused") private OperatorCreatorFunction exprTernaryOperator(final TernaryOperator> function) { return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 3); + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 3, "Ternary operator expected"); final Expr op1 = transformTerm(ops.get(0), type, model, vars); final Expr op2 = transformTerm(ops.get(1), type, model, vars); final Expr op3 = transformTerm(ops.get(2), type, model, vars); @@ -700,8 +777,8 @@ private OperatorCreatorFunction exprTernaryOperator(final TernaryOperator { - checkArgument(params.size() == 0); - checkArgument(ops.size() == 3); + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 3, "Ternary operator expected"); final var op1 = transformTerm(ops.get(0), Bool(), model, vars); if(type == null) { var op2 = transformTerm(ops.get(1), type, model, vars); @@ -710,10 +787,10 @@ private OperatorCreatorFunction exprIteOperator() { return null; } else if(op2 != null && op3 == null) { - op3 = checkNotNull(transformTerm(ops.get(2), op2.getType(), model, vars)); + op3 = checkNotNull(transformTerm(ops.get(2), op2.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); } else if(op2 == null /* && op3 != null */) { - op2 = checkNotNull(transformTerm(ops.get(1), op3.getType(), model, vars)); + op2 = checkNotNull(transformTerm(ops.get(1), op3.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); } return IteExpr.create(op1, op2, op3); } @@ -728,8 +805,8 @@ else if(op2 == null /* && op3 != null */) { private OperatorCreatorFunction exprArrayWriteOperator() { return (params, ops, type, model, vars) -> { assert type == null || type instanceof ArrayType; - checkArgument(params.size() == 0); - checkArgument(ops.size() == 3); + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 3, "Ternary operator expected"); if(type == null) { var op1 = transformTerm(ops.get(0), null, model, vars); @@ -739,15 +816,15 @@ private OperatorCreatorFunction exprArrayWriteOperator() { if(op1 != null && (op2 == null || op3 == null)) { final var arrayType = (ArrayType) op1.getType(); if(op2 == null) { - op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars)); + op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars), "Unsupported expression: was not able to deduce all types"); } if(op3 == null) { - op3 = checkNotNull(transformTerm(ops.get(2), arrayType.getElemType(), model, vars)); + op3 = checkNotNull(transformTerm(ops.get(2), arrayType.getElemType(), model, vars), "Unsupported expression: was not able to deduce all types"); } } else if(op1 == null && op2 != null && op3 != null) { final var arrayType = Array(op2.getType(), op3.getType()); - op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars)); + op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars), "Unsupported expression: was not able to deduce all types"); } else { return null; @@ -766,7 +843,7 @@ else if(op1 == null && op2 != null && op3 != null) { private OperatorCreatorFunction exprMultiaryOperator(final Function>, Expr> function) { return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0); + checkArgument(params.size() == 0, "No parameters expected"); if(type == null) { final var transformedOps = new ArrayList>(); ops.stream() @@ -796,27 +873,45 @@ private interface OperatorCreatorFunction extends QuintFunction< List, // Operands Type, // Expected type of result GetModelResponse, // The model - BiMap, String>, // The variable (param) store + BiMap, // The variable (param) store Expr // Return type > {} - private final static class DummyType implements Type {} + private final static class ParamTypeDeducer { + private final String name; + private Type type; + private ParamDecl paramDecl; - private final static class ParamTypeDeducedException extends RuntimeException { - private final ParamDecl decl; - private final Type type; + public ParamTypeDeducer(final String name, final Type type) { + this.name = name; + if(type != null) { + setType(type); + } + } - public ParamTypeDeducedException(ParamDecl decl, Type type) { - this.decl = decl; + public boolean isTypeUnknown() { + return type == null; + } + + public void setType(final Type type) { + checkArgument(type != null); + checkState(this.type == null); this.type = type; + this.paramDecl = Decls.Param(name, type); + } + + public String getName() { + return name; } - public ParamDecl getDecl() { - return decl; + public ParamDecl getParamDecl() { + checkState(paramDecl != null); + return paramDecl; } - public Type getType() { - return type; + public RefExpr getRef() { + checkState(paramDecl != null); + return paramDecl.getRef(); } } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java index 89e15a1c94..945c1b21ae 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java @@ -1,22 +1,14 @@ package hu.bme.mit.theta.solver.smtlib.parser; import hu.bme.mit.theta.common.Tuple2; -import hu.bme.mit.theta.core.type.Expr; -import hu.bme.mit.theta.core.type.inttype.IntExprs; -import hu.bme.mit.theta.core.type.rattype.RatExprs; -import hu.bme.mit.theta.core.utils.BvUtils; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; -import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.misc.Interval; -import java.math.BigDecimal; -import java.math.BigInteger; import java.util.Collection; import java.util.Map; import java.util.stream.Collectors; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.*; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Get_model_responseContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Model_response_funContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Model_response_fun_recContext; @@ -33,7 +25,7 @@ public static GetModelResponse fromContext(final Get_model_responseContext ctx) return new GetModelResponse(ctx.model_response().stream().map(member -> member.accept(new SMTLIBv2BaseVisitor>() { @Override public Tuple2 visitModel_response_fun(Model_response_funContext ctx) { - return Tuple2.of(extractString(ctx.function_def().symbol()), extractString(ctx.function_def().term())); + return Tuple2.of(extractString(ctx.function_def().symbol()), extractString(ctx.function_def())); } @Override @@ -48,6 +40,10 @@ public Tuple2 visitModel_response_funs_rec(Model_response_funs_r })).collect(Collectors.toUnmodifiableMap(Tuple2::get1, Tuple2::get2))); } + public static GetModelResponse empty() { + return new GetModelResponse(Map.of()); + } + public Collection getDecls() { return values.keySet(); } From 0c85c056a3495da19a900dbc69ab778d594c0067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 30 Aug 2020 13:51:10 +0200 Subject: [PATCH 31/99] Add function literal test --- .../mit/theta/solver/smtlib/SmtLibSolverTest.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index 31f3cf1409..bc3a6cf545 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -6,28 +6,23 @@ import hu.bme.mit.theta.core.model.Valuation; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.LitExpr; -import hu.bme.mit.theta.core.type.abstracttype.EqExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayExprs; import hu.bme.mit.theta.core.type.arraytype.ArrayLitExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.booltype.BoolExprs; import hu.bme.mit.theta.core.type.booltype.BoolType; -import hu.bme.mit.theta.core.type.booltype.ExistsExpr; import hu.bme.mit.theta.core.type.booltype.ForallExpr; import hu.bme.mit.theta.core.type.bvtype.BvExprs; -import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; import hu.bme.mit.theta.core.type.bvtype.BvType; import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.type.inttype.IntExprs; import hu.bme.mit.theta.core.type.inttype.IntType; -import hu.bme.mit.theta.core.utils.BvUtils; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; import org.junit.BeforeClass; import org.junit.Test; -import java.math.BigInteger; import java.nio.file.Path; import java.util.List; import java.util.Optional; @@ -38,7 +33,6 @@ import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Read; import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Write; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; import static hu.bme.mit.theta.core.type.functype.FuncExprs.App; @@ -69,7 +63,7 @@ public void test() { symbolTable.put(x, "x", "(declare-fun x () (_ BitVec 4))"); final var expr = termTransformer.toExpr( - "(forall ((y (Array (_ BitVec 4) Int))) (= (select y x) 0))", + "z () Bool (forall ((y (Array (_ BitVec 4) Int))) (= (select y x) 0))", BoolExprs.Bool(), GetModelResponse.empty() ); assertNotNull(expr); @@ -183,6 +177,12 @@ public void testFunc() { // Act final SolverStatus status = solver.check(); assertTrue(status.isSat()); + final Valuation model = solver.getModel(); + final Optional>> optVal = model.eval(ca); + final Expr> val = optVal.get(); + + // Assert + assertEquals(ca.getType(), val.getType()); } @Test From 5b3ec7e56a310095bbc502a3eae47db13cdce080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 30 Aug 2020 14:33:11 +0200 Subject: [PATCH 32/99] Move unsat core capabilities to separate UCSolver interface --- .../refinement/ExprTraceUnsatCoreChecker.java | 8 +-- .../analysis/expr/ExprTraceCheckersTest.java | 12 ++-- .../bme/mit/theta/solver/z3/Z3ItpSolver.java | 14 +---- .../hu/bme/mit/theta/solver/z3/Z3Solver.java | 3 +- .../mit/theta/solver/z3/Z3SolverFactory.java | 13 +++++ .../java/hu/bme/mit/theta/solver/Solver.java | 32 +---------- .../bme/mit/theta/solver/SolverFactory.java | 6 ++ .../bme/mit/theta/solver/impl/NullSolver.java | 10 ---- .../hu/bme/mit/theta/solver/SolverStub.java | 9 --- .../mit/theta/solver/smtlib/SmtLibSolver.java | 3 +- .../solver/smtlib/SmtLibSolverFactory.java | 10 ++++ .../theta/solver/smtlib/SmtLibSolverTest.java | 7 ++- .../hu/bme/mit/theta/solver/UCSolver.java | 50 +++++++++++++++++ .../sts/analysis/config/StsConfigBuilder.java | 56 +++++++++++-------- .../mit/theta/sts/analysis/StsExplTest.java | 46 ++++++++------- 15 files changed, 159 insertions(+), 120 deletions(-) create mode 100644 subprojects/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUnsatCoreChecker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUnsatCoreChecker.java index 60360a1f25..1595565a74 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUnsatCoreChecker.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUnsatCoreChecker.java @@ -33,7 +33,7 @@ import hu.bme.mit.theta.core.utils.IndexedVars; import hu.bme.mit.theta.core.utils.PathUtils; import hu.bme.mit.theta.core.utils.VarIndexing; -import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.utils.WithPushPop; /** @@ -42,18 +42,18 @@ */ public final class ExprTraceUnsatCoreChecker implements ExprTraceChecker { - private final Solver solver; + private final UCSolver solver; private final Expr init; private final Expr target; - private ExprTraceUnsatCoreChecker(final Expr init, final Expr target, final Solver solver) { + private ExprTraceUnsatCoreChecker(final Expr init, final Expr target, final UCSolver solver) { this.solver = checkNotNull(solver); this.init = checkNotNull(init); this.target = checkNotNull(target); } public static ExprTraceUnsatCoreChecker create(final Expr init, final Expr target, - final Solver solver) { + final UCSolver solver) { return new ExprTraceUnsatCoreChecker(init, target, solver); } diff --git a/subprojects/common/analysis/src/test/java/hu/bme/mit/theta/analysis/expr/ExprTraceCheckersTest.java b/subprojects/common/analysis/src/test/java/hu/bme/mit/theta/analysis/expr/ExprTraceCheckersTest.java index 1eeff7ace9..567c90491d 100644 --- a/subprojects/common/analysis/src/test/java/hu/bme/mit/theta/analysis/expr/ExprTraceCheckersTest.java +++ b/subprojects/common/analysis/src/test/java/hu/bme/mit/theta/analysis/expr/ExprTraceCheckersTest.java @@ -33,6 +33,7 @@ import java.util.Collection; import java.util.List; +import hu.bme.mit.theta.solver.UCSolver; import org.junit.Before; import org.junit.Test; @@ -55,12 +56,13 @@ public final class ExprTraceCheckersTest { @Before public void before() { - final ItpSolver solver = Z3SolverFactory.getInstance().createItpSolver(); + final ItpSolver itpSolver = Z3SolverFactory.getInstance().createItpSolver(); + final UCSolver ucSolver = Z3SolverFactory.getInstance().createUCSolver(); traceCheckers = new ArrayList<>(); - traceCheckers.add(ExprTraceSeqItpChecker.create(True(), True(), solver)); - traceCheckers.add(ExprTraceFwBinItpChecker.create(True(), True(), solver)); - traceCheckers.add(ExprTraceBwBinItpChecker.create(True(), True(), solver)); - traceCheckers.add(ExprTraceUnsatCoreChecker.create(True(), True(), solver)); + traceCheckers.add(ExprTraceSeqItpChecker.create(True(), True(), itpSolver)); + traceCheckers.add(ExprTraceFwBinItpChecker.create(True(), True(), itpSolver)); + traceCheckers.add(ExprTraceBwBinItpChecker.create(True(), True(), itpSolver)); + traceCheckers.add(ExprTraceUnsatCoreChecker.create(True(), True(), ucSolver)); } @Test diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java b/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java index 7e392db51e..96ca76ee79 100644 --- a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java +++ b/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java @@ -32,12 +32,13 @@ import hu.bme.mit.theta.solver.ItpMarker; import hu.bme.mit.theta.solver.ItpPattern; import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.Stack; import hu.bme.mit.theta.solver.impl.ItpPatternImpl; import hu.bme.mit.theta.solver.impl.StackImpl; -final class Z3ItpSolver implements ItpSolver { +final class Z3ItpSolver implements ItpSolver, Solver { private final Z3TransformationManager transformationManager; private final Z3TermTransformer termTransformer; @@ -149,12 +150,6 @@ public void add(final Expr assertion) { solver.add(assertion); } - @Override - public void track(final Expr assertion) { - checkNotNull(assertion); - solver.track(assertion); - } - @Override public SolverStatus check() { return solver.check(); @@ -193,11 +188,6 @@ public Valuation getModel() { return solver.getModel(); } - @Override - public Collection> getUnsatCore() { - return solver.getUnsatCore(); - } - @Override public Collection> getAssertions() { return solver.getAssertions(); diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java b/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java index 6a58baccba..5edbd4064d 100644 --- a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java +++ b/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java @@ -44,10 +44,11 @@ import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.Stack; +import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.UnknownSolverStatusException; import hu.bme.mit.theta.solver.impl.StackImpl; -final class Z3Solver implements Solver { +final class Z3Solver implements UCSolver, Solver { private final Z3SymbolTable symbolTable; private final Z3TransformationManager transformationManager; diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverFactory.java b/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverFactory.java index 305ec9af22..26e0e72674 100644 --- a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverFactory.java +++ b/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverFactory.java @@ -21,6 +21,7 @@ import hu.bme.mit.theta.solver.ItpSolver; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.UCSolver; public final class Z3SolverFactory implements SolverFactory { @@ -63,6 +64,18 @@ public Solver createSolver() { return new Z3Solver(symbolTable, transformationManager, termTransformer, z3Context, z3Solver); } + @Override + public UCSolver createUCSolver() { + final com.microsoft.z3.Context z3Context = new com.microsoft.z3.Context(); + final com.microsoft.z3.Solver z3Solver = z3Context.mkSimpleSolver(); + + final Z3SymbolTable symbolTable = new Z3SymbolTable(); + final Z3TransformationManager transformationManager = new Z3TransformationManager(symbolTable, z3Context); + final Z3TermTransformer termTransformer = new Z3TermTransformer(symbolTable); + + return new Z3Solver(symbolTable, transformationManager, termTransformer, z3Context, z3Solver); + } + @Override public ItpSolver createItpSolver() { final InterpolationContext z3Context = InterpolationContext.mkContext(); diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java index 35eba40709..65d5848f8a 100644 --- a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java +++ b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java @@ -24,7 +24,7 @@ /** * Common interface for SMT solvers. * - * Use the {@link #add(Expr)} or {@link #track(Expr)} methods to add expressions to the solver. + * Use the {@link #add(Expr)} methods to add expressions to the solver. * Then use {@link #check()} method to check their satisfiability. The result can be queried by * {@link #getStatus()}. If the expressions are satisfiable, a satisfying assignment can be * obtained by {@link #getModel()}. @@ -51,25 +51,6 @@ default void add(final Iterable> assertions) { } } - /** - * Add and track an expression. Required to calculate unsat cores. - * If you don't need unsat cores you can simply use {@link #add(Expr)}. - * - * @param assertion Expression to be tracked - */ - void track(Expr assertion); - - /** - * Add and track a collection of expressions. - * - * @param assertions Expressions to be tracked - */ - default void track(final Iterable> assertions) { - for (final Expr assertion : assertions) { - track(assertion); - } - } - /** * Check if the currently added expressions are satisfiable. * @@ -120,17 +101,6 @@ default void pop() { */ Valuation getModel(); - /** - * Get an unsat core, i.e., a (not necessarily) minimal subset of the - * expressions that are already unsatisfiable. It only works if expressions - * were added by {@link #track(Expr)} or {@link #track(Iterable)} instead of - * {@link #add(Expr)} or {@link #add(Iterable)}. Furthermore, it should only - * be called if {@link #check()} was already called and the result is UNSAT. - * - * @return Unsat core - */ - Collection> getUnsatCore(); - /** * Get the currently added expressions. * diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java index 0c74e0d3ef..e8bac9f596 100644 --- a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java +++ b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java @@ -26,6 +26,12 @@ public interface SolverFactory { */ Solver createSolver(); + /** + * Create a solver that is capable of producing unsat cores. + * @return Solver instance + */ + UCSolver createUCSolver(); + /** * Create a solver that is capable of interpolation. * @return Solver instance diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java index bd355cb0a5..d5b7d45055 100644 --- a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java +++ b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java @@ -41,11 +41,6 @@ public void add(final Expr assertion) { throw new UnsupportedOperationException(); } - @Override - public void track(final Expr assertion) { - throw new UnsupportedOperationException(); - } - @Override public SolverStatus check() { throw new UnsupportedOperationException(); @@ -76,11 +71,6 @@ public Valuation getModel() { throw new UnsupportedOperationException(); } - @Override - public Collection> getUnsatCore() { - throw new UnsupportedOperationException(); - } - @Override public Collection> getAssertions() { throw new UnsupportedOperationException(); diff --git a/subprojects/common/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java b/subprojects/common/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java index 1ce4403da7..78b76d2eee 100644 --- a/subprojects/common/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java +++ b/subprojects/common/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java @@ -33,10 +33,6 @@ public SolverStub() { public void add(final Expr assertion) { } - @Override - public void track(final Expr assertion) { - } - @Override public SolverStatus check() { return null; @@ -66,11 +62,6 @@ public Valuation getModel() { return null; } - @Override - public Collection> getUnsatCore() { - return null; - } - @Override public Collection> getAssertions() { return null; diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java index 3fd6b8f9ad..54e113dbaa 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java @@ -15,6 +15,7 @@ import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.Stack; +import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.UnknownSolverStatusException; import hu.bme.mit.theta.solver.impl.StackImpl; import hu.bme.mit.theta.solver.smtlib.binary.ContinousSolverBinary; @@ -43,7 +44,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -public class SmtLibSolver implements Solver { +public class SmtLibSolver implements UCSolver, Solver { private final SolverBinary solverBinary; private final SmtLibSymbolTable symbolTable; diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java index 2867a0ae05..22e0253ae7 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java @@ -3,6 +3,7 @@ import hu.bme.mit.theta.solver.ItpSolver; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.UCSolver; import java.nio.file.Path; @@ -28,6 +29,15 @@ public Solver createSolver() { return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverPath, args); } + @Override + public UCSolver createUCSolver() { + final var symbolTable = new SmtLibSymbolTable(); + final var transformationManager = new SmtLibTransformationManager(symbolTable); + final var termTransformer = new SmtLibTermTransformer(symbolTable); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverPath, args); + } + @Override public ItpSolver createItpSolver() { throw new UnsupportedOperationException("SmtLibSolver does not support interpolation"); diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index bc3a6cf545..8f185d1f69 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -19,6 +19,7 @@ import hu.bme.mit.theta.core.type.inttype.IntType; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; import org.junit.BeforeClass; import org.junit.Test; @@ -96,7 +97,7 @@ public void testSimple() { @Test public void testTrack() { - final Solver solver = solverFactory.createSolver(); + final UCSolver solver = solverFactory.createUCSolver(); final ConstDecl ca = Const("a", BoolExprs.Bool()); final Expr expr = BoolExprs.And(ca.getRef(), True()); @@ -113,7 +114,7 @@ public void testTrack() { @Test public void testUnsatCore() { - final Solver solver = solverFactory.createSolver(); + final UCSolver solver = solverFactory.createUCSolver(); final ConstDecl x = Const("x", IntExprs.Int()); final ConstDecl y = Const("y", IntExprs.Int()); @@ -136,7 +137,7 @@ public void testUnsatCore() { @Test public void testModel() { - final Solver solver = solverFactory.createSolver(); + final UCSolver solver = solverFactory.createUCSolver(); final ConstDecl x = Const("x", IntExprs.Int()); final ConstDecl y = Const("y", IntExprs.Int()); diff --git a/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java b/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java new file mode 100644 index 0000000000..e998ed51b9 --- /dev/null +++ b/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java @@ -0,0 +1,50 @@ +package hu.bme.mit.theta.solver; + +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolType; + +import java.util.Collection; + +/** + * Common interface for SMT solvers with unsat core capabilities. + * + * Use the {@link #add(Expr)} or {@link #track(Expr)} methods to add expressions to the solver. + * Then use {@link #check()} method to check their satisfiability. The result can be queried by + * {@link #getStatus()}. If the expressions are satisfiable, a satisfying assignment can be + * obtained by {@link #getModel()}. If the expressions are not satisfiable, use {@link #getUnsatCore()} + * to obtain the unsat core. + * + * The solver can also support incremental solving by {@link #push()} and {@link #pop()}. + */ +public interface UCSolver extends Solver { + + /** + * Add and track an expression. Required to calculate unsat cores. + * If you don't need unsat cores you can simply use {@link #add(Expr)}. + * + * @param assertion Expression to be tracked + */ + void track(Expr assertion); + + /** + * Add and track a collection of expressions. + * + * @param assertions Expressions to be tracked + */ + default void track(final Iterable> assertions) { + for (final Expr assertion : assertions) { + track(assertion); + } + } + + /** + * Get an unsat core, i.e., a (not necessarily) minimal subset of the + * expressions that are already unsatisfiable. It only works if expressions + * were added by {@link #track(Expr)} or {@link #track(Iterable)} instead of + * {@link #add(Expr)} or {@link #add(Iterable)}. Furthermore, it should only + * be called if {@link #check()} was already called and the result is UNSAT. + * + * @return Unsat core + */ + Collection> getUnsatCore(); +} diff --git a/subprojects/sts/sts-analysis/src/main/java/hu/bme/mit/theta/sts/analysis/config/StsConfigBuilder.java b/subprojects/sts/sts-analysis/src/main/java/hu/bme/mit/theta/sts/analysis/config/StsConfigBuilder.java index 622f322c96..fd3dbc2b3f 100644 --- a/subprojects/sts/sts-analysis/src/main/java/hu/bme/mit/theta/sts/analysis/config/StsConfigBuilder.java +++ b/subprojects/sts/sts-analysis/src/main/java/hu/bme/mit/theta/sts/analysis/config/StsConfigBuilder.java @@ -15,10 +15,6 @@ */ package hu.bme.mit.theta.sts.analysis.config; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; - -import java.util.function.Predicate; - import hu.bme.mit.theta.analysis.Action; import hu.bme.mit.theta.analysis.Analysis; import hu.bme.mit.theta.analysis.LTS; @@ -42,7 +38,16 @@ import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.analysis.expr.ExprState; import hu.bme.mit.theta.analysis.expr.ExprStatePredicate; -import hu.bme.mit.theta.analysis.expr.refinement.*; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceBwBinItpChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceFwBinItpChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceSeqItpChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceUnsatCoreChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ItpRefutation; +import hu.bme.mit.theta.analysis.expr.refinement.JoiningPrecRefiner; +import hu.bme.mit.theta.analysis.expr.refinement.MultiExprTraceRefiner; +import hu.bme.mit.theta.analysis.expr.refinement.PruneStrategy; +import hu.bme.mit.theta.analysis.expr.refinement.SingleExprTraceRefiner; import hu.bme.mit.theta.analysis.pred.ExprSplitters; import hu.bme.mit.theta.analysis.pred.ExprSplitters.ExprSplitter; import hu.bme.mit.theta.analysis.pred.ItpRefToPredPrec; @@ -56,7 +61,7 @@ import hu.bme.mit.theta.common.logging.NullLogger; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.booltype.BoolType; -import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.sts.STS; import hu.bme.mit.theta.sts.analysis.StsAction; @@ -65,6 +70,10 @@ import hu.bme.mit.theta.sts.analysis.initprec.StsInitPrec; import hu.bme.mit.theta.sts.analysis.initprec.StsPropInitPrec; +import java.util.function.Predicate; + +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; + public final class StsConfigBuilder { public enum Domain { @@ -154,14 +163,14 @@ public StsConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { } public StsConfig build(final STS sts) { - final ItpSolver solver = solverFactory.createItpSolver(); final LTS lts = StsLts.create(sts); final Expr init = sts.getInit(); final Expr negProp = Not(sts.getProp()); if (domain == Domain.EXPL) { - final Predicate target = new ExplStatePredicate(negProp, solver); - final Analysis analysis = ExplAnalysis.create(solver, init); + final Solver analysisSolver = solverFactory.createSolver(); + final Predicate target = new ExplStatePredicate(negProp, analysisSolver); + final Analysis analysis = ExplAnalysis.create(analysisSolver, init); final ArgBuilder argBuilder = ArgBuilder.create(lts, analysis, target, true); final Abstractor abstractor = BasicAbstractor.builder(argBuilder) @@ -174,23 +183,23 @@ public StsConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { switch (refinement) { case FW_BIN_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceFwBinItpChecker.create(init, negProp, solver), + refiner = SingleExprTraceRefiner.create(ExprTraceFwBinItpChecker.create(init, negProp, solverFactory.createItpSolver()), JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); break; case BW_BIN_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceBwBinItpChecker.create(init, negProp, solver), + refiner = SingleExprTraceRefiner.create(ExprTraceBwBinItpChecker.create(init, negProp, solverFactory.createItpSolver()), JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); break; case SEQ_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceSeqItpChecker.create(init, negProp, solver), + refiner = SingleExprTraceRefiner.create(ExprTraceSeqItpChecker.create(init, negProp, solverFactory.createItpSolver()), JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); break; case MULTI_SEQ: - refiner = MultiExprTraceRefiner.create(ExprTraceSeqItpChecker.create(init, negProp, solver), + refiner = MultiExprTraceRefiner.create(ExprTraceSeqItpChecker.create(init, negProp, solverFactory.createItpSolver()), JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); break; case UNSAT_CORE: - refiner = SingleExprTraceRefiner.create(ExprTraceUnsatCoreChecker.create(init, negProp, solver), + refiner = SingleExprTraceRefiner.create(ExprTraceUnsatCoreChecker.create(init, negProp, solverFactory.createUCSolver()), JoiningPrecRefiner.create(new VarsRefToExplPrec()), pruneStrategy, logger); break; default: @@ -204,22 +213,23 @@ public StsConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { return StsConfig.create(checker, prec); } else if (domain == Domain.PRED_BOOL || domain == Domain.PRED_CART || domain == Domain.PRED_SPLIT) { + final Solver analysisSolver = solverFactory.createSolver(); PredAbstractor predAbstractor = null; switch (domain) { case PRED_BOOL: - predAbstractor = PredAbstractors.booleanAbstractor(solver); + predAbstractor = PredAbstractors.booleanAbstractor(analysisSolver); break; case PRED_SPLIT: - predAbstractor = PredAbstractors.booleanSplitAbstractor(solver); + predAbstractor = PredAbstractors.booleanSplitAbstractor(analysisSolver); break; case PRED_CART: - predAbstractor = PredAbstractors.cartesianAbstractor(solver); + predAbstractor = PredAbstractors.cartesianAbstractor(analysisSolver); break; default: throw new UnsupportedOperationException(domain + " domain is not supported."); } - final Predicate target = new ExprStatePredicate(negProp, solver); - final Analysis analysis = PredAnalysis.create(solver, predAbstractor, + final Predicate target = new ExprStatePredicate(negProp, analysisSolver); + final Analysis analysis = PredAnalysis.create(analysisSolver, predAbstractor, init); final ArgBuilder argBuilder = ArgBuilder.create(lts, analysis, target, true); @@ -232,16 +242,16 @@ public StsConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { ExprTraceChecker exprTraceChecker = null; switch (refinement) { case FW_BIN_ITP: - exprTraceChecker = ExprTraceFwBinItpChecker.create(init, negProp, solver); + exprTraceChecker = ExprTraceFwBinItpChecker.create(init, negProp, solverFactory.createItpSolver()); break; case BW_BIN_ITP: - exprTraceChecker = ExprTraceBwBinItpChecker.create(init, negProp, solver); + exprTraceChecker = ExprTraceBwBinItpChecker.create(init, negProp, solverFactory.createItpSolver()); break; case SEQ_ITP: - exprTraceChecker = ExprTraceSeqItpChecker.create(init, negProp, solver); + exprTraceChecker = ExprTraceSeqItpChecker.create(init, negProp, solverFactory.createItpSolver()); break; case MULTI_SEQ: - exprTraceChecker = ExprTraceSeqItpChecker.create(init, negProp, solver); + exprTraceChecker = ExprTraceSeqItpChecker.create(init, negProp, solverFactory.createItpSolver()); break; default: throw new UnsupportedOperationException( diff --git a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java index de35443f5d..36637a0925 100644 --- a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java +++ b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java @@ -15,25 +15,6 @@ */ package hu.bme.mit.theta.sts.analysis; -import static hu.bme.mit.theta.analysis.algorithm.ArgUtils.isWellLabeled; -import static hu.bme.mit.theta.core.decl.Decls.Var; -import static hu.bme.mit.theta.core.type.anytype.Exprs.Prime; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.And; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Imply; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Add; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Eq; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Geq; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Lt; -import static org.junit.Assert.assertTrue; - -import java.util.Collections; -import java.util.function.Predicate; - -import hu.bme.mit.theta.analysis.expr.refinement.*; -import org.junit.Test; - import hu.bme.mit.theta.analysis.Analysis; import hu.bme.mit.theta.analysis.LTS; import hu.bme.mit.theta.analysis.State; @@ -52,6 +33,12 @@ import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.analysis.expr.ExprState; import hu.bme.mit.theta.analysis.expr.ExprStatePredicate; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceUnsatCoreChecker; +import hu.bme.mit.theta.analysis.expr.refinement.JoiningPrecRefiner; +import hu.bme.mit.theta.analysis.expr.refinement.PruneStrategy; +import hu.bme.mit.theta.analysis.expr.refinement.SingleExprTraceRefiner; +import hu.bme.mit.theta.analysis.expr.refinement.VarsRefutation; import hu.bme.mit.theta.analysis.waitlist.PriorityWaitlist; import hu.bme.mit.theta.common.logging.ConsoleLogger; import hu.bme.mit.theta.common.logging.Logger; @@ -59,10 +46,27 @@ import hu.bme.mit.theta.core.decl.VarDecl; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.inttype.IntType; -import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.z3.Z3SolverFactory; import hu.bme.mit.theta.sts.STS; import hu.bme.mit.theta.sts.STS.Builder; +import org.junit.Test; + +import java.util.Collections; +import java.util.function.Predicate; + +import static hu.bme.mit.theta.analysis.algorithm.ArgUtils.isWellLabeled; +import static hu.bme.mit.theta.core.decl.Decls.Var; +import static hu.bme.mit.theta.core.type.anytype.Exprs.Prime; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.And; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Imply; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Add; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Eq; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Geq; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Lt; +import static org.junit.Assert.assertTrue; public class StsExplTest { @@ -89,7 +93,7 @@ public void test() { final STS sts = builder.build(); - final ItpSolver solver = Z3SolverFactory.getInstance().createItpSolver(); + final UCSolver solver = Z3SolverFactory.getInstance().createUCSolver(); final Analysis analysis = ExplAnalysis.create(solver, sts.getInit()); final Predicate target = new ExprStatePredicate(Not(sts.getProp()), solver); From 15ec5cea5a28e799323923885a3dce1c10b92248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 30 Aug 2020 18:55:09 +0200 Subject: [PATCH 33/99] Add SmtLibItpSolver --- .../solver/smtlib/SmtLibInterpolant.java | 43 ++++++ .../theta/solver/smtlib/SmtLibItpMarker.java | 33 +++++ .../theta/solver/smtlib/SmtLibItpSolver.java | 128 ++++++++++++++++++ .../mit/theta/solver/smtlib/SmtLibSolver.java | 54 ++++---- .../solver/smtlib/SmtLibSolverFactory.java | 7 +- ...inary.java => ContinuousSolverBinary.java} | 4 +- 6 files changed, 240 insertions(+), 29 deletions(-) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java rename subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/{ContinousSolverBinary.java => ContinuousSolverBinary.java} (96%) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java new file mode 100644 index 0000000000..87fe02bc9d --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.solver.Interpolant; +import hu.bme.mit.theta.solver.ItpMarker; + +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; + +public class SmtLibInterpolant implements Interpolant { + + private final Map> itpMap; + + public SmtLibInterpolant(final Map> itpMap) { + this.itpMap = itpMap; + } + + @Override + public Expr eval(final ItpMarker marker) { + checkNotNull(marker); + final Expr itpExpr = itpMap.get(marker); + checkNotNull(itpExpr); + return itpExpr; + } + +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java new file mode 100644 index 0000000000..0158fd56f6 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java @@ -0,0 +1,33 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.Stack; +import hu.bme.mit.theta.solver.impl.StackImpl; + +import java.util.Collection; + +import static com.google.common.base.Preconditions.checkNotNull; + +public abstract class SmtLibItpMarker implements ItpMarker { + private final Stack terms; + + public SmtLibItpMarker() { + terms = new StackImpl<>(); + } + + public void add(final T term) { + terms.add(checkNotNull(term)); + } + + public void push() { + terms.push(); + } + + public void pop(final int n) { + terms.pop(n); + } + + public Collection getTerms() { + return terms.toCollection(); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java new file mode 100644 index 0000000000..58de36329c --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java @@ -0,0 +1,128 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.core.model.Valuation; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.solver.Interpolant; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpPattern; +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.Stack; +import hu.bme.mit.theta.solver.impl.ItpPatternImpl; +import hu.bme.mit.theta.solver.impl.StackImpl; +import hu.bme.mit.theta.solver.smtlib.binary.SolverBinary; + +import java.util.Collection; +import java.util.function.Supplier; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public abstract class SmtLibItpSolver> implements ItpSolver { + protected final SmtLibSolver solver; + protected final Stack markers; + protected final Supplier markerCreator; + + protected final SmtLibTransformationManager transformationManager; + protected final SmtLibTermTransformer termTransformer; + + public SmtLibItpSolver( + final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, + final SmtLibTermTransformer termTransformer, final SolverBinary solverBinary, + final Supplier markerCreator + ) { + this.solver = new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); + this.markers = new StackImpl<>(); + this.markerCreator = markerCreator; + + this.transformationManager = transformationManager; + this.termTransformer = termTransformer; + } + + @Override + public ItpPattern createPattern(ItpMarker marker) { + checkNotNull(marker); + checkArgument(marker instanceof SmtLibItpMarker); + return new ItpPatternImpl(marker); + } + + @Override + public ItpMarker createMarker() { + final ItpMarkerType marker = markerCreator.get(); + markers.add(marker); + return marker; + } + + @Override + public void add(ItpMarker marker, Expr assertion) { + checkNotNull(marker); + checkNotNull(assertion); + checkArgument(markers.toCollection().stream().map(m -> (ItpMarker) m).anyMatch(m -> m == marker)); + + final var term = transformationManager.toTerm(assertion); + add(marker, term); + } + + protected abstract String add(final ItpMarker marker, final String term); + + @Override + public abstract Interpolant getInterpolant(ItpPattern pattern); + + // Delegate + + @Override + public Collection getMarkers() { + return markers.toCollection(); + } + + @Override + public void add(Expr assertion) { + solver.add(assertion); + } + + @Override + public SolverStatus check() { + return solver.check(); + } + + @Override + public void push() { + markers.push(); + for (final var marker : markers) { + marker.push(); + } + solver.push(); + } + + @Override + public void pop(final int n) { + markers.pop(n); + for (final var marker : markers) { + marker.pop(n); + } + solver.pop(n); + } + + @Override + public void reset() { + solver.reset(); + } + + @Override + public SolverStatus getStatus() { + return solver.getStatus(); + } + + @Override + public Valuation getModel() { + return solver.getModel(); + } + + @Override + public Collection> getAssertions() { + return solver.getAssertions(); + } + + +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java index 54e113dbaa..e3621cc528 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java @@ -18,7 +18,6 @@ import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.UnknownSolverStatusException; import hu.bme.mit.theta.solver.impl.StackImpl; -import hu.bme.mit.theta.solver.smtlib.binary.ContinousSolverBinary; import hu.bme.mit.theta.solver.smtlib.binary.SolverBinary; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; @@ -30,31 +29,27 @@ import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; -import java.nio.file.Path; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedList; import java.util.Map; import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; public class SmtLibSolver implements UCSolver, Solver { - private final SolverBinary solverBinary; + protected final SolverBinary solverBinary; + private final boolean unsatCoreEnabled; - private final SmtLibSymbolTable symbolTable; - private final SmtLibTransformationManager transformationManager; - private final SmtLibTermTransformer termTransformer; + protected final SmtLibSymbolTable symbolTable; + protected final SmtLibTransformationManager transformationManager; + protected final SmtLibTermTransformer termTransformer; - private final Stack> assertions; - private final Map> assumptions; - private final Set> declarations; - private final Stack>> declarationStack; + protected final Stack> assertions; + protected final Map> assumptions; + protected final Stack> declarationStack; private static final String ASSUMPTION_LABEL = "_LABEL_%d"; private int labelNum = 0; @@ -65,17 +60,17 @@ public class SmtLibSolver implements UCSolver, Solver { public SmtLibSolver( final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, - final SmtLibTermTransformer termTransformer, final Path solverPath, final String[] args + final SmtLibTermTransformer termTransformer, final SolverBinary solverBinary, boolean unsatCoreEnabled ) { - this.solverBinary = new ContinousSolverBinary(solverPath, args); - this.symbolTable = symbolTable; this.transformationManager = transformationManager; this.termTransformer = termTransformer; + this.solverBinary = solverBinary; + this.unsatCoreEnabled = unsatCoreEnabled; + assertions = new StackImpl<>(); assumptions = new HashMap<>(); - declarations = new HashSet<>(); declarationStack = new StackImpl<>(); init(); @@ -84,8 +79,7 @@ public SmtLibSolver( @Override public void add(Expr assertion) { final var consts = ExprUtils.getConstants(assertion); - consts.removeAll(declarations); - declarations.addAll(consts); + consts.removeAll(declarationStack.toCollection()); declarationStack.add(consts); final var term = transformationManager.toTerm(assertion); @@ -96,11 +90,21 @@ public void add(Expr assertion) { clearState(); } + public void add(final Expr assertion, final String term) { + final var consts = ExprUtils.getConstants(assertion); + consts.removeAll(declarationStack.toCollection()); + declarationStack.add(consts); + + consts.stream().map(symbolTable::getDeclaration).forEach(this::issueGeneralCommand); + issueGeneralCommand(String.format("(assert %s)%n", term)); + + clearState(); + } + @Override public void track(Expr assertion) { final var consts = ExprUtils.getConstants(assertion); - consts.removeAll(declarations); - declarations.addAll(consts); + consts.removeAll(declarationStack.toCollection()); declarationStack.add(consts); final var term = transformationManager.toTerm(assertion); @@ -142,8 +146,6 @@ else if(checkSatResponse.isUnsat()) { public void push() { assertions.push(); declarationStack.push(); - declarations.clear(); - declarations.addAll(declarationStack.toCollection().stream().flatMap(Collection::stream).collect(Collectors.toSet())); issueGeneralCommand("(push)"); } @@ -240,10 +242,12 @@ public Collection> getAssertions() { return assertions.toCollection(); } - protected void init() { + private void init() { issueGeneralCommand("(set-option :print-success true)"); issueGeneralCommand("(set-option :produce-models true)"); - issueGeneralCommand("(set-option :produce-unsat-cores true)"); + if(unsatCoreEnabled) { + issueGeneralCommand("(set-option :produce-unsat-cores true)"); + } issueGeneralCommand("(set-logic ALL)"); } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java index 22e0253ae7..5908c5550d 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java @@ -4,6 +4,7 @@ import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.smtlib.binary.ContinuousSolverBinary; import java.nio.file.Path; @@ -25,8 +26,9 @@ public Solver createSolver() { final var symbolTable = new SmtLibSymbolTable(); final var transformationManager = new SmtLibTransformationManager(symbolTable); final var termTransformer = new SmtLibTermTransformer(symbolTable); + final var solverBinary = new ContinuousSolverBinary(solverPath, args); - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverPath, args); + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); } @Override @@ -34,8 +36,9 @@ public UCSolver createUCSolver() { final var symbolTable = new SmtLibSymbolTable(); final var transformationManager = new SmtLibTransformationManager(symbolTable); final var termTransformer = new SmtLibTermTransformer(symbolTable); + final var solverBinary = new ContinuousSolverBinary(solverPath, args); - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverPath, args); + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); } @Override diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinousSolverBinary.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinuousSolverBinary.java similarity index 96% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinousSolverBinary.java rename to subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinuousSolverBinary.java index 6e72446268..bc4f29dc48 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinousSolverBinary.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinuousSolverBinary.java @@ -13,13 +13,13 @@ import static com.google.common.base.Preconditions.checkState; -public final class ContinousSolverBinary implements SolverBinary { +public final class ContinuousSolverBinary implements SolverBinary { private final Process solverProcess; private final PrintWriter solverInput; private final Reader solverOutput; - public ContinousSolverBinary(final Path solverPath, final String[] args) { + public ContinuousSolverBinary(final Path solverPath, final String[] args) { final var processCmd = new ArrayList(); processCmd.add(solverPath.toAbsolutePath().toString()); processCmd.addAll(Arrays.asList(args)); From 11b6582f8d627f799403fbb763ad965d86552a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 30 Aug 2020 19:58:41 +0200 Subject: [PATCH 34/99] Refactor to generify SmtLibSolver interfaces --- .../solver/smtlib/SmtLibDeclTransformer.java | 92 +- .../solver/smtlib/SmtLibExprTransformer.java | 786 +-------------- .../theta/solver/smtlib/SmtLibItpSolver.java | 3 +- .../mit/theta/solver/smtlib/SmtLibModel.java | 20 + .../mit/theta/solver/smtlib/SmtLibSolver.java | 19 +- .../solver/smtlib/SmtLibSolverBinary.java | 5 + ....java => SmtLibSolverBinaryException.java} | 6 +- .../solver/smtlib/SmtLibSolverFactory.java | 48 - .../solver/smtlib/SmtLibSymbolTable.java | 49 +- .../solver/smtlib/SmtLibTermTransformer.java | 910 +---------------- .../smtlib/SmtLibTransformationManager.java | 38 +- .../solver/smtlib/SmtLibTypeTransformer.java | 63 +- .../solver/smtlib/SmtLibUCSolverBase.java | 17 + .../solver/smtlib/binary/SolverBinary.java | 5 - .../generic/GenericSmtLibDeclTransformer.java | 100 ++ .../generic/GenericSmtLibExprTransformer.java | 792 +++++++++++++++ .../GenericSmtLibSolverBinary.java} | 14 +- .../generic/GenericSmtLibSolverFactory.java | 48 + .../generic/GenericSmtLibSymbolTable.java | 59 ++ .../generic/GenericSmtLibTermTransformer.java | 926 ++++++++++++++++++ .../GenericSmtLibTransformationManager.java | 51 + .../generic/GenericSmtLibTypeTransformer.java | 68 ++ .../smtlib/parser/GetModelResponse.java | 18 +- .../solver/smtlib/SmtLibSolverBVTest.java | 3 +- .../theta/solver/smtlib/SmtLibSolverTest.java | 14 +- 25 files changed, 2146 insertions(+), 2008 deletions(-) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java rename subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{SmtLibSolverProcessFailureException.java => SmtLibSolverBinaryException.java} (80%) delete mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibUCSolverBase.java delete mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/SolverBinary.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java rename subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{binary/ContinuousSolverBinary.java => generic/GenericSmtLibSolverBinary.java} (89%) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java index d909b98f28..b80f851252 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java @@ -1,95 +1,9 @@ package hu.bme.mit.theta.solver.smtlib; -import com.google.common.collect.ImmutableList; -import hu.bme.mit.theta.common.Tuple2; -import hu.bme.mit.theta.core.decl.ConstDecl; import hu.bme.mit.theta.core.decl.Decl; -import hu.bme.mit.theta.core.type.Type; -import hu.bme.mit.theta.core.type.functype.FuncType; -import java.util.List; - -import static com.google.common.base.Preconditions.checkArgument; - -public class SmtLibDeclTransformer { - private final SmtLibTransformationManager transformer; - private final SmtLibSymbolTable symbolTable; - - private int symbolCount; - - public SmtLibDeclTransformer(final SmtLibTransformationManager transformer, final SmtLibSymbolTable symbolTable) { - this.transformer = transformer; - this.symbolTable = symbolTable; - - symbolCount = 0; - } - - public String toSymbol(final Decl decl) { - if (decl instanceof ConstDecl) { - final ConstDecl cdecl = (ConstDecl) decl; - if(!symbolTable.definesConst(cdecl)) { - transformConst(cdecl); - } - return symbolTable.getSymbol(cdecl); - } else { - throw new UnsupportedOperationException("Cannot transform declaration: " + decl); - } - } - - public String toDeclaration(final Decl decl) { - if (decl instanceof ConstDecl) { - final ConstDecl cdecl = (ConstDecl) decl; - if(!symbolTable.definesConst(cdecl)) { - transformConst(cdecl); - } - return symbolTable.getDeclaration(cdecl); - } else { - throw new UnsupportedOperationException("Cannot transform declaration: " + decl); - } - } - - private void transformConst(final ConstDecl decl) { - final Type type = decl.getType(); - - final Tuple2, Type> extractedTypes = extractTypes(type); - final List paramTypes = extractedTypes.get1(); - final Type returnType = extractedTypes.get2(); - - final String returnSort = transformer.toSort(returnType); - final String[] paramSorts = paramTypes.stream().map(transformer::toSort) - .toArray(String[]::new); - - final String symbolName = symbolNameFor(decl); - final String symbolDeclaration = String.format( - "(declare-fun %s (%s) %s)", - symbolName, String.join(" ", paramSorts), returnSort - ); - symbolTable.put(decl, symbolName, symbolDeclaration); - } - - private Tuple2, Type> extractTypes(final Type type) { - if (type instanceof FuncType) { - final FuncType funcType = (FuncType) type; - - final Type paramType = funcType.getParamType(); - final Type resultType = funcType.getResultType(); - - checkArgument(!(paramType instanceof FuncType)); - - final Tuple2, Type> subResult = extractTypes(resultType); - final List paramTypes = subResult.get1(); - final Type newResultType = subResult.get2(); - final List newParamTypes = ImmutableList.builder().add(paramType).addAll(paramTypes).build(); - final Tuple2, Type> result = Tuple2.of(newParamTypes, newResultType); - - return result; - } else { - return Tuple2.of(ImmutableList.of(), type); - } - } - - private String symbolNameFor(final Decl decl) { - return String.format("%s_%d", decl.getName(), symbolCount++); - } +public interface SmtLibDeclTransformer { + String toSymbol(Decl decl); + String toDeclaration(Decl decl); } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java index 14e2749758..717650fded 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java @@ -1,789 +1,7 @@ package hu.bme.mit.theta.solver.smtlib; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.collect.ImmutableList; -import hu.bme.mit.theta.common.DispatchTable; -import hu.bme.mit.theta.common.Tuple2; -import hu.bme.mit.theta.common.dsl.Env; -import hu.bme.mit.theta.core.decl.ConstDecl; -import hu.bme.mit.theta.core.decl.Decl; -import hu.bme.mit.theta.core.decl.ParamDecl; -import hu.bme.mit.theta.core.dsl.DeclSymbol; import hu.bme.mit.theta.core.type.Expr; -import hu.bme.mit.theta.core.type.Type; -import hu.bme.mit.theta.core.type.anytype.IteExpr; -import hu.bme.mit.theta.core.type.anytype.RefExpr; -import hu.bme.mit.theta.core.type.arraytype.ArrayEqExpr; -import hu.bme.mit.theta.core.type.arraytype.ArrayLitExpr; -import hu.bme.mit.theta.core.type.arraytype.ArrayNeqExpr; -import hu.bme.mit.theta.core.type.arraytype.ArrayReadExpr; -import hu.bme.mit.theta.core.type.arraytype.ArrayWriteExpr; -import hu.bme.mit.theta.core.type.booltype.AndExpr; -import hu.bme.mit.theta.core.type.booltype.ExistsExpr; -import hu.bme.mit.theta.core.type.booltype.FalseExpr; -import hu.bme.mit.theta.core.type.booltype.ForallExpr; -import hu.bme.mit.theta.core.type.booltype.IffExpr; -import hu.bme.mit.theta.core.type.booltype.ImplyExpr; -import hu.bme.mit.theta.core.type.booltype.NotExpr; -import hu.bme.mit.theta.core.type.booltype.OrExpr; -import hu.bme.mit.theta.core.type.booltype.TrueExpr; -import hu.bme.mit.theta.core.type.booltype.XorExpr; -import hu.bme.mit.theta.core.type.bvtype.BvAddExpr; -import hu.bme.mit.theta.core.type.bvtype.BvAndExpr; -import hu.bme.mit.theta.core.type.bvtype.BvArithShiftRightExpr; -import hu.bme.mit.theta.core.type.bvtype.BvDivExpr; -import hu.bme.mit.theta.core.type.bvtype.BvEqExpr; -import hu.bme.mit.theta.core.type.bvtype.BvGeqExpr; -import hu.bme.mit.theta.core.type.bvtype.BvGtExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLeqExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLogicShiftRightExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLtExpr; -import hu.bme.mit.theta.core.type.bvtype.BvModExpr; -import hu.bme.mit.theta.core.type.bvtype.BvMulExpr; -import hu.bme.mit.theta.core.type.bvtype.BvNegExpr; -import hu.bme.mit.theta.core.type.bvtype.BvNeqExpr; -import hu.bme.mit.theta.core.type.bvtype.BvNotExpr; -import hu.bme.mit.theta.core.type.bvtype.BvOrExpr; -import hu.bme.mit.theta.core.type.bvtype.BvPosExpr; -import hu.bme.mit.theta.core.type.bvtype.BvRemExpr; -import hu.bme.mit.theta.core.type.bvtype.BvRotateLeftExpr; -import hu.bme.mit.theta.core.type.bvtype.BvRotateRightExpr; -import hu.bme.mit.theta.core.type.bvtype.BvShiftLeftExpr; -import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; -import hu.bme.mit.theta.core.type.bvtype.BvToIntExpr; -import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; -import hu.bme.mit.theta.core.type.functype.FuncAppExpr; -import hu.bme.mit.theta.core.type.functype.FuncType; -import hu.bme.mit.theta.core.type.inttype.IntAddExpr; -import hu.bme.mit.theta.core.type.inttype.IntDivExpr; -import hu.bme.mit.theta.core.type.inttype.IntEqExpr; -import hu.bme.mit.theta.core.type.inttype.IntGeqExpr; -import hu.bme.mit.theta.core.type.inttype.IntGtExpr; -import hu.bme.mit.theta.core.type.inttype.IntLeqExpr; -import hu.bme.mit.theta.core.type.inttype.IntLitExpr; -import hu.bme.mit.theta.core.type.inttype.IntLtExpr; -import hu.bme.mit.theta.core.type.inttype.IntModExpr; -import hu.bme.mit.theta.core.type.inttype.IntMulExpr; -import hu.bme.mit.theta.core.type.inttype.IntNegExpr; -import hu.bme.mit.theta.core.type.inttype.IntNeqExpr; -import hu.bme.mit.theta.core.type.inttype.IntPosExpr; -import hu.bme.mit.theta.core.type.inttype.IntRemExpr; -import hu.bme.mit.theta.core.type.inttype.IntSubExpr; -import hu.bme.mit.theta.core.type.inttype.IntToBvExpr; -import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; -import hu.bme.mit.theta.core.type.rattype.RatAddExpr; -import hu.bme.mit.theta.core.type.rattype.RatDivExpr; -import hu.bme.mit.theta.core.type.rattype.RatEqExpr; -import hu.bme.mit.theta.core.type.rattype.RatGeqExpr; -import hu.bme.mit.theta.core.type.rattype.RatGtExpr; -import hu.bme.mit.theta.core.type.rattype.RatLeqExpr; -import hu.bme.mit.theta.core.type.rattype.RatLitExpr; -import hu.bme.mit.theta.core.type.rattype.RatLtExpr; -import hu.bme.mit.theta.core.type.rattype.RatMulExpr; -import hu.bme.mit.theta.core.type.rattype.RatNegExpr; -import hu.bme.mit.theta.core.type.rattype.RatNeqExpr; -import hu.bme.mit.theta.core.type.rattype.RatPosExpr; -import hu.bme.mit.theta.core.type.rattype.RatSubExpr; -import hu.bme.mit.theta.core.utils.BvUtils; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ExecutionException; - -public class SmtLibExprTransformer { - private static final int CACHE_SIZE = 1000; - - private final SmtLibTransformationManager transformer; - - private final Cache, String> exprToTerm; - private final DispatchTable table; - private final Env env; - - public SmtLibExprTransformer(final SmtLibTransformationManager transformer) { - this.transformer = transformer; - this.env = new Env(); - - this.exprToTerm = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).build(); - - this.table = DispatchTable.builder() - - // General - - .addCase(RefExpr.class, this::transformRef) - - .addCase(IteExpr.class, this::transformIte) - - // Boolean - - .addCase(FalseExpr.class, this::transformFalse) - - .addCase(TrueExpr.class, this::transformTrue) - - .addCase(NotExpr.class, this::transformNot) - - .addCase(ImplyExpr.class, this::transformImply) - - .addCase(IffExpr.class, this::transformIff) - - .addCase(XorExpr.class, this::transformXor) - - .addCase(AndExpr.class, this::transformAnd) - - .addCase(OrExpr.class, this::transformOr) - - .addCase(ExistsExpr.class, this::transformExists) - - .addCase(ForallExpr.class, this::transformForall) - - // Rationals - - .addCase(RatLitExpr.class, this::transformRatLit) - - .addCase(RatAddExpr.class, this::transformRatAdd) - - .addCase(RatSubExpr.class, this::transformRatSub) - - .addCase(RatPosExpr.class, this::transformRatPos) - - .addCase(RatNegExpr.class, this::transformRatNeg) - - .addCase(RatMulExpr.class, this::transformRatMul) - - .addCase(RatDivExpr.class, this::transformRatDiv) - - .addCase(RatEqExpr.class, this::transformRatEq) - - .addCase(RatNeqExpr.class, this::transformRatNeq) - - .addCase(RatGeqExpr.class, this::transformRatGeq) - - .addCase(RatGtExpr.class, this::transformRatGt) - - .addCase(RatLeqExpr.class, this::transformRatLeq) - - .addCase(RatLtExpr.class, this::transformRatLt) - - // Integers - - .addCase(IntLitExpr.class, this::transformIntLit) - - .addCase(IntAddExpr.class, this::transformIntAdd) - - .addCase(IntSubExpr.class, this::transformIntSub) - - .addCase(IntPosExpr.class, this::transformIntPos) - - .addCase(IntNegExpr.class, this::transformIntNeg) - - .addCase(IntMulExpr.class, this::transformIntMul) - - .addCase(IntDivExpr.class, this::transformIntDiv) - - .addCase(IntModExpr.class, this::transformIntMod) - - .addCase(IntRemExpr.class, this::transformIntRem) - - .addCase(IntEqExpr.class, this::transformIntEq) - - .addCase(IntNeqExpr.class, this::transformIntNeq) - - .addCase(IntGeqExpr.class, this::transformIntGeq) - - .addCase(IntGtExpr.class, this::transformIntGt) - - .addCase(IntLeqExpr.class, this::transformIntLeq) - - .addCase(IntLtExpr.class, this::transformIntLt) - - .addCase(IntToRatExpr.class, this::transformIntToRat) - - .addCase(IntToBvExpr.class, this::transformIntToBv) - - // Bitvectors - - .addCase(BvLitExpr.class, this::transformBvLit) - - .addCase(BvAddExpr.class, this::transformBvAdd) - - .addCase(BvSubExpr.class, this::transformBvSub) - - .addCase(BvPosExpr.class, this::transformBvPos) - - .addCase(BvNegExpr.class, this::transformBvNeg) - - .addCase(BvMulExpr.class, this::transformBvMul) - - .addCase(BvDivExpr.class, this::transformBvDiv) - - .addCase(BvModExpr.class, this::transformBvMod) - - .addCase(BvRemExpr.class, this::transformBvRem) - - .addCase(BvAndExpr.class, this::transformBvAnd) - - .addCase(BvOrExpr.class, this::transformBvOr) - - .addCase(BvXorExpr.class, this::transformBvXor) - - .addCase(BvNotExpr.class, this::transformBvNot) - - .addCase(BvShiftLeftExpr.class, this::transformBvShiftLeft) - - .addCase(BvArithShiftRightExpr.class, this::transformBvArithShiftRight) - - .addCase(BvLogicShiftRightExpr.class, this::transformBvLogicShiftRight) - - .addCase(BvRotateLeftExpr.class, this::transformBvRotateLeft) - - .addCase(BvRotateRightExpr.class, this::transformBvRotateRight) - - .addCase(BvEqExpr.class, this::transformBvEq) - - .addCase(BvNeqExpr.class, this::transformBvNeq) - - .addCase(BvGeqExpr.class, this::transformBvGeq) - - .addCase(BvGtExpr.class, this::transformBvGt) - - .addCase(BvLeqExpr.class, this::transformBvLeq) - - .addCase(BvLtExpr.class, this::transformBvLt) - - .addCase(BvToIntExpr.class, this::transformBvToInt) - - // Functions - - .addCase(FuncAppExpr.class, this::transformFuncApp) - - // Arrays - - .addCase(ArrayReadExpr.class, this::transformArrayRead) - - .addCase(ArrayWriteExpr.class, this::transformArrayWrite) - - .addCase(ArrayEqExpr.class, this::transformArrayEq) - - .addCase(ArrayNeqExpr.class, this::transformArrayNeq) - - .addCase(ArrayLitExpr.class, this::transformArrayLit) - - .build(); - } - - public final String toTerm(final Expr expr) { - try { - return exprToTerm.get(expr, () -> table.dispatch(expr)); - } catch (final ExecutionException e) { - throw new AssertionError(); - } - } - - //// - - /* - * General - */ - - protected String transformRef(final RefExpr expr) { - final Decl decl = expr.getDecl(); - if (decl instanceof ConstDecl) { - return transformer.toSymbol(decl); - } else if (decl instanceof ParamDecl) { - return (String) env.eval(DeclSymbol.of(decl)); - } else { - throw new UnsupportedOperationException("Cannot transform reference for declaration: " + decl); - } - } - - protected String transformIte(final IteExpr expr) { - final String condTerm = toTerm(expr.getCond()); - final String thenTerm = toTerm(expr.getThen()); - final String elzeTerm = toTerm(expr.getElse()); - return String.format("(ite %s %s %s)", condTerm, thenTerm, elzeTerm); - } - - /* - * Booleans - */ - - protected String transformFalse(final FalseExpr expr) { - return "false"; - } - - protected String transformTrue(final TrueExpr expr) { - return "true"; - } - - protected String transformNot(final NotExpr expr) { - return String.format("(not %s)", toTerm(expr.getOp())); - } - - protected String transformImply(final ImplyExpr expr) { - return String.format("(=> %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformIff(final IffExpr expr) { - return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformXor(final XorExpr expr) { - return String.format("(xor %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformAnd(final AndExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(and %s)", String.join(" ", opTerms)); - } - - protected String transformOr(final OrExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(or %s)", String.join(" ", opTerms)); - } - - protected String transformExists(final ExistsExpr expr) { - env.push(); - final String[] paramTerms = transformParamDecls(expr.getParamDecls()); - final String opTerm = toTerm(expr.getOp()); - final String result = String.format("(exists (%s) %s)", String.join(" ", paramTerms), opTerm); - env.pop(); - return result; - } - - protected String transformForall(final ForallExpr expr) { - env.push(); - final String[] paramTerms = transformParamDecls(expr.getParamDecls()); - final String opTerm = toTerm(expr.getOp()); - final String result = String.format("(forall (%s) %s)", String.join(" ", paramTerms), opTerm); - env.pop(); - return result; - } - - private String[] transformParamDecls(final List> paramDecls) { - final String[] paramTerms = new String[paramDecls.size()]; - int i = 0; - for (final ParamDecl paramDecl : paramDecls) { - final String paramSymbol = transformParamDecl(paramDecl); - paramTerms[i] = paramSymbol; - env.define(DeclSymbol.of(paramDecl), paramDecl.getName()); - i++; - } - return paramTerms; - } - - private String transformParamDecl(final ParamDecl paramDecl) { - final Type type = paramDecl.getType(); - if (type instanceof FuncType) { - throw new UnsupportedOperationException("Only simple types are supported"); - } else { - return String.format("(%s %s)", paramDecl.getName(), transformer.toSort(type)); - } - } - - /* - * Rationals - */ - - protected String transformRatLit(final RatLitExpr expr) { - return String.format("(/ %d.0 %d.0)", expr.getNum(), expr.getDenom()); - } - - protected String transformRatAdd(final RatAddExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(+ %s)", String.join(" ", opTerms)); - } - - protected String transformRatSub(final RatSubExpr expr) { - return String.format("(- %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformRatPos(final RatPosExpr expr) { - return toTerm(expr.getOp()); - } - - protected String transformRatNeg(final RatNegExpr expr) { - return String.format("(- %s)", toTerm(expr.getOp())); - } - - protected String transformRatMul(final RatMulExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(* %s)", String.join(" ", opTerms)); - } - - protected String transformRatDiv(final RatDivExpr expr) { - return String.format("(/ %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformRatEq(final RatEqExpr expr) { - return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformRatNeq(final RatNeqExpr expr) { - return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformRatGeq(final RatGeqExpr expr) { - return String.format("(>= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformRatGt(final RatGtExpr expr) { - return String.format("(> %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformRatLeq(final RatLeqExpr expr) { - return String.format("(<= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformRatLt(final RatLtExpr expr) { - return String.format("(< %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - /* - * Integers - */ - - protected String transformIntLit(final IntLitExpr expr) { - return expr.getValue().toString(); - } - - protected String transformIntAdd(final IntAddExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(+ %s)", String.join(" ", opTerms)); - } - - protected String transformIntSub(final IntSubExpr expr) { - return String.format("(- %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformIntPos(final IntPosExpr expr) { - return toTerm(expr.getOp()); - } - - protected String transformIntNeg(final IntNegExpr expr) { - return String.format("(- %s)", toTerm(expr.getOp())); - } - - protected String transformIntMul(final IntMulExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(* %s)", String.join(" ", opTerms)); - } - - protected String transformIntDiv(final IntDivExpr expr) { - return String.format("(/ %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformIntMod(final IntModExpr expr) { - return String.format("(mod %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformIntRem(final IntRemExpr expr) { - return String.format("(rem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformIntEq(final IntEqExpr expr) { - return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformIntNeq(final IntNeqExpr expr) { - return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformIntGeq(final IntGeqExpr expr) { - return String.format("(>= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformIntGt(final IntGtExpr expr) { - return String.format("(> %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformIntLeq(final IntLeqExpr expr) { - return String.format("(<= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformIntLt(final IntLtExpr expr) { - return String.format("(< %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformIntToRat(final IntToRatExpr expr) { - return String.format("(to_real %s)", toTerm(expr.getOp())); - } - - protected String transformIntToBv(final IntToBvExpr expr) { - throw new UnsupportedOperationException("SMT-LIB does not have the corresponding operation"); - /* Works with Z3, but it is not standard - return String.format("((_ int2bv %d) %s)", expr.getType().getSize(), toTerm(expr.getOp())); - */ - } - - /* - * Bitvectors - */ - - protected String transformBvLit(final BvLitExpr expr) { - final String value = Arrays.toString(expr.getValue()) - .replace("true", "1") - .replace("false", "0") - .replace("[", "") - .replace("]", "") - .replace(",", "") - .replace(" ", ""); - - return String.format("#b%s", value); - } - - protected String transformBvAdd(final BvAddExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(bvadd %s)", String.join(" ", opTerms)); - } - - protected String transformBvSub(final BvSubExpr expr) { - return String.format("(bvsub %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformBvPos(final BvPosExpr expr) { - return toTerm(expr.getOp()); - } - - protected String transformBvNeg(final BvNegExpr expr) { - return String.format("(bvneg %s)", toTerm(expr.getOp())); - } - - protected String transformBvMul(final BvMulExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(bvmul %s)", String.join(" ", opTerms)); - } - - protected String transformBvDiv(final BvDivExpr expr) { - if(expr.getType().isSigned()) { - return String.format("(bvsdiv %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvudiv %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - } - - protected String transformBvMod(final BvModExpr expr) { - if(expr.getType().isSigned()) { - return String.format("(bvsmod %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvurem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - } - - protected String transformBvRem(final BvRemExpr expr) { - if(expr.getType().isSigned()) { - return String.format("(bvsrem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvurem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - } - - protected String transformBvAnd(final BvAndExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(bvand %s)", String.join(" ", opTerms)); - } - - protected String transformBvOr(final BvOrExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(bvor %s)", String.join(" ", opTerms)); - } - - protected String transformBvXor(final BvXorExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(bvxor %s)", String.join(" ", opTerms)); - } - - protected String transformBvNot(final BvNotExpr expr) { - return String.format("(bvnot %s)", toTerm(expr.getOp())); - } - - protected String transformBvShiftLeft(final BvShiftLeftExpr expr) { - return String.format("(bvshl %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformBvArithShiftRight(final BvArithShiftRightExpr expr) { - return String.format("(bvashr %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformBvLogicShiftRight(final BvLogicShiftRightExpr expr) { - return String.format("(bvlshr %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformBvRotateLeft(final BvRotateLeftExpr expr) { - final var toRotate = toTerm(expr.getLeftOp()); - final var rotateWith = toTerm(expr.getRightOp()); - final var size = toTerm(BvUtils.intToBvLitExpr(expr.getType().getSize(), expr.getType().getSize(), expr.getRightOp().getType().isSigned())); - return String.format("(bvor (bvshl %s %s) (bvlshr %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); - // return String.format("((_ rotate_left %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); - } - - protected String transformBvRotateRight(final BvRotateRightExpr expr) { - final var toRotate = toTerm(expr.getLeftOp()); - final var rotateWith = toTerm(expr.getRightOp()); - final var size = toTerm(BvUtils.intToBvLitExpr(expr.getType().getSize(), expr.getType().getSize(), expr.getRightOp().getType().isSigned())); - return String.format("(bvor (bvlshr %s %s) (bvshl %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); - // return String.format("((_ rotate_right %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); - } - - protected String transformBvEq(final BvEqExpr expr) { - return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformBvNeq(final BvNeqExpr expr) { - return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformBvGeq(final BvGeqExpr expr) { - if(expr.getLeftOp().getType().isSigned()) { - return String.format("(bvsge %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvuge %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - } - - protected String transformBvGt(final BvGtExpr expr) { - if(expr.getLeftOp().getType().isSigned()) { - return String.format("(bvsgt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvugt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - } - - protected String transformBvLeq(final BvLeqExpr expr) { - if(expr.getLeftOp().getType().isSigned()) { - return String.format("(bvsle %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvule %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - } - - protected String transformBvLt(final BvLtExpr expr) { - if(expr.getLeftOp().getType().isSigned()) { - return String.format("(bvslt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvult %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - } - - protected String transformBvToInt(final BvToIntExpr expr) { - throw new UnsupportedOperationException("SMT-LIB does not have the corresponding operation"); - /* Works with Z3, but not standard - if(expr.getOp().getType().isSigned()) { - final String bv = toTerm(expr.getOp()); - final BigInteger exp = BigInteger.TWO.pow(expr.getOp().getType().getSize()); - return String.format( - "(ite (bvslt %s ((_ int2bv %d) 0)) (- (bv2int %s) %s) (bv2int %s))", - bv, expr.getOp().getType().getSize(), bv, exp.toString(), bv - ); - } - else { - return String.format("(bv2int %s)", toTerm(expr.getOp())); - } - */ - } - - /* - * Functions - */ - - protected String transformFuncApp(final FuncAppExpr expr) { - final Tuple2, List>> funcAndArgs = extractFuncAndArgs(expr); - final Expr func = funcAndArgs.get1(); - if (func instanceof RefExpr) { - final RefExpr ref = (RefExpr) func; - final Decl decl = ref.getDecl(); - final String funcDecl = transformer.toSymbol(decl); - final List> args = funcAndArgs.get2(); - final String[] argTerms = args.stream() - .map(this::toTerm) - .toArray(String[]::new); - - return String.format("(%s %s)", funcDecl, String.join(" ", argTerms)); - } else { - throw new UnsupportedOperationException("Higher order functions are not supported: " + func); - } - } - - private static Tuple2, List>> extractFuncAndArgs(final FuncAppExpr expr) { - final Expr func = expr.getFunc(); - final Expr arg = expr.getParam(); - if (func instanceof FuncAppExpr) { - final FuncAppExpr funcApp = (FuncAppExpr) func; - final Tuple2, List>> funcAndArgs = extractFuncAndArgs(funcApp); - final Expr resFunc = funcAndArgs.get1(); - final List> args = funcAndArgs.get2(); - final List> resArgs = ImmutableList.>builder().addAll(args).add(arg).build(); - return Tuple2.of(resFunc, resArgs); - } else { - return Tuple2.of(func, ImmutableList.of(arg)); - } - } - - /* - * Arrays - */ - - protected String transformArrayRead(final ArrayReadExpr expr) { - return String.format("(select %s %s)", toTerm(expr.getArray()), toTerm(expr.getIndex())); - } - - protected String transformArrayWrite(final ArrayWriteExpr expr) { - return String.format("(store %s %s %s)", toTerm(expr.getArray()), toTerm(expr.getIndex()), toTerm(expr.getElem())); - } - - protected String transformArrayEq(final ArrayEqExpr expr) { - return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformArrayNeq(final ArrayNeqExpr expr) { - return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - - protected String transformArrayLit(final ArrayLitExpr expr) { - String running = String.format("((as const %s) %s)", transformer.toSort(expr.getType()), toTerm(expr.getElseElem())); - for (Tuple2, ? extends Expr> elem : expr.getElements()) { - running = String.format("(store %s %s %s)", running, toTerm(elem.get1()), toTerm(elem.get2())); - } - return running; - } +public interface SmtLibExprTransformer { + String toTerm(Expr expr); } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java index 58de36329c..dbba75f52e 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java @@ -11,7 +11,6 @@ import hu.bme.mit.theta.solver.Stack; import hu.bme.mit.theta.solver.impl.ItpPatternImpl; import hu.bme.mit.theta.solver.impl.StackImpl; -import hu.bme.mit.theta.solver.smtlib.binary.SolverBinary; import java.util.Collection; import java.util.function.Supplier; @@ -29,7 +28,7 @@ public abstract class SmtLibItpSolver> public SmtLibItpSolver( final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, - final SmtLibTermTransformer termTransformer, final SolverBinary solverBinary, + final SmtLibTermTransformer termTransformer, final SmtLibSolverBinary solverBinary, final Supplier markerCreator ) { this.solver = new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java new file mode 100644 index 0000000000..ca8c5f1346 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java @@ -0,0 +1,20 @@ +package hu.bme.mit.theta.solver.smtlib; + +import java.util.Collection; +import java.util.Map; + +public class SmtLibModel { + protected final Map values; + + public SmtLibModel(final Map values) { + this.values = values; + } + + public Collection getDecls() { + return values.keySet(); + } + + public String getTerm(final String symbol) { + return values.get(symbol); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java index e3621cc528..861b231c7b 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java @@ -18,7 +18,6 @@ import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.UnknownSolverStatusException; import hu.bme.mit.theta.solver.impl.StackImpl; -import hu.bme.mit.theta.solver.smtlib.binary.SolverBinary; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; import hu.bme.mit.theta.solver.smtlib.parser.CheckSatResponse; @@ -40,13 +39,13 @@ import static com.google.common.base.Preconditions.checkState; public class SmtLibSolver implements UCSolver, Solver { - protected final SolverBinary solverBinary; - private final boolean unsatCoreEnabled; - protected final SmtLibSymbolTable symbolTable; protected final SmtLibTransformationManager transformationManager; protected final SmtLibTermTransformer termTransformer; + protected final SmtLibSolverBinary solverBinary; + private final boolean unsatCoreEnabled; + protected final Stack> assertions; protected final Map> assumptions; protected final Stack> declarationStack; @@ -60,13 +59,13 @@ public class SmtLibSolver implements UCSolver, Solver { public SmtLibSolver( final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, - final SmtLibTermTransformer termTransformer, final SolverBinary solverBinary, boolean unsatCoreEnabled + final SmtLibTermTransformer termTransformer, final SmtLibSolverBinary solverBinary, boolean unsatCoreEnabled ) { + this.solverBinary = solverBinary; this.symbolTable = symbolTable; this.transformationManager = transformationManager; this.termTransformer = termTransformer; - this.solverBinary = solverBinary; this.unsatCoreEnabled = unsatCoreEnabled; assertions = new StackImpl<>(); @@ -191,7 +190,7 @@ private Valuation extractModel() { } else if(res.isSpecific()) { final GetModelResponse getModelResponse = res.asSpecific(); - return new SmtLibValuation(getModelResponse); + return new SmtLibValuation(getModelResponse.getModel()); } else { throw new AssertionError(); @@ -280,11 +279,11 @@ private GeneralResponse parseResponse(final String response) { } private final class SmtLibValuation extends Valuation { - private final GetModelResponse model; + private final SmtLibModel model; private final Map, LitExpr> constToExpr; private volatile Collection> constDecls = null; - public SmtLibValuation(final GetModelResponse model) { + public SmtLibValuation(final SmtLibModel model) { this.model = model; constToExpr = new HashMap<>(); } @@ -381,7 +380,7 @@ public Map, LitExpr> toMap() { return Collections.unmodifiableMap(constToExpr); } - private Collection> constDeclsOf(final GetModelResponse model) { + private Collection> constDeclsOf(final SmtLibModel model) { final ImmutableList.Builder> builder = ImmutableList.builder(); for (final var symbol : model.getDecls()) { if (symbolTable.definesSymbol(symbol)) { diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java new file mode 100644 index 0000000000..5301a082cc --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java @@ -0,0 +1,5 @@ +package hu.bme.mit.theta.solver.smtlib; + +public interface SmtLibSolverBinary { + String issueCommand(String command); +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverProcessFailureException.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinaryException.java similarity index 80% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverProcessFailureException.java rename to subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinaryException.java index 5b6638d7cc..59f9b819ef 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverProcessFailureException.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinaryException.java @@ -15,14 +15,14 @@ */ package hu.bme.mit.theta.solver.smtlib; -public class SmtLibSolverProcessFailureException extends SmtLibSolverException { +public class SmtLibSolverBinaryException extends SmtLibSolverException { private static final long serialVersionUID = -7472824180590829943L; - public SmtLibSolverProcessFailureException(Exception e) { + public SmtLibSolverBinaryException(Exception e) { super(e); } - public SmtLibSolverProcessFailureException(String e) { + public SmtLibSolverBinaryException(String e) { super(e); } } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java deleted file mode 100644 index 5908c5550d..0000000000 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -package hu.bme.mit.theta.solver.smtlib; - -import hu.bme.mit.theta.solver.ItpSolver; -import hu.bme.mit.theta.solver.Solver; -import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.binary.ContinuousSolverBinary; - -import java.nio.file.Path; - -public class SmtLibSolverFactory implements SolverFactory { - private final Path solverPath; - private final String[] args; - - private SmtLibSolverFactory(Path solverPath, String[] args) { - this.solverPath = solverPath; - this.args = args; - } - - public static SmtLibSolverFactory create(Path solverPath, String[] args) { - return new SmtLibSolverFactory(solverPath, args); - } - - @Override - public Solver createSolver() { - final var symbolTable = new SmtLibSymbolTable(); - final var transformationManager = new SmtLibTransformationManager(symbolTable); - final var termTransformer = new SmtLibTermTransformer(symbolTable); - final var solverBinary = new ContinuousSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); - } - - @Override - public UCSolver createUCSolver() { - final var symbolTable = new SmtLibSymbolTable(); - final var transformationManager = new SmtLibTransformationManager(symbolTable); - final var termTransformer = new SmtLibTermTransformer(symbolTable); - final var solverBinary = new ContinuousSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); - } - - @Override - public ItpSolver createItpSolver() { - throw new UnsupportedOperationException("SmtLibSolver does not support interpolation"); - } -} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java index 1cc539a493..b6a4d2ccae 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java @@ -1,52 +1,17 @@ package hu.bme.mit.theta.solver.smtlib; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.Maps; import hu.bme.mit.theta.core.decl.ConstDecl; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; +public interface SmtLibSymbolTable { + boolean definesConst(ConstDecl constDecl); -public class SmtLibSymbolTable { - private final BiMap, String> constToSymbol; - private final BiMap, String> constToDeclaration; + boolean definesSymbol(String symbol); - public SmtLibSymbolTable() { - constToSymbol = Maps.synchronizedBiMap(HashBiMap.create()); - constToDeclaration = Maps.synchronizedBiMap(HashBiMap.create()); - } + String getSymbol(ConstDecl constDecl); - public boolean definesConst(final ConstDecl constDecl) { - return constToSymbol.containsKey(constDecl); - } + String getDeclaration(ConstDecl constDecl); - public boolean definesSymbol(final String symbol) { - return constToSymbol.inverse().containsKey(symbol); - } + ConstDecl getConst(String symbol); - public String getSymbol(final ConstDecl constDecl) { - checkArgument(definesConst(constDecl)); - return constToSymbol.get(constDecl); - } - - public String getDeclaration(final ConstDecl constDecl) { - checkArgument(definesConst(constDecl)); - return constToDeclaration.get(constDecl); - } - - public ConstDecl getConst(final String symbol) { - checkArgument(definesSymbol(symbol)); - return constToSymbol.inverse().get(symbol); - } - - public void put(final ConstDecl constDecl, final String symbol, final String declaration) { - checkNotNull(constDecl); - checkNotNull(symbol); - checkNotNull(declaration); - checkState(!constToSymbol.containsKey(constDecl), "Constant not found."); - constToSymbol.put(constDecl, symbol); - constToDeclaration.put(constDecl, declaration); - } + void put(ConstDecl constDecl, String symbol, String declaration); } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java index 6eba2b2e02..8f01ff2c43 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java @@ -1,918 +1,20 @@ package hu.bme.mit.theta.solver.smtlib; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.ImmutableList; -import hu.bme.mit.theta.common.QuintFunction; -import hu.bme.mit.theta.common.TernaryOperator; -import hu.bme.mit.theta.common.Tuple2; -import hu.bme.mit.theta.core.decl.Decls; -import hu.bme.mit.theta.core.decl.ParamDecl; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.LitExpr; import hu.bme.mit.theta.core.type.Type; -import hu.bme.mit.theta.core.type.abstracttype.AddExpr; -import hu.bme.mit.theta.core.type.abstracttype.DivExpr; -import hu.bme.mit.theta.core.type.abstracttype.EqExpr; -import hu.bme.mit.theta.core.type.abstracttype.GeqExpr; -import hu.bme.mit.theta.core.type.abstracttype.GtExpr; -import hu.bme.mit.theta.core.type.abstracttype.LeqExpr; -import hu.bme.mit.theta.core.type.abstracttype.LtExpr; -import hu.bme.mit.theta.core.type.abstracttype.ModExpr; -import hu.bme.mit.theta.core.type.abstracttype.MulExpr; -import hu.bme.mit.theta.core.type.abstracttype.NegExpr; -import hu.bme.mit.theta.core.type.abstracttype.RemExpr; -import hu.bme.mit.theta.core.type.abstracttype.SubExpr; -import hu.bme.mit.theta.core.type.anytype.IteExpr; -import hu.bme.mit.theta.core.type.anytype.RefExpr; -import hu.bme.mit.theta.core.type.arraytype.ArrayReadExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayType; -import hu.bme.mit.theta.core.type.arraytype.ArrayWriteExpr; -import hu.bme.mit.theta.core.type.booltype.AndExpr; -import hu.bme.mit.theta.core.type.booltype.BoolExprs; -import hu.bme.mit.theta.core.type.booltype.IffExpr; -import hu.bme.mit.theta.core.type.booltype.ImplyExpr; -import hu.bme.mit.theta.core.type.booltype.NotExpr; -import hu.bme.mit.theta.core.type.booltype.OrExpr; -import hu.bme.mit.theta.core.type.booltype.XorExpr; -import hu.bme.mit.theta.core.type.bvtype.BvAddExpr; -import hu.bme.mit.theta.core.type.bvtype.BvAndExpr; -import hu.bme.mit.theta.core.type.bvtype.BvArithShiftRightExpr; -import hu.bme.mit.theta.core.type.bvtype.BvDivExpr; -import hu.bme.mit.theta.core.type.bvtype.BvExprs; -import hu.bme.mit.theta.core.type.bvtype.BvGeqExpr; -import hu.bme.mit.theta.core.type.bvtype.BvGtExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLeqExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLogicShiftRightExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLtExpr; -import hu.bme.mit.theta.core.type.bvtype.BvModExpr; -import hu.bme.mit.theta.core.type.bvtype.BvNegExpr; -import hu.bme.mit.theta.core.type.bvtype.BvNotExpr; -import hu.bme.mit.theta.core.type.bvtype.BvOrExpr; -import hu.bme.mit.theta.core.type.bvtype.BvRemExpr; -import hu.bme.mit.theta.core.type.bvtype.BvShiftLeftExpr; -import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; import hu.bme.mit.theta.core.type.bvtype.BvType; -import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; -import hu.bme.mit.theta.core.type.functype.FuncExprs; import hu.bme.mit.theta.core.type.functype.FuncType; -import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; -import hu.bme.mit.theta.core.utils.BvUtils; -import hu.bme.mit.theta.core.utils.ExprUtils; -import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; -import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; -import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; -import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; -import org.antlr.v4.runtime.CharStreams; -import org.antlr.v4.runtime.CommonTokenStream; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.function.UnaryOperator; -import java.util.stream.Collectors; -import java.util.stream.IntStream; +public interface SmtLibTermTransformer { +

LitExpr> toFuncLitExpr(String funcLitImpl, FuncType type, SmtLibModel model); -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Exists; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Forall; -import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; -import static hu.bme.mit.theta.core.type.functype.FuncExprs.Func; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; -import static hu.bme.mit.theta.core.type.rattype.RatExprs.Rat; -import static hu.bme.mit.theta.core.utils.TypeUtils.cast; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.BinaryContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.DecimalContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Exists_termContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Forall_termContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Generic_termContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.HexadecimalContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.IdentifierContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.IndexContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.NumeralContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Qual_identifierContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.SortContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Spec_constantContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.SymbolContext; -import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.TermContext; -import static java.util.stream.Collectors.toList; + Expr toExpr(String term, Type type, SmtLibModel model); -public class SmtLibTermTransformer { - protected final SmtLibSymbolTable symbolTable; - protected final Map funAppTransformer; + LitExpr toLitExpr(String litImpl, T type, SmtLibModel model); - public SmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { - this.symbolTable = symbolTable; - this.funAppTransformer = new HashMap<>() {{ - // Generic - put("ite", exprIteOperator()); - - // Abstract - put("=", exprRelationalOperator(EqExpr::create2)); - put("<=", exprRelationalOperator(LeqExpr::create2)); - put("<", exprRelationalOperator(LtExpr::create2)); - put(">=", exprRelationalOperator(GeqExpr::create2)); - put(">", exprRelationalOperator(GtExpr::create2)); - put("+", exprMultiaryOperator(AddExpr::create2)); - put("-", exprMinusOperator()); - put("*", exprMultiaryOperator(MulExpr::create2)); - put("div", exprBinaryOperator(DivExpr::create2)); - put("mod", exprBinaryOperator(ModExpr::create2)); - put("rem", exprBinaryOperator(RemExpr::create2)); - - // Booleal - put("not", exprUnaryOperator(NotExpr::create)); - put("or", exprMultiaryOperator(OrExpr::create)); - put("and", exprMultiaryOperator(AndExpr::create)); - put("xor", exprBinaryOperator(XorExpr::create)); - put("iff", exprBinaryOperator(IffExpr::create)); - put("=>", exprBinaryOperator(ImplyExpr::create)); - - // Integer - put("to_real", exprUnaryOperator(IntToRatExpr::create)); - - // Rational - - // Bitvector - put("bvadd", exprMultiaryOperator(BvAddExpr::create)); - put("bvsub", exprBinaryOperator(BvSubExpr::create)); - put("bvneg", exprUnaryOperator(BvNegExpr::create)); - put("bvmul", exprMultiaryOperator(BvAddExpr::create)); - put("bvudiv", exprBinaryOperator(BvDivExpr::create)); - put("bvsdiv", exprBinaryOperator(BvDivExpr::create)); - put("bvsmod", exprBinaryOperator(BvModExpr::create)); - put("bvsrem", exprBinaryOperator(BvRemExpr::create)); - put("bvurem", exprBinaryOperator(BvRemExpr::create)); - put("bvand", exprMultiaryOperator(BvAndExpr::create)); - put("bvor", exprMultiaryOperator(BvOrExpr::create)); - put("bvxor", exprMultiaryOperator(BvXorExpr::create)); - put("bvnot", exprUnaryOperator(BvNotExpr::create)); - put("bvshl", exprBinaryOperator(BvShiftLeftExpr::create)); - put("bvashr", exprBinaryOperator(BvArithShiftRightExpr::create)); - put("bvlshr", exprBinaryOperator(BvLogicShiftRightExpr::create)); - put("bvult", exprBinaryOperator(BvLtExpr::create)); - put("bvslt", exprBinaryOperator(BvLtExpr::create)); - put("bvule", exprBinaryOperator(BvLeqExpr::create)); - put("bvsle", exprBinaryOperator(BvLeqExpr::create)); - put("bvugt", exprBinaryOperator(BvGtExpr::create)); - put("bvsgt", exprBinaryOperator(BvGtExpr::create)); - put("bvuge", exprBinaryOperator(BvGeqExpr::create)); - put("bvsge", exprBinaryOperator(BvGeqExpr::create)); - - // Array - put("select", exprArrayReadOperator()); - put("store", exprArrayWriteOperator()); - }}; - } - - /* Public interface */ - - public

LitExpr> toFuncLitExpr(final String funcLitImpl, final FuncType type, final GetModelResponse model) { - final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(funcLitImpl)); - final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); - lexer.removeErrorListeners(); - lexer.addErrorListener(new ThrowExceptionErrorListener()); - parser.removeErrorListeners(); - parser.addErrorListener(new ThrowExceptionErrorListener()); - - final var litExpr = transformFuncDef(parser.function_def(), type, model, HashBiMap.create()); - if(litExpr == null) { - return null; - } - else if(litExpr instanceof LitExpr) { - return (LitExpr>) cast(litExpr, type); - } - else { - return (LitExpr>) cast(ExprUtils.simplify(litExpr), type); - } - } - - public Expr toExpr(final String term, final Type type, final GetModelResponse model) { - final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(term)); - final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); - lexer.removeErrorListeners(); - lexer.addErrorListener(new ThrowExceptionErrorListener()); - parser.removeErrorListeners(); - parser.addErrorListener(new ThrowExceptionErrorListener()); - - final var expr = transformTerm(parser.function_def().term(), type, model, HashBiMap.create()); - if(expr == null) { - return null; - } - else { - return cast(expr, type); - } - } - - public LitExpr toLitExpr(final String litImpl, final T type, final GetModelResponse model) { - final var litExpr = toExpr(litImpl, type, model); - - if(litExpr == null) { - return null; - } - else if(litExpr instanceof LitExpr) { - return (LitExpr) cast(litExpr, type); - } - else { - return (LitExpr) cast(ExprUtils.simplify(litExpr), type); - } - } - - @SuppressWarnings("unchecked") - public LitExpr> toArrayLitExpr(final String arrayLitImpl, final ArrayType type, final GetModelResponse model) { - final var arrayLitExpr = toExpr(arrayLitImpl, type, model); - - if(arrayLitExpr == null) { - return null; - } - else if(arrayLitExpr instanceof IteExpr) { - final var entryExprsBuilder = new ImmutableList.Builder, Expr>>(); - var iteExpr = (IteExpr) arrayLitExpr; - while (true) { - entryExprsBuilder.add(Tuple2.of((Expr) iteExpr.getCond().getOps().get(1), iteExpr.getThen())); - if (iteExpr.getElse() instanceof IteExpr) { - iteExpr = (IteExpr) iteExpr.getElse(); - } else { - return Array(entryExprsBuilder.build(), iteExpr.getElse(), type); - } - } - } - else { - return (LitExpr>) cast(ExprUtils.simplify(arrayLitExpr), type); - } - } - - public LitExpr toBvLitExpr(final String bvLitImpl, final BvType type, final GetModelResponse model) { - final var bvLitExpr = toExpr(bvLitImpl, type, model); - - if(bvLitExpr == null) { - return null; - } - else if(bvLitExpr instanceof BvLitExpr) { - return Bv(((BvLitExpr) bvLitExpr).getValue(), type.isSigned()); - } - else { - return (LitExpr) cast(ExprUtils.simplify(bvLitExpr), type); - } - } - - /* End of public interface */ - - /* Visitor implementation */ - - protected Expr transformFuncDef(final SMTLIBv2Parser.Function_defContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert type == null || type instanceof FuncType; - assert model != null; - assert vars != null; - - final var funcType = type != null ? (FuncType) type : null; - - final var paramDecls = ctx.sorted_var().stream() - .map(sv -> new ParamTypeDeducer( - sv.symbol().getText(), transformSort(sv.sort(), - funcType != null ? funcType.getParamType() : null)) - ) - .collect(toList()); - checkArgument(paramDecls.size() == 1, "Only unary functions are supported"); - - pushParams(paramDecls, vars); - final var op = transformTerm(ctx.term(), funcType != null ? funcType.getResultType() : type, model, vars); - popParams(paramDecls, vars); - - if(paramDecls.get(0).isTypeUnknown()) { - return null; - } - else { - assert op != null; - return Func(paramDecls.get(0).getParamDecl(), op); - } - } - - protected Expr transformTerm(final TermContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert model != null; - assert vars != null; - - if(ctx.spec_constant() != null) { - return transformSpecConstant(ctx.spec_constant(), type, model, vars); - } - else if(ctx.qual_identifier() != null) { - return transformQualIdentifier(ctx.qual_identifier(), type, model, vars); - } - else if(ctx.generic_term() != null) { - return transformGenericTerm(ctx.generic_term(), type, model, vars); - } - else if(ctx.let_term() != null) { - throw new UnsupportedOperationException(); - } - else if(ctx.forall_term() != null) { - return transformForallTerm(ctx.forall_term(), type, model, vars); - } - else if(ctx.exists_term() != null) { - return transformExistsTerm(ctx.exists_term(), type, model, vars); - } - else if(ctx.match_term() != null) { - throw new UnsupportedOperationException(); - } - else if(ctx.annotate_term() != null) { - throw new UnsupportedOperationException(); - } - else { - throw new SmtLibSolverException("Invalid input"); - } - } - - protected Expr transformSpecConstant(final Spec_constantContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert model != null; - assert vars != null; - - if(ctx.numeral() != null) { - return transformNumeral(ctx.numeral(), type, model, vars); - } - else if(ctx.decimal() != null) { - return transformDecimal(ctx.decimal(), type, model, vars); - } - else if(ctx.hexadecimal() != null) { - return transformHexadecimal(ctx.hexadecimal(), type, model, vars); - } - else if(ctx.binary() != null) { - return transformBinary(ctx.binary(), type, model, vars); - } - else if(ctx.string() != null) { - throw new UnsupportedOperationException(); - } - else { - throw new SmtLibSolverException("Invalid input"); - } - } - - protected Expr transformQualIdentifier(final Qual_identifierContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert model != null; - assert vars != null; - - return transformIdentifier(ctx.identifier(), type, model, vars); - } - - protected Expr transformGenericTerm(final Generic_termContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert model != null; - assert vars != null; - - final var funName = ctx.qual_identifier().identifier().symbol().getText(); - - final var funParams = ctx.qual_identifier().identifier().index(); - final var funAppParams = ctx.term(); - - if (funName.equals("const")) { // as const construct - final var constType = transformSort(ctx.qual_identifier().sort(), type); - if (constType instanceof ArrayType) { - assert type == null || type.equals(constType); - checkArgument(funAppParams.size() == 1, "Invalid as const construct"); - - final var arrayType = (ArrayType) constType; - final var expr = transformTerm(funAppParams.get(0), arrayType.getElemType(), model, vars); - return createArrayLitExpr(expr, (ArrayType) type); - } - else { - throw new UnsupportedOperationException(); - } - } else if (funAppTransformer.containsKey(funName)) { // known function application - return funAppTransformer.get(funName).apply(funParams, funAppParams, type, model, vars); - } else { // custom function application - checkArgument(funParams.size() == 0, "Custom unary function application cannot vahe parameter"); - checkArgument(funAppParams.size() == 1, "Only unary functions are supported"); - - return createFuncAppExpr(funName, funAppParams.get(0), type, model, vars); - } - } - - @SuppressWarnings("unchecked") - private Expr createArrayLitExpr(final Expr elze, final ArrayType type) { - return Array(Collections.emptyList(), (Expr) elze, type); - } - - private

Expr createFuncAppExpr(final String funName, final TermContext funAppParam, final Type returnType, final GetModelResponse model, final BiMap vars) { - - var paramExpr = transformTerm(funAppParam, null, model, vars); - final Type paramType = paramExpr != null ? paramExpr.getType() : null; - - final Expr funcExpr; - if (symbolTable.definesSymbol(funName)) { - funcExpr = checkNotNull(symbolTable.getConst(funName).getRef()); - } else { - final var funDefImpl = model.getTerm(funName); - if(paramType == null || returnType == null) { - funcExpr = toFuncLitExpr(funDefImpl, null, model); - if(funcExpr == null) { - return null; - } - } - else { - funcExpr = checkNotNull(toFuncLitExpr(funDefImpl, FuncType.of(paramType, returnType), model), "Unsupported expression: was not able to deduce all types"); - } - } - - assert funcExpr.getType() instanceof FuncType; - @SuppressWarnings("unchecked") final var funType = (FuncType) funcExpr.getType(); - paramExpr = paramExpr == null ? transformTerm(funAppParam, funType.getParamType(), model, vars) : paramExpr; - - return FuncExprs.App(cast(funcExpr, funType), cast(paramExpr, funType.getParamType())); - } - - protected Expr transformForallTerm(final Forall_termContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert type == null || type.equals(Bool()); - assert model != null; - assert vars != null; - - final var paramDecls = ctx.sorted_var().stream() - .map(sv -> new ParamTypeDeducer(sv.symbol().getText(), transformSort(sv.sort(), null))) - .collect(toList()); - - pushParams(paramDecls, vars); - final var op = transformTerm(ctx.term(), type, model, vars); - popParams(paramDecls, vars); - - if(paramDecls.stream().anyMatch(ParamTypeDeducer::isTypeUnknown)) { - return null; - } - else { - assert op != null; - return Forall( - paramDecls.stream().map(ParamTypeDeducer::getParamDecl).collect(Collectors.toUnmodifiableList()), - cast(op, Bool()) - ); - } - } - - protected Expr transformExistsTerm(final Exists_termContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert type == null || type.equals(Bool()); - assert model != null; - assert vars != null; - - final var paramDecls = ctx.sorted_var().stream() - .map(sv -> new ParamTypeDeducer(sv.symbol().getText(), transformSort(sv.sort(), null))) - .collect(toList()); - - pushParams(paramDecls, vars); - final var op = transformTerm(ctx.term(), type, model, vars); - popParams(paramDecls, vars); - - if(paramDecls.stream().anyMatch(ParamTypeDeducer::isTypeUnknown)) { - return null; - } - else { - assert op != null; - return Exists( - paramDecls.stream().map(ParamTypeDeducer::getParamDecl).collect(Collectors.toUnmodifiableList()), - cast(op, Bool()) - ); - } - } - - protected Expr transformIdentifier(final IdentifierContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert model != null; - assert vars != null; - - if(ctx.symbol().getText().equals("as-array")) { - final var name = ctx.index().get(0).getText(); - return toExpr(model.getTerm(name), type, model); - } - else { - return transformSymbol(ctx.symbol(), type, model, vars); - } - } - - protected Expr transformSymbol(final SymbolContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert model != null; - assert vars != null; - - final var value = ctx.getText(); - switch (value) { - case "true": - return BoolExprs.True(); - case "false": - return BoolExprs.False(); - default: - if(vars.containsValue(value)) { - final var decl = vars.inverse().get(value); - if(decl.isTypeUnknown()) { - if(type == null) { - return null; - } - else { - decl.setType(type); - return decl.getRef(); - } - } - else { - final var ref = decl.getRef(); - assert type == null || type.equals(ref.getType()); - return ref; - } - } - else if(symbolTable.definesSymbol(value)) { - final var ref = symbolTable.getConst(value).getRef(); - assert type == null || type.equals(ref.getType()); - return ref; - } - else { - throw new UnsupportedOperationException(); - } - } - } - - protected Expr transformNumeral(final NumeralContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert type == null || type.equals(Int()); - assert model != null; - assert vars != null; - - return Int(ctx.getText()); - } - - protected Expr transformDecimal(final DecimalContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert type == null || type.equals(Rat()); - assert model != null; - assert vars != null; - - final var decimal = new BigDecimal(ctx.getText()); - if(decimal.scale() <= 0) { - return Rat(decimal.unscaledValue(), BigInteger.ONE); - } - else { - return Rat(decimal.unscaledValue(), BigInteger.TEN.pow(decimal.scale())); - } - } - - protected Expr transformHexadecimal(final HexadecimalContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert type == null || type instanceof BvType; - assert model != null; - assert vars != null; - - if(type == null) { - return null; - } - else { - final var bvType = (BvType) type; - final var numStr = ctx.getText().substring(2); - final var num = new BigInteger(numStr, 16); - checkState(bvType.getSize() == numStr.length() * 4, "Type mismatch"); - - return BvUtils.bigIntegerToBvLitExpr(num, bvType.getSize(), bvType.isSigned()); - } - } - - protected Expr transformBinary(final BinaryContext ctx, final Type type, final GetModelResponse model, final BiMap vars) { - assert type == null || type instanceof BvType; - assert model != null; - assert vars != null; - - if(type == null) { - return null; - } - else { - final var bvType = (BvType) type; - final var numStr = ctx.getText().substring(2); - final var num = new BigInteger(numStr, 2); - checkState(bvType.getSize() == numStr.length(), "Type mismatch"); - - return BvUtils.bigIntegerToBvLitExpr(num, bvType.getSize(), bvType.isSigned()); - } - } - - protected Type transformSort(final SortContext ctx, final Type type) { - final var name = ctx.identifier().symbol().getText(); - switch(name) { - case "Bool": - assert type == null || type.equals(Bool()); - return Bool(); - case "Int": - assert type == null || type.equals(Int()); - return Int(); - case "Real": - assert type == null || type.equals(Rat()); - return Rat(); - case "BitVec": - assert type == null || type instanceof BvType; - if(type == null) { - return null; - } - else { - final var bvType = (BvType) type; - checkArgument(Integer.parseInt(ctx.identifier().index().get(0).getText()) == bvType.getSize(), "Type mismatch"); - return BvExprs.BvType(bvType.getSize(), bvType.isSigned()); - } - case "Array": - assert type == null || type instanceof ArrayType; - if(type == null) { - final var indexType = transformSort(ctx.sort().get(0), null); - final var elemType = transformSort(ctx.sort().get(1), null); - if(indexType == null || elemType == null) { - return null; - } - else { - return Array(indexType, elemType); - } - } - else { - final var arrayType = (ArrayType) type; - return Array(transformSort(ctx.sort().get(0), arrayType.getIndexType()), transformSort(ctx.sort().get(1), arrayType.getElemType())); - } - default: - throw new UnsupportedOperationException(); - } - } - - /* End of visitor implementation */ - - /* Variable scope handling */ - - protected void pushParams(final List paramDecls, BiMap vars) { - vars.putAll(paramDecls.stream().collect(Collectors.toUnmodifiableMap(Function.identity(), ParamTypeDeducer::getName))); - } - - protected void popParams(final List paramDecls, BiMap vars) { - for (final var paramDecl : paramDecls) { - vars.remove(paramDecl, paramDecl.getName()); - } - } - - /* Utilities */ - - @SuppressWarnings("unused") - private OperatorCreatorFunction exprNullaryOperator(final Supplier> function) { - return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0, "No parameters expected"); - checkArgument(ops.size() == 0, "Nullary operator expected"); - return function.get(); - }; - } - - private OperatorCreatorFunction exprUnaryOperator(final UnaryOperator> function) { - return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0, "No parameters expected"); - checkArgument(ops.size() == 1, "Unary operator expected"); - - if(type == null) { - final var op = transformTerm(ops.get(0), type, model, vars); - return function.apply(op); - } - else { - final var op = checkNotNull(transformTerm(ops.get(0), type, model, vars), "Unsupported expression: was not able to deduce all types"); - return function.apply(op); - } - }; - } - - private OperatorCreatorFunction exprBinaryOperator(final BinaryOperator> function) { - return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0, "No parameters expected"); - checkArgument(ops.size() == 2, "Binary operator expected"); - - if(type == null) { - var op1 = transformTerm(ops.get(0), null, model, vars); - var op2 = transformTerm(ops.get(1), null, model, vars); - if(op1 == null && op2 == null) { - return null; - } - else if(op1 != null && op2 == null) { - op2 = checkNotNull(transformTerm(ops.get(1), op1.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - else if(op1 == null /* && op2 != null */) { - op1 = checkNotNull(transformTerm(ops.get(0), op2.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - return function.apply(op1, op2); - } - else { - final var op1 = transformTerm(ops.get(0), type, model, vars); - final var op2 = transformTerm(ops.get(1), type, model, vars); - return function.apply(op1, op2); - } - }; - } - - private OperatorCreatorFunction exprRelationalOperator(final BinaryOperator> function) { - return (params, ops, type, model, vars) -> { - assert type == null || type.equals(Bool()); - checkArgument(params.size() == 0, "No parameters expected"); - checkArgument(ops.size() == 2, "Binary operator expected"); - - var op1 = transformTerm(ops.get(0), null, model, vars); - var op2 = transformTerm(ops.get(1), null, model, vars); - if(op1 == null && op2 == null) { - return null; - } - else if(op1 != null && op2 == null) { - op2 = checkNotNull(transformTerm(ops.get(1), op1.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - else if(op1 == null /* && op2 != null */) { - op1 = checkNotNull(transformTerm(ops.get(0), op2.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - return function.apply(op1, op2); - }; - } - - private OperatorCreatorFunction exprArrayReadOperator() { - return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0, "No parameters expected"); - checkArgument(ops.size() == 2, "Binary operator expected"); - - var op1 = transformTerm(ops.get(0), null, model, vars); - var op2 = transformTerm(ops.get(1), null, model, vars); - if(op1 == null && op2 == null) { - return null; - } - else if(op1 != null && op2 == null) { - assert op1.getType() instanceof ArrayType; - final var arrayType = (ArrayType) op1.getType(); - op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - else if(op1 == null /* && op2 != null */) { - if(type == null) { - return null; - } - else { - final var arrayType = Array(op2.getType(), type); - op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars), "Unsupported expression: was not able to deduce all types"); - } - } - return ArrayReadExpr.create(op1, op2); - }; - } - - private OperatorCreatorFunction exprMinusOperator() { - return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0, "No parameters expected"); - checkArgument(ops.size() == 1 || ops.size() == 2, "Unary or binary operator expected"); - if(ops.size() == 2) { - return exprBinaryOperator(SubExpr::create2).apply(params, ops, type, model, vars); - } - else { - return exprUnaryOperator(NegExpr::create2).apply(params, ops, type, model, vars); - } - }; - } - - @SuppressWarnings("unused") - private OperatorCreatorFunction exprTernaryOperator(final TernaryOperator> function) { - return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0, "No parameters expected"); - checkArgument(ops.size() == 3, "Ternary operator expected"); - final Expr op1 = transformTerm(ops.get(0), type, model, vars); - final Expr op2 = transformTerm(ops.get(1), type, model, vars); - final Expr op3 = transformTerm(ops.get(2), type, model, vars); - return function.apply(op1, op2, op3); - }; - } - - private OperatorCreatorFunction exprIteOperator() { - return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0, "No parameters expected"); - checkArgument(ops.size() == 3, "Ternary operator expected"); - final var op1 = transformTerm(ops.get(0), Bool(), model, vars); - if(type == null) { - var op2 = transformTerm(ops.get(1), type, model, vars); - var op3 = transformTerm(ops.get(2), type, model, vars); - if(op2 == null && op3 == null) { - return null; - } - else if(op2 != null && op3 == null) { - op3 = checkNotNull(transformTerm(ops.get(2), op2.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - else if(op2 == null /* && op3 != null */) { - op2 = checkNotNull(transformTerm(ops.get(1), op3.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - return IteExpr.create(op1, op2, op3); - } - else { - final var op2 = transformTerm(ops.get(1), type, model, vars); - final var op3 = transformTerm(ops.get(2), type, model, vars); - return IteExpr.create(op1, op2, op3); - } - }; - } - - private OperatorCreatorFunction exprArrayWriteOperator() { - return (params, ops, type, model, vars) -> { - assert type == null || type instanceof ArrayType; - checkArgument(params.size() == 0, "No parameters expected"); - checkArgument(ops.size() == 3, "Ternary operator expected"); - - if(type == null) { - var op1 = transformTerm(ops.get(0), null, model, vars); - var op2 = transformTerm(ops.get(1), null, model, vars); - var op3 = transformTerm(ops.get(2), null, model, vars); - - if(op1 != null && (op2 == null || op3 == null)) { - final var arrayType = (ArrayType) op1.getType(); - if(op2 == null) { - op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - if(op3 == null) { - op3 = checkNotNull(transformTerm(ops.get(2), arrayType.getElemType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - } - else if(op1 == null && op2 != null && op3 != null) { - final var arrayType = Array(op2.getType(), op3.getType()); - op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars), "Unsupported expression: was not able to deduce all types"); - } - else { - return null; - } - return ArrayWriteExpr.create(op1, op2, op3); - } - else { - final var arrayType = (ArrayType) type; - final var op1 = transformTerm(ops.get(0), arrayType, model, vars); - final var op2 = transformTerm(ops.get(1), arrayType.getIndexType(), model, vars); - final var op3 = transformTerm(ops.get(2), arrayType.getElemType(), model, vars); - return ArrayWriteExpr.create(op1, op2, op3); - } - }; - } - - private OperatorCreatorFunction exprMultiaryOperator(final Function>, Expr> function) { - return (params, ops, type, model, vars) -> { - checkArgument(params.size() == 0, "No parameters expected"); - if(type == null) { - final var transformedOps = new ArrayList>(); - ops.stream() - .map(op -> transformTerm(op, type, model, vars)) - .forEach(transformedOps::add); - - if(transformedOps.stream().allMatch(Objects::isNull)) { - return null; - } - else { - final var opType = transformedOps.stream().filter(Objects::nonNull).findAny().get().getType(); - return function.apply(IntStream - .range(0, ops.size()) - .mapToObj(i -> transformedOps.get(i) == null ? transformTerm(ops.get(i), opType, model, vars) : transformedOps.get(i)) - .collect(Collectors.toUnmodifiableList()) - ); - } - } - else { - return function.apply(ops.stream().map(op -> transformTerm(op, type, model, vars)).collect(Collectors.toUnmodifiableList())); - } - }; - } - - private interface OperatorCreatorFunction extends QuintFunction< - List, // Parameters - List, // Operands - Type, // Expected type of result - GetModelResponse, // The model - BiMap, // The variable (param) store - Expr // Return type - > {} - - private final static class ParamTypeDeducer { - private final String name; - private Type type; - private ParamDecl paramDecl; - - public ParamTypeDeducer(final String name, final Type type) { - this.name = name; - if(type != null) { - setType(type); - } - } - - public boolean isTypeUnknown() { - return type == null; - } - - public void setType(final Type type) { - checkArgument(type != null); - checkState(this.type == null); - this.type = type; - this.paramDecl = Decls.Param(name, type); - } - - public String getName() { - return name; - } - - public ParamDecl getParamDecl() { - checkState(paramDecl != null); - return paramDecl; - } - - public RefExpr getRef() { - checkState(paramDecl != null); - return paramDecl.getRef(); - } - } + LitExpr> toArrayLitExpr(String arrayLitImpl, ArrayType type, SmtLibModel model); + LitExpr toBvLitExpr(String bvLitImpl, BvType type, SmtLibModel model); } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java index 38392c2989..009501e6a9 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java @@ -4,40 +4,10 @@ import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.Type; -public class SmtLibTransformationManager { - private final SmtLibTypeTransformer typeTransformer; - private final SmtLibDeclTransformer declTransformer; - private final SmtLibExprTransformer exprTransformer; +public interface SmtLibTransformationManager { + String toSort(Type type); - public SmtLibTransformationManager(final SmtLibSymbolTable symbolTable) { - this.typeTransformer = instantiateTypeTransformer(this); - this.declTransformer = instantiateDeclTransformer(this, symbolTable); - this.exprTransformer = instantiateExprTransformer(this); - } + String toSymbol(Decl decl); - public final String toSort(final Type type) { - return typeTransformer.toSort(type); - } - - public final String toSymbol(final Decl decl) { - return declTransformer.toSymbol(decl); - } - - public final String toTerm(final Expr expr) { - return exprTransformer.toTerm(expr); - } - - protected SmtLibTypeTransformer instantiateTypeTransformer(final SmtLibTransformationManager transformer) { - return new SmtLibTypeTransformer(transformer); - } - - protected SmtLibDeclTransformer instantiateDeclTransformer( - final SmtLibTransformationManager transformer, final SmtLibSymbolTable symbolTable - ) { - return new SmtLibDeclTransformer(transformer, symbolTable); - } - - protected SmtLibExprTransformer instantiateExprTransformer(final SmtLibTransformationManager transformer) { - return new SmtLibExprTransformer(transformer); - } + String toTerm(Expr expr); } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java index 38ce0dad63..f9e583080d 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java @@ -1,66 +1,7 @@ package hu.bme.mit.theta.solver.smtlib; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import hu.bme.mit.theta.common.DispatchTable; -import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.Type; -import hu.bme.mit.theta.core.type.arraytype.ArrayType; -import hu.bme.mit.theta.core.type.booltype.BoolType; -import hu.bme.mit.theta.core.type.bvtype.BvType; -import hu.bme.mit.theta.core.type.inttype.IntType; -import hu.bme.mit.theta.core.type.rattype.RatType; -import java.util.concurrent.ExecutionException; - -public class SmtLibTypeTransformer { - private static final int CACHE_SIZE = 1000; - - @SuppressWarnings("unused") - private final SmtLibTransformationManager transformer; - - private final Cache typeToSmtLib; - private final DispatchTable table; - - public SmtLibTypeTransformer(final SmtLibTransformationManager transformer) { - this.transformer = transformer; - - typeToSmtLib = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).build(); - - table = DispatchTable.builder() - .addCase(BoolType.class, this::boolType) - .addCase(IntType.class, this::intType) - .addCase(RatType.class, this::ratType) - .addCase(BvType.class, this::bvType) - .addCase(ArrayType.class, this::arrayType) - .build(); - } - - public final String toSort(final Type type) { - try { - return typeToSmtLib.get(type, () -> table.dispatch(type)); - } catch (final ExecutionException e) { - throw new AssertionError(); - } - } - - protected String boolType(final BoolType type) { - return "Bool"; - } - - protected String intType(final IntType type) { - return "Int"; - } - - protected String ratType(final RatType type) { - return "Real"; - } - - protected String bvType(final BvType type) { - return String.format("(_ BitVec %d)", type.getSize()); - } - - protected String arrayType(final ArrayType type) { - return String.format("(Array %s %s)", toSort(type.getIndexType()), toSort(type.getElemType())); - } +public interface SmtLibTypeTransformer { + String toSort(Type type); } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibUCSolverBase.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibUCSolverBase.java new file mode 100644 index 0000000000..9848fbb4fa --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibUCSolverBase.java @@ -0,0 +1,17 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.solver.UCSolver; + +public abstract class SmtLibUCSolverBase implements UCSolver { + protected final SmtLibSolverBinary solverBinary; + protected final SmtLibSymbolTable symbolTable; + protected final SmtLibTransformationManager transformationManager; + protected final SmtLibTermTransformer termTransformer; + + public SmtLibUCSolverBase(final SmtLibSolverBinary solverBinary, final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, final SmtLibTermTransformer termTransformer) { + this.solverBinary = solverBinary; + this.symbolTable = symbolTable; + this.transformationManager = transformationManager; + this.termTransformer = termTransformer; + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/SolverBinary.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/SolverBinary.java deleted file mode 100644 index b292b36cf0..0000000000 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/SolverBinary.java +++ /dev/null @@ -1,5 +0,0 @@ -package hu.bme.mit.theta.solver.smtlib.binary; - -public interface SolverBinary { - String issueCommand(String command); -} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java new file mode 100644 index 0000000000..5fbd6af3ac --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java @@ -0,0 +1,100 @@ +package hu.bme.mit.theta.solver.smtlib.generic; + +import com.google.common.collect.ImmutableList; +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.decl.Decl; +import hu.bme.mit.theta.core.type.Type; +import hu.bme.mit.theta.core.type.functype.FuncType; +import hu.bme.mit.theta.solver.smtlib.SmtLibDeclTransformer; +import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; + +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; + +public class GenericSmtLibDeclTransformer implements SmtLibDeclTransformer { + private final SmtLibTransformationManager transformer; + private final SmtLibSymbolTable symbolTable; + + private int symbolCount; + + public GenericSmtLibDeclTransformer(final SmtLibTransformationManager transformer, final SmtLibSymbolTable symbolTable) { + this.transformer = transformer; + this.symbolTable = symbolTable; + + symbolCount = 0; + } + + @Override + public String toSymbol(final Decl decl) { + if (decl instanceof ConstDecl) { + final ConstDecl cdecl = (ConstDecl) decl; + if(!symbolTable.definesConst(cdecl)) { + transformConst(cdecl); + } + return symbolTable.getSymbol(cdecl); + } else { + throw new UnsupportedOperationException("Cannot transform declaration: " + decl); + } + } + + @Override + public String toDeclaration(final Decl decl) { + if (decl instanceof ConstDecl) { + final ConstDecl cdecl = (ConstDecl) decl; + if(!symbolTable.definesConst(cdecl)) { + transformConst(cdecl); + } + return symbolTable.getDeclaration(cdecl); + } else { + throw new UnsupportedOperationException("Cannot transform declaration: " + decl); + } + } + + private void transformConst(final ConstDecl decl) { + final Type type = decl.getType(); + + final Tuple2, Type> extractedTypes = extractTypes(type); + final List paramTypes = extractedTypes.get1(); + final Type returnType = extractedTypes.get2(); + + final String returnSort = transformer.toSort(returnType); + final String[] paramSorts = paramTypes.stream().map(transformer::toSort) + .toArray(String[]::new); + + final String symbolName = symbolNameFor(decl); + final String symbolDeclaration = String.format( + "(declare-fun %s (%s) %s)", + symbolName, String.join(" ", paramSorts), returnSort + ); + symbolTable.put(decl, symbolName, symbolDeclaration); + } + + private Tuple2, Type> extractTypes(final Type type) { + if (type instanceof FuncType) { + final FuncType funcType = (FuncType) type; + + final Type paramType = funcType.getParamType(); + final Type resultType = funcType.getResultType(); + + checkArgument(!(paramType instanceof FuncType)); + + final Tuple2, Type> subResult = extractTypes(resultType); + final List paramTypes = subResult.get1(); + final Type newResultType = subResult.get2(); + final List newParamTypes = ImmutableList.builder().add(paramType).addAll(paramTypes).build(); + final Tuple2, Type> result = Tuple2.of(newParamTypes, newResultType); + + return result; + } else { + return Tuple2.of(ImmutableList.of(), type); + } + } + + private String symbolNameFor(final Decl decl) { + return String.format("%s_%d", decl.getName(), symbolCount++); + } + +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java new file mode 100644 index 0000000000..aa70bf17a4 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java @@ -0,0 +1,792 @@ +package hu.bme.mit.theta.solver.smtlib.generic; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.collect.ImmutableList; +import hu.bme.mit.theta.common.DispatchTable; +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.common.dsl.Env; +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.decl.Decl; +import hu.bme.mit.theta.core.decl.ParamDecl; +import hu.bme.mit.theta.core.dsl.DeclSymbol; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.Type; +import hu.bme.mit.theta.core.type.anytype.IteExpr; +import hu.bme.mit.theta.core.type.anytype.RefExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayEqExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayLitExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayNeqExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayReadExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayWriteExpr; +import hu.bme.mit.theta.core.type.booltype.AndExpr; +import hu.bme.mit.theta.core.type.booltype.ExistsExpr; +import hu.bme.mit.theta.core.type.booltype.FalseExpr; +import hu.bme.mit.theta.core.type.booltype.ForallExpr; +import hu.bme.mit.theta.core.type.booltype.IffExpr; +import hu.bme.mit.theta.core.type.booltype.ImplyExpr; +import hu.bme.mit.theta.core.type.booltype.NotExpr; +import hu.bme.mit.theta.core.type.booltype.OrExpr; +import hu.bme.mit.theta.core.type.booltype.TrueExpr; +import hu.bme.mit.theta.core.type.booltype.XorExpr; +import hu.bme.mit.theta.core.type.bvtype.BvAddExpr; +import hu.bme.mit.theta.core.type.bvtype.BvAndExpr; +import hu.bme.mit.theta.core.type.bvtype.BvArithShiftRightExpr; +import hu.bme.mit.theta.core.type.bvtype.BvDivExpr; +import hu.bme.mit.theta.core.type.bvtype.BvEqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvGeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvGtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLogicShiftRightExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvModExpr; +import hu.bme.mit.theta.core.type.bvtype.BvMulExpr; +import hu.bme.mit.theta.core.type.bvtype.BvNegExpr; +import hu.bme.mit.theta.core.type.bvtype.BvNeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvNotExpr; +import hu.bme.mit.theta.core.type.bvtype.BvOrExpr; +import hu.bme.mit.theta.core.type.bvtype.BvPosExpr; +import hu.bme.mit.theta.core.type.bvtype.BvRemExpr; +import hu.bme.mit.theta.core.type.bvtype.BvRotateLeftExpr; +import hu.bme.mit.theta.core.type.bvtype.BvRotateRightExpr; +import hu.bme.mit.theta.core.type.bvtype.BvShiftLeftExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; +import hu.bme.mit.theta.core.type.bvtype.BvToIntExpr; +import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; +import hu.bme.mit.theta.core.type.functype.FuncAppExpr; +import hu.bme.mit.theta.core.type.functype.FuncType; +import hu.bme.mit.theta.core.type.inttype.IntAddExpr; +import hu.bme.mit.theta.core.type.inttype.IntDivExpr; +import hu.bme.mit.theta.core.type.inttype.IntEqExpr; +import hu.bme.mit.theta.core.type.inttype.IntGeqExpr; +import hu.bme.mit.theta.core.type.inttype.IntGtExpr; +import hu.bme.mit.theta.core.type.inttype.IntLeqExpr; +import hu.bme.mit.theta.core.type.inttype.IntLitExpr; +import hu.bme.mit.theta.core.type.inttype.IntLtExpr; +import hu.bme.mit.theta.core.type.inttype.IntModExpr; +import hu.bme.mit.theta.core.type.inttype.IntMulExpr; +import hu.bme.mit.theta.core.type.inttype.IntNegExpr; +import hu.bme.mit.theta.core.type.inttype.IntNeqExpr; +import hu.bme.mit.theta.core.type.inttype.IntPosExpr; +import hu.bme.mit.theta.core.type.inttype.IntRemExpr; +import hu.bme.mit.theta.core.type.inttype.IntSubExpr; +import hu.bme.mit.theta.core.type.inttype.IntToBvExpr; +import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; +import hu.bme.mit.theta.core.type.rattype.RatAddExpr; +import hu.bme.mit.theta.core.type.rattype.RatDivExpr; +import hu.bme.mit.theta.core.type.rattype.RatEqExpr; +import hu.bme.mit.theta.core.type.rattype.RatGeqExpr; +import hu.bme.mit.theta.core.type.rattype.RatGtExpr; +import hu.bme.mit.theta.core.type.rattype.RatLeqExpr; +import hu.bme.mit.theta.core.type.rattype.RatLitExpr; +import hu.bme.mit.theta.core.type.rattype.RatLtExpr; +import hu.bme.mit.theta.core.type.rattype.RatMulExpr; +import hu.bme.mit.theta.core.type.rattype.RatNegExpr; +import hu.bme.mit.theta.core.type.rattype.RatNeqExpr; +import hu.bme.mit.theta.core.type.rattype.RatPosExpr; +import hu.bme.mit.theta.core.type.rattype.RatSubExpr; +import hu.bme.mit.theta.core.utils.BvUtils; +import hu.bme.mit.theta.solver.smtlib.SmtLibExprTransformer; +import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ExecutionException; + +public class GenericSmtLibExprTransformer implements SmtLibExprTransformer { + private static final int CACHE_SIZE = 1000; + + private final SmtLibTransformationManager transformer; + + private final Cache, String> exprToTerm; + private final DispatchTable table; + private final Env env; + + public GenericSmtLibExprTransformer(final SmtLibTransformationManager transformer) { + this.transformer = transformer; + this.env = new Env(); + + this.exprToTerm = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).build(); + + this.table = DispatchTable.builder() + + // General + + .addCase(RefExpr.class, this::transformRef) + + .addCase(IteExpr.class, this::transformIte) + + // Boolean + + .addCase(FalseExpr.class, this::transformFalse) + + .addCase(TrueExpr.class, this::transformTrue) + + .addCase(NotExpr.class, this::transformNot) + + .addCase(ImplyExpr.class, this::transformImply) + + .addCase(IffExpr.class, this::transformIff) + + .addCase(XorExpr.class, this::transformXor) + + .addCase(AndExpr.class, this::transformAnd) + + .addCase(OrExpr.class, this::transformOr) + + .addCase(ExistsExpr.class, this::transformExists) + + .addCase(ForallExpr.class, this::transformForall) + + // Rationals + + .addCase(RatLitExpr.class, this::transformRatLit) + + .addCase(RatAddExpr.class, this::transformRatAdd) + + .addCase(RatSubExpr.class, this::transformRatSub) + + .addCase(RatPosExpr.class, this::transformRatPos) + + .addCase(RatNegExpr.class, this::transformRatNeg) + + .addCase(RatMulExpr.class, this::transformRatMul) + + .addCase(RatDivExpr.class, this::transformRatDiv) + + .addCase(RatEqExpr.class, this::transformRatEq) + + .addCase(RatNeqExpr.class, this::transformRatNeq) + + .addCase(RatGeqExpr.class, this::transformRatGeq) + + .addCase(RatGtExpr.class, this::transformRatGt) + + .addCase(RatLeqExpr.class, this::transformRatLeq) + + .addCase(RatLtExpr.class, this::transformRatLt) + + // Integers + + .addCase(IntLitExpr.class, this::transformIntLit) + + .addCase(IntAddExpr.class, this::transformIntAdd) + + .addCase(IntSubExpr.class, this::transformIntSub) + + .addCase(IntPosExpr.class, this::transformIntPos) + + .addCase(IntNegExpr.class, this::transformIntNeg) + + .addCase(IntMulExpr.class, this::transformIntMul) + + .addCase(IntDivExpr.class, this::transformIntDiv) + + .addCase(IntModExpr.class, this::transformIntMod) + + .addCase(IntRemExpr.class, this::transformIntRem) + + .addCase(IntEqExpr.class, this::transformIntEq) + + .addCase(IntNeqExpr.class, this::transformIntNeq) + + .addCase(IntGeqExpr.class, this::transformIntGeq) + + .addCase(IntGtExpr.class, this::transformIntGt) + + .addCase(IntLeqExpr.class, this::transformIntLeq) + + .addCase(IntLtExpr.class, this::transformIntLt) + + .addCase(IntToRatExpr.class, this::transformIntToRat) + + .addCase(IntToBvExpr.class, this::transformIntToBv) + + // Bitvectors + + .addCase(BvLitExpr.class, this::transformBvLit) + + .addCase(BvAddExpr.class, this::transformBvAdd) + + .addCase(BvSubExpr.class, this::transformBvSub) + + .addCase(BvPosExpr.class, this::transformBvPos) + + .addCase(BvNegExpr.class, this::transformBvNeg) + + .addCase(BvMulExpr.class, this::transformBvMul) + + .addCase(BvDivExpr.class, this::transformBvDiv) + + .addCase(BvModExpr.class, this::transformBvMod) + + .addCase(BvRemExpr.class, this::transformBvRem) + + .addCase(BvAndExpr.class, this::transformBvAnd) + + .addCase(BvOrExpr.class, this::transformBvOr) + + .addCase(BvXorExpr.class, this::transformBvXor) + + .addCase(BvNotExpr.class, this::transformBvNot) + + .addCase(BvShiftLeftExpr.class, this::transformBvShiftLeft) + + .addCase(BvArithShiftRightExpr.class, this::transformBvArithShiftRight) + + .addCase(BvLogicShiftRightExpr.class, this::transformBvLogicShiftRight) + + .addCase(BvRotateLeftExpr.class, this::transformBvRotateLeft) + + .addCase(BvRotateRightExpr.class, this::transformBvRotateRight) + + .addCase(BvEqExpr.class, this::transformBvEq) + + .addCase(BvNeqExpr.class, this::transformBvNeq) + + .addCase(BvGeqExpr.class, this::transformBvGeq) + + .addCase(BvGtExpr.class, this::transformBvGt) + + .addCase(BvLeqExpr.class, this::transformBvLeq) + + .addCase(BvLtExpr.class, this::transformBvLt) + + .addCase(BvToIntExpr.class, this::transformBvToInt) + + // Functions + + .addCase(FuncAppExpr.class, this::transformFuncApp) + + // Arrays + + .addCase(ArrayReadExpr.class, this::transformArrayRead) + + .addCase(ArrayWriteExpr.class, this::transformArrayWrite) + + .addCase(ArrayEqExpr.class, this::transformArrayEq) + + .addCase(ArrayNeqExpr.class, this::transformArrayNeq) + + .addCase(ArrayLitExpr.class, this::transformArrayLit) + + .build(); + } + + @Override + public final String toTerm(final Expr expr) { + try { + return exprToTerm.get(expr, () -> table.dispatch(expr)); + } catch (final ExecutionException e) { + throw new AssertionError(); + } + } + + //// + + /* + * General + */ + + protected String transformRef(final RefExpr expr) { + final Decl decl = expr.getDecl(); + if (decl instanceof ConstDecl) { + return transformer.toSymbol(decl); + } else if (decl instanceof ParamDecl) { + return (String) env.eval(DeclSymbol.of(decl)); + } else { + throw new UnsupportedOperationException("Cannot transform reference for declaration: " + decl); + } + } + + protected String transformIte(final IteExpr expr) { + final String condTerm = toTerm(expr.getCond()); + final String thenTerm = toTerm(expr.getThen()); + final String elzeTerm = toTerm(expr.getElse()); + return String.format("(ite %s %s %s)", condTerm, thenTerm, elzeTerm); + } + + /* + * Booleans + */ + + protected String transformFalse(final FalseExpr expr) { + return "false"; + } + + protected String transformTrue(final TrueExpr expr) { + return "true"; + } + + protected String transformNot(final NotExpr expr) { + return String.format("(not %s)", toTerm(expr.getOp())); + } + + protected String transformImply(final ImplyExpr expr) { + return String.format("(=> %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIff(final IffExpr expr) { + return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformXor(final XorExpr expr) { + return String.format("(xor %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformAnd(final AndExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(and %s)", String.join(" ", opTerms)); + } + + protected String transformOr(final OrExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(or %s)", String.join(" ", opTerms)); + } + + protected String transformExists(final ExistsExpr expr) { + env.push(); + final String[] paramTerms = transformParamDecls(expr.getParamDecls()); + final String opTerm = toTerm(expr.getOp()); + final String result = String.format("(exists (%s) %s)", String.join(" ", paramTerms), opTerm); + env.pop(); + return result; + } + + protected String transformForall(final ForallExpr expr) { + env.push(); + final String[] paramTerms = transformParamDecls(expr.getParamDecls()); + final String opTerm = toTerm(expr.getOp()); + final String result = String.format("(forall (%s) %s)", String.join(" ", paramTerms), opTerm); + env.pop(); + return result; + } + + private String[] transformParamDecls(final List> paramDecls) { + final String[] paramTerms = new String[paramDecls.size()]; + int i = 0; + for (final ParamDecl paramDecl : paramDecls) { + final String paramSymbol = transformParamDecl(paramDecl); + paramTerms[i] = paramSymbol; + env.define(DeclSymbol.of(paramDecl), paramDecl.getName()); + i++; + } + return paramTerms; + } + + private String transformParamDecl(final ParamDecl paramDecl) { + final Type type = paramDecl.getType(); + if (type instanceof FuncType) { + throw new UnsupportedOperationException("Only simple types are supported"); + } else { + return String.format("(%s %s)", paramDecl.getName(), transformer.toSort(type)); + } + } + + /* + * Rationals + */ + + protected String transformRatLit(final RatLitExpr expr) { + return String.format("(/ %d.0 %d.0)", expr.getNum(), expr.getDenom()); + } + + protected String transformRatAdd(final RatAddExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(+ %s)", String.join(" ", opTerms)); + } + + protected String transformRatSub(final RatSubExpr expr) { + return String.format("(- %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatPos(final RatPosExpr expr) { + return toTerm(expr.getOp()); + } + + protected String transformRatNeg(final RatNegExpr expr) { + return String.format("(- %s)", toTerm(expr.getOp())); + } + + protected String transformRatMul(final RatMulExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(* %s)", String.join(" ", opTerms)); + } + + protected String transformRatDiv(final RatDivExpr expr) { + return String.format("(/ %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatEq(final RatEqExpr expr) { + return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatNeq(final RatNeqExpr expr) { + return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatGeq(final RatGeqExpr expr) { + return String.format("(>= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatGt(final RatGtExpr expr) { + return String.format("(> %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatLeq(final RatLeqExpr expr) { + return String.format("(<= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformRatLt(final RatLtExpr expr) { + return String.format("(< %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + /* + * Integers + */ + + protected String transformIntLit(final IntLitExpr expr) { + return expr.getValue().toString(); + } + + protected String transformIntAdd(final IntAddExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(+ %s)", String.join(" ", opTerms)); + } + + protected String transformIntSub(final IntSubExpr expr) { + return String.format("(- %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntPos(final IntPosExpr expr) { + return toTerm(expr.getOp()); + } + + protected String transformIntNeg(final IntNegExpr expr) { + return String.format("(- %s)", toTerm(expr.getOp())); + } + + protected String transformIntMul(final IntMulExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(* %s)", String.join(" ", opTerms)); + } + + protected String transformIntDiv(final IntDivExpr expr) { + return String.format("(/ %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntMod(final IntModExpr expr) { + return String.format("(mod %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntRem(final IntRemExpr expr) { + return String.format("(rem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntEq(final IntEqExpr expr) { + return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntNeq(final IntNeqExpr expr) { + return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntGeq(final IntGeqExpr expr) { + return String.format("(>= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntGt(final IntGtExpr expr) { + return String.format("(> %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntLeq(final IntLeqExpr expr) { + return String.format("(<= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntLt(final IntLtExpr expr) { + return String.format("(< %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformIntToRat(final IntToRatExpr expr) { + return String.format("(to_real %s)", toTerm(expr.getOp())); + } + + protected String transformIntToBv(final IntToBvExpr expr) { + throw new UnsupportedOperationException("SMT-LIB does not have the corresponding operation"); + /* Works with Z3, but it is not standard + return String.format("((_ int2bv %d) %s)", expr.getType().getSize(), toTerm(expr.getOp())); + */ + } + + /* + * Bitvectors + */ + + protected String transformBvLit(final BvLitExpr expr) { + final String value = Arrays.toString(expr.getValue()) + .replace("true", "1") + .replace("false", "0") + .replace("[", "") + .replace("]", "") + .replace(",", "") + .replace(" ", ""); + + return String.format("#b%s", value); + } + + protected String transformBvAdd(final BvAddExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(bvadd %s)", String.join(" ", opTerms)); + } + + protected String transformBvSub(final BvSubExpr expr) { + return String.format("(bvsub %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvPos(final BvPosExpr expr) { + return toTerm(expr.getOp()); + } + + protected String transformBvNeg(final BvNegExpr expr) { + return String.format("(bvneg %s)", toTerm(expr.getOp())); + } + + protected String transformBvMul(final BvMulExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(bvmul %s)", String.join(" ", opTerms)); + } + + protected String transformBvDiv(final BvDivExpr expr) { + if(expr.getType().isSigned()) { + return String.format("(bvsdiv %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvudiv %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvMod(final BvModExpr expr) { + if(expr.getType().isSigned()) { + return String.format("(bvsmod %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvurem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvRem(final BvRemExpr expr) { + if(expr.getType().isSigned()) { + return String.format("(bvsrem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvurem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvAnd(final BvAndExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(bvand %s)", String.join(" ", opTerms)); + } + + protected String transformBvOr(final BvOrExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(bvor %s)", String.join(" ", opTerms)); + } + + protected String transformBvXor(final BvXorExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(bvxor %s)", String.join(" ", opTerms)); + } + + protected String transformBvNot(final BvNotExpr expr) { + return String.format("(bvnot %s)", toTerm(expr.getOp())); + } + + protected String transformBvShiftLeft(final BvShiftLeftExpr expr) { + return String.format("(bvshl %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvArithShiftRight(final BvArithShiftRightExpr expr) { + return String.format("(bvashr %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvLogicShiftRight(final BvLogicShiftRightExpr expr) { + return String.format("(bvlshr %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvRotateLeft(final BvRotateLeftExpr expr) { + final var toRotate = toTerm(expr.getLeftOp()); + final var rotateWith = toTerm(expr.getRightOp()); + final var size = toTerm(BvUtils.intToBvLitExpr(expr.getType().getSize(), expr.getType().getSize(), expr.getRightOp().getType().isSigned())); + return String.format("(bvor (bvshl %s %s) (bvlshr %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); + // return String.format("((_ rotate_left %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); + } + + protected String transformBvRotateRight(final BvRotateRightExpr expr) { + final var toRotate = toTerm(expr.getLeftOp()); + final var rotateWith = toTerm(expr.getRightOp()); + final var size = toTerm(BvUtils.intToBvLitExpr(expr.getType().getSize(), expr.getType().getSize(), expr.getRightOp().getType().isSigned())); + return String.format("(bvor (bvlshr %s %s) (bvshl %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); + // return String.format("((_ rotate_right %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); + } + + protected String transformBvEq(final BvEqExpr expr) { + return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvNeq(final BvNeqExpr expr) { + return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvGeq(final BvGeqExpr expr) { + if(expr.getLeftOp().getType().isSigned()) { + return String.format("(bvsge %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvuge %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvGt(final BvGtExpr expr) { + if(expr.getLeftOp().getType().isSigned()) { + return String.format("(bvsgt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvugt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvLeq(final BvLeqExpr expr) { + if(expr.getLeftOp().getType().isSigned()) { + return String.format("(bvsle %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvule %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvLt(final BvLtExpr expr) { + if(expr.getLeftOp().getType().isSigned()) { + return String.format("(bvslt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + else { + return String.format("(bvult %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + } + + protected String transformBvToInt(final BvToIntExpr expr) { + throw new UnsupportedOperationException("SMT-LIB does not have the corresponding operation"); + /* Works with Z3, but not standard + if(expr.getOp().getType().isSigned()) { + final String bv = toTerm(expr.getOp()); + final BigInteger exp = BigInteger.TWO.pow(expr.getOp().getType().getSize()); + return String.format( + "(ite (bvslt %s ((_ int2bv %d) 0)) (- (bv2int %s) %s) (bv2int %s))", + bv, expr.getOp().getType().getSize(), bv, exp.toString(), bv + ); + } + else { + return String.format("(bv2int %s)", toTerm(expr.getOp())); + } + */ + } + + /* + * Functions + */ + + protected String transformFuncApp(final FuncAppExpr expr) { + final Tuple2, List>> funcAndArgs = extractFuncAndArgs(expr); + final Expr func = funcAndArgs.get1(); + if (func instanceof RefExpr) { + final RefExpr ref = (RefExpr) func; + final Decl decl = ref.getDecl(); + final String funcDecl = transformer.toSymbol(decl); + final List> args = funcAndArgs.get2(); + final String[] argTerms = args.stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(%s %s)", funcDecl, String.join(" ", argTerms)); + } else { + throw new UnsupportedOperationException("Higher order functions are not supported: " + func); + } + } + + private static Tuple2, List>> extractFuncAndArgs(final FuncAppExpr expr) { + final Expr func = expr.getFunc(); + final Expr arg = expr.getParam(); + if (func instanceof FuncAppExpr) { + final FuncAppExpr funcApp = (FuncAppExpr) func; + final Tuple2, List>> funcAndArgs = extractFuncAndArgs(funcApp); + final Expr resFunc = funcAndArgs.get1(); + final List> args = funcAndArgs.get2(); + final List> resArgs = ImmutableList.>builder().addAll(args).add(arg).build(); + return Tuple2.of(resFunc, resArgs); + } else { + return Tuple2.of(func, ImmutableList.of(arg)); + } + } + + /* + * Arrays + */ + + protected String transformArrayRead(final ArrayReadExpr expr) { + return String.format("(select %s %s)", toTerm(expr.getArray()), toTerm(expr.getIndex())); + } + + protected String transformArrayWrite(final ArrayWriteExpr expr) { + return String.format("(store %s %s %s)", toTerm(expr.getArray()), toTerm(expr.getIndex()), toTerm(expr.getElem())); + } + + protected String transformArrayEq(final ArrayEqExpr expr) { + return String.format("(= %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformArrayNeq(final ArrayNeqExpr expr) { + return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformArrayLit(final ArrayLitExpr expr) { + String running = String.format("((as const %s) %s)", transformer.toSort(expr.getType()), toTerm(expr.getElseElem())); + for (Tuple2, ? extends Expr> elem : expr.getElements()) { + running = String.format("(store %s %s %s)", running, toTerm(elem.get1()), toTerm(elem.get2())); + } + return running; + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinuousSolverBinary.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java similarity index 89% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinuousSolverBinary.java rename to subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java index bc4f29dc48..84b01c7dcf 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/binary/ContinuousSolverBinary.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java @@ -1,6 +1,6 @@ -package hu.bme.mit.theta.solver.smtlib.binary; +package hu.bme.mit.theta.solver.smtlib.generic; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverProcessFailureException; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverBinaryException; import java.io.IOException; import java.io.InputStreamReader; @@ -13,13 +13,13 @@ import static com.google.common.base.Preconditions.checkState; -public final class ContinuousSolverBinary implements SolverBinary { +public final class GenericSmtLibSolverBinary implements hu.bme.mit.theta.solver.smtlib.SmtLibSolverBinary { private final Process solverProcess; private final PrintWriter solverInput; private final Reader solverOutput; - public ContinuousSolverBinary(final Path solverPath, final String[] args) { + public GenericSmtLibSolverBinary(final Path solverPath, final String[] args) { final var processCmd = new ArrayList(); processCmd.add(solverPath.toAbsolutePath().toString()); processCmd.addAll(Arrays.asList(args)); @@ -31,7 +31,7 @@ public ContinuousSolverBinary(final Path solverPath, final String[] args) { solverOutput = new InputStreamReader(solverProcess.getInputStream(), StandardCharsets.US_ASCII); checkState(solverProcess.isAlive()); } catch (IOException e) { - throw new SmtLibSolverProcessFailureException(e); + throw new SmtLibSolverBinaryException(e); } } @@ -48,14 +48,14 @@ private String readResponse(final Reader solverOutput) { while (sb.length() == 0 || !readProcessor.isReady()) { Thread.yield(); if (!solverProcess.isAlive()) { - throw new SmtLibSolverProcessFailureException("Solver process terminated early"); + throw new SmtLibSolverBinaryException("Solver process terminated early"); } try { while (solverOutput.ready() && !readProcessor.isReady()) { readProcessor.step(sb, (char) solverOutput.read()); } } catch (IOException e) { - throw new SmtLibSolverProcessFailureException(e); + throw new SmtLibSolverBinaryException(e); } } return sb.toString().trim(); diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java new file mode 100644 index 0000000000..d172e1bc29 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java @@ -0,0 +1,48 @@ +package hu.bme.mit.theta.solver.smtlib.generic; + +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolver; + +import java.nio.file.Path; + +public class GenericSmtLibSolverFactory implements SolverFactory { + private final Path solverPath; + private final String[] args; + + private GenericSmtLibSolverFactory(Path solverPath, String[] args) { + this.solverPath = solverPath; + this.args = args; + } + + public static GenericSmtLibSolverFactory create(Path solverPath, String[] args) { + return new GenericSmtLibSolverFactory(solverPath, args); + } + + @Override + public Solver createSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); + } + + @Override + public UCSolver createUCSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); + } + + @Override + public ItpSolver createItpSolver() { + throw new UnsupportedOperationException("GenericSmtLibSolver does not support interpolation"); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java new file mode 100644 index 0000000000..3f3ff1c10c --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java @@ -0,0 +1,59 @@ +package hu.bme.mit.theta.solver.smtlib.generic; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Maps; +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public class GenericSmtLibSymbolTable implements SmtLibSymbolTable { + private final BiMap, String> constToSymbol; + private final BiMap, String> constToDeclaration; + + public GenericSmtLibSymbolTable() { + constToSymbol = Maps.synchronizedBiMap(HashBiMap.create()); + constToDeclaration = Maps.synchronizedBiMap(HashBiMap.create()); + } + + @Override + public boolean definesConst(final ConstDecl constDecl) { + return constToSymbol.containsKey(constDecl); + } + + @Override + public boolean definesSymbol(final String symbol) { + return constToSymbol.inverse().containsKey(symbol); + } + + @Override + public String getSymbol(final ConstDecl constDecl) { + checkArgument(definesConst(constDecl)); + return constToSymbol.get(constDecl); + } + + @Override + public String getDeclaration(final ConstDecl constDecl) { + checkArgument(definesConst(constDecl)); + return constToDeclaration.get(constDecl); + } + + @Override + public ConstDecl getConst(final String symbol) { + checkArgument(definesSymbol(symbol)); + return constToSymbol.inverse().get(symbol); + } + + @Override + public void put(final ConstDecl constDecl, final String symbol, final String declaration) { + checkNotNull(constDecl); + checkNotNull(symbol); + checkNotNull(declaration); + checkState(!constToSymbol.containsKey(constDecl), "Constant not found."); + constToSymbol.put(constDecl, symbol); + constToDeclaration.put(constDecl, declaration); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java new file mode 100644 index 0000000000..6a9e0f7525 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java @@ -0,0 +1,926 @@ +package hu.bme.mit.theta.solver.smtlib.generic; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableList; +import hu.bme.mit.theta.common.QuintFunction; +import hu.bme.mit.theta.common.TernaryOperator; +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.core.decl.Decls; +import hu.bme.mit.theta.core.decl.ParamDecl; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.LitExpr; +import hu.bme.mit.theta.core.type.Type; +import hu.bme.mit.theta.core.type.abstracttype.AddExpr; +import hu.bme.mit.theta.core.type.abstracttype.DivExpr; +import hu.bme.mit.theta.core.type.abstracttype.EqExpr; +import hu.bme.mit.theta.core.type.abstracttype.GeqExpr; +import hu.bme.mit.theta.core.type.abstracttype.GtExpr; +import hu.bme.mit.theta.core.type.abstracttype.LeqExpr; +import hu.bme.mit.theta.core.type.abstracttype.LtExpr; +import hu.bme.mit.theta.core.type.abstracttype.ModExpr; +import hu.bme.mit.theta.core.type.abstracttype.MulExpr; +import hu.bme.mit.theta.core.type.abstracttype.NegExpr; +import hu.bme.mit.theta.core.type.abstracttype.RemExpr; +import hu.bme.mit.theta.core.type.abstracttype.SubExpr; +import hu.bme.mit.theta.core.type.anytype.IteExpr; +import hu.bme.mit.theta.core.type.anytype.RefExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayReadExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayType; +import hu.bme.mit.theta.core.type.arraytype.ArrayWriteExpr; +import hu.bme.mit.theta.core.type.booltype.AndExpr; +import hu.bme.mit.theta.core.type.booltype.BoolExprs; +import hu.bme.mit.theta.core.type.booltype.IffExpr; +import hu.bme.mit.theta.core.type.booltype.ImplyExpr; +import hu.bme.mit.theta.core.type.booltype.NotExpr; +import hu.bme.mit.theta.core.type.booltype.OrExpr; +import hu.bme.mit.theta.core.type.booltype.XorExpr; +import hu.bme.mit.theta.core.type.bvtype.BvAddExpr; +import hu.bme.mit.theta.core.type.bvtype.BvAndExpr; +import hu.bme.mit.theta.core.type.bvtype.BvArithShiftRightExpr; +import hu.bme.mit.theta.core.type.bvtype.BvDivExpr; +import hu.bme.mit.theta.core.type.bvtype.BvExprs; +import hu.bme.mit.theta.core.type.bvtype.BvGeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvGtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLogicShiftRightExpr; +import hu.bme.mit.theta.core.type.bvtype.BvLtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvModExpr; +import hu.bme.mit.theta.core.type.bvtype.BvNegExpr; +import hu.bme.mit.theta.core.type.bvtype.BvNotExpr; +import hu.bme.mit.theta.core.type.bvtype.BvOrExpr; +import hu.bme.mit.theta.core.type.bvtype.BvRemExpr; +import hu.bme.mit.theta.core.type.bvtype.BvShiftLeftExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; +import hu.bme.mit.theta.core.type.bvtype.BvType; +import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; +import hu.bme.mit.theta.core.type.functype.FuncExprs; +import hu.bme.mit.theta.core.type.functype.FuncType; +import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; +import hu.bme.mit.theta.core.utils.BvUtils; +import hu.bme.mit.theta.core.utils.ExprUtils; +import hu.bme.mit.theta.solver.smtlib.SmtLibModel; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Exists; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Forall; +import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; +import static hu.bme.mit.theta.core.type.functype.FuncExprs.Func; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; +import static hu.bme.mit.theta.core.type.rattype.RatExprs.Rat; +import static hu.bme.mit.theta.core.utils.TypeUtils.cast; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.BinaryContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.DecimalContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Exists_termContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Forall_termContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Generic_termContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.HexadecimalContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.IdentifierContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.IndexContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.NumeralContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Qual_identifierContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.SortContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Spec_constantContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.SymbolContext; +import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.TermContext; +import static java.util.stream.Collectors.toList; + +public class GenericSmtLibTermTransformer implements SmtLibTermTransformer { + protected final SmtLibSymbolTable symbolTable; + protected final Map funAppTransformer; + + public GenericSmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { + this.symbolTable = symbolTable; + this.funAppTransformer = new HashMap<>() {{ + // Generic + put("ite", exprIteOperator()); + + // Abstract + put("=", exprRelationalOperator(EqExpr::create2)); + put("<=", exprRelationalOperator(LeqExpr::create2)); + put("<", exprRelationalOperator(LtExpr::create2)); + put(">=", exprRelationalOperator(GeqExpr::create2)); + put(">", exprRelationalOperator(GtExpr::create2)); + put("+", exprMultiaryOperator(AddExpr::create2)); + put("-", exprMinusOperator()); + put("*", exprMultiaryOperator(MulExpr::create2)); + put("div", exprBinaryOperator(DivExpr::create2)); + put("mod", exprBinaryOperator(ModExpr::create2)); + put("rem", exprBinaryOperator(RemExpr::create2)); + + // Booleal + put("not", exprUnaryOperator(NotExpr::create)); + put("or", exprMultiaryOperator(OrExpr::create)); + put("and", exprMultiaryOperator(AndExpr::create)); + put("xor", exprBinaryOperator(XorExpr::create)); + put("iff", exprBinaryOperator(IffExpr::create)); + put("=>", exprBinaryOperator(ImplyExpr::create)); + + // Integer + put("to_real", exprUnaryOperator(IntToRatExpr::create)); + + // Rational + + // Bitvector + put("bvadd", exprMultiaryOperator(BvAddExpr::create)); + put("bvsub", exprBinaryOperator(BvSubExpr::create)); + put("bvneg", exprUnaryOperator(BvNegExpr::create)); + put("bvmul", exprMultiaryOperator(BvAddExpr::create)); + put("bvudiv", exprBinaryOperator(BvDivExpr::create)); + put("bvsdiv", exprBinaryOperator(BvDivExpr::create)); + put("bvsmod", exprBinaryOperator(BvModExpr::create)); + put("bvsrem", exprBinaryOperator(BvRemExpr::create)); + put("bvurem", exprBinaryOperator(BvRemExpr::create)); + put("bvand", exprMultiaryOperator(BvAndExpr::create)); + put("bvor", exprMultiaryOperator(BvOrExpr::create)); + put("bvxor", exprMultiaryOperator(BvXorExpr::create)); + put("bvnot", exprUnaryOperator(BvNotExpr::create)); + put("bvshl", exprBinaryOperator(BvShiftLeftExpr::create)); + put("bvashr", exprBinaryOperator(BvArithShiftRightExpr::create)); + put("bvlshr", exprBinaryOperator(BvLogicShiftRightExpr::create)); + put("bvult", exprBinaryOperator(BvLtExpr::create)); + put("bvslt", exprBinaryOperator(BvLtExpr::create)); + put("bvule", exprBinaryOperator(BvLeqExpr::create)); + put("bvsle", exprBinaryOperator(BvLeqExpr::create)); + put("bvugt", exprBinaryOperator(BvGtExpr::create)); + put("bvsgt", exprBinaryOperator(BvGtExpr::create)); + put("bvuge", exprBinaryOperator(BvGeqExpr::create)); + put("bvsge", exprBinaryOperator(BvGeqExpr::create)); + + // Array + put("select", exprArrayReadOperator()); + put("store", exprArrayWriteOperator()); + }}; + } + + /* Public interface */ + + @Override + public

LitExpr> toFuncLitExpr(final String funcLitImpl, final FuncType type, final SmtLibModel model) { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(funcLitImpl)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + + final var litExpr = transformFuncDef(parser.function_def(), type, model, HashBiMap.create()); + if(litExpr == null) { + return null; + } + else if(litExpr instanceof LitExpr) { + return (LitExpr>) cast(litExpr, type); + } + else { + return (LitExpr>) cast(ExprUtils.simplify(litExpr), type); + } + } + + @Override + public Expr toExpr(final String term, final Type type, final SmtLibModel model) { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(term)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + + final var expr = transformTerm(parser.function_def().term(), type, model, HashBiMap.create()); + if(expr == null) { + return null; + } + else { + return cast(expr, type); + } + } + + @Override + public LitExpr toLitExpr(final String litImpl, final T type, final SmtLibModel model) { + final var litExpr = toExpr(litImpl, type, model); + + if(litExpr == null) { + return null; + } + else if(litExpr instanceof LitExpr) { + return (LitExpr) cast(litExpr, type); + } + else { + return (LitExpr) cast(ExprUtils.simplify(litExpr), type); + } + } + + @Override + @SuppressWarnings("unchecked") + public LitExpr> toArrayLitExpr(final String arrayLitImpl, final ArrayType type, final SmtLibModel model) { + final var arrayLitExpr = toExpr(arrayLitImpl, type, model); + + if(arrayLitExpr == null) { + return null; + } + else if(arrayLitExpr instanceof IteExpr) { + final var entryExprsBuilder = new ImmutableList.Builder, Expr>>(); + var iteExpr = (IteExpr) arrayLitExpr; + while (true) { + entryExprsBuilder.add(Tuple2.of((Expr) iteExpr.getCond().getOps().get(1), iteExpr.getThen())); + if (iteExpr.getElse() instanceof IteExpr) { + iteExpr = (IteExpr) iteExpr.getElse(); + } else { + return Array(entryExprsBuilder.build(), iteExpr.getElse(), type); + } + } + } + else { + return (LitExpr>) cast(ExprUtils.simplify(arrayLitExpr), type); + } + } + + @Override + public LitExpr toBvLitExpr(final String bvLitImpl, final BvType type, final SmtLibModel model) { + final var bvLitExpr = toExpr(bvLitImpl, type, model); + + if(bvLitExpr == null) { + return null; + } + else if(bvLitExpr instanceof BvLitExpr) { + return Bv(((BvLitExpr) bvLitExpr).getValue(), type.isSigned()); + } + else { + return (LitExpr) cast(ExprUtils.simplify(bvLitExpr), type); + } + } + + /* End of public interface */ + + /* Visitor implementation */ + + protected Expr transformFuncDef(final SMTLIBv2Parser.Function_defContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert type == null || type instanceof FuncType; + assert model != null; + assert vars != null; + + final var funcType = type != null ? (FuncType) type : null; + + final var paramDecls = ctx.sorted_var().stream() + .map(sv -> new ParamTypeDeducer( + sv.symbol().getText(), transformSort(sv.sort(), + funcType != null ? funcType.getParamType() : null)) + ) + .collect(toList()); + checkArgument(paramDecls.size() == 1, "Only unary functions are supported"); + + pushParams(paramDecls, vars); + final var op = transformTerm(ctx.term(), funcType != null ? funcType.getResultType() : type, model, vars); + popParams(paramDecls, vars); + + if(paramDecls.get(0).isTypeUnknown()) { + return null; + } + else { + assert op != null; + return Func(paramDecls.get(0).getParamDecl(), op); + } + } + + protected Expr transformTerm(final TermContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert model != null; + assert vars != null; + + if(ctx.spec_constant() != null) { + return transformSpecConstant(ctx.spec_constant(), type, model, vars); + } + else if(ctx.qual_identifier() != null) { + return transformQualIdentifier(ctx.qual_identifier(), type, model, vars); + } + else if(ctx.generic_term() != null) { + return transformGenericTerm(ctx.generic_term(), type, model, vars); + } + else if(ctx.let_term() != null) { + throw new UnsupportedOperationException(); + } + else if(ctx.forall_term() != null) { + return transformForallTerm(ctx.forall_term(), type, model, vars); + } + else if(ctx.exists_term() != null) { + return transformExistsTerm(ctx.exists_term(), type, model, vars); + } + else if(ctx.match_term() != null) { + throw new UnsupportedOperationException(); + } + else if(ctx.annotate_term() != null) { + throw new UnsupportedOperationException(); + } + else { + throw new SmtLibSolverException("Invalid input"); + } + } + + protected Expr transformSpecConstant(final Spec_constantContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert model != null; + assert vars != null; + + if(ctx.numeral() != null) { + return transformNumeral(ctx.numeral(), type, model, vars); + } + else if(ctx.decimal() != null) { + return transformDecimal(ctx.decimal(), type, model, vars); + } + else if(ctx.hexadecimal() != null) { + return transformHexadecimal(ctx.hexadecimal(), type, model, vars); + } + else if(ctx.binary() != null) { + return transformBinary(ctx.binary(), type, model, vars); + } + else if(ctx.string() != null) { + throw new UnsupportedOperationException(); + } + else { + throw new SmtLibSolverException("Invalid input"); + } + } + + protected Expr transformQualIdentifier(final Qual_identifierContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert model != null; + assert vars != null; + + return transformIdentifier(ctx.identifier(), type, model, vars); + } + + protected Expr transformGenericTerm(final Generic_termContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert model != null; + assert vars != null; + + final var funName = ctx.qual_identifier().identifier().symbol().getText(); + + final var funParams = ctx.qual_identifier().identifier().index(); + final var funAppParams = ctx.term(); + + if (funName.equals("const")) { // as const construct + final var constType = transformSort(ctx.qual_identifier().sort(), type); + if (constType instanceof ArrayType) { + assert type == null || type.equals(constType); + checkArgument(funAppParams.size() == 1, "Invalid as const construct"); + + final var arrayType = (ArrayType) constType; + final var expr = transformTerm(funAppParams.get(0), arrayType.getElemType(), model, vars); + return createArrayLitExpr(expr, (ArrayType) type); + } + else { + throw new UnsupportedOperationException(); + } + } else if (funAppTransformer.containsKey(funName)) { // known function application + return funAppTransformer.get(funName).apply(funParams, funAppParams, type, model, vars); + } else { // custom function application + checkArgument(funParams.size() == 0, "Custom unary function application cannot vahe parameter"); + checkArgument(funAppParams.size() == 1, "Only unary functions are supported"); + + return createFuncAppExpr(funName, funAppParams.get(0), type, model, vars); + } + } + + @SuppressWarnings("unchecked") + private Expr createArrayLitExpr(final Expr elze, final ArrayType type) { + return Array(Collections.emptyList(), (Expr) elze, type); + } + + private

Expr createFuncAppExpr(final String funName, final TermContext funAppParam, final Type returnType, final SmtLibModel model, final BiMap vars) { + + var paramExpr = transformTerm(funAppParam, null, model, vars); + final Type paramType = paramExpr != null ? paramExpr.getType() : null; + + final Expr funcExpr; + if (symbolTable.definesSymbol(funName)) { + funcExpr = checkNotNull(symbolTable.getConst(funName).getRef()); + } else { + final var funDefImpl = model.getTerm(funName); + if(paramType == null || returnType == null) { + funcExpr = toFuncLitExpr(funDefImpl, null, model); + if(funcExpr == null) { + return null; + } + } + else { + funcExpr = checkNotNull(toFuncLitExpr(funDefImpl, FuncType.of(paramType, returnType), model), "Unsupported expression: was not able to deduce all types"); + } + } + + assert funcExpr.getType() instanceof FuncType; + @SuppressWarnings("unchecked") final var funType = (FuncType) funcExpr.getType(); + paramExpr = paramExpr == null ? transformTerm(funAppParam, funType.getParamType(), model, vars) : paramExpr; + + return FuncExprs.App(cast(funcExpr, funType), cast(paramExpr, funType.getParamType())); + } + + protected Expr transformForallTerm(final Forall_termContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert type == null || type.equals(Bool()); + assert model != null; + assert vars != null; + + final var paramDecls = ctx.sorted_var().stream() + .map(sv -> new ParamTypeDeducer(sv.symbol().getText(), transformSort(sv.sort(), null))) + .collect(toList()); + + pushParams(paramDecls, vars); + final var op = transformTerm(ctx.term(), type, model, vars); + popParams(paramDecls, vars); + + if(paramDecls.stream().anyMatch(ParamTypeDeducer::isTypeUnknown)) { + return null; + } + else { + assert op != null; + return Forall( + paramDecls.stream().map(ParamTypeDeducer::getParamDecl).collect(Collectors.toUnmodifiableList()), + cast(op, Bool()) + ); + } + } + + protected Expr transformExistsTerm(final Exists_termContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert type == null || type.equals(Bool()); + assert model != null; + assert vars != null; + + final var paramDecls = ctx.sorted_var().stream() + .map(sv -> new ParamTypeDeducer(sv.symbol().getText(), transformSort(sv.sort(), null))) + .collect(toList()); + + pushParams(paramDecls, vars); + final var op = transformTerm(ctx.term(), type, model, vars); + popParams(paramDecls, vars); + + if(paramDecls.stream().anyMatch(ParamTypeDeducer::isTypeUnknown)) { + return null; + } + else { + assert op != null; + return Exists( + paramDecls.stream().map(ParamTypeDeducer::getParamDecl).collect(Collectors.toUnmodifiableList()), + cast(op, Bool()) + ); + } + } + + protected Expr transformIdentifier(final IdentifierContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert model != null; + assert vars != null; + + if(ctx.symbol().getText().equals("as-array")) { + final var name = ctx.index().get(0).getText(); + return toExpr(model.getTerm(name), type, model); + } + else { + return transformSymbol(ctx.symbol(), type, model, vars); + } + } + + protected Expr transformSymbol(final SymbolContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert model != null; + assert vars != null; + + final var value = ctx.getText(); + switch (value) { + case "true": + return BoolExprs.True(); + case "false": + return BoolExprs.False(); + default: + if(vars.containsValue(value)) { + final var decl = vars.inverse().get(value); + if(decl.isTypeUnknown()) { + if(type == null) { + return null; + } + else { + decl.setType(type); + return decl.getRef(); + } + } + else { + final var ref = decl.getRef(); + assert type == null || type.equals(ref.getType()); + return ref; + } + } + else if(symbolTable.definesSymbol(value)) { + final var ref = symbolTable.getConst(value).getRef(); + assert type == null || type.equals(ref.getType()); + return ref; + } + else { + throw new UnsupportedOperationException(); + } + } + } + + protected Expr transformNumeral(final NumeralContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert type == null || type.equals(Int()); + assert model != null; + assert vars != null; + + return Int(ctx.getText()); + } + + protected Expr transformDecimal(final DecimalContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert type == null || type.equals(Rat()); + assert model != null; + assert vars != null; + + final var decimal = new BigDecimal(ctx.getText()); + if(decimal.scale() <= 0) { + return Rat(decimal.unscaledValue(), BigInteger.ONE); + } + else { + return Rat(decimal.unscaledValue(), BigInteger.TEN.pow(decimal.scale())); + } + } + + protected Expr transformHexadecimal(final HexadecimalContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert type == null || type instanceof BvType; + assert model != null; + assert vars != null; + + if(type == null) { + return null; + } + else { + final var bvType = (BvType) type; + final var numStr = ctx.getText().substring(2); + final var num = new BigInteger(numStr, 16); + checkState(bvType.getSize() == numStr.length() * 4, "Type mismatch"); + + return BvUtils.bigIntegerToBvLitExpr(num, bvType.getSize(), bvType.isSigned()); + } + } + + protected Expr transformBinary(final BinaryContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + assert type == null || type instanceof BvType; + assert model != null; + assert vars != null; + + if(type == null) { + return null; + } + else { + final var bvType = (BvType) type; + final var numStr = ctx.getText().substring(2); + final var num = new BigInteger(numStr, 2); + checkState(bvType.getSize() == numStr.length(), "Type mismatch"); + + return BvUtils.bigIntegerToBvLitExpr(num, bvType.getSize(), bvType.isSigned()); + } + } + + protected Type transformSort(final SortContext ctx, final Type type) { + final var name = ctx.identifier().symbol().getText(); + switch(name) { + case "Bool": + assert type == null || type.equals(Bool()); + return Bool(); + case "Int": + assert type == null || type.equals(Int()); + return Int(); + case "Real": + assert type == null || type.equals(Rat()); + return Rat(); + case "BitVec": + assert type == null || type instanceof BvType; + if(type == null) { + return null; + } + else { + final var bvType = (BvType) type; + checkArgument(Integer.parseInt(ctx.identifier().index().get(0).getText()) == bvType.getSize(), "Type mismatch"); + return BvExprs.BvType(bvType.getSize(), bvType.isSigned()); + } + case "Array": + assert type == null || type instanceof ArrayType; + if(type == null) { + final var indexType = transformSort(ctx.sort().get(0), null); + final var elemType = transformSort(ctx.sort().get(1), null); + if(indexType == null || elemType == null) { + return null; + } + else { + return Array(indexType, elemType); + } + } + else { + final var arrayType = (ArrayType) type; + return Array(transformSort(ctx.sort().get(0), arrayType.getIndexType()), transformSort(ctx.sort().get(1), arrayType.getElemType())); + } + default: + throw new UnsupportedOperationException(); + } + } + + /* End of visitor implementation */ + + /* Variable scope handling */ + + protected void pushParams(final List paramDecls, BiMap vars) { + vars.putAll(paramDecls.stream().collect(Collectors.toUnmodifiableMap(Function.identity(), ParamTypeDeducer::getName))); + } + + protected void popParams(final List paramDecls, BiMap vars) { + for (final var paramDecl : paramDecls) { + vars.remove(paramDecl, paramDecl.getName()); + } + } + + /* Utilities */ + + @SuppressWarnings("unused") + private OperatorCreatorFunction exprNullaryOperator(final Supplier> function) { + return (params, ops, type, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 0, "Nullary operator expected"); + return function.get(); + }; + } + + private OperatorCreatorFunction exprUnaryOperator(final UnaryOperator> function) { + return (params, ops, type, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 1, "Unary operator expected"); + + if(type == null) { + final var op = transformTerm(ops.get(0), type, model, vars); + return function.apply(op); + } + else { + final var op = checkNotNull(transformTerm(ops.get(0), type, model, vars), "Unsupported expression: was not able to deduce all types"); + return function.apply(op); + } + }; + } + + private OperatorCreatorFunction exprBinaryOperator(final BinaryOperator> function) { + return (params, ops, type, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 2, "Binary operator expected"); + + if(type == null) { + var op1 = transformTerm(ops.get(0), null, model, vars); + var op2 = transformTerm(ops.get(1), null, model, vars); + if(op1 == null && op2 == null) { + return null; + } + else if(op1 != null && op2 == null) { + op2 = checkNotNull(transformTerm(ops.get(1), op1.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); + } + else if(op1 == null /* && op2 != null */) { + op1 = checkNotNull(transformTerm(ops.get(0), op2.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); + } + return function.apply(op1, op2); + } + else { + final var op1 = transformTerm(ops.get(0), type, model, vars); + final var op2 = transformTerm(ops.get(1), type, model, vars); + return function.apply(op1, op2); + } + }; + } + + private OperatorCreatorFunction exprRelationalOperator(final BinaryOperator> function) { + return (params, ops, type, model, vars) -> { + assert type == null || type.equals(Bool()); + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 2, "Binary operator expected"); + + var op1 = transformTerm(ops.get(0), null, model, vars); + var op2 = transformTerm(ops.get(1), null, model, vars); + if(op1 == null && op2 == null) { + return null; + } + else if(op1 != null && op2 == null) { + op2 = checkNotNull(transformTerm(ops.get(1), op1.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); + } + else if(op1 == null /* && op2 != null */) { + op1 = checkNotNull(transformTerm(ops.get(0), op2.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); + } + return function.apply(op1, op2); + }; + } + + private OperatorCreatorFunction exprArrayReadOperator() { + return (params, ops, type, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 2, "Binary operator expected"); + + var op1 = transformTerm(ops.get(0), null, model, vars); + var op2 = transformTerm(ops.get(1), null, model, vars); + if(op1 == null && op2 == null) { + return null; + } + else if(op1 != null && op2 == null) { + assert op1.getType() instanceof ArrayType; + final var arrayType = (ArrayType) op1.getType(); + op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars), "Unsupported expression: was not able to deduce all types"); + } + else if(op1 == null /* && op2 != null */) { + if(type == null) { + return null; + } + else { + final var arrayType = Array(op2.getType(), type); + op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars), "Unsupported expression: was not able to deduce all types"); + } + } + return ArrayReadExpr.create(op1, op2); + }; + } + + private OperatorCreatorFunction exprMinusOperator() { + return (params, ops, type, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 1 || ops.size() == 2, "Unary or binary operator expected"); + if(ops.size() == 2) { + return exprBinaryOperator(SubExpr::create2).apply(params, ops, type, model, vars); + } + else { + return exprUnaryOperator(NegExpr::create2).apply(params, ops, type, model, vars); + } + }; + } + + @SuppressWarnings("unused") + private OperatorCreatorFunction exprTernaryOperator(final TernaryOperator> function) { + return (params, ops, type, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 3, "Ternary operator expected"); + final Expr op1 = transformTerm(ops.get(0), type, model, vars); + final Expr op2 = transformTerm(ops.get(1), type, model, vars); + final Expr op3 = transformTerm(ops.get(2), type, model, vars); + return function.apply(op1, op2, op3); + }; + } + + private OperatorCreatorFunction exprIteOperator() { + return (params, ops, type, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 3, "Ternary operator expected"); + final var op1 = transformTerm(ops.get(0), Bool(), model, vars); + if(type == null) { + var op2 = transformTerm(ops.get(1), type, model, vars); + var op3 = transformTerm(ops.get(2), type, model, vars); + if(op2 == null && op3 == null) { + return null; + } + else if(op2 != null && op3 == null) { + op3 = checkNotNull(transformTerm(ops.get(2), op2.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); + } + else if(op2 == null /* && op3 != null */) { + op2 = checkNotNull(transformTerm(ops.get(1), op3.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); + } + return IteExpr.create(op1, op2, op3); + } + else { + final var op2 = transformTerm(ops.get(1), type, model, vars); + final var op3 = transformTerm(ops.get(2), type, model, vars); + return IteExpr.create(op1, op2, op3); + } + }; + } + + private OperatorCreatorFunction exprArrayWriteOperator() { + return (params, ops, type, model, vars) -> { + assert type == null || type instanceof ArrayType; + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 3, "Ternary operator expected"); + + if(type == null) { + var op1 = transformTerm(ops.get(0), null, model, vars); + var op2 = transformTerm(ops.get(1), null, model, vars); + var op3 = transformTerm(ops.get(2), null, model, vars); + + if(op1 != null && (op2 == null || op3 == null)) { + final var arrayType = (ArrayType) op1.getType(); + if(op2 == null) { + op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars), "Unsupported expression: was not able to deduce all types"); + } + if(op3 == null) { + op3 = checkNotNull(transformTerm(ops.get(2), arrayType.getElemType(), model, vars), "Unsupported expression: was not able to deduce all types"); + } + } + else if(op1 == null && op2 != null && op3 != null) { + final var arrayType = Array(op2.getType(), op3.getType()); + op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars), "Unsupported expression: was not able to deduce all types"); + } + else { + return null; + } + return ArrayWriteExpr.create(op1, op2, op3); + } + else { + final var arrayType = (ArrayType) type; + final var op1 = transformTerm(ops.get(0), arrayType, model, vars); + final var op2 = transformTerm(ops.get(1), arrayType.getIndexType(), model, vars); + final var op3 = transformTerm(ops.get(2), arrayType.getElemType(), model, vars); + return ArrayWriteExpr.create(op1, op2, op3); + } + }; + } + + private OperatorCreatorFunction exprMultiaryOperator(final Function>, Expr> function) { + return (params, ops, type, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + if(type == null) { + final var transformedOps = new ArrayList>(); + ops.stream() + .map(op -> transformTerm(op, type, model, vars)) + .forEach(transformedOps::add); + + if(transformedOps.stream().allMatch(Objects::isNull)) { + return null; + } + else { + final var opType = transformedOps.stream().filter(Objects::nonNull).findAny().get().getType(); + return function.apply(IntStream + .range(0, ops.size()) + .mapToObj(i -> transformedOps.get(i) == null ? transformTerm(ops.get(i), opType, model, vars) : transformedOps.get(i)) + .collect(Collectors.toUnmodifiableList()) + ); + } + } + else { + return function.apply(ops.stream().map(op -> transformTerm(op, type, model, vars)).collect(Collectors.toUnmodifiableList())); + } + }; + } + + private interface OperatorCreatorFunction extends QuintFunction< + List, // Parameters + List, // Operands + Type, // Expected type of result + SmtLibModel, // The model + BiMap, // The variable (param) store + Expr // Return type + > {} + + private final static class ParamTypeDeducer { + private final String name; + private Type type; + private ParamDecl paramDecl; + + public ParamTypeDeducer(final String name, final Type type) { + this.name = name; + if(type != null) { + setType(type); + } + } + + public boolean isTypeUnknown() { + return type == null; + } + + public void setType(final Type type) { + checkArgument(type != null); + checkState(this.type == null); + this.type = type; + this.paramDecl = Decls.Param(name, type); + } + + public String getName() { + return name; + } + + public ParamDecl getParamDecl() { + checkState(paramDecl != null); + return paramDecl; + } + + public RefExpr getRef() { + checkState(paramDecl != null); + return paramDecl.getRef(); + } + } + +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java new file mode 100644 index 0000000000..3c2981a9cb --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java @@ -0,0 +1,51 @@ +package hu.bme.mit.theta.solver.smtlib.generic; + +import hu.bme.mit.theta.core.decl.Decl; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.Type; +import hu.bme.mit.theta.solver.smtlib.SmtLibDeclTransformer; +import hu.bme.mit.theta.solver.smtlib.SmtLibExprTransformer; +import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.SmtLibTypeTransformer; + +public class GenericSmtLibTransformationManager implements SmtLibTransformationManager { + private final SmtLibTypeTransformer typeTransformer; + private final SmtLibDeclTransformer declTransformer; + private final SmtLibExprTransformer exprTransformer; + + public GenericSmtLibTransformationManager(final SmtLibSymbolTable symbolTable) { + this.typeTransformer = instantiateTypeTransformer(this); + this.declTransformer = instantiateDeclTransformer(this, symbolTable); + this.exprTransformer = instantiateExprTransformer(this); + } + + @Override + public final String toSort(final Type type) { + return typeTransformer.toSort(type); + } + + @Override + public final String toSymbol(final Decl decl) { + return declTransformer.toSymbol(decl); + } + + @Override + public final String toTerm(final Expr expr) { + return exprTransformer.toTerm(expr); + } + + protected SmtLibTypeTransformer instantiateTypeTransformer(final SmtLibTransformationManager transformer) { + return new GenericSmtLibTypeTransformer(transformer); + } + + protected SmtLibDeclTransformer instantiateDeclTransformer( + final SmtLibTransformationManager transformer, final SmtLibSymbolTable symbolTable + ) { + return new GenericSmtLibDeclTransformer(transformer, symbolTable); + } + + protected SmtLibExprTransformer instantiateExprTransformer(final SmtLibTransformationManager transformer) { + return new GenericSmtLibExprTransformer(transformer); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java new file mode 100644 index 0000000000..fe3e3c96f4 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java @@ -0,0 +1,68 @@ +package hu.bme.mit.theta.solver.smtlib.generic; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import hu.bme.mit.theta.common.DispatchTable; +import hu.bme.mit.theta.core.type.Type; +import hu.bme.mit.theta.core.type.arraytype.ArrayType; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.core.type.bvtype.BvType; +import hu.bme.mit.theta.core.type.inttype.IntType; +import hu.bme.mit.theta.core.type.rattype.RatType; +import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.SmtLibTypeTransformer; + +import java.util.concurrent.ExecutionException; + +public class GenericSmtLibTypeTransformer implements SmtLibTypeTransformer { + private static final int CACHE_SIZE = 1000; + + @SuppressWarnings("unused") + private final SmtLibTransformationManager transformer; + + private final Cache typeToSmtLib; + private final DispatchTable table; + + public GenericSmtLibTypeTransformer(final SmtLibTransformationManager transformer) { + this.transformer = transformer; + + typeToSmtLib = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).build(); + + table = DispatchTable.builder() + .addCase(BoolType.class, this::boolType) + .addCase(IntType.class, this::intType) + .addCase(RatType.class, this::ratType) + .addCase(BvType.class, this::bvType) + .addCase(ArrayType.class, this::arrayType) + .build(); + } + + @Override + public final String toSort(final Type type) { + try { + return typeToSmtLib.get(type, () -> table.dispatch(type)); + } catch (final ExecutionException e) { + throw new AssertionError(); + } + } + + protected String boolType(final BoolType type) { + return "Bool"; + } + + protected String intType(final IntType type) { + return "Int"; + } + + protected String ratType(final RatType type) { + return "Real"; + } + + protected String bvType(final BvType type) { + return String.format("(_ BitVec %d)", type.getSize()); + } + + protected String arrayType(final ArrayType type) { + return String.format("(Array %s %s)", toSort(type.getIndexType()), toSort(type.getElemType())); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java index 945c1b21ae..0d63f2a981 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java @@ -1,11 +1,11 @@ package hu.bme.mit.theta.solver.smtlib.parser; import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.solver.smtlib.SmtLibModel; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.misc.Interval; -import java.util.Collection; import java.util.Map; import java.util.stream.Collectors; @@ -15,10 +15,10 @@ import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Model_response_funs_recContext; public class GetModelResponse implements SpecificResponse { - private final Map values; + private final SmtLibModel model; private GetModelResponse(final Map values) { - this.values = values; + model = new SmtLibModel(values); } public static GetModelResponse fromContext(final Get_model_responseContext ctx) { @@ -40,16 +40,8 @@ public Tuple2 visitModel_response_funs_rec(Model_response_funs_r })).collect(Collectors.toUnmodifiableMap(Tuple2::get1, Tuple2::get2))); } - public static GetModelResponse empty() { - return new GetModelResponse(Map.of()); - } - - public Collection getDecls() { - return values.keySet(); - } - - public String getTerm(final String symbol) { - return values.get(symbol); + public SmtLibModel getModel() { + return model; } private static String extractString(final ParserRuleContext ctx) { diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java index 1e5783dea6..8219b00a5b 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java @@ -5,6 +5,7 @@ import hu.bme.mit.theta.core.utils.BvTestUtils; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -60,7 +61,7 @@ public void testOperationEquals() { ); // Equality check - final Solver solver = SmtLibSolverFactory.create( + final Solver solver = GenericSmtLibSolverFactory.create( Path.of("/home/vagrant/Vagrant/z3-4.8.8-x64-ubuntu-16.04/bin/z3"), new String[] { "-in", "-smt2" } ).createSolver(); diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index 8f185d1f69..8fd5f1af16 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -20,12 +20,16 @@ import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTermTransformer; import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; import org.junit.BeforeClass; import org.junit.Test; import java.nio.file.Path; import java.util.List; +import java.util.Map; import java.util.Optional; import static com.google.common.collect.ImmutableList.of; @@ -45,11 +49,11 @@ import static org.junit.Assert.assertTrue; public final class SmtLibSolverTest { - private static SmtLibSolverFactory solverFactory; + private static GenericSmtLibSolverFactory solverFactory; @BeforeClass public static void init() { - solverFactory = SmtLibSolverFactory.create( + solverFactory = GenericSmtLibSolverFactory.create( Path.of("/home/vagrant/Vagrant/z3-4.8.8-x64-ubuntu-16.04/bin/z3"), new String[] { "-in", "-smt2" } ); @@ -57,15 +61,15 @@ public static void init() { @Test public void test() { - final var symbolTable = new SmtLibSymbolTable(); - final var termTransformer = new SmtLibTermTransformer(symbolTable); + final var symbolTable = new GenericSmtLibSymbolTable(); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); final var x = Const("x", BvExprs.BvType(4, true)); symbolTable.put(x, "x", "(declare-fun x () (_ BitVec 4))"); final var expr = termTransformer.toExpr( "z () Bool (forall ((y (Array (_ BitVec 4) Int))) (= (select y x) 0))", - BoolExprs.Bool(), GetModelResponse.empty() + BoolExprs.Bool(), new SmtLibModel(Map.of()) ); assertNotNull(expr); assertTrue(expr instanceof ForallExpr); From 84eece228a0ab5c109171e50220954d4c8b95b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 31 Aug 2020 01:38:00 +0200 Subject: [PATCH 35/99] Remove unnecessary SmtLibUCSolverBase.java --- .../theta/solver/smtlib/SmtLibUCSolverBase.java | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibUCSolverBase.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibUCSolverBase.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibUCSolverBase.java deleted file mode 100644 index 9848fbb4fa..0000000000 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibUCSolverBase.java +++ /dev/null @@ -1,17 +0,0 @@ -package hu.bme.mit.theta.solver.smtlib; - -import hu.bme.mit.theta.solver.UCSolver; - -public abstract class SmtLibUCSolverBase implements UCSolver { - protected final SmtLibSolverBinary solverBinary; - protected final SmtLibSymbolTable symbolTable; - protected final SmtLibTransformationManager transformationManager; - protected final SmtLibTermTransformer termTransformer; - - public SmtLibUCSolverBase(final SmtLibSolverBinary solverBinary, final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, final SmtLibTermTransformer termTransformer) { - this.solverBinary = solverBinary; - this.symbolTable = symbolTable; - this.transformationManager = transformationManager; - this.termTransformer = termTransformer; - } -} From 64b301e3c3c030e4a8aefe2e4604ee2413052ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 31 Aug 2020 01:40:59 +0200 Subject: [PATCH 36/99] Create installer framework for GenericSmtLibSolver --- .../solver/smtlib/SmtLibSolverInstaller.java | 24 +++ .../SmtLibSolverInstallerException.java | 32 +++ .../generic/GenericSmtLibSolverInstaller.java | 197 ++++++++++++++++++ 3 files changed, 253 insertions(+) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java new file mode 100644 index 0000000000..38f366920d --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java @@ -0,0 +1,24 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.solver.SolverFactory; + +import java.nio.file.Path; +import java.util.List; + +public interface SmtLibSolverInstaller { + void install(Path home, String version) throws SmtLibSolverInstallerException; + + void uninstall(Path home, String version) throws SmtLibSolverInstallerException; + + void reinstall(Path home, String version) throws SmtLibSolverInstallerException; + + String getInfo(Path home, String version) throws SmtLibSolverInstallerException; + + Path getArgsFile(Path home, String version) throws SmtLibSolverInstallerException; + + SolverFactory getSolverFactory(Path home, String version) throws SmtLibSolverInstallerException; + + List getSupportedVersions() throws SmtLibSolverInstallerException; + + List getInstalledVersions(Path home) throws SmtLibSolverInstallerException; +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java new file mode 100644 index 0000000000..2b0fd262ff --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hu.bme.mit.theta.solver.smtlib; + +public class SmtLibSolverInstallerException extends Exception { + private static final long serialVersionUID = -7472824180590329943L; + + public SmtLibSolverInstallerException(Exception e) { + super(e); + } + + public SmtLibSolverInstallerException(String e) { + super(e); + } + + public SmtLibSolverInstallerException(String e, Throwable c) { + super(e, c); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java new file mode 100644 index 0000000000..decb537ff0 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java @@ -0,0 +1,197 @@ +package hu.bme.mit.theta.solver.smtlib.generic; + +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class GenericSmtLibSolverInstaller implements SmtLibSolverInstaller { + final Logger logger; + + public GenericSmtLibSolverInstaller(Logger logger) { + this.logger = logger; + } + + @Override + public void install(final Path home, final String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + throw new SmtLibSolverInstallerException("Unsupported operation for generic solvers"); + } + + public void install(final Path home, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + checkArgument(Files.exists(solverPath)); + checkNotNull(solverArgs); + + final var installDir = home.resolve(version); + if(Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is already installed"); + } + + try { + logger.write(Logger.Level.MAINSTEP, "Beginning installation...\n"); + + Files.createDirectory(installDir); + + final var solverFilePath = solverFile(installDir); + Files.writeString(solverFilePath, solverPath.toAbsolutePath().toString(), StandardCharsets.UTF_8); + + final var solverArgsPath = argsFile(installDir); + Files.writeString(solverArgsPath, String.join("\n", solverArgs), StandardCharsets.UTF_8); + + logger.write(Logger.Level.MAINSTEP, "Installation finished"); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public void uninstall(final Path home, final String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final var installDir = home.resolve(version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + try { + logger.write(Logger.Level.MAINSTEP, "Beginning uninstallation...\n"); + + final var solverFilePath = solverFile(installDir); + Files.delete(solverFilePath); + final var solverArgsPath = argsFile(installDir); + Files.delete(solverArgsPath); + + Files.delete(installDir); + + logger.write(Logger.Level.MAINSTEP, "Uninstallation finished"); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + + } + + @Override + public void reinstall(final Path home, final String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + throw new SmtLibSolverInstallerException("Unsupported operation for generic solvers"); + } + + @Override + public String getInfo(final Path home, final String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final var installDir = home.resolve(version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + try { + final var solverFilePath = solverFile(installDir); + final var solverPathStr = Files.readAllLines(solverFilePath, StandardCharsets.UTF_8).get(0); + final var solverArgsPath = argsFile(installDir); + final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); + + return "Generic solver" + + "Solver binary: " + solverPathStr + + "Arguments: " + String.join(" ", solverArgs); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public Path getArgsFile(final Path home, final String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final var installDir = home.resolve(version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + return argsFile(installDir); + } + + @Override + public SolverFactory getSolverFactory(final Path home, final String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final var installDir = home.resolve(version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + try { + final var solverFilePath = solverFile(installDir); + final var solverPathStr = Files.readAllLines(solverFilePath, StandardCharsets.UTF_8).get(0); + final var solverArgsPath = argsFile(installDir); + final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); + + return GenericSmtLibSolverFactory.create(Path.of(solverPathStr), solverArgs); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public List getSupportedVersions() throws SmtLibSolverInstallerException { + return Collections.emptyList(); + } + + @Override + public List getInstalledVersions(final Path home) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + + final var installedDirs = home.toFile() + .list((current, name) -> new File(current, name).isDirectory()); + + assert installedDirs != null; + return Arrays.asList(installedDirs); + } + + private void checkVersion(final String version) throws SmtLibSolverInstallerException { + if(!version.matches("^[a-zA-Z0-9_.-]+$")) { + throw new SmtLibSolverInstallerException("Unsupported version format: " + version); + } + } + + private Path solverFile(final Path installDir) { + return installDir.resolve("solver.txt"); + } + + private Path argsFile(final Path installDir) { + return installDir.resolve("solver-args.txt"); + } +} From 948f8041fa0c27bdaeb045f0ab34114f822001be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 31 Aug 2020 01:42:40 +0200 Subject: [PATCH 37/99] Create SMT-LIB solver manager framework --- .../smtlib/manager/SmtLibSolverManager.java | 197 ++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java new file mode 100644 index 0000000000..2a0ea735b4 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java @@ -0,0 +1,197 @@ +package hu.bme.mit.theta.solver.smtlib.manager; + +import com.google.common.collect.ImmutableList; +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverInstaller; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public final class SmtLibSolverManager { + private static final Map> installerDeclarations = new HashMap<>(); + private static Tuple2> genericInstallerDeclaration; + + public static void registerInstaller(final String name, final Class decl) { + installerDeclarations.put(name, decl); + } + + public static void registerGenericInstaller(final String name, final Class decl) { + checkState(genericInstallerDeclaration == null); + genericInstallerDeclaration = Tuple2.of(name, decl); + } + + static { + registerGenericInstaller("generic", GenericSmtLibSolverInstaller.class); + } + + private final Path home; + private final Logger logger; + + private final Map installers; + private final Tuple2 genericInstaller; + + private SmtLibSolverManager(final Path home, final Logger logger) { + this.logger = logger; + checkNotNull(home); + checkArgument(Files.exists(home)); + + this.home = home; + + try { + this.genericInstaller = Tuple2.of( + genericInstallerDeclaration.get1(), + genericInstallerDeclaration.get2().getDeclaredConstructor(Logger.class).newInstance(logger) + ); + + this.installers = Stream.concat( + Stream.of(this.genericInstaller), + installerDeclarations.entrySet().stream() + .map(p -> { + try { + return Tuple2.of(p.getKey(), p.getValue().getDeclaredConstructor(Logger.class).newInstance(logger)); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException(e); + } + }) + ).collect(Collectors.toUnmodifiableMap(Tuple2::get1, Tuple2::get2)); + } catch (InstantiationException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) { + throw new RuntimeException(e); + } + + } + + public static SmtLibSolverManager create(final Path home, final Logger logger) { + return new SmtLibSolverManager(home, logger); + } + + public String getGenericInstallerName() { + return genericInstaller.get1(); + } + + public void install(final String solver, final String version) throws SmtLibSolverInstallerException { + checkArgument(!solver.equals(genericInstaller.get1())); + + if(!installers.containsKey(solver)) { + throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); + } + + final var installDir = home.resolve(solver); + try { + if (!Files.exists(installDir)) { + Files.createDirectory(installDir); + } + } catch (IOException e) { + throw new SmtLibSolverInstallerException(e); + } + + installers.get(solver).install(installDir, version); + } + + public void installGeneric(final String version, final Path solverPath, final String[] args) throws SmtLibSolverInstallerException { + final var installDir = home.resolve(genericInstaller.get1()); + try { + if (!Files.exists(installDir)) { + Files.createDirectory(installDir); + } + } catch (IOException e) { + throw new SmtLibSolverInstallerException(e); + } + genericInstaller.get2().install(installDir, version, solverPath, args); + } + + public void uninstall(final String solver, final String version) throws SmtLibSolverInstallerException { + if(!installers.containsKey(solver)) { + throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); + } + + installers.get(solver).uninstall(home.resolve(solver), version); + } + + public void reinstall(final String solver, final String version) throws SmtLibSolverInstallerException { + if(!installers.containsKey(solver)) { + throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); + } + + installers.get(solver).reinstall(home.resolve(solver), version); + } + + + public String getInfo(final String solver, final String version) throws SmtLibSolverInstallerException { + if(!installers.containsKey(solver)) { + throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); + } + + return installers.get(solver).getInfo(home.resolve(solver), version); + } + + public Path getArgsFile(final String solver, final String version) throws SmtLibSolverInstallerException { + if(!installers.containsKey(solver)) { + throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); + } + + return installers.get(solver).getArgsFile(home.resolve(solver), version); + } + + public SolverFactory getSolverFactory(final String solver, final String version) throws SmtLibSolverInstallerException { + if(!installers.containsKey(solver)) { + throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); + } + + return installers.get(solver).getSolverFactory(home.resolve(solver), version); + } + + public List getSupportedSolvers() throws SmtLibSolverInstallerException { + return installers.keySet().stream().collect(Collectors.toUnmodifiableList()); + } + + public List>> getSupportedVersions() throws SmtLibSolverInstallerException { + final var builder = ImmutableList.>>builder(); + + for(final var solver : getSupportedSolvers()) { + builder.add(Tuple2.of(solver, getSupportedVersions(solver))); + } + + return builder.build(); + } + + public List getSupportedVersions(final String solver) throws SmtLibSolverInstallerException { + if(!installers.containsKey(solver)) { + throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); + } + + return installers.get(solver).getSupportedVersions(); + } + + public List>> getInstalledVersions() throws SmtLibSolverInstallerException { + final var builder = ImmutableList.>>builder(); + + for(final var solver : getSupportedSolvers()) { + builder.add(Tuple2.of(solver, getInstalledVersions(solver))); + } + + return builder.build(); + } + + public List getInstalledVersions(final String solver) throws SmtLibSolverInstallerException { + if(!installers.containsKey(solver)) { + throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); + } + + return installers.get(solver).getInstalledVersions(home.resolve(solver)); + } +} From 703f6214352df8b1665bdfd62ff38898ad0f99a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 31 Aug 2020 01:43:34 +0200 Subject: [PATCH 38/99] Create cli tool for managing SMT-LIB solvers --- subprojects/solver-smtlib-cli/README.md | 1 + subprojects/solver-smtlib-cli/bin/.gitignore | 2 + .../solver-smtlib-cli/build.gradle.kts | 12 ++ .../theta/solver/smtlib/cli/SmtLibCli.java | 168 ++++++++++++++++++ 4 files changed, 183 insertions(+) create mode 100644 subprojects/solver-smtlib-cli/README.md create mode 100644 subprojects/solver-smtlib-cli/bin/.gitignore create mode 100644 subprojects/solver-smtlib-cli/build.gradle.kts create mode 100644 subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java diff --git a/subprojects/solver-smtlib-cli/README.md b/subprojects/solver-smtlib-cli/README.md new file mode 100644 index 0000000000..227a82f08b --- /dev/null +++ b/subprojects/solver-smtlib-cli/README.md @@ -0,0 +1 @@ +This project is a cli tool for installing, managing the SMT-LIB compatible solvers. \ No newline at end of file diff --git a/subprojects/solver-smtlib-cli/bin/.gitignore b/subprojects/solver-smtlib-cli/bin/.gitignore new file mode 100644 index 0000000000..7eed456bec --- /dev/null +++ b/subprojects/solver-smtlib-cli/bin/.gitignore @@ -0,0 +1,2 @@ +/main/ +/test/ diff --git a/subprojects/solver-smtlib-cli/build.gradle.kts b/subprojects/solver-smtlib-cli/build.gradle.kts new file mode 100644 index 0000000000..ccc506edcb --- /dev/null +++ b/subprojects/solver-smtlib-cli/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + id("java-common") + id("cli-tool") +} + +dependencies { + compile(project(":theta-solver-smtlib")) +} + +application { + mainClassName = "hu.bme.mit.theta.solver.smtlib.cli.SmtLibCli" +} diff --git a/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java new file mode 100644 index 0000000000..1940735364 --- /dev/null +++ b/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java @@ -0,0 +1,168 @@ +package hu.bme.mit.theta.solver.smtlib.cli; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import com.beust.jcommander.ParameterException; +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.common.logging.ConsoleLogger; +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; + +public class SmtLibCli { + private static final String JAR_NAME = "theta-solver-smtlib-cli.jar"; + private final String[] args; + + private Logger logger; + + @Parameter(names = "--install", description = "Install a solver") + String install; + + @Parameter(names = "--install-solverPath", description = "The path of the generic solver to install") + String installSolverPath; + + @Parameter(names = "--install-solverArgs", description = "The arguments of the generic solver to invoke with") + String installSolverArgs; + + @Parameter(names = "--uninstall", description = "Uninstall a solver") + String uninstall; + + @Parameter(names = "--list-installed", help = true) + private boolean listInstalled; + + @Parameter(names = "--home", description = "The path of the solver registry") + String home = Path.of(System.getProperty("user.home"), ".theta").toAbsolutePath().toString(); + + @Parameter(names = "--loglevel", description = "Detailedness of logging") + Logger.Level logLevel = Logger.Level.MAINSTEP; + + @Parameter(names = "--help", help = true) + private boolean help; + + public SmtLibCli(final String[] args) { + this.args = args; + } + + public static void main(final String[] args) { + final SmtLibCli mainApp = new SmtLibCli(args); + mainApp.run(); + } + + private void run() { + final var jc = JCommander.newBuilder().addObject(this).programName(JAR_NAME).build(); + try { + jc.parse(args); + logger = new ConsoleLogger(logLevel); + } catch (final ParameterException ex) { + System.out.println("Invalid parameters, details:"); + System.out.println(ex.getMessage()); + ex.usage(); + return; + } + + if(help) { + jc.usage(); + return; + } + + if(!isExactlyOneGiven(install, uninstall, listInstalled ? true : null)) { + jc.usage(); + return; + } + + if(install == null && (installSolverPath != null || installSolverArgs != null)) { + jc.usage(); + return; + } + + try { + final var homePath = createIfNotExists(Path.of(home)); + final var smtLibSolverManager = SmtLibSolverManager.create(homePath, logger); + + if (install != null) { + final var solver = decodeVersionString(install, smtLibSolverManager); + if(solver.get1().equals(smtLibSolverManager.getGenericInstallerName())) { + if(installSolverPath == null) { + jc.usage(); + return; + } + + smtLibSolverManager.installGeneric( + solver.get2(), + Path.of(installSolverPath), + (installSolverArgs == null ? "" : installSolverArgs).split(" ") + ); + } + else { + smtLibSolverManager.install(solver.get1(), solver.get2()); + } + } + else if(uninstall != null) { + final var solver = decodeVersionString(uninstall, smtLibSolverManager); + smtLibSolverManager.uninstall(solver.get1(), solver.get2()); + } + else if(listInstalled) { + logger.write(Logger.Level.RESULT, "The currently installed solvers are: \n"); + smtLibSolverManager.getInstalledVersions().forEach(solver -> { + solver.get2().forEach(version -> { + logger.write(Logger.Level.RESULT, "\t%s:%s\n", solver.get1(), version); + }); + }); + } + } catch (SmtLibSolverInstallerException | IOException e) { + printError(e); + } + } + + private boolean isExactlyOneGiven(final Object ...args) { + int count = 0; + for(final var arg : args) { + if(arg != null) count++; + } + return count == 1; + } + + private Tuple2 decodeVersionString(final String version, final SmtLibSolverManager solverManager) throws SmtLibSolverInstallerException { + final var versionArr = version.split(":"); + + if(versionArr.length != 1 && versionArr.length != 2) { + throw new IllegalArgumentException("Invalid version string: " + version); + } + + final var solver = versionArr[0]; + if(versionArr.length == 2) { + return Tuple2.of(solver, versionArr[1]); + } + else { + final var versions = solverManager.getSupportedVersions(solver); + if(versions.size() > 0) { + return Tuple2.of(solver, versions.get(0)); + } + else { + throw new IllegalArgumentException("Invalid version string: " + version); + } + } + } + + private Path createIfNotExists(final Path path) throws IOException { + if(!Files.exists(path)) { + Files.createDirectory(path); + } + return path; + } + + private void printError(final Throwable ex) { + final String message = ex.getMessage() == null ? "" : ": " + ex.getMessage(); + logger.write(Logger.Level.RESULT, "Exception of type %s occurred%n", ex.getClass().getSimpleName()); + logger.write(Logger.Level.MAINSTEP, "Message:%n%s%n", ex.getMessage()); + final StringWriter errors = new StringWriter(); + ex.printStackTrace(new PrintWriter(errors)); + logger.write(Logger.Level.SUBSTEP, "Trace:%n%s%n", errors.toString()); + } +} From 5cf9a7918db2fa65d57d39cebf1afacefad2b8f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 31 Aug 2020 01:45:43 +0200 Subject: [PATCH 39/99] Migrate tests to use SmtLibSolverManager --- .../theta/solver/smtlib/SmtLibSolverBVTest.java | 14 +++++++++----- .../theta/solver/smtlib/SmtLibSolverTest.java | 17 ++++++++++------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java index 8219b00a5b..5c68bf8907 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java @@ -1,11 +1,13 @@ package hu.bme.mit.theta.solver.smtlib; +import hu.bme.mit.theta.common.logging.NullLogger; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.abstracttype.EqExpr; import hu.bme.mit.theta.core.utils.BvTestUtils; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; +import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -31,6 +33,11 @@ public class SmtLibSolverBVTest { @Parameterized.Parameter(2) public Expr actual; + private static final SmtLibSolverManager solverManager = SmtLibSolverManager.create( + Path.of(System.getProperty("user.home")).resolve(".theta"), + NullLogger.getInstance() + ); + @Parameters(name = "expr: {0}, expected: {1}, actual: {2}") public static Collection operations() { return Stream.concat( @@ -43,7 +50,7 @@ public static Collection operations() { } @Test - public void testOperationEquals() { + public void testOperationEquals() throws SmtLibSolverInstallerException { // Sanity check assertNotNull(exprType); assertNotNull(expected); @@ -61,10 +68,7 @@ public void testOperationEquals() { ); // Equality check - final Solver solver = GenericSmtLibSolverFactory.create( - Path.of("/home/vagrant/Vagrant/z3-4.8.8-x64-ubuntu-16.04/bin/z3"), - new String[] { "-in", "-smt2" } - ).createSolver(); + final Solver solver = solverManager.getSolverFactory("generic", "cvc4").createSolver(); solver.push(); solver.add(EqExpr.create2(expected, actual)); diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index 8fd5f1af16..9bfa48f760 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -1,5 +1,6 @@ package hu.bme.mit.theta.solver.smtlib; +import hu.bme.mit.theta.common.logging.NullLogger; import hu.bme.mit.theta.core.decl.ConstDecl; import hu.bme.mit.theta.core.decl.ParamDecl; import hu.bme.mit.theta.core.model.ImmutableValuation; @@ -18,12 +19,12 @@ import hu.bme.mit.theta.core.type.inttype.IntExprs; import hu.bme.mit.theta.core.type.inttype.IntType; import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSymbolTable; import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTermTransformer; -import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; +import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; import org.junit.BeforeClass; import org.junit.Test; @@ -49,14 +50,16 @@ import static org.junit.Assert.assertTrue; public final class SmtLibSolverTest { - private static GenericSmtLibSolverFactory solverFactory; + private static SolverFactory solverFactory; @BeforeClass - public static void init() { - solverFactory = GenericSmtLibSolverFactory.create( - Path.of("/home/vagrant/Vagrant/z3-4.8.8-x64-ubuntu-16.04/bin/z3"), - new String[] { "-in", "-smt2" } + public static void init() throws SmtLibSolverInstallerException { + final var solverManager = SmtLibSolverManager.create( + Path.of(System.getProperty("user.home")).resolve(".theta"), + NullLogger.getInstance() ); + + solverFactory = solverManager.getSolverFactory("generic", "cvc4"); } @Test From 46cdf59e29970ad8b1153b2a007909f47abeb863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 12 Sep 2020 16:20:14 +0200 Subject: [PATCH 40/99] Refactor Theta to SMT-LIB transformation to match changes in ftsrg#77 --- .../generic/GenericSmtLibExprTransformer.java | 201 ++++++++++-------- 1 file changed, 107 insertions(+), 94 deletions(-) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java index aa70bf17a4..4ee3a52d6a 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java @@ -32,28 +32,37 @@ import hu.bme.mit.theta.core.type.bvtype.BvAddExpr; import hu.bme.mit.theta.core.type.bvtype.BvAndExpr; import hu.bme.mit.theta.core.type.bvtype.BvArithShiftRightExpr; -import hu.bme.mit.theta.core.type.bvtype.BvDivExpr; +import hu.bme.mit.theta.core.type.bvtype.BvConcatExpr; import hu.bme.mit.theta.core.type.bvtype.BvEqExpr; -import hu.bme.mit.theta.core.type.bvtype.BvGeqExpr; -import hu.bme.mit.theta.core.type.bvtype.BvGtExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvExtractExpr; import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; import hu.bme.mit.theta.core.type.bvtype.BvLogicShiftRightExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLtExpr; -import hu.bme.mit.theta.core.type.bvtype.BvModExpr; import hu.bme.mit.theta.core.type.bvtype.BvMulExpr; import hu.bme.mit.theta.core.type.bvtype.BvNegExpr; import hu.bme.mit.theta.core.type.bvtype.BvNeqExpr; import hu.bme.mit.theta.core.type.bvtype.BvNotExpr; import hu.bme.mit.theta.core.type.bvtype.BvOrExpr; import hu.bme.mit.theta.core.type.bvtype.BvPosExpr; -import hu.bme.mit.theta.core.type.bvtype.BvRemExpr; import hu.bme.mit.theta.core.type.bvtype.BvRotateLeftExpr; import hu.bme.mit.theta.core.type.bvtype.BvRotateRightExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSDivExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSExtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSGeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSGtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSLeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSLtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSModExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSRemExpr; import hu.bme.mit.theta.core.type.bvtype.BvShiftLeftExpr; import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; -import hu.bme.mit.theta.core.type.bvtype.BvToIntExpr; +import hu.bme.mit.theta.core.type.bvtype.BvUDivExpr; +import hu.bme.mit.theta.core.type.bvtype.BvUGeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvUGtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvULeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvULtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvURemExpr; import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; +import hu.bme.mit.theta.core.type.bvtype.BvZExtExpr; import hu.bme.mit.theta.core.type.functype.FuncAppExpr; import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.type.inttype.IntAddExpr; @@ -71,7 +80,6 @@ import hu.bme.mit.theta.core.type.inttype.IntPosExpr; import hu.bme.mit.theta.core.type.inttype.IntRemExpr; import hu.bme.mit.theta.core.type.inttype.IntSubExpr; -import hu.bme.mit.theta.core.type.inttype.IntToBvExpr; import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; import hu.bme.mit.theta.core.type.rattype.RatAddExpr; import hu.bme.mit.theta.core.type.rattype.RatDivExpr; @@ -90,6 +98,7 @@ import hu.bme.mit.theta.solver.smtlib.SmtLibExprTransformer; import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; +import java.math.BigInteger; import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutionException; @@ -201,12 +210,18 @@ public GenericSmtLibExprTransformer(final SmtLibTransformationManager transforme .addCase(IntToRatExpr.class, this::transformIntToRat) - .addCase(IntToBvExpr.class, this::transformIntToBv) - // Bitvectors .addCase(BvLitExpr.class, this::transformBvLit) + .addCase(BvConcatExpr.class, this::transformBvConcat) + + .addCase(BvExtractExpr.class, this::transformBvExtract) + + .addCase(BvZExtExpr.class, this::transformBvZExt) + + .addCase(BvSExtExpr.class, this::transformBvSExt) + .addCase(BvAddExpr.class, this::transformBvAdd) .addCase(BvSubExpr.class, this::transformBvSub) @@ -217,11 +232,15 @@ public GenericSmtLibExprTransformer(final SmtLibTransformationManager transforme .addCase(BvMulExpr.class, this::transformBvMul) - .addCase(BvDivExpr.class, this::transformBvDiv) + .addCase(BvUDivExpr.class, this::transformBvUDiv) + + .addCase(BvSDivExpr.class, this::transformBvSDiv) + + .addCase(BvSModExpr.class, this::transformBvSMod) - .addCase(BvModExpr.class, this::transformBvMod) + .addCase(BvURemExpr.class, this::transformBvURem) - .addCase(BvRemExpr.class, this::transformBvRem) + .addCase(BvSRemExpr.class, this::transformBvSRem) .addCase(BvAndExpr.class, this::transformBvAnd) @@ -245,15 +264,21 @@ public GenericSmtLibExprTransformer(final SmtLibTransformationManager transforme .addCase(BvNeqExpr.class, this::transformBvNeq) - .addCase(BvGeqExpr.class, this::transformBvGeq) + .addCase(BvUGeqExpr.class, this::transformBvUGeq) - .addCase(BvGtExpr.class, this::transformBvGt) + .addCase(BvUGtExpr.class, this::transformBvUGt) - .addCase(BvLeqExpr.class, this::transformBvLeq) + .addCase(BvULeqExpr.class, this::transformBvULeq) - .addCase(BvLtExpr.class, this::transformBvLt) + .addCase(BvULtExpr.class, this::transformBvULt) - .addCase(BvToIntExpr.class, this::transformBvToInt) + .addCase(BvSGeqExpr.class, this::transformBvSGeq) + + .addCase(BvSGtExpr.class, this::transformBvSGt) + + .addCase(BvSLeqExpr.class, this::transformBvSLeq) + + .addCase(BvSLtExpr.class, this::transformBvSLt) // Functions @@ -530,13 +555,6 @@ protected String transformIntToRat(final IntToRatExpr expr) { return String.format("(to_real %s)", toTerm(expr.getOp())); } - protected String transformIntToBv(final IntToBvExpr expr) { - throw new UnsupportedOperationException("SMT-LIB does not have the corresponding operation"); - /* Works with Z3, but it is not standard - return String.format("((_ int2bv %d) %s)", expr.getType().getSize(), toTerm(expr.getOp())); - */ - } - /* * Bitvectors */ @@ -553,6 +571,31 @@ protected String transformBvLit(final BvLitExpr expr) { return String.format("#b%s", value); } + protected String transformBvConcat(final BvConcatExpr expr) { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(concat %s)", String.join(" ", opTerms)); + } + + protected String transformBvExtract(final BvExtractExpr expr) { + final var until = expr.getUntil().getValue().subtract(BigInteger.ONE); + final var from = expr.getFrom().getValue(); + + return String.format("((_ extract %s %s) %s)", until.toString(), from.toString(), toTerm(expr.getBitvec())); + } + + protected String transformBvZExt(final BvZExtExpr expr) { + final var extendWith = expr.getExtendType().getSize() - expr.getOp().getType().getSize(); + return String.format("((_ zero_extend %d) %s)", extendWith, toTerm(expr.getOp())); + } + + protected String transformBvSExt(final BvSExtExpr expr) { + final var extendWith = expr.getExtendType().getSize() - expr.getOp().getType().getSize(); + return String.format("((_ sign_extend %d) %s)", extendWith, toTerm(expr.getOp())); + } + protected String transformBvAdd(final BvAddExpr expr) { final String[] opTerms = expr.getOps().stream() .map(this::toTerm) @@ -581,31 +624,24 @@ protected String transformBvMul(final BvMulExpr expr) { return String.format("(bvmul %s)", String.join(" ", opTerms)); } - protected String transformBvDiv(final BvDivExpr expr) { - if(expr.getType().isSigned()) { - return String.format("(bvsdiv %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvudiv %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } + protected String transformBvUDiv(final BvUDivExpr expr) { + return String.format("(bvudiv %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } - protected String transformBvMod(final BvModExpr expr) { - if(expr.getType().isSigned()) { - return String.format("(bvsmod %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvurem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } + protected String transformBvSDiv(final BvSDivExpr expr) { + return String.format("(bvsdiv %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } - protected String transformBvRem(final BvRemExpr expr) { - if(expr.getType().isSigned()) { - return String.format("(bvsrem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvurem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } + protected String transformBvSMod(final BvSModExpr expr) { + return String.format("(bvsmod %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvURem(final BvURemExpr expr) { + return String.format("(bvurem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvSRem(final BvSRemExpr expr) { + return String.format("(bvsrem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } protected String transformBvAnd(final BvAndExpr expr) { @@ -651,17 +687,15 @@ protected String transformBvLogicShiftRight(final BvLogicShiftRightExpr expr) { protected String transformBvRotateLeft(final BvRotateLeftExpr expr) { final var toRotate = toTerm(expr.getLeftOp()); final var rotateWith = toTerm(expr.getRightOp()); - final var size = toTerm(BvUtils.intToBvLitExpr(expr.getType().getSize(), expr.getType().getSize(), expr.getRightOp().getType().isSigned())); + final var size = toTerm(BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.valueOf(expr.getType().getSize()), expr.getType().getSize())); return String.format("(bvor (bvshl %s %s) (bvlshr %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); - // return String.format("((_ rotate_left %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); } protected String transformBvRotateRight(final BvRotateRightExpr expr) { final var toRotate = toTerm(expr.getLeftOp()); final var rotateWith = toTerm(expr.getRightOp()); - final var size = toTerm(BvUtils.intToBvLitExpr(expr.getType().getSize(), expr.getType().getSize(), expr.getRightOp().getType().isSigned())); + final var size = toTerm(BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.valueOf(expr.getType().getSize()), expr.getType().getSize())); return String.format("(bvor (bvlshr %s %s) (bvshl %s (bvsub %s %s)))", toRotate, rotateWith, toRotate, size, rotateWith); - // return String.format("((_ rotate_right %s) %s)", toTerm(expr.getRightOp()), toTerm(expr.getLeftOp())); } protected String transformBvEq(final BvEqExpr expr) { @@ -672,57 +706,36 @@ protected String transformBvNeq(final BvNeqExpr expr) { return String.format("(not (= %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } - protected String transformBvGeq(final BvGeqExpr expr) { - if(expr.getLeftOp().getType().isSigned()) { - return String.format("(bvsge %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvuge %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } + protected String transformBvUGeq(final BvUGeqExpr expr) { + return String.format("(bvuge %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } - protected String transformBvGt(final BvGtExpr expr) { - if(expr.getLeftOp().getType().isSigned()) { - return String.format("(bvsgt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvugt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } + protected String transformBvUGt(final BvUGtExpr expr) { + return String.format("(bvugt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } - protected String transformBvLeq(final BvLeqExpr expr) { - if(expr.getLeftOp().getType().isSigned()) { - return String.format("(bvsle %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvule %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } + protected String transformBvULeq(final BvULeqExpr expr) { + return String.format("(bvule %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } - protected String transformBvLt(final BvLtExpr expr) { - if(expr.getLeftOp().getType().isSigned()) { - return String.format("(bvslt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } - else { - return String.format("(bvult %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); - } + protected String transformBvULt(final BvULtExpr expr) { + return String.format("(bvult %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } - protected String transformBvToInt(final BvToIntExpr expr) { - throw new UnsupportedOperationException("SMT-LIB does not have the corresponding operation"); - /* Works with Z3, but not standard - if(expr.getOp().getType().isSigned()) { - final String bv = toTerm(expr.getOp()); - final BigInteger exp = BigInteger.TWO.pow(expr.getOp().getType().getSize()); - return String.format( - "(ite (bvslt %s ((_ int2bv %d) 0)) (- (bv2int %s) %s) (bv2int %s))", - bv, expr.getOp().getType().getSize(), bv, exp.toString(), bv - ); - } - else { - return String.format("(bv2int %s)", toTerm(expr.getOp())); - } - */ + protected String transformBvSGeq(final BvSGeqExpr expr) { + return String.format("(bvsge %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvSGt(final BvSGtExpr expr) { + return String.format("(bvsgt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvSLeq(final BvSLeqExpr expr) { + return String.format("(bvsle %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformBvSLt(final BvSLtExpr expr) { + return String.format("(bvslt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } /* From 493a6b39d74d174240ffca8373d9a07dd9dc8bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 12 Sep 2020 16:20:43 +0200 Subject: [PATCH 41/99] Refactor SMT-LIB to Theta transformation to match changes in ftsrg#77 --- .../solver/smtlib/SmtLibTermTransformer.java | 2 +- .../generic/GenericSmtLibTermTransformer.java | 586 ++++++------------ 2 files changed, 187 insertions(+), 401 deletions(-) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java index 8f01ff2c43..cc1dff40de 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java @@ -10,7 +10,7 @@ public interface SmtLibTermTransformer {

LitExpr> toFuncLitExpr(String funcLitImpl, FuncType type, SmtLibModel model); - Expr toExpr(String term, Type type, SmtLibModel model); + Expr toExpr(String term, T type, SmtLibModel model); LitExpr toLitExpr(String litImpl, T type, SmtLibModel model); diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java index 6a9e0f7525..170606e74c 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java @@ -3,10 +3,10 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableList; -import hu.bme.mit.theta.common.QuintFunction; +import hu.bme.mit.theta.common.QuadFunction; import hu.bme.mit.theta.common.TernaryOperator; import hu.bme.mit.theta.common.Tuple2; -import hu.bme.mit.theta.core.decl.Decls; +import hu.bme.mit.theta.core.decl.Decl; import hu.bme.mit.theta.core.decl.ParamDecl; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.LitExpr; @@ -24,7 +24,6 @@ import hu.bme.mit.theta.core.type.abstracttype.RemExpr; import hu.bme.mit.theta.core.type.abstracttype.SubExpr; import hu.bme.mit.theta.core.type.anytype.IteExpr; -import hu.bme.mit.theta.core.type.anytype.RefExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayReadExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.arraytype.ArrayWriteExpr; @@ -38,23 +37,33 @@ import hu.bme.mit.theta.core.type.bvtype.BvAddExpr; import hu.bme.mit.theta.core.type.bvtype.BvAndExpr; import hu.bme.mit.theta.core.type.bvtype.BvArithShiftRightExpr; -import hu.bme.mit.theta.core.type.bvtype.BvDivExpr; +import hu.bme.mit.theta.core.type.bvtype.BvConcatExpr; import hu.bme.mit.theta.core.type.bvtype.BvExprs; -import hu.bme.mit.theta.core.type.bvtype.BvGeqExpr; -import hu.bme.mit.theta.core.type.bvtype.BvGtExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvExtractExpr; import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; import hu.bme.mit.theta.core.type.bvtype.BvLogicShiftRightExpr; -import hu.bme.mit.theta.core.type.bvtype.BvLtExpr; -import hu.bme.mit.theta.core.type.bvtype.BvModExpr; import hu.bme.mit.theta.core.type.bvtype.BvNegExpr; import hu.bme.mit.theta.core.type.bvtype.BvNotExpr; import hu.bme.mit.theta.core.type.bvtype.BvOrExpr; -import hu.bme.mit.theta.core.type.bvtype.BvRemExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSDivExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSExtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSGeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSGtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSLeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSLtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSModExpr; +import hu.bme.mit.theta.core.type.bvtype.BvSRemExpr; import hu.bme.mit.theta.core.type.bvtype.BvShiftLeftExpr; import hu.bme.mit.theta.core.type.bvtype.BvSubExpr; import hu.bme.mit.theta.core.type.bvtype.BvType; +import hu.bme.mit.theta.core.type.bvtype.BvUDivExpr; +import hu.bme.mit.theta.core.type.bvtype.BvUGeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvUGtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvULeqExpr; +import hu.bme.mit.theta.core.type.bvtype.BvULtExpr; +import hu.bme.mit.theta.core.type.bvtype.BvURemExpr; import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; +import hu.bme.mit.theta.core.type.bvtype.BvZExtExpr; import hu.bme.mit.theta.core.type.functype.FuncExprs; import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; @@ -72,31 +81,29 @@ import java.math.BigDecimal; import java.math.BigInteger; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; +import java.util.function.BiFunction; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.function.UnaryOperator; import java.util.stream.Collectors; -import java.util.stream.IntStream; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.decl.Decls.Param; import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Exists; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Forall; -import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; import static hu.bme.mit.theta.core.type.functype.FuncExprs.Func; import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; import static hu.bme.mit.theta.core.type.rattype.RatExprs.Rat; import static hu.bme.mit.theta.core.utils.TypeUtils.cast; +import static hu.bme.mit.theta.core.utils.TypeUtils.castBv; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.BinaryContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.DecimalContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Exists_termContext; @@ -150,15 +157,19 @@ public GenericSmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { // Rational // Bitvector + put("concat", exprMultiaryOperator(BvConcatExpr::create)); + put("extract", exprBvExtractOperator()); + put("zero_extend", exprBvExtendOperator(BvZExtExpr::create)); + put("sign_extend", exprBvExtendOperator(BvSExtExpr::create)); put("bvadd", exprMultiaryOperator(BvAddExpr::create)); put("bvsub", exprBinaryOperator(BvSubExpr::create)); put("bvneg", exprUnaryOperator(BvNegExpr::create)); put("bvmul", exprMultiaryOperator(BvAddExpr::create)); - put("bvudiv", exprBinaryOperator(BvDivExpr::create)); - put("bvsdiv", exprBinaryOperator(BvDivExpr::create)); - put("bvsmod", exprBinaryOperator(BvModExpr::create)); - put("bvsrem", exprBinaryOperator(BvRemExpr::create)); - put("bvurem", exprBinaryOperator(BvRemExpr::create)); + put("bvudiv", exprBinaryOperator(BvUDivExpr::create)); + put("bvsdiv", exprBinaryOperator(BvSDivExpr::create)); + put("bvsmod", exprBinaryOperator(BvSModExpr::create)); + put("bvsrem", exprBinaryOperator(BvURemExpr::create)); + put("bvurem", exprBinaryOperator(BvSRemExpr::create)); put("bvand", exprMultiaryOperator(BvAndExpr::create)); put("bvor", exprMultiaryOperator(BvOrExpr::create)); put("bvxor", exprMultiaryOperator(BvXorExpr::create)); @@ -166,14 +177,14 @@ public GenericSmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { put("bvshl", exprBinaryOperator(BvShiftLeftExpr::create)); put("bvashr", exprBinaryOperator(BvArithShiftRightExpr::create)); put("bvlshr", exprBinaryOperator(BvLogicShiftRightExpr::create)); - put("bvult", exprBinaryOperator(BvLtExpr::create)); - put("bvslt", exprBinaryOperator(BvLtExpr::create)); - put("bvule", exprBinaryOperator(BvLeqExpr::create)); - put("bvsle", exprBinaryOperator(BvLeqExpr::create)); - put("bvugt", exprBinaryOperator(BvGtExpr::create)); - put("bvsgt", exprBinaryOperator(BvGtExpr::create)); - put("bvuge", exprBinaryOperator(BvGeqExpr::create)); - put("bvsge", exprBinaryOperator(BvGeqExpr::create)); + put("bvult", exprBinaryOperator(BvULtExpr::create)); + put("bvslt", exprBinaryOperator(BvSLtExpr::create)); + put("bvule", exprBinaryOperator(BvULeqExpr::create)); + put("bvsle", exprBinaryOperator(BvSLeqExpr::create)); + put("bvugt", exprBinaryOperator(BvUGtExpr::create)); + put("bvsgt", exprBinaryOperator(BvSGtExpr::create)); + put("bvuge", exprBinaryOperator(BvUGeqExpr::create)); + put("bvsge", exprBinaryOperator(BvSGeqExpr::create)); // Array put("select", exprArrayReadOperator()); @@ -185,14 +196,7 @@ public GenericSmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { @Override public

LitExpr> toFuncLitExpr(final String funcLitImpl, final FuncType type, final SmtLibModel model) { - final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(funcLitImpl)); - final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); - lexer.removeErrorListeners(); - lexer.addErrorListener(new ThrowExceptionErrorListener()); - parser.removeErrorListeners(); - parser.addErrorListener(new ThrowExceptionErrorListener()); - - final var litExpr = transformFuncDef(parser.function_def(), type, model, HashBiMap.create()); + final var litExpr = toFuncLitExpr(funcLitImpl, model); if(litExpr == null) { return null; } @@ -204,8 +208,24 @@ else if(litExpr instanceof LitExpr) { } } + private Expr toFuncLitExpr(final String funcLitImpl, final SmtLibModel model) { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(funcLitImpl)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + + return transformFuncDef(parser.function_def(), model, HashBiMap.create()); + } + @Override - public Expr toExpr(final String term, final Type type, final SmtLibModel model) { + public Expr toExpr(final String term, final T type, final SmtLibModel model) { + final var expr = toExpr(term, model); + return cast(expr, type); + } + + private Expr toExpr(final String term, final SmtLibModel model) { final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(term)); final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); lexer.removeErrorListeners(); @@ -213,18 +233,12 @@ public Expr toExpr(final String term, final Type type, final SmtLibModel mode parser.removeErrorListeners(); parser.addErrorListener(new ThrowExceptionErrorListener()); - final var expr = transformTerm(parser.function_def().term(), type, model, HashBiMap.create()); - if(expr == null) { - return null; - } - else { - return cast(expr, type); - } + return transformTerm(parser.function_def().term(), model, HashBiMap.create()); } @Override public LitExpr toLitExpr(final String litImpl, final T type, final SmtLibModel model) { - final var litExpr = toExpr(litImpl, type, model); + final var litExpr = toExpr(litImpl, model); if(litExpr == null) { return null; @@ -240,7 +254,7 @@ else if(litExpr instanceof LitExpr) { @Override @SuppressWarnings("unchecked") public LitExpr> toArrayLitExpr(final String arrayLitImpl, final ArrayType type, final SmtLibModel model) { - final var arrayLitExpr = toExpr(arrayLitImpl, type, model); + final var arrayLitExpr = toExpr(arrayLitImpl, model); if(arrayLitExpr == null) { return null; @@ -264,13 +278,13 @@ else if(arrayLitExpr instanceof IteExpr) { @Override public LitExpr toBvLitExpr(final String bvLitImpl, final BvType type, final SmtLibModel model) { - final var bvLitExpr = toExpr(bvLitImpl, type, model); + final var bvLitExpr = toExpr(bvLitImpl, model); if(bvLitExpr == null) { return null; } else if(bvLitExpr instanceof BvLitExpr) { - return Bv(((BvLitExpr) bvLitExpr).getValue(), type.isSigned()); + return (BvLitExpr) bvLitExpr; } else { return (LitExpr) cast(ExprUtils.simplify(bvLitExpr), type); @@ -281,55 +295,43 @@ else if(bvLitExpr instanceof BvLitExpr) { /* Visitor implementation */ - protected Expr transformFuncDef(final SMTLIBv2Parser.Function_defContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { - assert type == null || type instanceof FuncType; + protected Expr transformFuncDef(final SMTLIBv2Parser.Function_defContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; - final var funcType = type != null ? (FuncType) type : null; - final var paramDecls = ctx.sorted_var().stream() - .map(sv -> new ParamTypeDeducer( - sv.symbol().getText(), transformSort(sv.sort(), - funcType != null ? funcType.getParamType() : null)) - ) + .map(sv -> Param(sv.symbol().getText(), transformSort(sv.sort()))) .collect(toList()); checkArgument(paramDecls.size() == 1, "Only unary functions are supported"); pushParams(paramDecls, vars); - final var op = transformTerm(ctx.term(), funcType != null ? funcType.getResultType() : type, model, vars); + final var op = transformTerm(ctx.term(), model, vars); popParams(paramDecls, vars); - if(paramDecls.get(0).isTypeUnknown()) { - return null; - } - else { - assert op != null; - return Func(paramDecls.get(0).getParamDecl(), op); - } + return Func(paramDecls.get(0), op); } - protected Expr transformTerm(final TermContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + protected Expr transformTerm(final TermContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; if(ctx.spec_constant() != null) { - return transformSpecConstant(ctx.spec_constant(), type, model, vars); + return transformSpecConstant(ctx.spec_constant(), model, vars); } else if(ctx.qual_identifier() != null) { - return transformQualIdentifier(ctx.qual_identifier(), type, model, vars); + return transformQualIdentifier(ctx.qual_identifier(), model, vars); } else if(ctx.generic_term() != null) { - return transformGenericTerm(ctx.generic_term(), type, model, vars); + return transformGenericTerm(ctx.generic_term(), model, vars); } else if(ctx.let_term() != null) { throw new UnsupportedOperationException(); } else if(ctx.forall_term() != null) { - return transformForallTerm(ctx.forall_term(), type, model, vars); + return transformForallTerm(ctx.forall_term(), model, vars); } else if(ctx.exists_term() != null) { - return transformExistsTerm(ctx.exists_term(), type, model, vars); + return transformExistsTerm(ctx.exists_term(), model, vars); } else if(ctx.match_term() != null) { throw new UnsupportedOperationException(); @@ -342,21 +344,21 @@ else if(ctx.annotate_term() != null) { } } - protected Expr transformSpecConstant(final Spec_constantContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + protected Expr transformSpecConstant(final Spec_constantContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; if(ctx.numeral() != null) { - return transformNumeral(ctx.numeral(), type, model, vars); + return transformNumeral(ctx.numeral(), model, vars); } else if(ctx.decimal() != null) { - return transformDecimal(ctx.decimal(), type, model, vars); + return transformDecimal(ctx.decimal(), model, vars); } else if(ctx.hexadecimal() != null) { - return transformHexadecimal(ctx.hexadecimal(), type, model, vars); + return transformHexadecimal(ctx.hexadecimal(), model, vars); } else if(ctx.binary() != null) { - return transformBinary(ctx.binary(), type, model, vars); + return transformBinary(ctx.binary(), model, vars); } else if(ctx.string() != null) { throw new UnsupportedOperationException(); @@ -366,14 +368,14 @@ else if(ctx.string() != null) { } } - protected Expr transformQualIdentifier(final Qual_identifierContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + protected Expr transformQualIdentifier(final Qual_identifierContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; - return transformIdentifier(ctx.identifier(), type, model, vars); + return transformIdentifier(ctx.identifier(), model, vars); } - protected Expr transformGenericTerm(final Generic_termContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + protected Expr transformGenericTerm(final Generic_termContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; @@ -383,25 +385,24 @@ protected Expr transformGenericTerm(final Generic_termContext ctx, final Type final var funAppParams = ctx.term(); if (funName.equals("const")) { // as const construct - final var constType = transformSort(ctx.qual_identifier().sort(), type); + final var constType = transformSort(ctx.qual_identifier().sort()); if (constType instanceof ArrayType) { - assert type == null || type.equals(constType); checkArgument(funAppParams.size() == 1, "Invalid as const construct"); final var arrayType = (ArrayType) constType; - final var expr = transformTerm(funAppParams.get(0), arrayType.getElemType(), model, vars); - return createArrayLitExpr(expr, (ArrayType) type); + final var expr = transformTerm(funAppParams.get(0), model, vars); + return createArrayLitExpr(expr, arrayType); } else { throw new UnsupportedOperationException(); } } else if (funAppTransformer.containsKey(funName)) { // known function application - return funAppTransformer.get(funName).apply(funParams, funAppParams, type, model, vars); + return funAppTransformer.get(funName).apply(funParams, funAppParams, model, vars); } else { // custom function application checkArgument(funParams.size() == 0, "Custom unary function application cannot vahe parameter"); checkArgument(funAppParams.size() == 1, "Only unary functions are supported"); - return createFuncAppExpr(funName, funAppParams.get(0), type, model, vars); + return createFuncAppExpr(funName, funAppParams.get(0), model, vars); } } @@ -410,98 +411,68 @@ private Expr createArrayLitExpr(final Expr) elze, type); } - private

Expr createFuncAppExpr(final String funName, final TermContext funAppParam, final Type returnType, final SmtLibModel model, final BiMap vars) { - - var paramExpr = transformTerm(funAppParam, null, model, vars); - final Type paramType = paramExpr != null ? paramExpr.getType() : null; - + private

Expr createFuncAppExpr(final String funName, final TermContext funAppParam, final SmtLibModel model, final BiMap, String> vars) { final Expr funcExpr; if (symbolTable.definesSymbol(funName)) { funcExpr = checkNotNull(symbolTable.getConst(funName).getRef()); } else { final var funDefImpl = model.getTerm(funName); - if(paramType == null || returnType == null) { - funcExpr = toFuncLitExpr(funDefImpl, null, model); - if(funcExpr == null) { - return null; - } - } - else { - funcExpr = checkNotNull(toFuncLitExpr(funDefImpl, FuncType.of(paramType, returnType), model), "Unsupported expression: was not able to deduce all types"); - } + funcExpr = toFuncLitExpr(funDefImpl, model); } assert funcExpr.getType() instanceof FuncType; @SuppressWarnings("unchecked") final var funType = (FuncType) funcExpr.getType(); - paramExpr = paramExpr == null ? transformTerm(funAppParam, funType.getParamType(), model, vars) : paramExpr; + final var paramExpr = transformTerm(funAppParam, model, vars); return FuncExprs.App(cast(funcExpr, funType), cast(paramExpr, funType.getParamType())); } - protected Expr transformForallTerm(final Forall_termContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { - assert type == null || type.equals(Bool()); + protected Expr transformForallTerm(final Forall_termContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; final var paramDecls = ctx.sorted_var().stream() - .map(sv -> new ParamTypeDeducer(sv.symbol().getText(), transformSort(sv.sort(), null))) + .map(sv -> Param(sv.symbol().getText(), transformSort(sv.sort()))) .collect(toList()); pushParams(paramDecls, vars); - final var op = transformTerm(ctx.term(), type, model, vars); + final var op = transformTerm(ctx.term(), model, vars); popParams(paramDecls, vars); - if(paramDecls.stream().anyMatch(ParamTypeDeducer::isTypeUnknown)) { - return null; - } - else { - assert op != null; - return Forall( - paramDecls.stream().map(ParamTypeDeducer::getParamDecl).collect(Collectors.toUnmodifiableList()), - cast(op, Bool()) - ); - } + assert op != null; + return Forall(paramDecls, cast(op, Bool())); } - protected Expr transformExistsTerm(final Exists_termContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { - assert type == null || type.equals(Bool()); + protected Expr transformExistsTerm(final Exists_termContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; final var paramDecls = ctx.sorted_var().stream() - .map(sv -> new ParamTypeDeducer(sv.symbol().getText(), transformSort(sv.sort(), null))) + .map(sv -> Param(sv.symbol().getText(), transformSort(sv.sort()))) .collect(toList()); pushParams(paramDecls, vars); - final var op = transformTerm(ctx.term(), type, model, vars); + final var op = transformTerm(ctx.term(), model, vars); popParams(paramDecls, vars); - if(paramDecls.stream().anyMatch(ParamTypeDeducer::isTypeUnknown)) { - return null; - } - else { - assert op != null; - return Exists( - paramDecls.stream().map(ParamTypeDeducer::getParamDecl).collect(Collectors.toUnmodifiableList()), - cast(op, Bool()) - ); - } + assert op != null; + return Exists(paramDecls, cast(op, Bool())); } - protected Expr transformIdentifier(final IdentifierContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + protected Expr transformIdentifier(final IdentifierContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; if(ctx.symbol().getText().equals("as-array")) { final var name = ctx.index().get(0).getText(); - return toExpr(model.getTerm(name), type, model); + return toExpr(model.getTerm(name), model); } else { - return transformSymbol(ctx.symbol(), type, model, vars); + return transformSymbol(ctx.symbol(), model, vars); } } - protected Expr transformSymbol(final SymbolContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { + protected Expr transformSymbol(final SymbolContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; @@ -514,25 +485,10 @@ protected Expr transformSymbol(final SymbolContext ctx, final Type type, fina default: if(vars.containsValue(value)) { final var decl = vars.inverse().get(value); - if(decl.isTypeUnknown()) { - if(type == null) { - return null; - } - else { - decl.setType(type); - return decl.getRef(); - } - } - else { - final var ref = decl.getRef(); - assert type == null || type.equals(ref.getType()); - return ref; - } + return decl.getRef(); } else if(symbolTable.definesSymbol(value)) { - final var ref = symbolTable.getConst(value).getRef(); - assert type == null || type.equals(ref.getType()); - return ref; + return symbolTable.getConst(value).getRef(); } else { throw new UnsupportedOperationException(); @@ -540,16 +496,14 @@ else if(symbolTable.definesSymbol(value)) { } } - protected Expr transformNumeral(final NumeralContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { - assert type == null || type.equals(Int()); + protected Expr transformNumeral(final NumeralContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; return Int(ctx.getText()); } - protected Expr transformDecimal(final DecimalContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { - assert type == null || type.equals(Rat()); + protected Expr transformDecimal(final DecimalContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; @@ -562,80 +516,39 @@ protected Expr transformDecimal(final DecimalContext ctx, final Type type, fi } } - protected Expr transformHexadecimal(final HexadecimalContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { - assert type == null || type instanceof BvType; + protected Expr transformHexadecimal(final HexadecimalContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; - if(type == null) { - return null; - } - else { - final var bvType = (BvType) type; - final var numStr = ctx.getText().substring(2); - final var num = new BigInteger(numStr, 16); - checkState(bvType.getSize() == numStr.length() * 4, "Type mismatch"); - - return BvUtils.bigIntegerToBvLitExpr(num, bvType.getSize(), bvType.isSigned()); - } + final var numStr = ctx.getText().substring(2); + final var num = new BigInteger(numStr, 16); + return BvUtils.bigIntegerToNeutralBvLitExpr(num, numStr.length() * 4); } - protected Expr transformBinary(final BinaryContext ctx, final Type type, final SmtLibModel model, final BiMap vars) { - assert type == null || type instanceof BvType; + protected Expr transformBinary(final BinaryContext ctx, final SmtLibModel model, final BiMap, String> vars) { assert model != null; assert vars != null; - if(type == null) { - return null; - } - else { - final var bvType = (BvType) type; - final var numStr = ctx.getText().substring(2); - final var num = new BigInteger(numStr, 2); - checkState(bvType.getSize() == numStr.length(), "Type mismatch"); - - return BvUtils.bigIntegerToBvLitExpr(num, bvType.getSize(), bvType.isSigned()); - } + final var numStr = ctx.getText().substring(2); + final var num = new BigInteger(numStr, 2); + return BvUtils.bigIntegerToNeutralBvLitExpr(num, numStr.length()); } - protected Type transformSort(final SortContext ctx, final Type type) { + protected Type transformSort(final SortContext ctx) { final var name = ctx.identifier().symbol().getText(); switch(name) { case "Bool": - assert type == null || type.equals(Bool()); return Bool(); case "Int": - assert type == null || type.equals(Int()); return Int(); case "Real": - assert type == null || type.equals(Rat()); return Rat(); case "BitVec": - assert type == null || type instanceof BvType; - if(type == null) { - return null; - } - else { - final var bvType = (BvType) type; - checkArgument(Integer.parseInt(ctx.identifier().index().get(0).getText()) == bvType.getSize(), "Type mismatch"); - return BvExprs.BvType(bvType.getSize(), bvType.isSigned()); - } + assert ctx.identifier().index().size() == 1; + return BvExprs.BvType(Integer.parseInt(ctx.identifier().index().get(0).getText())); case "Array": - assert type == null || type instanceof ArrayType; - if(type == null) { - final var indexType = transformSort(ctx.sort().get(0), null); - final var elemType = transformSort(ctx.sort().get(1), null); - if(indexType == null || elemType == null) { - return null; - } - else { - return Array(indexType, elemType); - } - } - else { - final var arrayType = (ArrayType) type; - return Array(transformSort(ctx.sort().get(0), arrayType.getIndexType()), transformSort(ctx.sort().get(1), arrayType.getElemType())); - } + assert ctx.sort().size() == 2; + return Array(transformSort(ctx.sort().get(0)), transformSort(ctx.sort().get(1))); default: throw new UnsupportedOperationException(); } @@ -645,11 +558,11 @@ protected Type transformSort(final SortContext ctx, final Type type) { /* Variable scope handling */ - protected void pushParams(final List paramDecls, BiMap vars) { - vars.putAll(paramDecls.stream().collect(Collectors.toUnmodifiableMap(Function.identity(), ParamTypeDeducer::getName))); + protected void pushParams(final List> paramDecls, BiMap, String> vars) { + vars.putAll(paramDecls.stream().collect(Collectors.toUnmodifiableMap(Function.identity(), Decl::getName))); } - protected void popParams(final List paramDecls, BiMap vars) { + protected void popParams(final List> paramDecls, BiMap, String> vars) { for (final var paramDecl : paramDecls) { vars.remove(paramDecl, paramDecl.getName()); } @@ -659,7 +572,7 @@ protected void popParams(final List paramDecls, BiMap> function) { - return (params, ops, type, model, vars) -> { + return (params, ops, model, vars) -> { checkArgument(params.size() == 0, "No parameters expected"); checkArgument(ops.size() == 0, "Nullary operator expected"); return function.get(); @@ -667,260 +580,133 @@ private OperatorCreatorFunction exprNullaryOperator(final Supplier> func } private OperatorCreatorFunction exprUnaryOperator(final UnaryOperator> function) { - return (params, ops, type, model, vars) -> { + return (params, ops, model, vars) -> { checkArgument(params.size() == 0, "No parameters expected"); checkArgument(ops.size() == 1, "Unary operator expected"); - if(type == null) { - final var op = transformTerm(ops.get(0), type, model, vars); - return function.apply(op); - } - else { - final var op = checkNotNull(transformTerm(ops.get(0), type, model, vars), "Unsupported expression: was not able to deduce all types"); - return function.apply(op); - } + final var op = transformTerm(ops.get(0), model, vars); + return function.apply(op); + }; + } + + private OperatorCreatorFunction exprBvExtractOperator() { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 2, "Two parameters expected"); + checkArgument(ops.size() == 1, "Unary operator expected"); + + final var until = Integer.parseInt(params.get(0).numeral().getText()) + 1; + final var from = Integer.parseInt(params.get(1).numeral().getText()); + final var extractFrom = castBv(transformTerm(ops.get(0), model, vars)); + return BvExtractExpr.create(extractFrom, Int(from), Int(until)); + }; + } + + private OperatorCreatorFunction exprBvExtendOperator(final BiFunction, BvType, Expr> function) { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 1, "One parameters expected"); + checkArgument(ops.size() == 1, "Unary operator expected"); + + final var extendWith = Integer.parseInt(params.get(0).numeral().getText()); + final var toExtend = castBv(transformTerm(ops.get(0), model, vars)); + return function.apply(toExtend, BvType.of(toExtend.getType().getSize() + extendWith)); }; } private OperatorCreatorFunction exprBinaryOperator(final BinaryOperator> function) { - return (params, ops, type, model, vars) -> { + return (params, ops, model, vars) -> { checkArgument(params.size() == 0, "No parameters expected"); checkArgument(ops.size() == 2, "Binary operator expected"); - if(type == null) { - var op1 = transformTerm(ops.get(0), null, model, vars); - var op2 = transformTerm(ops.get(1), null, model, vars); - if(op1 == null && op2 == null) { - return null; - } - else if(op1 != null && op2 == null) { - op2 = checkNotNull(transformTerm(ops.get(1), op1.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - else if(op1 == null /* && op2 != null */) { - op1 = checkNotNull(transformTerm(ops.get(0), op2.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - return function.apply(op1, op2); - } - else { - final var op1 = transformTerm(ops.get(0), type, model, vars); - final var op2 = transformTerm(ops.get(1), type, model, vars); - return function.apply(op1, op2); - } + final var op1 = transformTerm(ops.get(0), model, vars); + final var op2 = transformTerm(ops.get(1), model, vars); + return function.apply(op1, op2); }; } private OperatorCreatorFunction exprRelationalOperator(final BinaryOperator> function) { - return (params, ops, type, model, vars) -> { - assert type == null || type.equals(Bool()); + return (params, ops, model, vars) -> { checkArgument(params.size() == 0, "No parameters expected"); checkArgument(ops.size() == 2, "Binary operator expected"); - var op1 = transformTerm(ops.get(0), null, model, vars); - var op2 = transformTerm(ops.get(1), null, model, vars); - if(op1 == null && op2 == null) { - return null; - } - else if(op1 != null && op2 == null) { - op2 = checkNotNull(transformTerm(ops.get(1), op1.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - else if(op1 == null /* && op2 != null */) { - op1 = checkNotNull(transformTerm(ops.get(0), op2.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } + final var op1 = transformTerm(ops.get(0), model, vars); + final var op2 = transformTerm(ops.get(1), model, vars); return function.apply(op1, op2); }; } private OperatorCreatorFunction exprArrayReadOperator() { - return (params, ops, type, model, vars) -> { + return (params, ops, model, vars) -> { checkArgument(params.size() == 0, "No parameters expected"); checkArgument(ops.size() == 2, "Binary operator expected"); - var op1 = transformTerm(ops.get(0), null, model, vars); - var op2 = transformTerm(ops.get(1), null, model, vars); - if(op1 == null && op2 == null) { - return null; - } - else if(op1 != null && op2 == null) { - assert op1.getType() instanceof ArrayType; - final var arrayType = (ArrayType) op1.getType(); - op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - else if(op1 == null /* && op2 != null */) { - if(type == null) { - return null; - } - else { - final var arrayType = Array(op2.getType(), type); - op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars), "Unsupported expression: was not able to deduce all types"); - } - } + final var op1 = transformTerm(ops.get(0), model, vars); + final var op2 = transformTerm(ops.get(1), model, vars); return ArrayReadExpr.create(op1, op2); }; } private OperatorCreatorFunction exprMinusOperator() { - return (params, ops, type, model, vars) -> { + return (params, ops, model, vars) -> { checkArgument(params.size() == 0, "No parameters expected"); checkArgument(ops.size() == 1 || ops.size() == 2, "Unary or binary operator expected"); if(ops.size() == 2) { - return exprBinaryOperator(SubExpr::create2).apply(params, ops, type, model, vars); + return exprBinaryOperator(SubExpr::create2).apply(params, ops, model, vars); } else { - return exprUnaryOperator(NegExpr::create2).apply(params, ops, type, model, vars); + return exprUnaryOperator(NegExpr::create2).apply(params, ops, model, vars); } }; } @SuppressWarnings("unused") private OperatorCreatorFunction exprTernaryOperator(final TernaryOperator> function) { - return (params, ops, type, model, vars) -> { + return (params, ops, model, vars) -> { checkArgument(params.size() == 0, "No parameters expected"); checkArgument(ops.size() == 3, "Ternary operator expected"); - final Expr op1 = transformTerm(ops.get(0), type, model, vars); - final Expr op2 = transformTerm(ops.get(1), type, model, vars); - final Expr op3 = transformTerm(ops.get(2), type, model, vars); + final Expr op1 = transformTerm(ops.get(0), model, vars); + final Expr op2 = transformTerm(ops.get(1), model, vars); + final Expr op3 = transformTerm(ops.get(2), model, vars); return function.apply(op1, op2, op3); }; } private OperatorCreatorFunction exprIteOperator() { - return (params, ops, type, model, vars) -> { + return (params, ops, model, vars) -> { checkArgument(params.size() == 0, "No parameters expected"); checkArgument(ops.size() == 3, "Ternary operator expected"); - final var op1 = transformTerm(ops.get(0), Bool(), model, vars); - if(type == null) { - var op2 = transformTerm(ops.get(1), type, model, vars); - var op3 = transformTerm(ops.get(2), type, model, vars); - if(op2 == null && op3 == null) { - return null; - } - else if(op2 != null && op3 == null) { - op3 = checkNotNull(transformTerm(ops.get(2), op2.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - else if(op2 == null /* && op3 != null */) { - op2 = checkNotNull(transformTerm(ops.get(1), op3.getType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - return IteExpr.create(op1, op2, op3); - } - else { - final var op2 = transformTerm(ops.get(1), type, model, vars); - final var op3 = transformTerm(ops.get(2), type, model, vars); - return IteExpr.create(op1, op2, op3); - } + + final var op1 = transformTerm(ops.get(0), model, vars); + final var op2 = transformTerm(ops.get(1), model, vars); + final var op3 = transformTerm(ops.get(2), model, vars); + return IteExpr.create(op1, op2, op3); }; } private OperatorCreatorFunction exprArrayWriteOperator() { - return (params, ops, type, model, vars) -> { - assert type == null || type instanceof ArrayType; + return (params, ops, model, vars) -> { checkArgument(params.size() == 0, "No parameters expected"); checkArgument(ops.size() == 3, "Ternary operator expected"); - if(type == null) { - var op1 = transformTerm(ops.get(0), null, model, vars); - var op2 = transformTerm(ops.get(1), null, model, vars); - var op3 = transformTerm(ops.get(2), null, model, vars); - - if(op1 != null && (op2 == null || op3 == null)) { - final var arrayType = (ArrayType) op1.getType(); - if(op2 == null) { - op2 = checkNotNull(transformTerm(ops.get(1), arrayType.getIndexType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - if(op3 == null) { - op3 = checkNotNull(transformTerm(ops.get(2), arrayType.getElemType(), model, vars), "Unsupported expression: was not able to deduce all types"); - } - } - else if(op1 == null && op2 != null && op3 != null) { - final var arrayType = Array(op2.getType(), op3.getType()); - op1 = checkNotNull(transformTerm(ops.get(0), arrayType, model, vars), "Unsupported expression: was not able to deduce all types"); - } - else { - return null; - } - return ArrayWriteExpr.create(op1, op2, op3); - } - else { - final var arrayType = (ArrayType) type; - final var op1 = transformTerm(ops.get(0), arrayType, model, vars); - final var op2 = transformTerm(ops.get(1), arrayType.getIndexType(), model, vars); - final var op3 = transformTerm(ops.get(2), arrayType.getElemType(), model, vars); - return ArrayWriteExpr.create(op1, op2, op3); - } + final var op1 = transformTerm(ops.get(0), model, vars); + final var op2 = transformTerm(ops.get(1), model, vars); + final var op3 = transformTerm(ops.get(2), model, vars); + return ArrayWriteExpr.create(op1, op2, op3); }; } private OperatorCreatorFunction exprMultiaryOperator(final Function>, Expr> function) { - return (params, ops, type, model, vars) -> { + return (params, ops, model, vars) -> { checkArgument(params.size() == 0, "No parameters expected"); - if(type == null) { - final var transformedOps = new ArrayList>(); - ops.stream() - .map(op -> transformTerm(op, type, model, vars)) - .forEach(transformedOps::add); - - if(transformedOps.stream().allMatch(Objects::isNull)) { - return null; - } - else { - final var opType = transformedOps.stream().filter(Objects::nonNull).findAny().get().getType(); - return function.apply(IntStream - .range(0, ops.size()) - .mapToObj(i -> transformedOps.get(i) == null ? transformTerm(ops.get(i), opType, model, vars) : transformedOps.get(i)) - .collect(Collectors.toUnmodifiableList()) - ); - } - } - else { - return function.apply(ops.stream().map(op -> transformTerm(op, type, model, vars)).collect(Collectors.toUnmodifiableList())); - } + + return function.apply(ops.stream().map(op -> transformTerm(op, model, vars)).collect(Collectors.toUnmodifiableList())); }; } - private interface OperatorCreatorFunction extends QuintFunction< - List, // Parameters - List, // Operands - Type, // Expected type of result - SmtLibModel, // The model - BiMap, // The variable (param) store - Expr // Return type + private interface OperatorCreatorFunction extends QuadFunction< + List, // Parameters + List, // Operands + SmtLibModel, // The model + BiMap, String>, // The variable (param) store + Expr // Return type > {} - - private final static class ParamTypeDeducer { - private final String name; - private Type type; - private ParamDecl paramDecl; - - public ParamTypeDeducer(final String name, final Type type) { - this.name = name; - if(type != null) { - setType(type); - } - } - - public boolean isTypeUnknown() { - return type == null; - } - - public void setType(final Type type) { - checkArgument(type != null); - checkState(this.type == null); - this.type = type; - this.paramDecl = Decls.Param(name, type); - } - - public String getName() { - return name; - } - - public ParamDecl getParamDecl() { - checkState(paramDecl != null); - return paramDecl; - } - - public RefExpr getRef() { - checkState(paramDecl != null); - return paramDecl.getRef(); - } - } - } From fc1309976273343ab3ce4ec85e6b08f543c4fdd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 12 Sep 2020 16:20:59 +0200 Subject: [PATCH 42/99] Refactor tests to match changes in ftsrg#77 --- .../theta/solver/smtlib/SmtLibSolverTest.java | 110 ++++++++---------- 1 file changed, 48 insertions(+), 62 deletions(-) diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index 9bfa48f760..75b7bcd853 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -44,7 +44,6 @@ import static hu.bme.mit.theta.core.type.functype.FuncExprs.App; import static hu.bme.mit.theta.core.type.functype.FuncExprs.Func; import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; -import static hu.bme.mit.theta.core.utils.BvUtils.uint16ToBvLitExpr; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -67,7 +66,7 @@ public void test() { final var symbolTable = new GenericSmtLibSymbolTable(); final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var x = Const("x", BvExprs.BvType(4, true)); + final var x = Const("x", BvExprs.BvType(4)); symbolTable.put(x, "x", "(declare-fun x () (_ BitVec 4))"); final var expr = termTransformer.toExpr( @@ -220,13 +219,13 @@ public void testArray() { public void testBV1() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[]{false, false, true, false}, true))); - solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[]{false, false, true, false}, true))); + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[]{false, false, true, false}))); + solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[]{false, false, true, false}))); solver.add(BvExprs.Eq(cx.getRef(), cy.getRef())); SolverStatus status = solver.check(); @@ -239,13 +238,13 @@ public void testBV1() { public void testBV2() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); - final ConstDecl cz = Const("z", BvExprs.BvType(4, true)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); + final ConstDecl cz = Const("z", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[]{false, false, false, false}, true))); + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[]{false, false, false, false}))); solver.add(BvExprs.Neq(cx.getRef(), cz.getRef())); SolverStatus status = solver.check(); @@ -262,13 +261,13 @@ public void testBV2() { public void testBV3() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, false, false}, true))); - solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Add(List.of(cx.getRef(), Bv(new boolean[] {false, false, false, true}, true))))); + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, false, false}))); + solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Add(List.of(cx.getRef(), Bv(new boolean[] {false, false, false, true}))))); SolverStatus status = solver.check(); assertTrue(status.isSat()); @@ -284,13 +283,13 @@ public void testBV3() { public void testBV4() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, true, false}, true))); - solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Sub(cx.getRef(), Bv(new boolean[] {false, false, false, true}, true)))); + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, true, false}))); + solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Sub(cx.getRef(), Bv(new boolean[] {false, false, false, true})))); SolverStatus status = solver.check(); assertTrue(status.isSat()); @@ -306,12 +305,12 @@ public void testBV4() { public void testBV5() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, true, false}, true))); + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, true, false}))); solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Neg(cx.getRef()))); SolverStatus status = solver.check(); @@ -328,13 +327,13 @@ public void testBV5() { public void testBV6() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, true)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, true, false}, true))); - solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Mul(List.of(cx.getRef(), Bv(new boolean[] {false, false, true, false}, true))))); + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {false, false, true, false}))); + solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Mul(List.of(cx.getRef(), Bv(new boolean[] {false, false, true, false}))))); SolverStatus status = solver.check(); assertTrue(status.isSat()); @@ -350,13 +349,13 @@ public void testBV6() { public void testBV7() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, true)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Lt(cx.getRef(), Bv(new boolean[] {true, true, true, true}, true))); - solver.add(BvExprs.Lt(cy.getRef(), Bv(new boolean[] {true, true, true, true}, false))); + solver.add(BvExprs.ULt(cx.getRef(), Bv(new boolean[] {true, true, true, true}))); + solver.add(BvExprs.ULt(cy.getRef(), Bv(new boolean[] {true, true, true, true}))); SolverStatus status = solver.check(); assertTrue(status.isSat()); @@ -372,13 +371,13 @@ public void testBV7() { public void testBV8() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, false)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {true, false, true, false}, false))); - solver.add(BvExprs.Eq(cy.getRef(), BvExprs.Mod(cx.getRef(), Bv(new boolean[] {false, true, false, false}, false)))); + solver.add(BvExprs.Eq(cx.getRef(), Bv(new boolean[] {true, false, true, false}))); + solver.add(BvExprs.Eq(cy.getRef(), BvExprs.SMod(cx.getRef(), Bv(new boolean[] {false, true, false, false})))); SolverStatus status = solver.check(); assertTrue(status.isSat()); @@ -394,13 +393,13 @@ public void testBV8() { public void testBV9() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, false)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}, false))); - solver.add(BvExprs.Eq(BvExprs.Or(List.of(cx.getRef(), cy.getRef())), Bv(new boolean[] {true, true, false, false}, false))); + solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}))); + solver.add(BvExprs.Eq(BvExprs.Or(List.of(cx.getRef(), cy.getRef())), Bv(new boolean[] {true, true, false, false}))); SolverStatus status = solver.check(); assertTrue(status.isSat()); @@ -416,13 +415,13 @@ public void testBV9() { public void testBV10() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, false)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}, false))); - solver.add(BvExprs.Eq(BvExprs.And(List.of(cx.getRef(), cy.getRef())), Bv(new boolean[] {false, true, false, false}, false))); + solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}))); + solver.add(BvExprs.Eq(BvExprs.And(List.of(cx.getRef(), cy.getRef())), Bv(new boolean[] {false, true, false, false}))); SolverStatus status = solver.check(); assertTrue(status.isSat()); @@ -438,13 +437,13 @@ public void testBV10() { public void testBV11() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, false)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}, false))); - solver.add(BvExprs.Eq(BvExprs.Xor(List.of(cx.getRef(), cy.getRef())), Bv(new boolean[] {false, true, false, false}, false))); + solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}))); + solver.add(BvExprs.Eq(BvExprs.Xor(List.of(cx.getRef(), cy.getRef())), Bv(new boolean[] {false, true, false, false}))); SolverStatus status = solver.check(); assertTrue(status.isSat()); @@ -460,13 +459,13 @@ public void testBV11() { public void testBV12() { final Solver solver = solverFactory.createSolver(); - final ConstDecl cx = Const("x", BvExprs.BvType(4, false)); - final ConstDecl cy = Const("y", BvExprs.BvType(4, false)); + final ConstDecl cx = Const("x", BvExprs.BvType(4)); + final ConstDecl cy = Const("y", BvExprs.BvType(4)); solver.push(); - solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}, false))); - solver.add(BvExprs.Eq(BvExprs.ArithShiftRight(cy.getRef(), Bv(new boolean[] {false, false, false, true}, false)), cx.getRef())); + solver.add(BvExprs.Eq(cy.getRef(), Bv(new boolean[] {false, true, false, false}))); + solver.add(BvExprs.Eq(BvExprs.ArithShiftRight(cy.getRef(), Bv(new boolean[] {false, false, false, true})), cx.getRef())); SolverStatus status = solver.check(); assertTrue(status.isSat()); @@ -477,17 +476,4 @@ public void testBV12() { solver.pop(); } - - public void testBV13() { - final Solver solver = solverFactory.createSolver(); - solver.push(); - - solver.add(BvExprs.Eq(uint16ToBvLitExpr(4), BvExprs.Add(List.of(uint16ToBvLitExpr(1), uint16ToBvLitExpr(3))))); - solver.add(BvExprs.Eq(uint16ToBvLitExpr(1), BvExprs.Sub(uint16ToBvLitExpr(4), uint16ToBvLitExpr(3)))); - solver.add(BvExprs.Eq(uint16ToBvLitExpr(12), BvExprs.Mul(List.of(uint16ToBvLitExpr(3), uint16ToBvLitExpr(4))))); - solver.add(BvExprs.Eq(uint16ToBvLitExpr(4), BvExprs.Div(uint16ToBvLitExpr(12), uint16ToBvLitExpr(3)))); - solver.add(BvExprs.Eq(uint16ToBvLitExpr(1), BvExprs.Mod(uint16ToBvLitExpr(13), uint16ToBvLitExpr(3)))); - solver.add(BvExprs.Eq(uint16ToBvLitExpr(1), BvExprs.Rem(uint16ToBvLitExpr(13), uint16ToBvLitExpr(3)))); - - } } From 740b3de88d760c91baf0b6d965362fb535c0686c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 12 Sep 2020 16:21:23 +0200 Subject: [PATCH 43/99] Fix smtlib-cli usability issues --- .../main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java | 2 +- .../mit/theta/solver/smtlib/manager/SmtLibSolverManager.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java index 1940735364..0d495ab8ba 100644 --- a/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java +++ b/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java @@ -33,7 +33,7 @@ public class SmtLibCli { @Parameter(names = "--uninstall", description = "Uninstall a solver") String uninstall; - @Parameter(names = "--list-installed", help = true) + @Parameter(names = "--list-installed", description = "Lists installed solvers and their versions") private boolean listInstalled; @Parameter(names = "--home", description = "The path of the solver registry") diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java index 2a0ea735b4..874e7b3b2c 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java @@ -48,7 +48,7 @@ public static void registerGenericInsta private SmtLibSolverManager(final Path home, final Logger logger) { this.logger = logger; checkNotNull(home); - checkArgument(Files.exists(home)); + checkArgument(Files.exists(home), "Home directory does not exist"); this.home = home; From 6c98f4145d43e5781951a08026e45aedff8ae174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 12 Sep 2020 17:56:37 +0200 Subject: [PATCH 44/99] Refactor smtlib-cli to support more user firendly command system. --- .../theta/solver/smtlib/cli/SmtLibCli.java | 314 ++++++++++++++---- .../solver/smtlib/SmtLibSolverInstaller.java | 2 +- .../generic/GenericSmtLibSolverInstaller.java | 4 +- .../smtlib/manager/SmtLibSolverManager.java | 6 +- 4 files changed, 255 insertions(+), 71 deletions(-) diff --git a/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java index 0d495ab8ba..5f36f481f2 100644 --- a/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java +++ b/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java @@ -1,19 +1,26 @@ package hu.bme.mit.theta.solver.smtlib.cli; +import com.beust.jcommander.IParameterValidator; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; +import com.beust.jcommander.Parameters; import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.common.logging.ConsoleLogger; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; +import java.awt.Desktop; +import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.regex.Pattern; +import java.util.stream.Stream; public class SmtLibCli { private static final String JAR_NAME = "theta-solver-smtlib-cli.jar"; @@ -21,29 +28,92 @@ public class SmtLibCli { private Logger logger; - @Parameter(names = "--install", description = "Install a solver") - String install; + static class MainParams { + @Parameter(names = "--home", description = "The path of the solver registry") + String home = Path.of(System.getProperty("user.home"), ".theta").toAbsolutePath().toString(); - @Parameter(names = "--install-solverPath", description = "The path of the generic solver to install") - String installSolverPath; + @Parameter(names = "--loglevel", description = "Detailedness of logging") + Logger.Level logLevel = Logger.Level.MAINSTEP; - @Parameter(names = "--install-solverArgs", description = "The arguments of the generic solver to invoke with") - String installSolverArgs; + @Parameter(names = "--help", help = true) + private boolean help = false; + } + + @Parameters(commandDescription = "Installs the solver") + static class InstallCommand { + static final String COMMAND = "install"; + + @Parameter(description = "The solver to install (:)", validateWith = SolverNameAndVersionValidator.class, required = true) + String solver; + + @Parameter(names = "--name", description = "Install the solver version under this custom name (:), instead of the default (:)") + String name; + } + + @Parameters(commandDescription = "Installs a generic solver") + static class InstallGenericCommand { + static final String COMMAND = "install-generic"; + + @Parameter(names = "--solverPath", description = "The path of the generic solver to install", required = true) + String solverPath; + + @Parameter(names = "--solverArgs", description = "The arguments of the generic solver to invoke with") + String solverArgs; + + @Parameter(names = "--name", description = "Install the solver version under this custom name (:), instead of the default (:)", required = true) + String name; + } + + @Parameters(commandDescription = "Uninstalls the solver") + static class UninstallCommand { + static final String COMMAND = "uninstall"; + + @Parameter(description = "The solver to uninstall (:)", validateWith = SolverNameAndVersionValidator.class, required = true) + String solver; + } + + @Parameters(commandDescription = "Reinstalls the solver") + static class ReinstallCommand { + static final String COMMAND = "reinstall"; + + @Parameter(description = "The solver to reinstall (:)", validateWith = SolverNameAndVersionValidator.class, required = true) + String solver; + } + + @Parameters(commandDescription = "Prints info about the solver") + static class GetInfoCommand { + static final String COMMAND = "get-info"; + + @Parameter(description = "The solver to print info about (:)", validateWith = SolverNameAndVersionValidator.class, required = true) + String solver; + } - @Parameter(names = "--uninstall", description = "Uninstall a solver") - String uninstall; + @Parameters(commandDescription = "Edits the runtime arguments passed to the solver") + static class EditArgsCommand { + static final String COMMAND = "edit-args"; - @Parameter(names = "--list-installed", description = "Lists installed solvers and their versions") - private boolean listInstalled; + @Parameter(description = "The solver, whose runtime arguments are to be edited (:)", validateWith = SolverNameAndVersionValidator.class, required = true) + String solver; - @Parameter(names = "--home", description = "The path of the solver registry") - String home = Path.of(System.getProperty("user.home"), ".theta").toAbsolutePath().toString(); + @Parameter(names = "--print", description = "Print the path instead of opening it for editing") + boolean print = false; + } + + @Parameters(commandDescription = "Lists installed solvers and their versions") + static class ListInstalledCommand { + static final String COMMAND = "list-installed"; - @Parameter(names = "--loglevel", description = "Detailedness of logging") - Logger.Level logLevel = Logger.Level.MAINSTEP; + @Parameter(description = "The solver, whose installed versions are to be listed ()", validateWith = SolverNameValidator.class) + String solver; + } - @Parameter(names = "--help", help = true) - private boolean help; + @Parameters(commandDescription = "Lists supported solvers and their versions") + static class ListSupportedCommand { + static final String COMMAND = "list-supported"; + + @Parameter(description = "The solver, whose supported versions are to be listed ()", validateWith = SolverNameValidator.class) + String solver; + } public SmtLibCli(final String[] args) { this.args = args; @@ -55,10 +125,32 @@ public static void main(final String[] args) { } private void run() { - final var jc = JCommander.newBuilder().addObject(this).programName(JAR_NAME).build(); + final var mainParams = new MainParams(); + final var installCommand = new InstallCommand(); + final var installGenericCommand = new InstallGenericCommand(); + final var uninstallCommand = new UninstallCommand(); + final var reinstallCommand = new ReinstallCommand(); + final var getInfoCommand = new GetInfoCommand(); + final var editArgsCommand = new EditArgsCommand(); + final var listInstalledCommand = new ListInstalledCommand(); + final var listSupportedCommand = new ListSupportedCommand(); + + final var jc = JCommander.newBuilder() + .addObject(mainParams) + .addCommand(InstallCommand.COMMAND, installCommand) + .addCommand(InstallGenericCommand.COMMAND, installGenericCommand) + .addCommand(UninstallCommand.COMMAND, uninstallCommand) + .addCommand(ReinstallCommand.COMMAND, reinstallCommand) + .addCommand(GetInfoCommand.COMMAND, getInfoCommand) + .addCommand(EditArgsCommand.COMMAND, editArgsCommand) + .addCommand(ListInstalledCommand.COMMAND, listInstalledCommand) + .addCommand(ListSupportedCommand.COMMAND, listSupportedCommand) + .programName(JAR_NAME) + .build(); + try { jc.parse(args); - logger = new ConsoleLogger(logLevel); + logger = new ConsoleLogger(mainParams.logLevel); } catch (final ParameterException ex) { System.out.println("Invalid parameters, details:"); System.out.println(ex.getMessage()); @@ -66,77 +158,141 @@ private void run() { return; } - if(help) { - jc.usage(); - return; - } - - if(!isExactlyOneGiven(install, uninstall, listInstalled ? true : null)) { - jc.usage(); - return; - } - - if(install == null && (installSolverPath != null || installSolverArgs != null)) { + if(mainParams.help) { jc.usage(); return; } try { - final var homePath = createIfNotExists(Path.of(home)); + final var homePath = createIfNotExists(Path.of(mainParams.home)); final var smtLibSolverManager = SmtLibSolverManager.create(homePath, logger); - if (install != null) { - final var solver = decodeVersionString(install, smtLibSolverManager); - if(solver.get1().equals(smtLibSolverManager.getGenericInstallerName())) { - if(installSolverPath == null) { - jc.usage(); + switch(jc.getParsedCommand()) { + case InstallCommand.COMMAND: { + final var solver = decodeVersionString(installCommand.solver, smtLibSolverManager); + + if(solver.get1().equals(smtLibSolverManager.getGenericInstallerName())) { + logger.write(Logger.Level.RESULT, "To install a generic solver, use the \"%s\" command", InstallGenericCommand.COMMAND); return; } + if(installCommand.name != null) { + smtLibSolverManager.install(solver.get1(), solver.get2(), installCommand.name); + } + else { + smtLibSolverManager.install(solver.get1(), solver.get2(), solver.get2()); + } + + return; + } + case InstallGenericCommand.COMMAND: { smtLibSolverManager.installGeneric( - solver.get2(), - Path.of(installSolverPath), - (installSolverArgs == null ? "" : installSolverArgs).split(" ") + installGenericCommand.name, + Path.of(installGenericCommand.solverPath), + (installGenericCommand.solverArgs == null ? "" : installGenericCommand.solverArgs).split(" ") ); + return; } - else { - smtLibSolverManager.install(solver.get1(), solver.get2()); + case UninstallCommand.COMMAND: { + final var solver = decodeVersionString(uninstallCommand.solver, smtLibSolverManager); + smtLibSolverManager.uninstall(solver.get1(), solver.get2()); + return; + } + case ReinstallCommand.COMMAND: { + final var solver = decodeVersionString(reinstallCommand.solver, smtLibSolverManager); + smtLibSolverManager.reinstall(solver.get1(), solver.get2()); + return; + } + case GetInfoCommand.COMMAND: { + final var solver = decodeVersionString(getInfoCommand.solver, smtLibSolverManager); + final var info = smtLibSolverManager.getInfo(solver.get1(), solver.get2()); + logger.write(Logger.Level.RESULT, "%s\n", info); + return; + } + case EditArgsCommand.COMMAND: { + final var solver = decodeVersionString(editArgsCommand.solver, smtLibSolverManager); + final var argsFilePath = smtLibSolverManager.getArgsFile(solver.get1(), solver.get2()); + + if(smtLibSolverManager.getSupportedVersions(solver.get1()).contains(solver.get2())) { + logger.write(Logger.Level.RESULT, "Supported versions of solvers cannot be edited. If you want to pass custom arguments to a supported solver, install a new instance of the version with a custom name."); + return; + } + + boolean nanoInPath = Stream.of(System.getenv("PATH").split(Pattern.quote(File.pathSeparator))) + .map(Paths::get) + .anyMatch(path -> Files.exists(path.resolve("nano"))); + + if(editArgsCommand.print) { + logger.write(Logger.Level.RESULT, String.format("%s\n", argsFilePath.toAbsolutePath().toString())); + } + else if(Desktop.isDesktopSupported()) { + Desktop.getDesktop().edit(argsFilePath.toFile()); + } + else if(nanoInPath) { + Runtime.getRuntime().exec("nano", new String[] { argsFilePath.toAbsolutePath().toString() }); + } + else { + logger.write(Logger.Level.MAINSTEP, "Open the following text file in your favourite editor, and edit the content:\n"); + logger.write(Logger.Level.RESULT, String.format("%s\n", argsFilePath.toAbsolutePath().toString())); + } + + return; + } + case ListInstalledCommand.COMMAND: { + if(listInstalledCommand.solver != null) { + logger.write(Logger.Level.MAINSTEP, "The currently installed versions of solver %s are: \n", listInstalledCommand.solver); + smtLibSolverManager.getInstalledVersions(listInstalledCommand.solver).forEach(version -> { + logger.write(Logger.Level.RESULT, "\t%s:%s\n", listInstalledCommand.solver, version); + }); + } + else { + logger.write(Logger.Level.MAINSTEP, "The currently installed solvers are: \n"); + smtLibSolverManager.getInstalledVersions().forEach(solver -> { + solver.get2().forEach(version -> { + logger.write(Logger.Level.RESULT, "\t%s:%s\n", solver.get1(), version); + }); + }); + } + return; + } + case ListSupportedCommand.COMMAND: { + if(listSupportedCommand.solver != null) { + logger.write(Logger.Level.MAINSTEP, "The currently supported versions of solver %s are: \n", listSupportedCommand.solver); + smtLibSolverManager.getSupportedVersions(listSupportedCommand.solver).forEach(version -> { + logger.write(Logger.Level.RESULT, "\t%s:%s\n", listSupportedCommand.solver, version); + }); + } + else { + logger.write(Logger.Level.MAINSTEP, "The currently supported solvers are: \n"); + smtLibSolverManager.getSupportedVersions().forEach(solver -> { + solver.get2().forEach(version -> { + logger.write(Logger.Level.RESULT, "\t%s:%s\n", solver.get1(), version); + }); + }); + } + return; + } + default: { + logger.write(Logger.Level.RESULT, "Unknown command\n"); + jc.usage(); + return; } - } - else if(uninstall != null) { - final var solver = decodeVersionString(uninstall, smtLibSolverManager); - smtLibSolverManager.uninstall(solver.get1(), solver.get2()); - } - else if(listInstalled) { - logger.write(Logger.Level.RESULT, "The currently installed solvers are: \n"); - smtLibSolverManager.getInstalledVersions().forEach(solver -> { - solver.get2().forEach(version -> { - logger.write(Logger.Level.RESULT, "\t%s:%s\n", solver.get1(), version); - }); - }); } } catch (SmtLibSolverInstallerException | IOException e) { printError(e); } } - private boolean isExactlyOneGiven(final Object ...args) { - int count = 0; - for(final var arg : args) { - if(arg != null) count++; - } - return count == 1; - } - - private Tuple2 decodeVersionString(final String version, final SmtLibSolverManager solverManager) throws SmtLibSolverInstallerException { + private static Tuple2 decodeVersionString(final String version, final SmtLibSolverManager solverManager) throws SmtLibSolverInstallerException { final var versionArr = version.split(":"); - if(versionArr.length != 1 && versionArr.length != 2) { + if(versionArr.length != 2) { throw new IllegalArgumentException("Invalid version string: " + version); } final var solver = versionArr[0]; - if(versionArr.length == 2) { + final var ver = versionArr[1]; + if(!ver.equals("latest")) { return Tuple2.of(solver, versionArr[1]); } else { @@ -145,7 +301,7 @@ private Tuple2 decodeVersionString(final String version, final S return Tuple2.of(solver, versions.get(0)); } else { - throw new IllegalArgumentException("Invalid version string: " + version); + throw new IllegalArgumentException("There are no supported versions of solver: " + solver); } } } @@ -160,9 +316,37 @@ private Path createIfNotExists(final Path path) throws IOException { private void printError(final Throwable ex) { final String message = ex.getMessage() == null ? "" : ": " + ex.getMessage(); logger.write(Logger.Level.RESULT, "Exception of type %s occurred%n", ex.getClass().getSimpleName()); - logger.write(Logger.Level.MAINSTEP, "Message:%n%s%n", ex.getMessage()); + logger.write(Logger.Level.MAINSTEP, "Message:%n%s%n", message); final StringWriter errors = new StringWriter(); ex.printStackTrace(new PrintWriter(errors)); logger.write(Logger.Level.SUBSTEP, "Trace:%n%s%n", errors.toString()); } + + static class SolverNameValidator implements IParameterValidator { + @Override + public void validate(String name, String value) throws ParameterException { + if(!value.matches("[a-zA-Z0-9]+")) { + throw new ParameterException( + String.format("Invalid solver name in parameter %s", name) + ); + } + } + } + + static class SolverNameAndVersionValidator implements IParameterValidator { + @Override + public void validate(String name, String value) throws ParameterException { + final var versionArr = value.split(":"); + + if(versionArr.length != 2) { + throw new ParameterException(String.format("Invalid version string %s in parameter %s", value, name)); + } + + if(!versionArr[0].matches("[a-zA-Z0-9]+") || !versionArr[1].matches("[a-zA-Z0-9]+")) { + throw new ParameterException( + String.format("Invalid version string %s in parameter %s", value, name) + ); + } + } + } } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java index 38f366920d..973f6ef70f 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java @@ -6,7 +6,7 @@ import java.util.List; public interface SmtLibSolverInstaller { - void install(Path home, String version) throws SmtLibSolverInstallerException; + void install(Path home, String version, String name) throws SmtLibSolverInstallerException; void uninstall(Path home, String version) throws SmtLibSolverInstallerException; diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java index decb537ff0..625c686705 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java @@ -4,7 +4,6 @@ import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; -import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; import java.io.File; import java.io.IOException; @@ -26,10 +25,11 @@ public GenericSmtLibSolverInstaller(Logger logger) { } @Override - public void install(final Path home, final String version) throws SmtLibSolverInstallerException { + public void install(final Path home, final String version, String name) throws SmtLibSolverInstallerException { checkNotNull(home); checkArgument(Files.exists(home)); checkVersion(version); + checkVersion(name); throw new SmtLibSolverInstallerException("Unsupported operation for generic solvers"); } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java index 874e7b3b2c..454a3b3eb4 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java @@ -83,7 +83,7 @@ public String getGenericInstallerName() { return genericInstaller.get1(); } - public void install(final String solver, final String version) throws SmtLibSolverInstallerException { + public void install(final String solver, final String version, final String name) throws SmtLibSolverInstallerException { checkArgument(!solver.equals(genericInstaller.get1())); if(!installers.containsKey(solver)) { @@ -99,7 +99,7 @@ public void install(final String solver, final String version) throws SmtLibSolv throw new SmtLibSolverInstallerException(e); } - installers.get(solver).install(installDir, version); + installers.get(solver).install(installDir, version, name); } public void installGeneric(final String version, final Path solverPath, final String[] args) throws SmtLibSolverInstallerException { @@ -155,7 +155,7 @@ public SolverFactory getSolverFactory(final String solver, final String version) return installers.get(solver).getSolverFactory(home.resolve(solver), version); } - public List getSupportedSolvers() throws SmtLibSolverInstallerException { + public List getSupportedSolvers() { return installers.keySet().stream().collect(Collectors.toUnmodifiableList()); } From 747ac4bf1d5f3242e4a4b765740559680de6f8ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 12 Sep 2020 18:18:16 +0200 Subject: [PATCH 45/99] Refactor trace checkers to use UCSolver instead of Solver --- .../refinement/ExprTraceNewtonChecker.java | 607 ++++++++++++++++++ .../expr/refinement/ExprTraceUCBChecker.java | 277 ++++++++ .../refinement/ExprTraceNewtonChecker.java | 82 ++- 3 files changed, 937 insertions(+), 29 deletions(-) create mode 100644 subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java create mode 100644 subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java diff --git a/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java b/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java new file mode 100644 index 0000000000..349a83fb9b --- /dev/null +++ b/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java @@ -0,0 +1,607 @@ +package hu.bme.mit.theta.analysis.expr.refinement; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import hu.bme.mit.theta.analysis.Trace; +import hu.bme.mit.theta.analysis.expr.ExprAction; +import hu.bme.mit.theta.analysis.expr.ExprState; +import hu.bme.mit.theta.analysis.expr.ExprTraceUtils; +import hu.bme.mit.theta.analysis.expr.StmtAction; +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.common.Utils; +import hu.bme.mit.theta.core.decl.VarDecl; +import hu.bme.mit.theta.core.model.BasicSubstitution; +import hu.bme.mit.theta.core.model.ImmutableValuation; +import hu.bme.mit.theta.core.model.Valuation; +import hu.bme.mit.theta.core.stmt.AssignStmt; +import hu.bme.mit.theta.core.stmt.AssumeStmt; +import hu.bme.mit.theta.core.stmt.HavocStmt; +import hu.bme.mit.theta.core.stmt.SkipStmt; +import hu.bme.mit.theta.core.stmt.Stmt; +import hu.bme.mit.theta.core.stmt.StmtVisitor; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.Type; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.core.utils.ExprSimplifier; +import hu.bme.mit.theta.core.utils.ExprUtils; +import hu.bme.mit.theta.core.utils.PathUtils; +import hu.bme.mit.theta.core.utils.SpState; +import hu.bme.mit.theta.core.utils.StmtUtils; +import hu.bme.mit.theta.core.utils.VarIndexing; +import hu.bme.mit.theta.core.utils.WpState; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.utils.WithPushPop; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static com.google.common.base.Preconditions.checkNotNull; +import static hu.bme.mit.theta.core.decl.Decls.Param; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Exists; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Forall; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toUnmodifiableMap; + +/** + * An ExprTraceChecker that generates new predicates based on the Newton-style algorithms described in + * Daniel Dietsch, Matthias Heizmann, Betim Musa, Alexander Nutz, and Andreas Podelski. 2017. + * Craig vs. Newton in software model checking. In Proceedings of the 2017 11th Joint Meeting on Foundations + * of Software Engineering (ESEC/FSE 2017). Association for Computing Machinery, New York, NY, USA, + * 487–497. DOI:https://doi.org/10.1145/3106237.3106307 + */ +public class ExprTraceNewtonChecker implements ExprTraceChecker { + private enum AssertionGeneratorMethod { SP, WP } + + private final UCSolver solver; + private final Expr init; + private final Expr target; + + private final boolean IT; // Whether to abstract the trace or not + private final AssertionGeneratorMethod SPorWP; // Whether to use pre- or postconditions + private final boolean LV; // Whether to project the assertions to live variables + + private ExprTraceNewtonChecker( + final Expr init, final Expr target, final UCSolver solver, + boolean it, AssertionGeneratorMethod sPorWP, boolean lv + ) { + this.solver = checkNotNull(solver); + this.init = checkNotNull(init); + this.target = checkNotNull(target); + this.IT = it; + this.SPorWP = checkNotNull(sPorWP); + this.LV = lv; + } + + public static ExprTraceNewtonCheckerITBuilder create( + final Expr init, final Expr target, final UCSolver solver + ) { + return new ExprTraceNewtonCheckerITBuilder(solver, init, target); + } + + @SuppressWarnings("unchecked") + @Override + public ExprTraceStatus check(final Trace trace) { + checkNotNull(trace); + try { + return check2((Trace) trace); + } + catch(ClassCastException e) { + throw new UnsupportedOperationException("Actions must be of type StmtAction", e); + } + } + + private ExprTraceStatus check2(final Trace trace) { + var ftrace = flattenTrace(trace); // Moves the expressions in the states to the corresponting actions as assumptions + + final int stateCount = ftrace.getStates().size(); + final List indexings = new ArrayList<>(stateCount); + indexings.add(VarIndexing.all(0)); + + final Valuation model; + final Collection> unsatCore; + final boolean concretizable; + + try (WithPushPop wpp = new WithPushPop(solver)) { + for (int i = 1; i < stateCount; ++i) { + var curIndexing = indexings.get(i - 1); + for(var stmt : ftrace.getAction(i - 1).getStmts()) { + var stmtUnfoldResult = StmtUtils.toExpr(stmt, VarIndexing.all(0)); + solver.track(PathUtils.unfold(stmtUnfoldResult.getExprs().iterator().next(), curIndexing)); + curIndexing = curIndexing.add(stmtUnfoldResult.getIndexing()); + } + indexings.add(curIndexing); + } + + concretizable = solver.check().isSat(); + + if (concretizable) { + model = solver.getModel(); + unsatCore = null; + } else { + model = null; + unsatCore = solver.getUnsatCore(); + } + } + + if (concretizable) { + checkNotNull(model); + return createCounterexample(model, indexings, trace); + } else { + checkNotNull(unsatCore); + return createRefinement(unsatCore, indexings, ftrace); + } + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + private Trace flattenTrace(final Trace trace) { + final var stateCount = trace.getStates().size(); + final var flattenedActions = new ArrayList(stateCount - 1); + + for(var i = 1; i < stateCount; i++) { + var initStream = + (i == 1) + ? ExprUtils.getConjuncts(init).stream().map(AssumeStmt::of) + : Stream.empty(); + + var stateStream = ExprUtils.getConjuncts(trace.getState(i - 1).toExpr()).stream().map(AssumeStmt::of); + + var actionStream = trace.getAction(i - 1).getStmts().stream(); + + var targetStream = + (i == stateCount - 1) + ? Stream.concat( + ExprUtils.getConjuncts(trace.getState(i).toExpr()).stream().map(AssumeStmt::of), + ExprUtils.getConjuncts(target).stream().map(AssumeStmt::of) + ) + : Stream.empty(); + + flattenedActions.add( + NewtonAction.of( + Stream.of(initStream, stateStream, actionStream, targetStream).flatMap(e -> e).collect(toList()) + ) + ); + } + + return ExprTraceUtils.traceFrom(flattenedActions); + } + + private ExprTraceStatus.Feasible createCounterexample( + final Valuation model, + final List indexings, + final Trace trace + ) { + final ImmutableList.Builder builder = ImmutableList.builder(); + for (final VarIndexing indexing : indexings) { + builder.add(PathUtils.extractValuation(model, indexing)); + } + return ExprTraceStatus.feasible(Trace.of(builder.build(), trace.getActions())); + } + + private ExprTraceStatus.Infeasible createRefinement( + final Collection> unsatCore, + final List indexings, + Trace trace + ) { + if(IT) { + trace = computeAbstractTrace(unsatCore, trace); + } + + final List> assertions; + if(SPorWP == AssertionGeneratorMethod.SP) { + assertions = computeAssertionsFromTraceWithStrongestPostcondition(trace); + } + else if(SPorWP == AssertionGeneratorMethod.WP) { + assertions = computeAssertionsFromTraceWithWeakestPrecondition(trace); + } + else { + throw new AssertionError("There should be no other option"); + } + + return ExprTraceStatus.infeasible(ItpRefutation.sequence(assertions)); + } + + /* + * State abstraction + */ + + private Trace computeAbstractTrace( + final Collection> unsatCore, + final Trace trace + ) { + final var stateCount = trace.getStates().size(); + var curIndexing = VarIndexing.all(0); + + final var actions = new ArrayList(); + + for (int i = 1; i < stateCount; ++i) { + final var stmts = new ArrayList(); + for(final var stmt : trace.getAction(i - 1).getStmts()) { + final var stmtUnfoldResult = StmtUtils.toExpr(stmt, VarIndexing.all(0)); + final var stmtExpr = PathUtils.unfold(stmtUnfoldResult.getExprs().iterator().next(), curIndexing); + + if(unsatCore.contains(stmtExpr)) { + stmts.add(stmt); + } + else { + stmts.add(computeAbstractStmt(stmt)); + } + + curIndexing = curIndexing.add(stmtUnfoldResult.getIndexing()); + } + actions.add(NewtonAction.of(stmts)); + } + + return Trace.of(trace.getStates(), actions); + } + + private Stmt computeAbstractStmt(Stmt stmt) { + return stmt.accept(new StmtVisitor() { + @Override + public Stmt visit(SkipStmt stmt, Void param) { + return SkipStmt.getInstance(); + } + + @Override + public Stmt visit(AssumeStmt stmt, Void param) { + return AssumeStmt.of(True()); + } + + @Override + public Stmt visit(AssignStmt stmt, Void param) { + return HavocStmt.of(stmt.getVarDecl()); + } + + @Override + public Stmt visit(HavocStmt stmt, Void param) { + return HavocStmt.of(stmt.getVarDecl()); + } + }, null); + } + + /* + * Assertion computation + */ + + private List> computeAssertionsFromTraceWithStrongestPostcondition( + final Trace trace + ) { + final int stateCount = trace.getStates().size(); + final List> assertions = new ArrayList<>(stateCount); + + assertions.add(True()); + var constCount = 0; + for(var i = 1; i < stateCount; i++) { + var spState = SpState.of(assertions.get(i - 1), constCount); + for(var stmt : trace.getAction(i - 1).getStmts()) { + spState = spState.sp(stmt); + } + assertions.add(ExprSimplifier.simplify(spState.getExpr(), ImmutableValuation.empty())); + constCount = spState.getConstCount(); + } + + if(LV) { + var allVariables = collectVariablesInTrace(trace); + var futureLiveVariables = collectFutureLiveVariablesForTrace(trace); + return IntStream.range(0, assertions.size()) + .mapToObj(i -> existentialProjection(assertions.get(i), futureLiveVariables.get(i), allVariables)) + .collect(Collectors.toUnmodifiableList()); + } + else { + return assertions; + } + } + + private List> computeAssertionsFromTraceWithWeakestPrecondition( + final Trace trace + ) { + final int stateCount = trace.getStates().size(); + final List> assertions = new ArrayList<>(Collections.nCopies(stateCount, null)); + + assertions.set(stateCount - 1, True()); + var constCount = 0; + for(var i = stateCount - 2; i >= 0; i--) { + var wpState = WpState.of(assertions.get(i + 1), constCount); + for(var stmt : Lists.reverse(trace.getAction(i).getStmts())) { + wpState = wpState.wep(stmt); + } + assertions.set(i, ExprSimplifier.simplify(wpState.getExpr(), ImmutableValuation.empty())); + constCount = wpState.getConstCount(); + } + + if(LV) { + var allVariables = collectVariablesInTrace(trace); + var pastLiveVariables = collectPastLiveVariablesForTrace(trace); + return IntStream.range(0, assertions.size()) + .mapToObj(i -> universalProjection(assertions.get(i), pastLiveVariables.get(i), allVariables)) + .collect(Collectors.toUnmodifiableList()); + } + else { + return assertions; + } + } + + /* + * Live variable collection + */ + + private Collection> collectVariablesInTrace(final Trace trace) { + var variables = new HashSet>(); + + for(var state : trace.getStates()) { + ExprUtils.collectVars(state.toExpr(), variables); + } + for(var action : trace.getActions()) { + ExprUtils.collectVars(action.toExpr(), variables); + } + + return variables; + } + + private Collection> stmtReadsVariables(final Stmt stmt) { + return stmt.accept(new StmtVisitor>>() { + @Override + public Collection> visit(SkipStmt stmt, Void param) { + return Collections.emptySet(); + } + + @Override + public Collection> visit(AssumeStmt stmt, Void param) { + return ExprUtils.getVars(stmt.getCond()); + } + + @Override + public Collection> visit(AssignStmt stmt, Void param) { + return ExprUtils.getVars(stmt.getExpr()); + } + + @Override + public Collection> visit(HavocStmt stmt, Void param) { + return Collections.emptySet(); + } + }, null); + } + + private Collection> stmtWritesVariables(final Stmt stmt) { + return stmt.accept(new StmtVisitor>>() { + @Override + public Collection> visit(SkipStmt stmt, Void param) { + return Collections.emptySet(); + } + + @Override + public Collection> visit(AssumeStmt stmt, Void param) { + return Collections.emptySet(); + } + + @Override + public Collection> visit(AssignStmt stmt, Void param) { + return Collections.singletonList(stmt.getVarDecl()); + } + + @Override + public Collection> visit(HavocStmt stmt, Void param) { + return Collections.emptySet(); + } + }, null); + } + + private Collection> stmtHavocsVariables(final Stmt stmt) { + return stmt.accept(new StmtVisitor>>() { + @Override + public Collection> visit(SkipStmt stmt, Void param) { + return Collections.emptySet(); + } + + @Override + public Collection> visit(AssumeStmt stmt, Void param) { + return Collections.emptySet(); + } + + @Override + public Collection> visit(AssignStmt stmt, Void param) { + return Collections.emptySet(); + } + + @Override + public Collection> visit(HavocStmt stmt, Void param) { + return Collections.singletonList(stmt.getVarDecl()); + } + }, null); + } + + private Collection> actionReadsVariables(final StmtAction action) { + return action.getStmts().stream().flatMap(stmt -> stmtReadsVariables(stmt).stream()).collect(Collectors.toUnmodifiableSet()); + } + + private Collection> actionWritesVariables(final StmtAction action) { + return action.getStmts().stream().flatMap(stmt -> stmtWritesVariables(stmt).stream()).collect(Collectors.toUnmodifiableSet()); + } + + private Collection> actionHavocsVariables(final StmtAction action) { + return action.getStmts().stream().flatMap(stmt -> stmtHavocsVariables(stmt).stream()).collect(Collectors.toUnmodifiableSet()); + } + + private List>> collectFutureLiveVariablesForTrace(final Trace trace) { + final var stateCount = trace.getStates().size(); + final var futureLiveVariables = new ArrayList>>(Collections.nCopies(stateCount, null)); + + futureLiveVariables.set(stateCount - 1, Collections.emptySet()); + for(var i = stateCount - 2; i >= 0; i--) { + var vars = new HashSet<>(futureLiveVariables.get(i + 1)); + vars.addAll(actionReadsVariables(trace.getAction(i))); + vars.removeAll(actionWritesVariables(trace.getAction(i))); + vars.removeAll(actionHavocsVariables(trace.getAction(i))); + futureLiveVariables.set(i, vars); + } + + return futureLiveVariables; + } + + private List>> collectPastLiveVariablesForTrace(final Trace trace) { + final var stateCount = trace.getStates().size(); + final var pastLiveVariables = new ArrayList>>(Collections.nCopies(stateCount, null)); + + pastLiveVariables.set(0, Collections.emptySet()); + for(var i = 1; i < stateCount; i++) { + var vars = new HashSet<>(pastLiveVariables.get(i - 1)); + vars.addAll(actionReadsVariables(trace.getAction(i - 1))); + vars.addAll(actionWritesVariables(trace.getAction(i - 1))); + vars.removeAll(actionHavocsVariables(trace.getAction(i - 1))); + pastLiveVariables.set(i, vars); + } + + return pastLiveVariables; + } + + /* + * Projection to live variables + */ + + private Expr existentialProjection( + final Expr expr, + final Collection> variables, + final Collection> allVariables + ) { + var params = allVariables.stream() + .filter(e -> !variables.contains(e)) + .map(e -> Tuple2.of(e, Param(e.getName(), e.getType()))) + .collect(Collectors.toUnmodifiableSet()); + + var substitution = BasicSubstitution.builder() + .putAll(params.stream().collect(toUnmodifiableMap(Tuple2::get1, e -> e.get2().getRef()))) + .build(); + + return params.size() > 0 + ? Exists(params.stream().map(Tuple2::get2).collect(toList()), substitution.apply(expr)) + : expr; + } + + private Expr universalProjection( + final Expr expr, + final Collection> variables, + final Collection> allVariables + ) { + var params = allVariables.stream() + .filter(e -> !variables.contains(e)) + .map(e -> Tuple2.of(e, Param(e.getName(), e.getType()))) + .collect(Collectors.toUnmodifiableSet()); + + var substitution = BasicSubstitution.builder() + .putAll(params.stream().collect(toUnmodifiableMap(Tuple2::get1, e -> e.get2().getRef()))) + .build(); + + return params.size() > 0 + ? Forall(params.stream().map(Tuple2::get2).collect(toList()), substitution.apply(expr)) + : expr; + } + + /* + * Builder for ExprTraceNewtonChecker + */ + + public static class ExprTraceNewtonCheckerITBuilder { + private final UCSolver solver; + private final Expr init; + private final Expr target; + + public ExprTraceNewtonCheckerITBuilder(UCSolver solver, Expr init, Expr target) { + this.solver = solver; + this.init = init; + this.target = target; + } + + public ExprTraceNewtonCheckerAssertBuilder withIT() { + return new ExprTraceNewtonCheckerAssertBuilder(solver, init, target, true); + } + + public ExprTraceNewtonCheckerAssertBuilder withoutIT() { + return new ExprTraceNewtonCheckerAssertBuilder(solver, init, target, false); + } + } + + public static class ExprTraceNewtonCheckerAssertBuilder { + private final UCSolver solver; + private final Expr init; + private final Expr target; + + private final boolean IT; + + public ExprTraceNewtonCheckerAssertBuilder(UCSolver solver, Expr init, Expr target, boolean it) { + this.solver = solver; + this.init = init; + this.target = target; + this.IT = it; + } + + public ExprTraceNewtonCheckerLVBuilder withSP() { + return new ExprTraceNewtonCheckerLVBuilder(solver, init, target, IT, AssertionGeneratorMethod.SP); + } + + public ExprTraceNewtonCheckerLVBuilder withWP() { + return new ExprTraceNewtonCheckerLVBuilder(solver, init, target, IT, AssertionGeneratorMethod.WP); + } + } + + public static class ExprTraceNewtonCheckerLVBuilder { + private final UCSolver solver; + private final Expr init; + private final Expr target; + + private final boolean IT; + private final AssertionGeneratorMethod SPorWP; + + public ExprTraceNewtonCheckerLVBuilder(UCSolver solver, Expr init, Expr target, boolean it, AssertionGeneratorMethod sPorWP) { + this.solver = solver; + this.init = init; + this.target = target; + this.IT = it; + this.SPorWP = sPorWP; + } + + public ExprTraceNewtonChecker withLV() { + return new ExprTraceNewtonChecker(init, target, solver, IT, SPorWP, true); + } + + public ExprTraceNewtonChecker withoutLV() { + return new ExprTraceNewtonChecker(init, target, solver, IT, SPorWP, false); + } + } + + /* + * Custom StmtAction to use when constructing helper traces + */ + + private static class NewtonAction extends StmtAction { + private final List stmts; + + private NewtonAction(List stmts) { + this.stmts = stmts; + } + + public static NewtonAction of(List stmts) { + return new NewtonAction(stmts); + } + + @Override + public List getStmts() { + return stmts; + } + + @Override + public String toString() { + return Utils.lispStringBuilder(getClass().getSimpleName()).body().addAll(stmts).toString(); + } + } +} diff --git a/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java b/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java new file mode 100644 index 0000000000..5107976f6b --- /dev/null +++ b/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java @@ -0,0 +1,277 @@ +package hu.bme.mit.theta.analysis.expr.refinement; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import hu.bme.mit.theta.analysis.Trace; +import hu.bme.mit.theta.analysis.expr.ExprAction; +import hu.bme.mit.theta.analysis.expr.ExprState; +import hu.bme.mit.theta.analysis.expr.ExprTraceUtils; +import hu.bme.mit.theta.analysis.expr.StmtAction; +import hu.bme.mit.theta.common.Utils; +import hu.bme.mit.theta.core.model.ImmutableValuation; +import hu.bme.mit.theta.core.model.Valuation; +import hu.bme.mit.theta.core.stmt.AssumeStmt; +import hu.bme.mit.theta.core.stmt.Stmt; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.core.utils.ExprSimplifier; +import hu.bme.mit.theta.core.utils.ExprUtils; +import hu.bme.mit.theta.core.utils.PathUtils; +import hu.bme.mit.theta.core.utils.SpState; +import hu.bme.mit.theta.core.utils.VarIndexing; +import hu.bme.mit.theta.core.utils.WpState; +import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.utils.WithPushPop; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static com.google.common.base.Preconditions.checkNotNull; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; +import static hu.bme.mit.theta.core.type.booltype.SmartBoolExprs.And; +import static hu.bme.mit.theta.core.type.booltype.SmartBoolExprs.Not; +import static java.util.stream.Collectors.toList; + +/** + * An ExprTraceChecker that generates new predicates based on the UCB algorithm by + * Leucker, Martin & Markin, Grigory & Neuhäußer, Martin. (2015). A New Refinement + * Strategy for CEGAR-Based Industrial Model Checking. 155-170. 10.1007/978-3-319-26287-1_10. + */ +public class ExprTraceUCBChecker implements ExprTraceChecker { + + private final UCSolver solver; + private final Expr init; + private final Expr target; + + private ExprTraceUCBChecker(final Expr init, final Expr target, final UCSolver solver) { + this.solver = checkNotNull(solver); + this.init = checkNotNull(init); + this.target = checkNotNull(target); + } + + public static ExprTraceUCBChecker create( + final Expr init, final Expr target, final UCSolver solver + ) { + return new ExprTraceUCBChecker(init, target, solver); + } + + @SuppressWarnings("unchecked") + @Override + public ExprTraceStatus check(final Trace trace) { + checkNotNull(trace); + try { + return check2((Trace) trace); + } + catch(ClassCastException e) { + throw new UnsupportedOperationException("Actions must be of type StmtAction", e); + } + } + +private ExprTraceStatus check2(final Trace trace) { + final var ftrace = flattenTrace(trace); + final int stateCount = trace.getStates().size(); + + final List indexings = new ArrayList<>(stateCount); + indexings.add(VarIndexing.all(0)); + + final Valuation model; + final Collection> unsatCore; + final boolean concretizable; + + try (WithPushPop wpp = new WithPushPop(solver)) { + for (int i = 1; i < stateCount; ++i) { + indexings.add(indexings.get(i - 1).add(trace.getAction(i - 1).nextIndexing())); + solver.track( + ExprUtils.getConjuncts( + PathUtils.unfold(trace.getAction(i - 1).toExpr(), indexings.get(i - 1)) + ) + ); + } + + concretizable = solver.check().isSat(); + + if (concretizable) { + model = solver.getModel(); + unsatCore = null; + } else { + model = null; + unsatCore = solver.getUnsatCore(); + } + } + + if (concretizable) { + checkNotNull(model); + return createCounterexample(model, indexings, trace); + } else { + checkNotNull(unsatCore); + return createRefinement(unsatCore, indexings, ftrace); + } + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + + private ExprTraceStatus.Feasible createCounterexample( + final Valuation model, + final List indexings, + final Trace trace + ) { + final ImmutableList.Builder builder = ImmutableList.builder(); + for (final VarIndexing indexing : indexings) { + builder.add(PathUtils.extractValuation(model, indexing)); + } + return ExprTraceStatus.feasible(Trace.of(builder.build(), trace.getActions())); + } + + private ExprTraceStatus.Infeasible createRefinement( + final Collection> unsatCore, + final List indexings, + final Trace trace + ) { + final int stateCount = trace.getStates().size(); + final List> wps = calculateWpStates(trace, indexings); + + final List> predicates = new ArrayList<>(); + + var constCount = 0; + for(var i = 0; i < stateCount; i++) { + try(final var wpp = new WithPushPop(solver)) { + final List> dataRegion = new ArrayList<>(); + + /* Calculate SP */ + if (i == 0) { + solver.track(True()); + dataRegion.add(True()); + } else /* i > 0 */ { + var spState = SpState.of(PathUtils.foldin(predicates.get(i - 1), indexings.get(i - 1)), constCount); + for(var stmt : trace.getAction(i - 1).getStmts()) { + spState = spState.sp(stmt); + } + + final var expr = PathUtils.unfold(spState.getExpr(), indexings.get(i)); + constCount = spState.getConstCount(); + solver.track(ExprUtils.getConjuncts(expr)); + dataRegion.addAll(ExprUtils.getConjuncts(expr)); + } + + /* Add wp */ + solver.track(ExprUtils.getConjuncts(wps.get(i))); + + solver.check(); + assert solver.check().isUnsat(); // It must be unsat + Collection> uc = solver.getUnsatCore(); + + /* Keep only those expressions from uc that are not in the data region */ + final Collection> predicate = new ArrayList<>(); + for (var ucExpr : uc) { + if (!dataRegion.contains(ucExpr)) { + predicate.add(ucExpr); + } + } + + /* Add the negated of the above expression as the new predicate */ + predicates.add( + ExprSimplifier.simplify( + Not(And(new HashSet<>(predicate))), + ImmutableValuation.empty() + ) + ); + } + } + return ExprTraceStatus.infeasible( + ItpRefutation.sequence( + IntStream.range(0, predicates.size()) + .mapToObj(i -> PathUtils.foldin(predicates.get(i), indexings.get(i))) + .collect(Collectors.toUnmodifiableList()) + ) + ); + } + + private List> calculateWpStates( + final Trace trace, + final List indexings + ) { + final int stateCount = trace.getStates().size(); + final List> wps = new ArrayList<>(Collections.nCopies(stateCount, null)); + + var wpstate = WpState.of(target); + wps.set(stateCount - 1, target); + for(var i = stateCount - 1; i > 0; i--) { + var action = trace.getAction(i - 1); + + for(var stmt : Lists.reverse(action.getStmts())) { + wpstate = wpstate.wep(stmt); + } + + wps.set(i - 1, PathUtils.unfold(wpstate.getExpr(), indexings.get(i - 1))); + } + + return wps; + } + + private Trace flattenTrace(final Trace trace) { + final var stateCount = trace.getStates().size(); + final var flattenedActions = new ArrayList(stateCount - 1); + + for(var i = 1; i < stateCount; i++) { + var initStream = + (i == 1) + ? ExprUtils.getConjuncts(init).stream().map(AssumeStmt::of) + : Stream.empty(); + + var stateStream = ExprUtils.getConjuncts(trace.getState(i - 1).toExpr()).stream().map(AssumeStmt::of); + + var actionStream = trace.getAction(i - 1).getStmts().stream(); + + var targetStream = + (i == stateCount - 1) + ? Stream.concat( + ExprUtils.getConjuncts(trace.getState(i).toExpr()).stream().map(AssumeStmt::of), + ExprUtils.getConjuncts(target).stream().map(AssumeStmt::of) + ) + : Stream.empty(); + + flattenedActions.add( + UCBAction.of( + Stream.of(initStream, stateStream, actionStream, targetStream).flatMap(e -> e).collect(toList()) + ) + ); + } + + return ExprTraceUtils.traceFrom(flattenedActions); + } + + /* + * Custom StmtAction to use when constructing helper traces + */ + + private static class UCBAction extends StmtAction { + private final List stmts; + + private UCBAction(List stmts) { + this.stmts = stmts; + } + + public static UCBAction of(List stmts) { + return new UCBAction(stmts); + } + + @Override + public List getStmts() { + return stmts; + } + + @Override + public String toString() { + return Utils.lispStringBuilder(getClass().getSimpleName()).body().addAll(stmts).toString(); + } + } +} diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java index 7dff233ca1..5321992d04 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java @@ -13,7 +13,17 @@ import hu.bme.mit.theta.core.model.BasicSubstitution; import hu.bme.mit.theta.core.model.ImmutableValuation; import hu.bme.mit.theta.core.model.Valuation; -import hu.bme.mit.theta.core.stmt.*; +import hu.bme.mit.theta.core.stmt.AssignStmt; +import hu.bme.mit.theta.core.stmt.AssumeStmt; +import hu.bme.mit.theta.core.stmt.HavocStmt; +import hu.bme.mit.theta.core.stmt.IfStmt; +import hu.bme.mit.theta.core.stmt.LoopStmt; +import hu.bme.mit.theta.core.stmt.NonDetStmt; +import hu.bme.mit.theta.core.stmt.OrtStmt; +import hu.bme.mit.theta.core.stmt.SequenceStmt; +import hu.bme.mit.theta.core.stmt.SkipStmt; +import hu.bme.mit.theta.core.stmt.Stmt; +import hu.bme.mit.theta.core.stmt.StmtVisitor; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.Type; import hu.bme.mit.theta.core.type.booltype.BoolType; @@ -25,12 +35,14 @@ import hu.bme.mit.theta.core.utils.VarIndexing; import hu.bme.mit.theta.core.utils.WpState; import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.utils.WithPushPop; -import java.util.*; - -import hu.bme.mit.theta.common.container.Containers; - +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -53,7 +65,7 @@ public class ExprTraceNewtonChecker implements ExprTraceChecker { private enum AssertionGeneratorMethod { SP, WP } - private final Solver solver; + private final UCSolver solver; private final Expr init; private final Expr target; @@ -62,7 +74,7 @@ private enum AssertionGeneratorMethod { SP, WP } private final boolean LV; // Whether to project the assertions to live variables private ExprTraceNewtonChecker( - final Expr init, final Expr target, final Solver solver, + final Expr init, final Expr target, final UCSolver solver, boolean it, AssertionGeneratorMethod sPorWP, boolean lv ) { this.solver = checkNotNull(solver); @@ -74,7 +86,7 @@ private ExprTraceNewtonChecker( } public static ExprTraceNewtonCheckerITBuilder create( - final Expr init, final Expr target, final Solver solver + final Expr init, final Expr target, final UCSolver solver ) { return new ExprTraceNewtonCheckerITBuilder(solver, init, target); } @@ -145,8 +157,8 @@ public String toString() { for(var i = 1; i < stateCount; i++) { var initStream = (i == 1) - ? ExprUtils.getConjuncts(init).stream().map(AssumeStmt::of) - : Stream.empty(); + ? ExprUtils.getConjuncts(init).stream().map(AssumeStmt::of) + : Stream.empty(); var stateStream = ExprUtils.getConjuncts(trace.getState(i - 1).toExpr()).stream().map(AssumeStmt::of); @@ -154,11 +166,11 @@ public String toString() { var targetStream = (i == stateCount - 1) - ? Stream.concat( + ? Stream.concat( ExprUtils.getConjuncts(trace.getState(i).toExpr()).stream().map(AssumeStmt::of), ExprUtils.getConjuncts(target).stream().map(AssumeStmt::of) ) - : Stream.empty(); + : Stream.empty(); flattenedActions.add( NewtonAction.of( @@ -355,7 +367,7 @@ private List> computeAssertionsFromTraceWithWeakestPrecondition( */ private Collection> collectVariablesInTrace(final Trace trace) { - Set> variables = Containers.createSet(); + var variables = new HashSet>(); for(var state : trace.getStates()) { ExprUtils.collectVars(state.toExpr(), variables); @@ -405,10 +417,14 @@ public Collection> visit(OrtStmt stmt, Void param) { } @Override - public Collection> visit(LoopStmt stmt, Void param) { throw new UnsupportedOperationException(); } + public Collection> visit(LoopStmt stmt, Void param) { + throw new UnsupportedOperationException(); + } @Override - public Collection> visit(IfStmt stmt, Void param) { throw new UnsupportedOperationException(); } + public Collection> visit(IfStmt stmt, Void param) { + throw new UnsupportedOperationException(); + } }, null); } @@ -450,10 +466,14 @@ public Collection> visit(OrtStmt stmt, Void param) { } @Override - public Collection> visit(LoopStmt stmt, Void param) { throw new UnsupportedOperationException(); } + public Collection> visit(LoopStmt stmt, Void param) { + throw new UnsupportedOperationException(); + } @Override - public Collection> visit(IfStmt stmt, Void param) { throw new UnsupportedOperationException(); } + public Collection> visit(IfStmt stmt, Void param) { + throw new UnsupportedOperationException(); + } }, null); } @@ -495,10 +515,14 @@ public Collection> visit(OrtStmt stmt, Void param) { } @Override - public Collection> visit(LoopStmt stmt, Void param) { throw new UnsupportedOperationException(); } + public Collection> visit(LoopStmt stmt, Void param) { + throw new UnsupportedOperationException(); + } @Override - public Collection> visit(IfStmt stmt, Void param) { throw new UnsupportedOperationException(); } + public Collection> visit(IfStmt stmt, Void param) { + throw new UnsupportedOperationException(); + } }, null); } @@ -520,7 +544,7 @@ private List>> collectFutureLiveVariablesForTrace(final Tr futureLiveVariables.set(stateCount - 1, Collections.emptySet()); for(var i = stateCount - 2; i >= 0; i--) { - var vars = Containers.createSet(futureLiveVariables.get(i + 1)); + var vars = new HashSet<>(futureLiveVariables.get(i + 1)); vars.addAll(actionReadsVariables(trace.getAction(i))); vars.removeAll(actionWritesVariables(trace.getAction(i))); vars.removeAll(actionHavocsVariables(trace.getAction(i))); @@ -536,7 +560,7 @@ private List>> collectPastLiveVariablesForTrace(final Trac pastLiveVariables.set(0, Collections.emptySet()); for(var i = 1; i < stateCount; i++) { - var vars = Containers.createSet(pastLiveVariables.get(i - 1)); + var vars = new HashSet<>(pastLiveVariables.get(i - 1)); vars.addAll(actionReadsVariables(trace.getAction(i - 1))); vars.addAll(actionWritesVariables(trace.getAction(i - 1))); vars.removeAll(actionHavocsVariables(trace.getAction(i - 1))); @@ -580,8 +604,8 @@ private Expr universalProjection( .collect(Collectors.toUnmodifiableSet()); var substitution = BasicSubstitution.builder() - .putAll(params.stream().collect(toUnmodifiableMap(Tuple2::get1, e -> e.get2().getRef()))) - .build(); + .putAll(params.stream().collect(toUnmodifiableMap(Tuple2::get1, e -> e.get2().getRef()))) + .build(); return params.size() > 0 ? Forall(params.stream().map(Tuple2::get2).collect(toList()), substitution.apply(expr)) @@ -593,11 +617,11 @@ private Expr universalProjection( */ public static class ExprTraceNewtonCheckerITBuilder { - private final Solver solver; + private final UCSolver solver; private final Expr init; private final Expr target; - public ExprTraceNewtonCheckerITBuilder(Solver solver, Expr init, Expr target) { + public ExprTraceNewtonCheckerITBuilder(UCSolver solver, Expr init, Expr target) { this.solver = solver; this.init = init; this.target = target; @@ -613,13 +637,13 @@ public ExprTraceNewtonCheckerAssertBuilder withoutIT() { } public static class ExprTraceNewtonCheckerAssertBuilder { - private final Solver solver; + private final UCSolver solver; private final Expr init; private final Expr target; private final boolean IT; - public ExprTraceNewtonCheckerAssertBuilder(Solver solver, Expr init, Expr target, boolean it) { + public ExprTraceNewtonCheckerAssertBuilder(UCSolver solver, Expr init, Expr target, boolean it) { this.solver = solver; this.init = init; this.target = target; @@ -636,14 +660,14 @@ public ExprTraceNewtonCheckerLVBuilder withWP() { } public static class ExprTraceNewtonCheckerLVBuilder { - private final Solver solver; + private final UCSolver solver; private final Expr init; private final Expr target; private final boolean IT; private final AssertionGeneratorMethod SPorWP; - public ExprTraceNewtonCheckerLVBuilder(Solver solver, Expr init, Expr target, boolean it, AssertionGeneratorMethod sPorWP) { + public ExprTraceNewtonCheckerLVBuilder(UCSolver solver, Expr init, Expr target, boolean it, AssertionGeneratorMethod sPorWP) { this.solver = solver; this.init = init; this.target = target; From 93eb3837bcbe396d63398ec14a010820b1ce3c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 12 Sep 2020 19:07:10 +0200 Subject: [PATCH 46/99] Extract common functionality to BaseSmtLibSolverInstaller --- .../smtlib/BaseSmtLibSolverInstaller.java | 202 ++++++++++++++++++ .../generic/GenericSmtLibSolverInstaller.java | 140 +++--------- 2 files changed, 233 insertions(+), 109 deletions(-) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java new file mode 100644 index 0000000000..bd16bc2a96 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java @@ -0,0 +1,202 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public abstract class BaseSmtLibSolverInstaller implements SmtLibSolverInstaller { + protected final Logger logger; + + public BaseSmtLibSolverInstaller(final Logger logger) { + this.logger = logger; + } + + @Override + public final void install(Path home, String version, String name) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + checkName(name); + + final var installDir = getInstallDir(home, name); + if(Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("There is already a solver instance with this name installed"); + } + + try { + logger.write(Logger.Level.MAINSTEP, "Beginning installation...\n"); + + Files.createDirectory(installDir); + + installSolver(installDir, version); + + final var solverArgsPath = argsFile(installDir); + Files.writeString(solverArgsPath, String.join("\n", getDefaultSolverArgs(version)), StandardCharsets.UTF_8); + + final var solverInfoPath = infoFile(installDir); + Files.writeString( + solverInfoPath, + String.format("solver=%s\n", getSolverName()) + + String.format("version=%s\n", version) + + String.format("name=%s\n", name), + StandardCharsets.UTF_8 + ); + + logger.write(Logger.Level.MAINSTEP, "Installation finished"); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public final void uninstall(Path home, String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final var installDir = getInstallDir(home, version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + try { + logger.write(Logger.Level.MAINSTEP, "Beginning uninstallation...\n"); + + uninstallSolver(installDir, version); + + final var solverArgsPath = argsFile(installDir); + Files.delete(solverArgsPath); + + final var solverInfoPath = infoFile(installDir); + Files.delete(solverInfoPath); + + Files.delete(installDir); + + logger.write(Logger.Level.MAINSTEP, "Uninstallation finished"); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public void reinstall(Path home, String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final String solverVersion; + try { + final var installDir = getInstallDir(home, version); + final var solverInfoPath = infoFile(installDir); + final var solverInfo = Files + .readAllLines(solverInfoPath, StandardCharsets.UTF_8).stream() + .filter(l -> l.startsWith("version=")) + .map(l -> l.substring("version=".length())) + .findAny(); + + if(solverInfo.isPresent()) { + solverVersion = solverInfo.get(); + } + else { + throw new SmtLibSolverInstallerException("The solver installation is corrupted"); + } + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + + uninstall(home, version); + install(home, solverVersion, version); + } + + @Override + public final String getInfo(Path home, String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final var installDir = getInstallDir(home, version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + try { + final var solverInfoPath = infoFile(installDir); + final var solverInfoStr = Files.readAllLines(solverInfoPath, StandardCharsets.UTF_8).get(0); + final var solverArgsPath = argsFile(installDir); + final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); + + return solverInfoStr + String.format("args=%s\n", String.join(" ", solverArgs)); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public final Path getArgsFile(Path home, String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final var installDir = home.resolve(version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + return argsFile(installDir); + } + + @Override + public final List getInstalledVersions(Path home) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + + final var installedDirs = home.toFile() + .list((current, name) -> new File(current, name).isDirectory()); + + assert installedDirs != null; + return Arrays.asList(installedDirs); + } + + protected abstract String getSolverName() throws SmtLibSolverInstallerException; + protected abstract void installSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException; + protected abstract void uninstallSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException; + protected abstract String[] getDefaultSolverArgs(final String version) throws SmtLibSolverInstallerException; + + protected final void checkName(final String version) throws SmtLibSolverInstallerException { + if(!version.matches("^[a-zA-Z0-9_.-]+$")) { + throw new SmtLibSolverInstallerException("Unsupported name format: " + version); + } + } + + protected final void checkVersion(final String version) throws SmtLibSolverInstallerException { + if(!version.matches("^[a-zA-Z0-9_.-]+$")) { + throw new SmtLibSolverInstallerException("Unsupported version format: " + version); + } + } + + protected final Path getInstallDir(final Path home, final String version) { + return home.resolve(version); + } + + protected final Path argsFile(final Path installDir) { + return installDir.resolve("solver-args.txt"); + } + + protected final Path infoFile(final Path installDir) { + return installDir.resolve("solver-info.txt"); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java index 625c686705..fd11044336 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java @@ -2,61 +2,55 @@ import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.BaseSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; -import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; import java.util.Collections; import java.util.List; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; -public final class GenericSmtLibSolverInstaller implements SmtLibSolverInstaller { - final Logger logger; +public final class GenericSmtLibSolverInstaller extends BaseSmtLibSolverInstaller { + private Path solverPath; + private String[] solverArgs; - public GenericSmtLibSolverInstaller(Logger logger) { - this.logger = logger; + public GenericSmtLibSolverInstaller(final Logger logger) { + super(logger); } @Override - public void install(final Path home, final String version, String name) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkVersion(version); - checkVersion(name); - throw new SmtLibSolverInstallerException("Unsupported operation for generic solvers"); + protected String getSolverName() { + return "generic"; } public void install(final Path home, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkVersion(version); - checkArgument(Files.exists(solverPath)); - checkNotNull(solverArgs); - - final var installDir = home.resolve(version); - if(Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("The version is already installed"); - } + this.solverPath = solverPath; + this.solverArgs = solverArgs; + super.install(home, version, version); + } + @Override + protected void installSolver(Path installDir, String version) throws SmtLibSolverInstallerException { + checkState(solverPath != null); try { - logger.write(Logger.Level.MAINSTEP, "Beginning installation...\n"); - - Files.createDirectory(installDir); - final var solverFilePath = solverFile(installDir); Files.writeString(solverFilePath, solverPath.toAbsolutePath().toString(), StandardCharsets.UTF_8); - final var solverArgsPath = argsFile(installDir); - Files.writeString(solverArgsPath, String.join("\n", solverArgs), StandardCharsets.UTF_8); + final var solverInfoPath = infoFile(installDir); + final var info = Files.readString(solverInfoPath, StandardCharsets.UTF_8); + Files.writeString( + solverInfoPath, + info + String.format("binary=%s\n", solverPath.toAbsolutePath().toString()), + StandardCharsets.UTF_8 + ); - logger.write(Logger.Level.MAINSTEP, "Installation finished"); + solverPath = null; } catch (IOException e) { throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); @@ -64,32 +58,14 @@ public void install(final Path home, final String version, final Path solverPath } @Override - public void uninstall(final Path home, final String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkVersion(version); - - final var installDir = home.resolve(version); - if(!Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("The version is not installed"); - } - + protected void uninstallSolver(Path installDir, String version) throws SmtLibSolverInstallerException { try { - logger.write(Logger.Level.MAINSTEP, "Beginning uninstallation...\n"); - final var solverFilePath = solverFile(installDir); Files.delete(solverFilePath); - final var solverArgsPath = argsFile(installDir); - Files.delete(solverArgsPath); - - Files.delete(installDir); - - logger.write(Logger.Level.MAINSTEP, "Uninstallation finished"); } catch (IOException e) { throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); } - } @Override @@ -100,46 +76,6 @@ public void reinstall(final Path home, final String version) throws SmtLibSolver throw new SmtLibSolverInstallerException("Unsupported operation for generic solvers"); } - @Override - public String getInfo(final Path home, final String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkVersion(version); - - final var installDir = home.resolve(version); - if(!Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("The version is not installed"); - } - - try { - final var solverFilePath = solverFile(installDir); - final var solverPathStr = Files.readAllLines(solverFilePath, StandardCharsets.UTF_8).get(0); - final var solverArgsPath = argsFile(installDir); - final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); - - return "Generic solver" + - "Solver binary: " + solverPathStr + - "Arguments: " + String.join(" ", solverArgs); - } - catch (IOException e) { - throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); - } - } - - @Override - public Path getArgsFile(final Path home, final String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkVersion(version); - - final var installDir = home.resolve(version); - if(!Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("The version is not installed"); - } - - return argsFile(installDir); - } - @Override public SolverFactory getSolverFactory(final Path home, final String version) throws SmtLibSolverInstallerException { checkNotNull(home); @@ -165,33 +101,19 @@ public SolverFactory getSolverFactory(final Path home, final String version) thr } @Override - public List getSupportedVersions() throws SmtLibSolverInstallerException { + public List getSupportedVersions() { return Collections.emptyList(); } @Override - public List getInstalledVersions(final Path home) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - - final var installedDirs = home.toFile() - .list((current, name) -> new File(current, name).isDirectory()); - - assert installedDirs != null; - return Arrays.asList(installedDirs); - } - - private void checkVersion(final String version) throws SmtLibSolverInstallerException { - if(!version.matches("^[a-zA-Z0-9_.-]+$")) { - throw new SmtLibSolverInstallerException("Unsupported version format: " + version); - } + protected String[] getDefaultSolverArgs(String version) { + checkState(solverArgs != null); + final var tmp = solverArgs; + solverArgs = null; + return tmp; } private Path solverFile(final Path installDir) { return installDir.resolve("solver.txt"); } - - private Path argsFile(final Path installDir) { - return installDir.resolve("solver-args.txt"); - } } From 48831c366433fbcc4f588a0f2357d9d5513ed770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 13 Sep 2020 14:52:31 +0200 Subject: [PATCH 47/99] Add Mac to OsHelper --- .../hu/bme/mit/theta/common/OsHelper.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/OsHelper.java b/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/OsHelper.java index 16320df513..5fb7a52489 100644 --- a/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/OsHelper.java +++ b/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/OsHelper.java @@ -24,7 +24,7 @@ private OsHelper() { } public enum OperatingSystem { - WINDOWS, LINUX + WINDOWS, LINUX, MAC } public static OperatingSystem getOs() { @@ -35,12 +35,31 @@ public static OperatingSystem getOs() { return OperatingSystem.LINUX; } else if (os.toLowerCase().startsWith("windows")) { return OperatingSystem.WINDOWS; + } else if ((os.toLowerCase().contains("mac")) || (os.toLowerCase().contains("darwin"))) { + return OperatingSystem.MAC; } else { throw new UnsupportedOperationException("Operating system \"" + os + "\" not supported."); } } + public enum Architecture { + X86, X64 + } + + public static Architecture getArch() { + final String arch = StandardSystemProperty.OS_ARCH.value(); + + if (arch.toLowerCase().equals("x86")) { + return Architecture.X86; + } else if (arch.toLowerCase().equals("amd64")) { + return Architecture.X64; + } else { + throw new UnsupportedOperationException("Architecture \"" + arch + "\" not supported."); + } + } + public static void main(final String[] args) { System.out.println(getOs()); + System.out.println(getArch()); } } From 0e4ea0af7edbbd2008e6fb71bd0f141ce2164af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 13 Sep 2020 14:52:52 +0200 Subject: [PATCH 48/99] Add SemVer to support decoding of semantic versioning --- .../java/hu/bme/mit/theta/common/SemVer.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 subprojects/common/src/main/java/hu/bme/mit/theta/common/SemVer.java diff --git a/subprojects/common/src/main/java/hu/bme/mit/theta/common/SemVer.java b/subprojects/common/src/main/java/hu/bme/mit/theta/common/SemVer.java new file mode 100644 index 0000000000..d3ea250acf --- /dev/null +++ b/subprojects/common/src/main/java/hu/bme/mit/theta/common/SemVer.java @@ -0,0 +1,86 @@ +package hu.bme.mit.theta.common; + +import java.util.Arrays; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public class SemVer implements Comparable { + private final int[] version; + + private SemVer(final String version) { + checkNotNull(version); + checkArgument(version.matches("[0-9]+(\\.[0-9]+)*")); + + this.version = Arrays.stream(version.split("\\.")).mapToInt(Integer::parseInt).toArray(); + } + + public static SemVer of(final String version) { + return new SemVer(version); + } + + public boolean hasMajor() { + return version.length > 0; + } + + public int getMajor() { + return version[0]; + } + + public boolean hasMinor() { + return version.length > 1; + } + + public int getMinor() { + return version[1]; + } + + public boolean hasPatch() { + return version.length > 2; + } + + public int getPatch() { + return version[2]; + } + + public int[] getAll() { + return version; + } + + @Override + public int compareTo(final SemVer that) { + if(that == null) { + return 1; + } + + for(int i = 0; i < Math.max(this.version.length, that.version.length); i++) { + final var thisVer = i < this.version.length ? this.version[i] : 0; + final var thatVer = i < that.version.length ? that.version[i] : 0; + + if(thisVer < thatVer) { + return -1; + } + else if(thisVer > thatVer) { + return 1; + } + else { + continue; + } + } + + return 0; + } + + @Override + public boolean equals(Object obj) { + if(obj == null) { + return false; + } + else if(obj instanceof SemVer) { + return this.compareTo((SemVer) obj) == 0; + } + else { + return false; + } + } +} From 6a9613704470322d8019e225cdc1bcda1a756ddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 13 Sep 2020 14:53:30 +0200 Subject: [PATCH 49/99] Add z3 support to solver-smtlib --- .../theta/solver/smtlib/cli/SmtLibCli.java | 57 ++-- .../smtlib/BaseSmtLibSolverInstaller.java | 55 ++-- .../smtlib/manager/SmtLibSolverManager.java | 35 ++- .../smtlib/z3/Z3SmtLibSolverInstaller.java | 250 ++++++++++++++++++ 4 files changed, 331 insertions(+), 66 deletions(-) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java diff --git a/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java index 5f36f481f2..5cd0b21204 100644 --- a/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java +++ b/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java @@ -48,16 +48,19 @@ static class InstallCommand { @Parameter(names = "--name", description = "Install the solver version under this custom name (:), instead of the default (:)") String name; + + @Parameter(names = "--tempt-murphy", description = "Allows the installation of unsupported solver version") + boolean temptMurphy = false; } @Parameters(commandDescription = "Installs a generic solver") static class InstallGenericCommand { static final String COMMAND = "install-generic"; - @Parameter(names = "--solverPath", description = "The path of the generic solver to install", required = true) + @Parameter(names = "--solver-path", description = "The path of the generic solver to install", required = true) String solverPath; - @Parameter(names = "--solverArgs", description = "The arguments of the generic solver to invoke with") + @Parameter(names = "--solver-args", description = "The arguments of the generic solver to invoke with") String solverArgs; @Parameter(names = "--name", description = "Install the solver version under this custom name (:), instead of the default (:)", required = true) @@ -167,6 +170,12 @@ private void run() { final var homePath = createIfNotExists(Path.of(mainParams.home)); final var smtLibSolverManager = SmtLibSolverManager.create(homePath, logger); + if(jc.getParsedCommand() == null) { + logger.write(Logger.Level.RESULT, "Missing command\n"); + jc.usage(); + return; + } + switch(jc.getParsedCommand()) { case InstallCommand.COMMAND: { final var solver = decodeVersionString(installCommand.solver, smtLibSolverManager); @@ -177,10 +186,10 @@ private void run() { } if(installCommand.name != null) { - smtLibSolverManager.install(solver.get1(), solver.get2(), installCommand.name); + smtLibSolverManager.install(solver.get1(), solver.get2(), installCommand.name, installCommand.temptMurphy); } else { - smtLibSolverManager.install(solver.get1(), solver.get2(), solver.get2()); + smtLibSolverManager.install(solver.get1(), solver.get2(), solver.get2(), installCommand.temptMurphy); } return; @@ -213,24 +222,12 @@ private void run() { final var solver = decodeVersionString(editArgsCommand.solver, smtLibSolverManager); final var argsFilePath = smtLibSolverManager.getArgsFile(solver.get1(), solver.get2()); - if(smtLibSolverManager.getSupportedVersions(solver.get1()).contains(solver.get2())) { - logger.write(Logger.Level.RESULT, "Supported versions of solvers cannot be edited. If you want to pass custom arguments to a supported solver, install a new instance of the version with a custom name."); - return; - } - - boolean nanoInPath = Stream.of(System.getenv("PATH").split(Pattern.quote(File.pathSeparator))) - .map(Paths::get) - .anyMatch(path -> Files.exists(path.resolve("nano"))); - if(editArgsCommand.print) { logger.write(Logger.Level.RESULT, String.format("%s\n", argsFilePath.toAbsolutePath().toString())); } - else if(Desktop.isDesktopSupported()) { + else if(Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.EDIT)) { Desktop.getDesktop().edit(argsFilePath.toFile()); } - else if(nanoInPath) { - Runtime.getRuntime().exec("nano", new String[] { argsFilePath.toAbsolutePath().toString() }); - } else { logger.write(Logger.Level.MAINSTEP, "Open the following text file in your favourite editor, and edit the content:\n"); logger.write(Logger.Level.RESULT, String.format("%s\n", argsFilePath.toAbsolutePath().toString())); @@ -290,20 +287,7 @@ private static Tuple2 decodeVersionString(final String version, throw new IllegalArgumentException("Invalid version string: " + version); } - final var solver = versionArr[0]; - final var ver = versionArr[1]; - if(!ver.equals("latest")) { - return Tuple2.of(solver, versionArr[1]); - } - else { - final var versions = solverManager.getSupportedVersions(solver); - if(versions.size() > 0) { - return Tuple2.of(solver, versions.get(0)); - } - else { - throw new IllegalArgumentException("There are no supported versions of solver: " + solver); - } - } + return Tuple2.of(versionArr[0], versionArr[1]); } private Path createIfNotExists(final Path path) throws IOException { @@ -314,15 +298,14 @@ private Path createIfNotExists(final Path path) throws IOException { } private void printError(final Throwable ex) { - final String message = ex.getMessage() == null ? "" : ": " + ex.getMessage(); - logger.write(Logger.Level.RESULT, "Exception of type %s occurred%n", ex.getClass().getSimpleName()); - logger.write(Logger.Level.MAINSTEP, "Message:%n%s%n", message); + logger.write(Logger.Level.MAINSTEP, "Exception of type %s occurred%n", ex.getClass().getSimpleName()); + logger.write(Logger.Level.RESULT, "Error:%n%s%n", ex.getMessage()); final StringWriter errors = new StringWriter(); ex.printStackTrace(new PrintWriter(errors)); logger.write(Logger.Level.SUBSTEP, "Trace:%n%s%n", errors.toString()); } - static class SolverNameValidator implements IParameterValidator { + public static class SolverNameValidator implements IParameterValidator { @Override public void validate(String name, String value) throws ParameterException { if(!value.matches("[a-zA-Z0-9]+")) { @@ -333,7 +316,7 @@ public void validate(String name, String value) throws ParameterException { } } - static class SolverNameAndVersionValidator implements IParameterValidator { + public static class SolverNameAndVersionValidator implements IParameterValidator { @Override public void validate(String name, String value) throws ParameterException { final var versionArr = value.split(":"); @@ -342,7 +325,7 @@ public void validate(String name, String value) throws ParameterException { throw new ParameterException(String.format("Invalid version string %s in parameter %s", value, name)); } - if(!versionArr[0].matches("[a-zA-Z0-9]+") || !versionArr[1].matches("[a-zA-Z0-9]+")) { + if(!versionArr[0].matches("[a-zA-Z0-9]+") || !versionArr[1].matches("[a-zA-Z0-9-._]+")) { throw new ParameterException( String.format("Invalid version string %s in parameter %s", value, name) ); diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java index bd16bc2a96..826a340ecc 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java @@ -1,7 +1,6 @@ package hu.bme.mit.theta.solver.smtlib; import hu.bme.mit.theta.common.logging.Logger; -import hu.bme.mit.theta.solver.SolverFactory; import java.io.File; import java.io.IOException; @@ -9,6 +8,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; +import java.util.Collections; import java.util.List; import static com.google.common.base.Preconditions.checkArgument; @@ -52,7 +52,11 @@ public final void install(Path home, String version, String name) throws SmtLibS StandardCharsets.UTF_8 ); - logger.write(Logger.Level.MAINSTEP, "Installation finished"); + logger.write(Logger.Level.MAINSTEP, "Installation finished\n"); + } + catch (SmtLibSolverInstallerException e) { + uninstall(home, version); + throw e; } catch (IOException e) { throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); @@ -63,7 +67,7 @@ public final void install(Path home, String version, String name) throws SmtLibS public final void uninstall(Path home, String version) throws SmtLibSolverInstallerException { checkNotNull(home); checkArgument(Files.exists(home)); - checkVersion(version); + checkName(version); final var installDir = getInstallDir(home, version); if(!Files.exists(installDir)) { @@ -75,15 +79,9 @@ public final void uninstall(Path home, String version) throws SmtLibSolverInstal uninstallSolver(installDir, version); - final var solverArgsPath = argsFile(installDir); - Files.delete(solverArgsPath); - - final var solverInfoPath = infoFile(installDir); - Files.delete(solverInfoPath); + deleteDirectory(installDir.toFile()); - Files.delete(installDir); - - logger.write(Logger.Level.MAINSTEP, "Uninstallation finished"); + logger.write(Logger.Level.MAINSTEP, "Uninstallation finished\n"); } catch (IOException e) { throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); @@ -94,7 +92,7 @@ public final void uninstall(Path home, String version) throws SmtLibSolverInstal public void reinstall(Path home, String version) throws SmtLibSolverInstallerException { checkNotNull(home); checkArgument(Files.exists(home)); - checkVersion(version); + checkName(version); final String solverVersion; try { @@ -125,7 +123,7 @@ public void reinstall(Path home, String version) throws SmtLibSolverInstallerExc public final String getInfo(Path home, String version) throws SmtLibSolverInstallerException { checkNotNull(home); checkArgument(Files.exists(home)); - checkVersion(version); + checkName(version); final var installDir = getInstallDir(home, version); if(!Files.exists(installDir)) { @@ -134,7 +132,7 @@ public final String getInfo(Path home, String version) throws SmtLibSolverInstal try { final var solverInfoPath = infoFile(installDir); - final var solverInfoStr = Files.readAllLines(solverInfoPath, StandardCharsets.UTF_8).get(0); + final var solverInfoStr = Files.readString(solverInfoPath, StandardCharsets.UTF_8); final var solverArgsPath = argsFile(installDir); final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); @@ -149,7 +147,7 @@ public final String getInfo(Path home, String version) throws SmtLibSolverInstal public final Path getArgsFile(Path home, String version) throws SmtLibSolverInstallerException { checkNotNull(home); checkArgument(Files.exists(home)); - checkVersion(version); + checkName(version); final var installDir = home.resolve(version); if(!Files.exists(installDir)) { @@ -162,13 +160,17 @@ public final Path getArgsFile(Path home, String version) throws SmtLibSolverInst @Override public final List getInstalledVersions(Path home) throws SmtLibSolverInstallerException { checkNotNull(home); - checkArgument(Files.exists(home)); - final var installedDirs = home.toFile() - .list((current, name) -> new File(current, name).isDirectory()); + if(Files.exists(home)) { + final var installedDirs = home.toFile() + .list((current, name) -> new File(current, name).isDirectory()); - assert installedDirs != null; - return Arrays.asList(installedDirs); + assert installedDirs != null; + return Arrays.asList(installedDirs); + } + else { + return Collections.emptyList(); + } } protected abstract String getSolverName() throws SmtLibSolverInstallerException; @@ -183,7 +185,7 @@ protected final void checkName(final String version) throws SmtLibSolverInstalle } protected final void checkVersion(final String version) throws SmtLibSolverInstallerException { - if(!version.matches("^[a-zA-Z0-9_.-]+$")) { + if(!version.matches("^[0-9]+(\\.[0-9]+)*$")) { throw new SmtLibSolverInstallerException("Unsupported version format: " + version); } } @@ -199,4 +201,15 @@ protected final Path argsFile(final Path installDir) { protected final Path infoFile(final Path installDir) { return installDir.resolve("solver-info.txt"); } + + private void deleteDirectory(File directoryToBeDeleted) throws IOException { + File[] allContents = directoryToBeDeleted.listFiles(); + if (allContents != null) { + for (File file : allContents) { + deleteDirectory(file); + } + } + + Files.delete(directoryToBeDeleted.toPath()); + } } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java index 454a3b3eb4..c5873d5f7b 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java @@ -7,6 +7,7 @@ import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibSolverInstaller; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -36,6 +37,7 @@ public static void registerGenericInsta } static { + registerInstaller("z3", Z3SmtLibSolverInstaller.class); registerGenericInstaller("generic", GenericSmtLibSolverInstaller.class); } @@ -83,12 +85,15 @@ public String getGenericInstallerName() { return genericInstaller.get1(); } - public void install(final String solver, final String version, final String name) throws SmtLibSolverInstallerException { + public void install(final String solver, final String version, final String name, final boolean installUnsupported) throws SmtLibSolverInstallerException { checkArgument(!solver.equals(genericInstaller.get1())); if(!installers.containsKey(solver)) { throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); } + else if(!getSupportedVersions(solver).contains(getVersionString(solver, version, false)) && !installUnsupported) { + throw new SmtLibSolverInstallerException("Installing unsupported solvers is not enabled"); + } final var installDir = home.resolve(solver); try { @@ -99,7 +104,7 @@ public void install(final String solver, final String version, final String name throw new SmtLibSolverInstallerException(e); } - installers.get(solver).install(installDir, version, name); + installers.get(solver).install(installDir, getVersionString(solver, version, false), getVersionString(solver, name, false)); } public void installGeneric(final String version, final Path solverPath, final String[] args) throws SmtLibSolverInstallerException { @@ -119,7 +124,7 @@ public void uninstall(final String solver, final String version) throws SmtLibSo throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); } - installers.get(solver).uninstall(home.resolve(solver), version); + installers.get(solver).uninstall(home.resolve(solver), getVersionString(solver, version, true)); } public void reinstall(final String solver, final String version) throws SmtLibSolverInstallerException { @@ -127,16 +132,15 @@ public void reinstall(final String solver, final String version) throws SmtLibSo throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); } - installers.get(solver).reinstall(home.resolve(solver), version); + installers.get(solver).reinstall(home.resolve(solver), getVersionString(solver, version, true)); } - public String getInfo(final String solver, final String version) throws SmtLibSolverInstallerException { if(!installers.containsKey(solver)) { throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); } - return installers.get(solver).getInfo(home.resolve(solver), version); + return installers.get(solver).getInfo(home.resolve(solver), getVersionString(solver, version, true)); } public Path getArgsFile(final String solver, final String version) throws SmtLibSolverInstallerException { @@ -144,7 +148,7 @@ public Path getArgsFile(final String solver, final String version) throws SmtLib throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); } - return installers.get(solver).getArgsFile(home.resolve(solver), version); + return installers.get(solver).getArgsFile(home.resolve(solver), getVersionString(solver, version, true)); } public SolverFactory getSolverFactory(final String solver, final String version) throws SmtLibSolverInstallerException { @@ -152,7 +156,7 @@ public SolverFactory getSolverFactory(final String solver, final String version) throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); } - return installers.get(solver).getSolverFactory(home.resolve(solver), version); + return installers.get(solver).getSolverFactory(home.resolve(solver), getVersionString(solver, version, true)); } public List getSupportedSolvers() { @@ -194,4 +198,19 @@ public List getInstalledVersions(final String solver) throws SmtLibSolve return installers.get(solver).getInstalledVersions(home.resolve(solver)); } + + private String getVersionString(final String solver, final String version, final boolean installed) throws SmtLibSolverInstallerException { + if(!version.equals("latest")) { + return version; + } + else { + final var versions = installed ? getInstalledVersions(solver) : getSupportedVersions(solver); + if(versions.size() > 0) { + return versions.get(0); + } + else { + throw new IllegalArgumentException("There are no supported versions of solver: " + solver); + } + } + } } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java new file mode 100644 index 0000000000..5239f45b53 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java @@ -0,0 +1,250 @@ +package hu.bme.mit.theta.solver.smtlib.z3; + +import hu.bme.mit.theta.common.OsHelper; +import hu.bme.mit.theta.common.SemVer; +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.BaseSmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; + +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; +import static hu.bme.mit.theta.common.OsHelper.Architecture.X86; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.MAC; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; + +public class Z3SmtLibSolverInstaller extends BaseSmtLibSolverInstaller { + private final List versions; + + public Z3SmtLibSolverInstaller(final Logger logger) { + super(logger); + + versions = new ArrayList<>(); + versions.add(VersionDecoder.create(SemVer.of("4.8.5")) + .addString(LINUX, X64, "x64-ubuntu-16.04") + .addString(WINDOWS, X64, "x64-win") + .addString(WINDOWS, X86, "x86-win") + .addString(MAC, X64, "x64-osx-10.14.6") + .build() + ); + versions.add(VersionDecoder.create(SemVer.of("4.8.5")) + .addString(LINUX, X64, "x64-ubuntu-16.04") + .addString(WINDOWS, X64, "x64-win") + .addString(WINDOWS, X86, "x86-win") + .addString(MAC, X64, "x64-osx-10.14.2") + .build() + ); + versions.add(VersionDecoder.create(SemVer.of("4.8.4")) + .addString(LINUX, X64, "x64-ubuntu-16.04") + .addString(WINDOWS, X64, "x64-win") + .addString(WINDOWS, X86, "x86-win") + .addString(MAC, X64, "x64-osx-10.14.1") + .build() + ); + versions.add(VersionDecoder.create(SemVer.of("4.8.3")) + .addString(LINUX, X64, "x64-ubuntu-16.04") + .addString(WINDOWS, X64, "x64-win") + .addString(WINDOWS, X86, "x86-win") + .addString(MAC, X64, "x64-osx-10.13.6") + .build() + ); + versions.add(VersionDecoder.create(SemVer.of("4.6.0")) + .addString(LINUX, X64, "x64-ubuntu-16.04") + .addString(WINDOWS, X64, "x64-win") + .addString(WINDOWS, X86, "x86-win") + .addString(MAC, X64, "x64-osx-10.11.6") + .build() + ); + versions.add(VersionDecoder.create(SemVer.of("4.4.0")) + .addString(LINUX, X64, "x64-ubuntu-14.04") + .addString(LINUX, X86, "x86-ubuntu-14.04") + .addString(WINDOWS, X64, "x64-win") + .addString(WINDOWS, X86, "x86-win") + .addString(MAC, X64, "x64-osx-10.11.6") + .build() + ); + versions.add(VersionDecoder.create(SemVer.of("4.3.2")) + .addString(WINDOWS, X64, "x64-win") + .addString(WINDOWS, X86, "x86-win") + .build() + ); + } + + @Override + protected String getSolverName() { + return "z3"; + } + + @Override + protected void installSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException { + final var semVer = SemVer.of(version); + String archStr = null; + + for(final var versionDecoder : versions) { + if(semVer.compareTo(versionDecoder.getVersion()) >= 0) { + archStr = versionDecoder.getOsArchString(OsHelper.getOs(), OsHelper.getArch()); + break; + } + } + if(archStr == null) { + throw new SmtLibSolverInstallerException(String.format("z3 on operating system %s and architecture %s is not supported", OsHelper.getOs(), OsHelper.getArch())); + } + + final var downloadUrl = URI.create(String.format( + "https://github.com/Z3Prover/z3/releases/download/z3-%s/z3-%s-%s.zip", + version, version, archStr + )); + + logger.write(Logger.Level.MAINSTEP, "Starting download (%s)...\n", downloadUrl.toString()); + try(final var zipInputStream = new ZipInputStream(downloadUrl.toURL().openStream())) { + unzip(zipInputStream, installDir); + installDir.resolve("bin").resolve(getSolverBinaryName()).toFile().setExecutable(true, true); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(e); + } + + + + logger.write(Logger.Level.MAINSTEP, "Download finished\n"); + } + + @Override + protected void uninstallSolver(Path installDir, String version) { } + + @Override + protected String[] getDefaultSolverArgs(String version) { + return new String[] { "-smt2", "-in" }; + } + + @Override + public SolverFactory getSolverFactory(final Path home, final String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final var installDir = home.resolve(version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + try { + final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); + final var solverArgsPath = argsFile(installDir); + final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); + + return GenericSmtLibSolverFactory.create(solverFilePath, solverArgs); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public List getSupportedVersions() { + return Arrays.asList( + "4.8.9", "4.8.8", "4.8.7", "4.8.6", "4.8.5", "4.8.4", "4.8.3", "4.8.2", "4.8.1", + "4.7.1", "4.6.0", "4.5.0", "4.4.1", "4.4.0", "4.3.2" + ); + } + + private String getSolverBinaryName() { + switch(OsHelper.getOs()) { + case WINDOWS: + return "z3.exe"; + case LINUX: + return "z3"; + case MAC: + return "z3.dmg"; + default: + throw new AssertionError(); + } + } + + private static void unzip(final ZipInputStream zipInputStream, final Path installDir) throws SmtLibSolverInstallerException { + try { + for(ZipEntry entry = zipInputStream.getNextEntry(); entry != null; entry = zipInputStream.getNextEntry()) { + final var entryPath = Path.of(entry.getName()); + final var entryResolvedPath = installDir.resolve(entryPath.subpath(1, entryPath.getNameCount())); + if(entry.isDirectory()) { + Files.createDirectories(entryResolvedPath); + } + else { + Files.createDirectories(entryResolvedPath.getParent()); + Files.copy(zipInputStream, entryResolvedPath); + } + } + } + catch(IOException e) { + throw new SmtLibSolverInstallerException(e.getMessage(), e); + } + } + + private static class VersionDecoder { + private final SemVer version; + private final Map> string; + + private VersionDecoder(final SemVer version, final Map> string) { + this.version = version; + this.string = string; + } + + public static Builder create(final SemVer version) { + return new Builder(version); + } + + public SemVer getVersion() { + return version; + } + + public String getOsArchString(final OsHelper.OperatingSystem os, final OsHelper.Architecture arch) throws SmtLibSolverInstallerException { + if(!string.containsKey(os)) { + throw new SmtLibSolverInstallerException(String.format("Operating system %s is not supported by z3", os)); + } + else if(!string.get(os).containsKey(arch)) { + throw new SmtLibSolverInstallerException(String.format("Architecture %s on operating system %s is not supported by z3", arch, os)); + } + else { + return string.get(os).get(arch); + } + } + + public static class Builder { + private final SemVer version; + private final Map> string; + + private Builder(final SemVer version) { + this.version = version; + this.string = new HashMap<>(); + } + + public Builder addString(final OsHelper.OperatingSystem os, final OsHelper.Architecture arch, final String string) { + if(!this.string.containsKey(os)) { + this.string.put(os, new HashMap<>()); + } + this.string.get(os).put(arch, string); + return this; + } + + public VersionDecoder build() { + return new VersionDecoder(version, string); + } + } + } +} From 1164360c75b6b48fa8cb2a9d8b3b8d25bed3ab18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 13 Sep 2020 14:53:57 +0200 Subject: [PATCH 50/99] Modify smtlib tests to use latest z3 for testing --- .../generic/GenericSmtLibTermTransformer.java | 4 ++- .../solver/smtlib/SmtLibSolverBVTest.java | 25 +++++++++++++++---- .../theta/solver/smtlib/SmtLibSolverTest.java | 21 +++++++++++----- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java index 170606e74c..e432b1a6e9 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java @@ -65,6 +65,7 @@ import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; import hu.bme.mit.theta.core.type.bvtype.BvZExtExpr; import hu.bme.mit.theta.core.type.functype.FuncExprs; +import hu.bme.mit.theta.core.type.functype.FuncLitExpr; import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; import hu.bme.mit.theta.core.utils.BvUtils; @@ -465,7 +466,8 @@ protected Expr transformIdentifier(final IdentifierContext ctx, final SmtLibM if(ctx.symbol().getText().equals("as-array")) { final var name = ctx.index().get(0).getText(); - return toExpr(model.getTerm(name), model); + final var funcLit = (FuncLitExpr) toFuncLitExpr(model.getTerm(name), model); + return funcLit.getResult(); } else { return transformSymbol(ctx.symbol(), model, vars); diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java index 5c68bf8907..1d8b6445e4 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java @@ -5,13 +5,18 @@ import hu.bme.mit.theta.core.type.abstracttype.EqExpr; import hu.bme.mit.theta.core.utils.BvTestUtils; import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Collection; import java.util.stream.Collectors; @@ -24,6 +29,8 @@ @RunWith(Parameterized.class) public class SmtLibSolverBVTest { + private static SmtLibSolverManager solverManager; + @Parameterized.Parameter(0) public Class exprType; @@ -33,10 +40,18 @@ public class SmtLibSolverBVTest { @Parameterized.Parameter(2) public Expr actual; - private static final SmtLibSolverManager solverManager = SmtLibSolverManager.create( - Path.of(System.getProperty("user.home")).resolve(".theta"), - NullLogger.getInstance() - ); + @BeforeClass + public static void init() throws SmtLibSolverInstallerException, IOException { + Path home = Files.createTempDirectory("theta-solver"); + + solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); + solverManager.install("z3", "latest", "latest", false); + } + + @AfterClass + public static void destroy() throws SmtLibSolverInstallerException { + solverManager.uninstall("z3", "latest"); + } @Parameters(name = "expr: {0}, expected: {1}, actual: {2}") public static Collection operations() { @@ -68,7 +83,7 @@ public void testOperationEquals() throws SmtLibSolverInstallerException { ); // Equality check - final Solver solver = solverManager.getSolverFactory("generic", "cvc4").createSolver(); + final Solver solver = solverManager.getSolverFactory("z3", "latest").createSolver(); solver.push(); solver.add(EqExpr.create2(expected, actual)); diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index 75b7bcd853..4af13d2a9e 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -25,9 +25,12 @@ import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSymbolTable; import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTermTransformer; import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Map; @@ -49,16 +52,22 @@ import static org.junit.Assert.assertTrue; public final class SmtLibSolverTest { + private static SmtLibSolverManager solverManager; private static SolverFactory solverFactory; @BeforeClass - public static void init() throws SmtLibSolverInstallerException { - final var solverManager = SmtLibSolverManager.create( - Path.of(System.getProperty("user.home")).resolve(".theta"), - NullLogger.getInstance() - ); + public static void init() throws SmtLibSolverInstallerException, IOException { + Path home = Files.createTempDirectory("theta-solver"); + + solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); + solverManager.install("z3", "latest", "latest", false); + + solverFactory = solverManager.getSolverFactory("z3", "latest"); + } - solverFactory = solverManager.getSolverFactory("generic", "cvc4"); + @AfterClass + public static void destroy() throws SmtLibSolverInstallerException { + solverManager.uninstall("z3", "latest"); } @Test From 630a89c13d0815a553f8e9db3a87eacc48479e02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 13 Sep 2020 17:43:41 +0200 Subject: [PATCH 51/99] Add cvc4 support to solver-smtlib --- .../theta/solver/smtlib/cli/SmtLibCli.java | 49 +++--- .../cvc4/CVC4SmtLibSolverInstaller.java | 141 ++++++++++++++++++ .../smtlib/manager/SmtLibSolverManager.java | 4 +- .../smtlib/z3/Z3SmtLibSolverInstaller.java | 2 - 4 files changed, 174 insertions(+), 22 deletions(-) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java diff --git a/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java index 5cd0b21204..d95e5520ea 100644 --- a/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java +++ b/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java @@ -12,15 +12,11 @@ import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; import java.awt.Desktop; -import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.regex.Pattern; -import java.util.stream.Stream; public class SmtLibCli { private static final String JAR_NAME = "theta-solver-smtlib-cli.jar"; @@ -35,7 +31,10 @@ static class MainParams { @Parameter(names = "--loglevel", description = "Detailedness of logging") Logger.Level logLevel = Logger.Level.MAINSTEP; - @Parameter(names = "--help", help = true) + @Parameter(names = "--stacktrace", description = "Prints the stacktrace in case of an error") + private boolean stacktrace = false; + + @Parameter(names = "--help", help = true, description = "Prints this help message") private boolean help = false; } @@ -178,7 +177,7 @@ private void run() { switch(jc.getParsedCommand()) { case InstallCommand.COMMAND: { - final var solver = decodeVersionString(installCommand.solver, smtLibSolverManager); + final var solver = decodeVersionString(installCommand.solver); if(solver.get1().equals(smtLibSolverManager.getGenericInstallerName())) { logger.write(Logger.Level.RESULT, "To install a generic solver, use the \"%s\" command", InstallGenericCommand.COMMAND); @@ -203,23 +202,23 @@ private void run() { return; } case UninstallCommand.COMMAND: { - final var solver = decodeVersionString(uninstallCommand.solver, smtLibSolverManager); + final var solver = decodeVersionString(uninstallCommand.solver); smtLibSolverManager.uninstall(solver.get1(), solver.get2()); return; } case ReinstallCommand.COMMAND: { - final var solver = decodeVersionString(reinstallCommand.solver, smtLibSolverManager); + final var solver = decodeVersionString(reinstallCommand.solver); smtLibSolverManager.reinstall(solver.get1(), solver.get2()); return; } case GetInfoCommand.COMMAND: { - final var solver = decodeVersionString(getInfoCommand.solver, smtLibSolverManager); + final var solver = decodeVersionString(getInfoCommand.solver); final var info = smtLibSolverManager.getInfo(solver.get1(), solver.get2()); logger.write(Logger.Level.RESULT, "%s\n", info); return; } case EditArgsCommand.COMMAND: { - final var solver = decodeVersionString(editArgsCommand.solver, smtLibSolverManager); + final var solver = decodeVersionString(editArgsCommand.solver); final var argsFilePath = smtLibSolverManager.getArgsFile(solver.get1(), solver.get2()); if(editArgsCommand.print) { @@ -275,12 +274,19 @@ else if(Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop return; } } - } catch (SmtLibSolverInstallerException | IOException e) { - printError(e); + } + catch (SmtLibSolverInstallerException e) { + logger.write(Logger.Level.RESULT, "%s\n", e.getMessage()); + if(mainParams.stacktrace) { + printError(e, true); + } + } + catch (IOException e) { + printError(e, mainParams.stacktrace); } } - private static Tuple2 decodeVersionString(final String version, final SmtLibSolverManager solverManager) throws SmtLibSolverInstallerException { + private static Tuple2 decodeVersionString(final String version) { final var versionArr = version.split(":"); if(versionArr.length != 2) { @@ -297,12 +303,17 @@ private Path createIfNotExists(final Path path) throws IOException { return path; } - private void printError(final Throwable ex) { - logger.write(Logger.Level.MAINSTEP, "Exception of type %s occurred%n", ex.getClass().getSimpleName()); - logger.write(Logger.Level.RESULT, "Error:%n%s%n", ex.getMessage()); - final StringWriter errors = new StringWriter(); - ex.printStackTrace(new PrintWriter(errors)); - logger.write(Logger.Level.SUBSTEP, "Trace:%n%s%n", errors.toString()); + private void printError(final Throwable ex, final boolean printStackTrace) { + final String message = ex.getMessage() == null ? "" : ex.getMessage(); + logger.write(Logger.Level.RESULT, "%s occurred, message: %s%n", ex.getClass().getSimpleName(), message); + if (printStackTrace) { + final StringWriter errors = new StringWriter(); + ex.printStackTrace(new PrintWriter(errors)); + logger.write(Logger.Level.RESULT, "Trace:%n%s%n", errors.toString()); + } + else { + logger.write(Logger.Level.RESULT, "Use --stacktrace for stack trace%n"); + } } public static class SolverNameValidator implements IParameterValidator { diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java new file mode 100644 index 0000000000..cca24fac80 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java @@ -0,0 +1,141 @@ +package hu.bme.mit.theta.solver.smtlib.cvc4; + +import hu.bme.mit.theta.common.OsHelper; +import hu.bme.mit.theta.common.SemVer; +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.BaseSmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; + +public class CVC4SmtLibSolverInstaller extends BaseSmtLibSolverInstaller { + + public CVC4SmtLibSolverInstaller(final Logger logger) { + super(logger); + } + + @Override + protected String getSolverName() { + return "cvc4"; + } + + @Override + protected void installSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException { + + try( + final var inputChannel = Channels.newChannel(getDownloadUrl(version).openStream()); + final var outputChannel = new FileOutputStream(installDir.resolve(getSolverBinaryName()).toAbsolutePath().toString()).getChannel() + ) { + logger.write(Logger.Level.MAINSTEP, "Starting download (%s)...\n", getDownloadUrl(version).toString()); + outputChannel.transferFrom(inputChannel, 0, Long.MAX_VALUE); + installDir.resolve(getSolverBinaryName()).toFile().setExecutable(true, true); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(e); + } + + logger.write(Logger.Level.MAINSTEP, "Download finished\n"); + } + + @Override + protected void uninstallSolver(final Path installDir, final String version) { } + + @Override + protected String[] getDefaultSolverArgs(String version) { + return new String[] { + "--lang", "smt2", + "--output-lang", "smt2", + "--quiet", + "--incremental" + }; + } + + @Override + public SolverFactory getSolverFactory(Path home, String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final var installDir = home.resolve(version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + try { + final var solverFilePath = installDir.resolve(getSolverBinaryName()); + final var solverArgsPath = argsFile(installDir); + final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); + + return GenericSmtLibSolverFactory.create(solverFilePath, solverArgs); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public List getSupportedVersions() { + return Arrays.asList("1.8", "1.7", "1.6", "1.5", "1.4", "1.3", "1.2", "1.1", "1.0"); + } + + private URL getDownloadUrl(final String version) throws SmtLibSolverInstallerException, MalformedURLException { + final var os = OsHelper.getOs(); + final var arch = OsHelper.getArch(); + + final String archString; + final String platformExtension; + if(arch != X64) { + throw new SmtLibSolverInstallerException("cvc4 is available only for x64 architecture"); + } + else if(os != LINUX && os != WINDOWS) { + throw new SmtLibSolverInstallerException("cvc4 is available only for Windows and Linux"); + } + else if(os == LINUX) { + archString = "x86_64-linux-opt"; + platformExtension = ""; + } + else /* if(os == WINDOWS) */ { + if(SemVer.of(version).compareTo(SemVer.of("1.6")) >= 0) { + archString = "win64-opt"; + platformExtension = ".exe"; + } + else { + throw new SmtLibSolverInstallerException("Windows platform is only supported for version 1.6 and forward"); + } + } + + return URI.create(String.format( + "https://cvc4.cs.stanford.edu/downloads/builds/%s/cvc4-%s-%s%s", + archString, version, archString, platformExtension + )).toURL(); + } + + private String getSolverBinaryName() { + switch(OsHelper.getOs()) { + case WINDOWS: + return "cvc4.exe"; + case LINUX: + return "cvc4"; + default: + throw new AssertionError(); + } + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java index c5873d5f7b..85d749e237 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java @@ -6,6 +6,7 @@ import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.cvc4.CVC4SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibSolverInstaller; @@ -38,6 +39,7 @@ public static void registerGenericInsta static { registerInstaller("z3", Z3SmtLibSolverInstaller.class); + registerInstaller("cvc4", CVC4SmtLibSolverInstaller.class); registerGenericInstaller("generic", GenericSmtLibSolverInstaller.class); } @@ -209,7 +211,7 @@ private String getVersionString(final String solver, final String version, final return versions.get(0); } else { - throw new IllegalArgumentException("There are no supported versions of solver: " + solver); + throw new SmtLibSolverInstallerException(String.format("There are no %s versions of solver: %s", installed ? "installed" : "supported", solver)); } } } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java index 5239f45b53..7baed63787 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java @@ -120,8 +120,6 @@ protected void installSolver(final Path installDir, final String version) throws throw new SmtLibSolverInstallerException(e); } - - logger.write(Logger.Level.MAINSTEP, "Download finished\n"); } From 7642420d67675ca1bb266d3fbddd91bb0da7d19b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 13 Sep 2020 19:02:00 +0200 Subject: [PATCH 52/99] Extract common solver functions to SolverBase --- .../analysis/impact/PredImpactChecker.java | 18 +++-- .../hu/bme/mit/theta/solver/ItpSolver.java | 2 +- .../mit/theta/solver/utils/WithPushPop.java | 5 +- .../hu/bme/mit/theta/solver/SolverBase.java | 66 +++++++++++++++++++ .../hu/bme/mit/theta/solver/UCSolver.java | 8 +-- .../mit/theta/sts/analysis/StsExplTest.java | 12 ++-- .../mit/theta/sts/analysis/StsPredTest.java | 16 +++-- 7 files changed, 100 insertions(+), 27 deletions(-) create mode 100644 subprojects/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java diff --git a/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/impact/PredImpactChecker.java b/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/impact/PredImpactChecker.java index d4fee50573..88b2114529 100644 --- a/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/impact/PredImpactChecker.java +++ b/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/impact/PredImpactChecker.java @@ -40,19 +40,22 @@ import hu.bme.mit.theta.cfa.analysis.CfaState; import hu.bme.mit.theta.cfa.analysis.prec.GlobalCfaPrec; import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; public final class PredImpactChecker implements SafetyChecker, CfaAction, UnitPrec> { private final ImpactChecker, CfaAction, UnitPrec> checker; private PredImpactChecker(final LTS, ? extends CfaAction> lts, final Loc initLoc, - final Predicate targetLocs, final ItpSolver solver) { + final Predicate targetLocs, + final Solver abstractionSolver, final ItpSolver refinementSolver) { checkNotNull(lts); checkNotNull(initLoc); - checkNotNull(solver); + checkNotNull(abstractionSolver); + checkNotNull(refinementSolver); - final Analysis predAnalysis = PredAnalysis.create(solver, - PredAbstractors.booleanSplitAbstractor(solver), True()); + final Analysis predAnalysis = PredAnalysis.create(abstractionSolver, + PredAbstractors.booleanSplitAbstractor(abstractionSolver), True()); final CfaPrec fixedPrec = GlobalCfaPrec.create(PredPrec.of(emptySet())); @@ -67,14 +70,15 @@ private PredImpactChecker(final LTS, ? extends CfaAc final ArgBuilder, CfaAction, UnitPrec> argBuilder = ArgBuilder.create(lts, analysis, target); - final ImpactRefiner, CfaAction> refiner = PredImpactRefiner.create(solver); + final ImpactRefiner, CfaAction> refiner = PredImpactRefiner.create(refinementSolver); checker = ImpactChecker.create(argBuilder, refiner, CfaState::getLoc); } public static PredImpactChecker create(final LTS, ? extends CfaAction> lts, - final Loc initLoc, final Predicate targetLocs, final ItpSolver solver) { - return new PredImpactChecker(lts, initLoc, targetLocs, solver); + final Loc initLoc, final Predicate targetLocs, + final Solver abstractionSolver, final ItpSolver refinementSolver) { + return new PredImpactChecker(lts, initLoc, targetLocs, abstractionSolver, refinementSolver); } @Override diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java index 460d133e94..30747e07fd 100644 --- a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java +++ b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java @@ -35,7 +35,7 @@ * expressions are unsatisfiable, an interpolant can be calculated with * {@link #getInterpolant(ItpPattern)}. */ -public interface ItpSolver extends Solver { +public interface ItpSolver extends SolverBase { /** * Create a pattern for a given marker. diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java index c46c183ea1..20eab0dc40 100644 --- a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java +++ b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java @@ -18,6 +18,7 @@ import java.io.Closeable; import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverBase; /** * A helper class for automatic push and pop for solvers using the @@ -25,9 +26,9 @@ */ public class WithPushPop implements Closeable { - private final Solver solver; + private final SolverBase solver; - public WithPushPop(final Solver solver) { + public WithPushPop(final SolverBase solver) { this.solver = solver; solver.push(); } diff --git a/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java b/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java new file mode 100644 index 0000000000..cb6af94eb4 --- /dev/null +++ b/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java @@ -0,0 +1,66 @@ +package hu.bme.mit.theta.solver; + +import hu.bme.mit.theta.core.model.Valuation; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolType; + +import java.util.Collection; + +public interface SolverBase { + + + /** + * Check if the currently added expressions are satisfiable. + * + * @return Status + */ + SolverStatus check(); + + /** + * Push the current solver state. When calling {@link #pop()}, all expressions added after + * the last push will be removed. + */ + void push(); + + /** + * Remove expressions added after the previous n {@link #push()} calls. + * + * @param n + */ + void pop(final int n); + + /** + * Remove expressions added after the previous {@link #push()} call. + */ + default void pop() { + pop(1); + } + + /** + * Reset the solver state. + */ + void reset(); + + /** + * Get the current status of the solver. + * + * @return Status + */ + SolverStatus getStatus(); + + /** + * Get the satisfying assignment for the currently added expressions. + * Should only be called if {@link #check()} was already called and + * the result is SAT. + * + * @return Satisfying assignment + */ + Valuation getModel(); + + /** + * Get the currently added expressions. + * + * @return Expressions + */ + Collection> getAssertions(); +} diff --git a/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java b/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java index e998ed51b9..68a4b3a690 100644 --- a/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java +++ b/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java @@ -8,7 +8,7 @@ /** * Common interface for SMT solvers with unsat core capabilities. * - * Use the {@link #add(Expr)} or {@link #track(Expr)} methods to add expressions to the solver. + * Use the {@link #track(Expr)} method to add expressions to the solver. * Then use {@link #check()} method to check their satisfiability. The result can be queried by * {@link #getStatus()}. If the expressions are satisfiable, a satisfying assignment can be * obtained by {@link #getModel()}. If the expressions are not satisfiable, use {@link #getUnsatCore()} @@ -16,11 +16,10 @@ * * The solver can also support incremental solving by {@link #push()} and {@link #pop()}. */ -public interface UCSolver extends Solver { +public interface UCSolver extends SolverBase { /** * Add and track an expression. Required to calculate unsat cores. - * If you don't need unsat cores you can simply use {@link #add(Expr)}. * * @param assertion Expression to be tracked */ @@ -40,8 +39,7 @@ default void track(final Iterable> assertions) { /** * Get an unsat core, i.e., a (not necessarily) minimal subset of the * expressions that are already unsatisfiable. It only works if expressions - * were added by {@link #track(Expr)} or {@link #track(Iterable)} instead of - * {@link #add(Expr)} or {@link #add(Iterable)}. Furthermore, it should only + * were added by {@link #track(Expr)} or {@link #track(Iterable)}. Furthermore, it should only * be called if {@link #check()} was already called and the result is UNSAT. * * @return Unsat core diff --git a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java index 36637a0925..acbc09b188 100644 --- a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java +++ b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java @@ -46,6 +46,7 @@ import hu.bme.mit.theta.core.decl.VarDecl; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.inttype.IntType; +import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.z3.Z3SolverFactory; import hu.bme.mit.theta.sts.STS; @@ -93,10 +94,11 @@ public void test() { final STS sts = builder.build(); - final UCSolver solver = Z3SolverFactory.getInstance().createUCSolver(); + final Solver abstractionSolver = Z3SolverFactory.getInstance().createSolver(); + final UCSolver refinementSolver = Z3SolverFactory.getInstance().createUCSolver(); - final Analysis analysis = ExplAnalysis.create(solver, sts.getInit()); - final Predicate target = new ExprStatePredicate(Not(sts.getProp()), solver); + final Analysis analysis = ExplAnalysis.create(abstractionSolver, sts.getInit()); + final Predicate target = new ExprStatePredicate(Not(sts.getProp()), abstractionSolver); final ExplPrec prec = ExplPrec.of(Collections.singleton(vy)); @@ -108,7 +110,7 @@ public void test() { .waitlist(PriorityWaitlist.create(ArgNodeComparators.bfs())).logger(logger).build(); final ExprTraceChecker exprTraceChecker = ExprTraceUnsatCoreChecker.create(sts.getInit(), - Not(sts.getProp()), solver); + Not(sts.getProp()), refinementSolver); final SingleExprTraceRefiner refiner = SingleExprTraceRefiner .create(exprTraceChecker, JoiningPrecRefiner.create(new VarsRefToExplPrec()), PruneStrategy.LAZY, logger); @@ -118,7 +120,7 @@ public void test() { final SafetyResult safetyStatus = checker.check(prec); final ARG arg = safetyStatus.getArg(); - assertTrue(isWellLabeled(arg, solver)); + assertTrue(isWellLabeled(arg, abstractionSolver)); // System.out.println(new // GraphvizWriter().writeString(ArgVisualizer.visualize(arg))); diff --git a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java index bf338f813c..2712527c1b 100644 --- a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java +++ b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java @@ -31,6 +31,8 @@ import java.util.function.Predicate; import hu.bme.mit.theta.analysis.expr.refinement.*; +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; import org.junit.Before; import org.junit.Test; @@ -59,14 +61,14 @@ import hu.bme.mit.theta.core.decl.VarDecl; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.inttype.IntType; -import hu.bme.mit.theta.solver.ItpSolver; import hu.bme.mit.theta.solver.z3.Z3SolverFactory; import hu.bme.mit.theta.sts.STS; import hu.bme.mit.theta.sts.STS.Builder; public class StsPredTest { final Logger logger = new ConsoleLogger(Level.VERBOSE); - final ItpSolver solver = Z3SolverFactory.getInstance().createItpSolver(); + final Solver abstractionSolver = Z3SolverFactory.getInstance().createSolver(); + final ItpSolver refinementSolver = Z3SolverFactory.getInstance().createItpSolver(); STS sts = null; @Before @@ -87,9 +89,9 @@ public void setUp() { @Test public void testPredPrec() { - final Analysis analysis = PredAnalysis.create(solver, - PredAbstractors.booleanSplitAbstractor(solver), sts.getInit()); - final Predicate target = new ExprStatePredicate(Not(sts.getProp()), solver); + final Analysis analysis = PredAnalysis.create(abstractionSolver, + PredAbstractors.booleanSplitAbstractor(abstractionSolver), sts.getInit()); + final Predicate target = new ExprStatePredicate(Not(sts.getProp()), abstractionSolver); final PredPrec prec = PredPrec.of(); @@ -101,7 +103,7 @@ public void testPredPrec() { .build(); final ExprTraceChecker exprTraceChecker = ExprTraceFwBinItpChecker.create(sts.getInit(), - Not(sts.getProp()), solver); + Not(sts.getProp()), refinementSolver); final SingleExprTraceRefiner refiner = SingleExprTraceRefiner .create(exprTraceChecker, JoiningPrecRefiner.create(new ItpRefToPredPrec(ExprSplitters.atoms())), @@ -113,7 +115,7 @@ public void testPredPrec() { System.out.println(safetyStatus); final ARG arg = safetyStatus.getArg(); - assertTrue(isWellLabeled(arg, solver)); + assertTrue(isWellLabeled(arg, abstractionSolver)); // System.out.println(new // GraphvizWriter().writeString(ArgVisualizer.visualize(arg))); From dbb2ae17ed8b02d9b8de2e2dc830a8c878307d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 14 Sep 2020 20:22:32 +0200 Subject: [PATCH 53/99] Refactor ItpPattern, to handle partial interpolation support --- .../hu/bme/mit/theta/solver/ItpPattern.java | 58 +++++++++++++------ .../hu/bme/mit/theta/solver/ItpSolver.java | 25 ++++---- .../bme/mit/theta/solver/ItpMarkerTree.java | 44 ++++++++++++++ 3 files changed, 96 insertions(+), 31 deletions(-) create mode 100644 subprojects/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarkerTree.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java index 5d908b626c..cdc7029ae4 100644 --- a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java +++ b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java @@ -16,40 +16,62 @@ package hu.bme.mit.theta.solver; import java.util.Collection; +import java.util.List; /** * Interface for an element of an interpolation pattern. - * For example, in sequence interpolation the patterns form a linear chain. */ public interface ItpPattern { /** - * Get the current marker. - * - * @return Marker + * ItpPatter visitor function + * @param visitor The visitor + * @param The return type of the visitor + * @return Returns the result of the visitor */ - ItpMarker getMarker(); + E visit(final ItpPatternVisitor visitor); /** - * Get the parent pattern. - * - * @return Parent + * Interface for a binary interpolation pattern */ - ItpPattern getParent(); + interface Binary extends ItpPattern { + T getA(); + T getB(); + + @Override + default E visit(final ItpPatternVisitor visitor) { + return visitor.visitBinaryPattern(this); + } + } /** - * Get child patterns. - * - * @return Children + * Interface for a sequence interpolation pattern */ - Collection getChildren(); + interface Sequence extends ItpPattern { + List getSequence(); + + @Override + default E visit(final ItpPatternVisitor visitor) { + return visitor.visitSequencePattern(this); + } + } /** - * Create a child for the current pattern with a given marker. - * - * @param marker Marker - * @return Child + * Interface for a tree interpolation pattern */ - ItpPattern createChild(final ItpMarker marker); + interface Tree extends ItpPattern { + ItpMarkerTree getRoot(); + + @Override + default E visit(final ItpPatternVisitor visitor) { + return visitor.visitTreePattern(this); + } + } + + interface ItpPatternVisitor { + E visitBinaryPattern(final Binary binaryPattern); + E visitSequencePattern(final Sequence sequencePattern); + E visitTreePattern(final Tree treePattern); + } } diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java index 30747e07fd..d8d83a0534 100644 --- a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java +++ b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java @@ -36,15 +36,6 @@ * {@link #getInterpolant(ItpPattern)}. */ public interface ItpSolver extends SolverBase { - - /** - * Create a pattern for a given marker. - * - * @param marker Marker - * @return Pattern - */ - ItpPattern createPattern(final ItpMarker marker); - /** * Create a binary pattern, which is a sequence of two markers: A and B. * @@ -52,12 +43,12 @@ public interface ItpSolver extends SolverBase { * @param markerB Marker B * @return Binary interpolant pattern */ - default ItpPattern createBinPattern(final ItpMarker markerA, final ItpMarker markerB) { + ItpPattern createBinPattern(final ItpMarker markerA, final ItpMarker markerB); /* { checkNotNull(markerA); checkNotNull(markerB); return createSeqPattern(Arrays.asList(markerA, markerB)); - } + }*/ /** * Create a sequence pattern, which is a linear sequence of N markers. @@ -65,7 +56,7 @@ default ItpPattern createBinPattern(final ItpMarker markerA, final ItpMarker mar * @param markers Markers * @return Sequence interpolant pattern */ - default ItpPattern createSeqPattern(final List markers) { + ItpPattern createSeqPattern(final List markers); /* { checkNotNull(markers); checkArgument(!markers.isEmpty()); @@ -81,7 +72,15 @@ default ItpPattern createSeqPattern(final List markers) { } } return result; - } + }*/ + + /** + * Create a tree pattern, in which each node can have multiple children + * + * @param root Root of the marker tree + * @return Tree interpolant pattern + */ + ItpPattern createTreePattern(final ItpMarkerTree root); /** * Create a new marker. diff --git a/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarkerTree.java b/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarkerTree.java new file mode 100644 index 0000000000..cec9093f15 --- /dev/null +++ b/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarkerTree.java @@ -0,0 +1,44 @@ +package hu.bme.mit.theta.solver; + +import java.util.Arrays; +import java.util.List; + +public final class ItpMarkerTree { + private final T marker; + private final List> children; + + private ItpMarkerTree(final T marker, final List> children) { + this.marker = marker; + this.children = children; + } + + public T getMarker() { + return marker; + } + + public List> getChildren() { + return children; + } + + public ItpMarkerTree getChild(int i) { + return children.get(i); + } + + public int getChildrenNumber() { + return children.size(); + } + + @SafeVarargs + public static ItpMarkerTree Tree(final T marker, final ItpMarkerTree ...subtrees) { + return new ItpMarkerTree<>(marker, Arrays.asList(subtrees)); + } + + @SafeVarargs + public static ItpMarkerTree Subtree(final T marker, final ItpMarkerTree ...subtrees) { + return Tree(marker, subtrees); + } + + public static ItpMarkerTree Leaf(final T marker) { + return Tree(marker); + } +} From 2b1264f8da22e3954127b75fcdcfdff196b0a3cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 14 Sep 2020 20:23:02 +0200 Subject: [PATCH 54/99] Propagate ItpPattern changes to Z3ItpSolver --- .../mit/theta/solver/z3/Z3ItpSolverTest.java | 37 +++++--- .../bme/mit/theta/solver/z3/Z3ItpPattern.java | 94 +++++++++++++++++++ 2 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 subprojects/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpPattern.java diff --git a/subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ItpSolverTest.java b/subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ItpSolverTest.java index b162ade10e..529eec7f06 100644 --- a/subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ItpSolverTest.java +++ b/subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ItpSolverTest.java @@ -28,6 +28,9 @@ import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; import static hu.bme.mit.theta.core.type.inttype.IntExprs.Mul; import static hu.bme.mit.theta.core.type.inttype.IntExprs.Neq; +import static hu.bme.mit.theta.solver.ItpMarkerTree.Leaf; +import static hu.bme.mit.theta.solver.ItpMarkerTree.Subtree; +import static hu.bme.mit.theta.solver.ItpMarkerTree.Tree; import hu.bme.mit.theta.core.utils.ExprUtils; import hu.bme.mit.theta.solver.*; @@ -102,13 +105,15 @@ public void testSequenceInterpolation() { final ItpMarker I1 = solver.createMarker(); final ItpMarker I2 = solver.createMarker(); final ItpMarker I3 = solver.createMarker(); - final ItpPattern pattern = solver.createSeqPattern(ImmutableList.of(I1, I2, I3)); + final ItpMarker I4 = solver.createMarker(); + final ItpMarker I5 = solver.createMarker(); + final ItpPattern pattern = solver.createSeqPattern(ImmutableList.of(I1, I2, I3, I4, I5)); - solver.add(I1, Eq(a, b)); - solver.add(I1, Eq(a, c)); - solver.add(I2, Eq(c, d)); - solver.add(I3, Eq(b, e)); - solver.add(I3, Neq(d, e)); + solver.add(I1, Eq(a, Int(0))); + solver.add(I2, Eq(a, b)); + solver.add(I3, Eq(c, d)); + solver.add(I4, Eq(d, Int(1))); + solver.add(I5, Eq(b, c)); solver.check(); Assert.assertEquals(SolverStatus.UNSAT, solver.getStatus()); @@ -116,6 +121,9 @@ public void testSequenceInterpolation() { System.out.println(itp.eval(I1)); System.out.println(itp.eval(I2)); + System.out.println(itp.eval(I3)); + System.out.println(itp.eval(I4)); + System.out.println(itp.eval(I5)); System.out.println("----------"); } @@ -124,15 +132,15 @@ public void testTreeInterpolation() { final ItpMarker I1 = solver.createMarker(); final ItpMarker I2 = solver.createMarker(); final ItpMarker I3 = solver.createMarker(); - final ItpPattern pattern = solver.createPattern(I3); - pattern.createChild(I1); - pattern.createChild(I2); + final ItpMarker I4 = solver.createMarker(); + final ItpMarker I5 = solver.createMarker(); + final ItpPattern pattern = solver.createTreePattern(Tree(I3, Subtree(I1, Leaf(I4), Leaf(I5)), Leaf(I2))); solver.add(I1, Eq(a, Int(0))); - solver.add(I1, Eq(a, b)); - solver.add(I2, Eq(c, d)); - solver.add(I2, Eq(d, Int(1))); - solver.add(I3, Eq(b, c)); + solver.add(I2, Eq(a, b)); + solver.add(I3, Eq(c, d)); + solver.add(I4, Eq(d, Int(1))); + solver.add(I5, Eq(b, c)); solver.check(); Assert.assertEquals(SolverStatus.UNSAT, solver.getStatus()); @@ -140,6 +148,9 @@ public void testTreeInterpolation() { System.out.println(itp.eval(I1)); System.out.println(itp.eval(I2)); + System.out.println(itp.eval(I3)); + System.out.println(itp.eval(I4)); + System.out.println(itp.eval(I5)); System.out.println("----------"); } diff --git a/subprojects/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpPattern.java b/subprojects/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpPattern.java new file mode 100644 index 0000000000..133e4d90f9 --- /dev/null +++ b/subprojects/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpPattern.java @@ -0,0 +1,94 @@ +package hu.bme.mit.theta.solver.z3; + +import com.google.common.collect.Lists; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; +import hu.bme.mit.theta.solver.ItpPattern; + +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +public class Z3ItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { + final ItpMarkerTree markerTree; + + Z3ItpPattern(final ItpMarkerTree markerTree) { + this.markerTree = markerTree; + } + + @SuppressWarnings("unchecked") + static Z3ItpPattern of(final ItpMarkerTree markerTree) { + final var list = new ArrayList>(); + list.add(markerTree); + while(!list.isEmpty()) { + final var node = list.get(0); + list.remove(0); + + checkArgument(node.getMarker() instanceof Z3ItpMarker); + + list.addAll(node.getChildren()); + } + + return new Z3ItpPattern((ItpMarkerTree) markerTree); + } + + @Override + public Z3ItpMarker getA() { + checkState(isBinary()); + return markerTree.getChild(0).getMarker(); + } + + @Override + public Z3ItpMarker getB() { + checkState(isBinary()); + return markerTree.getMarker(); + } + + @Override + public List getSequence() { + checkState(isSequence()); + final var markerList = new ArrayList(); + + var current = markerTree; + while(current.getChildrenNumber() > 0) { + markerList.add(current.getMarker()); + current = current.getChild(0); + } + markerList.add(current.getMarker()); + + return Lists.reverse(markerList); + } + + @Override + public ItpMarkerTree getRoot() { + return markerTree; + } + + @Override + public E visit(ItpPatternVisitor visitor) { + return visitor.visitTreePattern(this); + } + + private boolean isBinary() { + return + markerTree != null && + markerTree.getChildrenNumber() == 1 && + markerTree.getChild(0) != null && + markerTree.getChild(0).getChildrenNumber() == 0; + } + + private boolean isSequence() { + var current = markerTree; + while(current.getChildrenNumber() > 0) { + if(current.getChildrenNumber() > 1) { + return false; + } + else { + current = current.getChild(0); + } + } + return true; + } +} From 372e52c669dbdf16fe630b2de7dd226333db3939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 14 Sep 2020 20:28:30 +0200 Subject: [PATCH 55/99] Propagate ItpPattern changes to Z3ItpSolver --- .../hu/bme/mit/theta/solver/ItpSolver.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java index d8d83a0534..1309f6281d 100644 --- a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java +++ b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java @@ -43,12 +43,12 @@ public interface ItpSolver extends SolverBase { * @param markerB Marker B * @return Binary interpolant pattern */ - ItpPattern createBinPattern(final ItpMarker markerA, final ItpMarker markerB); /* { + default ItpPattern createBinPattern(final ItpMarker markerA, final ItpMarker markerB) { checkNotNull(markerA); checkNotNull(markerB); return createSeqPattern(Arrays.asList(markerA, markerB)); - }*/ + } /** * Create a sequence pattern, which is a linear sequence of N markers. @@ -56,23 +56,21 @@ public interface ItpSolver extends SolverBase { * @param markers Markers * @return Sequence interpolant pattern */ - ItpPattern createSeqPattern(final List markers); /* { + default ItpPattern createSeqPattern(final List markers) { checkNotNull(markers); checkArgument(!markers.isEmpty()); - ItpPattern result = null; - ItpPattern current = null; + ItpMarkerTree current = null; - for (final ItpMarker marker : Lists.reverse(markers)) { - if (result == null) { - current = createPattern(marker); - result = current; + for (final var marker : markers) { + if (current == null) { + current = ItpMarkerTree.Leaf(marker); } else { - current = current.createChild(marker); + current = ItpMarkerTree.Tree(marker, current); } } - return result; - }*/ + return createTreePattern(current); + } /** * Create a tree pattern, in which each node can have multiple children From 20e01bf0b4f8110c9dc0a54c10d1e75e2b54891d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 15 Sep 2020 11:29:46 +0200 Subject: [PATCH 56/99] Refactor SmtLibSolverBinary interface to allow multiple answers for commands (in case of interpolation) --- .../mit/theta/solver/smtlib/SmtLibSolver.java | 152 ++---------------- .../solver/smtlib/SmtLibSolverBinary.java | 3 +- .../theta/solver/smtlib/SmtLibValuation.java | 140 ++++++++++++++++ .../generic/GenericSmtLibSolverBinary.java | 7 +- 4 files changed, 163 insertions(+), 139 deletions(-) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java index 861b231c7b..29600c7371 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java @@ -1,16 +1,9 @@ package hu.bme.mit.theta.solver.smtlib; -import com.google.common.collect.ImmutableList; import hu.bme.mit.theta.core.decl.ConstDecl; -import hu.bme.mit.theta.core.decl.Decl; import hu.bme.mit.theta.core.model.Valuation; import hu.bme.mit.theta.core.type.Expr; -import hu.bme.mit.theta.core.type.LitExpr; -import hu.bme.mit.theta.core.type.Type; -import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.booltype.BoolType; -import hu.bme.mit.theta.core.type.bvtype.BvType; -import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.utils.ExprUtils; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; @@ -33,7 +26,6 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.Map; -import java.util.Optional; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; @@ -84,7 +76,7 @@ public void add(Expr assertion) { final var term = transformationManager.toTerm(assertion); consts.stream().map(symbolTable::getDeclaration).forEach(this::issueGeneralCommand); - issueGeneralCommand(String.format("(assert %s)%n", term)); + issueGeneralCommand(String.format("(assert %s)", term)); clearState(); } @@ -95,7 +87,7 @@ public void add(final Expr assertion, final String term) { declarationStack.add(consts); consts.stream().map(symbolTable::getDeclaration).forEach(this::issueGeneralCommand); - issueGeneralCommand(String.format("(assert %s)%n", term)); + issueGeneralCommand(String.format("(assert %s)", term)); clearState(); } @@ -111,14 +103,15 @@ public void track(Expr assertion) { assumptions.put(label, assertion); consts.stream().map(symbolTable::getDeclaration).forEach(this::issueGeneralCommand); - issueGeneralCommand(String.format("(assert (! %s :named %s))%n", term, label)); + issueGeneralCommand(String.format("(assert (! %s :named %s))", term, label)); clearState(); } @Override public SolverStatus check() { - var res = parseResponse(solverBinary.issueCommand("(check-sat)")); + solverBinary.issueCommand("(check-sat)"); + var res = parseResponse(solverBinary.readResponse()); if(res.isError()) { throw new SmtLibSolverException(res.getReason()); } @@ -145,14 +138,14 @@ else if(checkSatResponse.isUnsat()) { public void push() { assertions.push(); declarationStack.push(); - issueGeneralCommand("(push)"); + issueGeneralCommand("(push 1)"); } @Override public void pop(int n) { assertions.pop(n); declarationStack.pop(n); - issueGeneralCommand("(pop)"); + issueGeneralCommand("(pop 1)"); clearState(); } @@ -184,13 +177,14 @@ private Valuation extractModel() { assert status == SolverStatus.SAT; assert model == null; - final var res = parseResponse(solverBinary.issueCommand("(get-model)")); + solverBinary.issueCommand("(get-model)"); + final var res = parseResponse(solverBinary.readResponse()); if(res.isError()) { throw new SmtLibSolverException(res.getReason()); } else if(res.isSpecific()) { final GetModelResponse getModelResponse = res.asSpecific(); - return new SmtLibValuation(getModelResponse.getModel()); + return new SmtLibValuation(symbolTable, transformationManager, termTransformer, getModelResponse.getModel()); } else { throw new AssertionError(); @@ -215,7 +209,8 @@ private Collection> extractUnsatCore() { final Collection> unsatCore = new LinkedList<>(); final Collection unsatCoreLabels; - final var res = parseResponse(solverBinary.issueCommand("(get-unsat-core)")); + solverBinary.issueCommand("(get-unsat-core)"); + final var res = parseResponse(solverBinary.readResponse()); if(res.isError()) { throw new SmtLibSolverException(res.getReason()); } @@ -250,20 +245,21 @@ private void init() { issueGeneralCommand("(set-logic ALL)"); } - private void clearState() { + protected void clearState() { status = null; model = null; unsatCore = null; } - private void issueGeneralCommand(String command) { - var res = parseResponse(solverBinary.issueCommand(command)); + protected final void issueGeneralCommand(String command) { + solverBinary.issueCommand(command); + var res = parseResponse(solverBinary.readResponse()); if(res.isError()) { throw new SmtLibSolverException(res.getReason()); } } - private GeneralResponse parseResponse(final String response) { + protected final GeneralResponse parseResponse(final String response) { try { final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(response)); final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); @@ -278,118 +274,4 @@ private GeneralResponse parseResponse(final String response) { } } - private final class SmtLibValuation extends Valuation { - private final SmtLibModel model; - private final Map, LitExpr> constToExpr; - private volatile Collection> constDecls = null; - - public SmtLibValuation(final SmtLibModel model) { - this.model = model; - constToExpr = new HashMap<>(); - } - - @Override - public Collection> getDecls() { - Collection> result = constDecls; - if (result == null) { - result = constDeclsOf(model); - constDecls = result; - } - return result; - } - - @Override - public Optional> eval(Decl decl) { - checkNotNull(decl); - - if (!(decl instanceof ConstDecl)) { - return Optional.empty(); - } - - final ConstDecl constDecl = (ConstDecl) decl; - - LitExpr val = constToExpr.get(constDecl); - if (val == null) { - val = extractLiteral(constDecl); - if (val != null) { - constToExpr.put(constDecl, val); - } - } - - @SuppressWarnings("unchecked") final LitExpr tVal = (LitExpr) val; - return Optional.ofNullable(tVal); - } - - private LitExpr extractLiteral(final ConstDecl decl) { - final String symbol = transformationManager.toSymbol(decl); - final Type type = decl.getType(); - - if(type instanceof FuncType) { - return extractFuncLiteral(symbol, (FuncType) type); - } - else if(type instanceof ArrayType) { - return extractArrayLiteral(symbol, (ArrayType) type); - } - else if (type instanceof BvType) { - return extractBvConstLiteral(symbol, (BvType) type); - } - else { - return extractConstLiteral(symbol, type); - } - } - - private LitExpr extractFuncLiteral(final String symbol, final FuncType type) { - final String term = model.getTerm(symbol); - if (term == null) { - return null; - } else { - return checkNotNull(termTransformer.toFuncLitExpr(term, type, model)); - } - } - - private LitExpr extractArrayLiteral(final String symbol, final ArrayType type) { - final String term = model.getTerm(symbol); - if (term == null) { - return null; - } else { - return checkNotNull(termTransformer.toArrayLitExpr(term, type, model)); - } - } - - private LitExpr extractBvConstLiteral(final String symbol, final BvType type) { - final String term = model.getTerm(symbol); - if (term == null) { - return null; - } else { - return checkNotNull(termTransformer.toBvLitExpr(term, type, model)); - } - } - - private LitExpr extractConstLiteral(final String symbol, final Type type) { - final String term = model.getTerm(symbol); - if (term == null) { - return null; - } else { - return checkNotNull(termTransformer.toLitExpr(term, type, model)); - } - } - - @Override - public Map, LitExpr> toMap() { - getDecls().forEach(this::eval); - return Collections.unmodifiableMap(constToExpr); - } - - private Collection> constDeclsOf(final SmtLibModel model) { - final ImmutableList.Builder> builder = ImmutableList.builder(); - for (final var symbol : model.getDecls()) { - if (symbolTable.definesSymbol(symbol)) { - final ConstDecl constDecl = symbolTable.getConst(symbol); - builder.add(constDecl); - } - } - return builder.build(); - } - } - } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java index 5301a082cc..ed96597888 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java @@ -1,5 +1,6 @@ package hu.bme.mit.theta.solver.smtlib; public interface SmtLibSolverBinary { - String issueCommand(String command); + void issueCommand(String command); + String readResponse(); } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java new file mode 100644 index 0000000000..172657ce5e --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java @@ -0,0 +1,140 @@ +package hu.bme.mit.theta.solver.smtlib; + +import com.google.common.collect.ImmutableList; +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.decl.Decl; +import hu.bme.mit.theta.core.model.Valuation; +import hu.bme.mit.theta.core.type.LitExpr; +import hu.bme.mit.theta.core.type.Type; +import hu.bme.mit.theta.core.type.arraytype.ArrayType; +import hu.bme.mit.theta.core.type.bvtype.BvType; +import hu.bme.mit.theta.core.type.functype.FuncType; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import static com.google.common.base.Preconditions.checkNotNull; + +public final class SmtLibValuation extends Valuation { + private final SmtLibSymbolTable symbolTable; + private final SmtLibTransformationManager transformationManager; + private final SmtLibTermTransformer termTransformer; + + private final SmtLibModel model; + private final Map, LitExpr> constToExpr; + private volatile Collection> constDecls = null; + + public SmtLibValuation( + final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, + final SmtLibTermTransformer termTransformer, final SmtLibModel model + ) { + this.symbolTable = symbolTable; + this.transformationManager = transformationManager; + this.termTransformer = termTransformer; + this.model = model; + constToExpr = new HashMap<>(); + } + + @Override + public Collection> getDecls() { + Collection> result = constDecls; + if (result == null) { + result = constDeclsOf(model); + constDecls = result; + } + return result; + } + + @Override + public Optional> eval(Decl decl) { + checkNotNull(decl); + + if (!(decl instanceof ConstDecl)) { + return Optional.empty(); + } + + final ConstDecl constDecl = (ConstDecl) decl; + + LitExpr val = constToExpr.get(constDecl); + if (val == null) { + val = extractLiteral(constDecl); + if (val != null) { + constToExpr.put(constDecl, val); + } + } + + @SuppressWarnings("unchecked") final LitExpr tVal = (LitExpr) val; + return Optional.ofNullable(tVal); + } + + private LitExpr extractLiteral(final ConstDecl decl) { + final String symbol = transformationManager.toSymbol(decl); + final Type type = decl.getType(); + + if (type instanceof FuncType) { + return extractFuncLiteral(symbol, (FuncType) type); + } else if (type instanceof ArrayType) { + return extractArrayLiteral(symbol, (ArrayType) type); + } else if (type instanceof BvType) { + return extractBvConstLiteral(symbol, (BvType) type); + } else { + return extractConstLiteral(symbol, type); + } + } + + private LitExpr extractFuncLiteral(final String symbol, final FuncType type) { + final String term = model.getTerm(symbol); + if (term == null) { + return null; + } else { + return checkNotNull(termTransformer.toFuncLitExpr(term, type, model)); + } + } + + private LitExpr extractArrayLiteral(final String symbol, final ArrayType type) { + final String term = model.getTerm(symbol); + if (term == null) { + return null; + } else { + return checkNotNull(termTransformer.toArrayLitExpr(term, type, model)); + } + } + + private LitExpr extractBvConstLiteral(final String symbol, final BvType type) { + final String term = model.getTerm(symbol); + if (term == null) { + return null; + } else { + return checkNotNull(termTransformer.toBvLitExpr(term, type, model)); + } + } + + private LitExpr extractConstLiteral(final String symbol, final Type type) { + final String term = model.getTerm(symbol); + if (term == null) { + return null; + } else { + return checkNotNull(termTransformer.toLitExpr(term, type, model)); + } + } + + @Override + public Map, LitExpr> toMap() { + getDecls().forEach(this::eval); + return Collections.unmodifiableMap(constToExpr); + } + + private Collection> constDeclsOf(final SmtLibModel model) { + final ImmutableList.Builder> builder = ImmutableList.builder(); + for (final var symbol : model.getDecls()) { + if (symbolTable.definesSymbol(symbol)) { + final ConstDecl constDecl = symbolTable.getConst(symbol); + builder.add(constDecl); + } + } + return builder.build(); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java index 84b01c7dcf..0b5e6f1118 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java @@ -36,13 +36,14 @@ public GenericSmtLibSolverBinary(final Path solverPath, final String[] args) { } @Override - public String issueCommand(final String command) { + public void issueCommand(final String command) { checkState(solverProcess.isAlive()); solverInput.println(command); - return readResponse(solverOutput); } - private String readResponse(final Reader solverOutput) { + @Override + public String readResponse() { + checkState(solverProcess.isAlive()); final var sb = new StringBuilder(256); final var readProcessor = new ReadProcessor(); while (sb.length() == 0 || !readProcessor.isReady()) { From 1e4a5f366644f7ea26a3f5ae2b251695444f7273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 15 Sep 2020 11:30:37 +0200 Subject: [PATCH 57/99] Make toExpr in SmtLibTermTransformer process terms instead of function definitions --- .../generic/GenericSmtLibTermTransformer.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java index e432b1a6e9..cfe9f62b2b 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java @@ -234,7 +234,7 @@ private Expr toExpr(final String term, final SmtLibModel model) { parser.removeErrorListeners(); parser.addErrorListener(new ThrowExceptionErrorListener()); - return transformTerm(parser.function_def().term(), model, HashBiMap.create()); + return transformTerm(parser.term(), model, HashBiMap.create()); } @Override @@ -252,10 +252,21 @@ else if(litExpr instanceof LitExpr) { } } + private Expr toLitExpr(final String litImpl, final SmtLibModel model) { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(litImpl)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + + return transformTerm(parser.function_def().term(), model, HashBiMap.create()); + } + @Override @SuppressWarnings("unchecked") public LitExpr> toArrayLitExpr(final String arrayLitImpl, final ArrayType type, final SmtLibModel model) { - final var arrayLitExpr = toExpr(arrayLitImpl, model); + final var arrayLitExpr = toLitExpr(arrayLitImpl, model); if(arrayLitExpr == null) { return null; @@ -279,7 +290,7 @@ else if(arrayLitExpr instanceof IteExpr) { @Override public LitExpr toBvLitExpr(final String bvLitImpl, final BvType type, final SmtLibModel model) { - final var bvLitExpr = toExpr(bvLitImpl, model); + final var bvLitExpr = toLitExpr(bvLitImpl, model); if(bvLitExpr == null) { return null; @@ -338,7 +349,7 @@ else if(ctx.match_term() != null) { throw new UnsupportedOperationException(); } else if(ctx.annotate_term() != null) { - throw new UnsupportedOperationException(); + return transformTerm(ctx.annotate_term().term(), model, vars); } else { throw new SmtLibSolverException("Invalid input"); From 4898702f74496cc58062e1bdb72c9aaab8f281d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 15 Sep 2020 11:31:49 +0200 Subject: [PATCH 58/99] Refactor SmtLibItpSolver, to use support extension by inheritance instead of delegation --- .../solver/smtlib/BaseSmtLibItpSolver.java | 230 ++++++++++++++++++ .../theta/solver/smtlib/SmtLibItpMarker.java | 13 +- .../theta/solver/smtlib/SmtLibItpSolver.java | 127 ---------- 3 files changed, 238 insertions(+), 132 deletions(-) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java delete mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java new file mode 100644 index 0000000000..9ef122cf24 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java @@ -0,0 +1,230 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.model.Valuation; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.core.utils.ExprUtils; +import hu.bme.mit.theta.solver.Interpolant; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; +import hu.bme.mit.theta.solver.ItpPattern; +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.Stack; +import hu.bme.mit.theta.solver.UnknownSolverStatusException; +import hu.bme.mit.theta.solver.impl.StackImpl; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.parser.CheckSatResponse; +import hu.bme.mit.theta.solver.smtlib.parser.GeneralResponse; +import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; +import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; + +import java.util.Collection; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public abstract class BaseSmtLibItpSolver implements ItpSolver { + protected final SmtLibSymbolTable symbolTable; + protected final SmtLibTransformationManager transformationManager; + protected final SmtLibTermTransformer termTransformer; + + protected final SmtLibSolverBinary solverBinary; + + protected final Stack> assertions; + protected final Stack markers; + protected final Stack> declarationStack; + + private Valuation model; + private SolverStatus status; + + + public BaseSmtLibItpSolver( + final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, + final SmtLibTermTransformer termTransformer, final SmtLibSolverBinary solverBinary + ) { + this.symbolTable = symbolTable; + this.transformationManager = transformationManager; + this.termTransformer = termTransformer; + + this.solverBinary = solverBinary; + + this.assertions = new StackImpl<>(); + this.markers = new StackImpl<>(); + this.declarationStack = new StackImpl<>(); + + init(); + } + + @Override + public abstract ItpPattern createTreePattern(ItpMarkerTree root); + + @Override + public abstract T createMarker(); + + @Override + public Collection getMarkers() { + return markers.toCollection(); + } + + @Override + public void add(final ItpMarker marker, final Expr assertion) { + checkNotNull(marker); + checkNotNull(assertion); + checkArgument(marker instanceof SmtLibItpMarker); + checkArgument(markers.toCollection().contains(marker)); + + final var consts = ExprUtils.getConstants(assertion); + consts.removeAll(declarationStack.toCollection()); + declarationStack.add(consts); + + final var itpMarker = (SmtLibItpMarker) marker; + final var term = transformationManager.toTerm(assertion); + itpMarker.add(assertion, term); + + add(marker, assertion, consts, term); + + clearState(); + } + + protected abstract void add(final ItpMarker marker, final Expr assertion, final Set> consts, final String term); + + @Override + public SolverStatus check() { + solverBinary.issueCommand("(check-sat)"); + var res = parseResponse(solverBinary.readResponse()); + if(res.isError()) { + throw new SmtLibSolverException(res.getReason()); + } + else if(res.isSpecific()) { + final CheckSatResponse checkSatResponse = res.asSpecific(); + if(checkSatResponse.isSat()) { + status = SolverStatus.SAT; + } + else if(checkSatResponse.isUnsat()) { + status = SolverStatus.UNSAT; + } + else { + throw new UnknownSolverStatusException(); + } + } + else { + throw new AssertionError(); + } + + return status; + } + + @Override + public void push() { + markers.push(); + for (final var marker : markers) { + marker.push(); + } + assertions.push(); + declarationStack.push(); + issueGeneralCommand("(push 1)"); + } + + @Override + public void pop(final int n) { + markers.pop(n); + for (final var marker : markers) { + marker.pop(n); + } + assertions.pop(n); + declarationStack.pop(n); + issueGeneralCommand("(pop 1)"); + clearState(); + } + + @Override + public void reset() { + issueGeneralCommand("(reset)"); + clearState(); + init(); + } + + @Override + public SolverStatus getStatus() { + checkState(status != null, "Solver status is unknown."); + return status; + } + + @Override + public Valuation getModel() { + checkState(status == SolverStatus.SAT, "Cannot get model if status is not SAT."); + + if (model == null) { + model = extractModel(); + } + + return model; + } + + private Valuation extractModel() { + assert status == SolverStatus.SAT; + assert model == null; + + solverBinary.issueCommand("(get-model)"); + final var res = parseResponse(solverBinary.readResponse()); + if(res.isError()) { + throw new SmtLibSolverException(res.getReason()); + } + else if(res.isSpecific()) { + final GetModelResponse getModelResponse = res.asSpecific(); + return new SmtLibValuation(symbolTable, transformationManager, termTransformer, getModelResponse.getModel()); + } + else { + throw new AssertionError(); + } + } + + @Override + public abstract Interpolant getInterpolant(ItpPattern pattern); + + @Override + public Collection> getAssertions() { + return assertions.toCollection(); + } + + protected void clearState() { + status = null; + model = null; + } + + protected void init() { + issueGeneralCommand("(set-option :print-success true)"); + issueGeneralCommand("(set-option :produce-models true)"); + issueGeneralCommand("(set-logic ALL)"); + } + + protected final void issueGeneralCommand(String command) { + solverBinary.issueCommand(command); + var res = parseResponse(solverBinary.readResponse()); + if(res.isError()) { + throw new SmtLibSolverException(res.getReason()); + } + } + + protected final GeneralResponse parseResponse(final String response) { + try { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(response)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + return GeneralResponse.fromContext(parser.response()); + } + catch (Exception e) { + throw new SmtLibSolverException("Could not parse solver output: " + response, e); + } + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java index 0158fd56f6..2b854210f0 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java @@ -1,5 +1,8 @@ package hu.bme.mit.theta.solver.smtlib; +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolType; import hu.bme.mit.theta.solver.ItpMarker; import hu.bme.mit.theta.solver.Stack; import hu.bme.mit.theta.solver.impl.StackImpl; @@ -8,15 +11,15 @@ import static com.google.common.base.Preconditions.checkNotNull; -public abstract class SmtLibItpMarker implements ItpMarker { - private final Stack terms; +public class SmtLibItpMarker implements ItpMarker { + private final Stack, String>> terms; public SmtLibItpMarker() { terms = new StackImpl<>(); } - public void add(final T term) { - terms.add(checkNotNull(term)); + public void add(final Expr assertion, final String term) { + terms.add(Tuple2.of(checkNotNull(assertion), checkNotNull(term))); } public void push() { @@ -27,7 +30,7 @@ public void pop(final int n) { terms.pop(n); } - public Collection getTerms() { + public Collection, String>> getTerms() { return terms.toCollection(); } } diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java deleted file mode 100644 index dbba75f52e..0000000000 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolver.java +++ /dev/null @@ -1,127 +0,0 @@ -package hu.bme.mit.theta.solver.smtlib; - -import hu.bme.mit.theta.core.model.Valuation; -import hu.bme.mit.theta.core.type.Expr; -import hu.bme.mit.theta.core.type.booltype.BoolType; -import hu.bme.mit.theta.solver.Interpolant; -import hu.bme.mit.theta.solver.ItpMarker; -import hu.bme.mit.theta.solver.ItpPattern; -import hu.bme.mit.theta.solver.ItpSolver; -import hu.bme.mit.theta.solver.SolverStatus; -import hu.bme.mit.theta.solver.Stack; -import hu.bme.mit.theta.solver.impl.ItpPatternImpl; -import hu.bme.mit.theta.solver.impl.StackImpl; - -import java.util.Collection; -import java.util.function.Supplier; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -public abstract class SmtLibItpSolver> implements ItpSolver { - protected final SmtLibSolver solver; - protected final Stack markers; - protected final Supplier markerCreator; - - protected final SmtLibTransformationManager transformationManager; - protected final SmtLibTermTransformer termTransformer; - - public SmtLibItpSolver( - final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, - final SmtLibTermTransformer termTransformer, final SmtLibSolverBinary solverBinary, - final Supplier markerCreator - ) { - this.solver = new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); - this.markers = new StackImpl<>(); - this.markerCreator = markerCreator; - - this.transformationManager = transformationManager; - this.termTransformer = termTransformer; - } - - @Override - public ItpPattern createPattern(ItpMarker marker) { - checkNotNull(marker); - checkArgument(marker instanceof SmtLibItpMarker); - return new ItpPatternImpl(marker); - } - - @Override - public ItpMarker createMarker() { - final ItpMarkerType marker = markerCreator.get(); - markers.add(marker); - return marker; - } - - @Override - public void add(ItpMarker marker, Expr assertion) { - checkNotNull(marker); - checkNotNull(assertion); - checkArgument(markers.toCollection().stream().map(m -> (ItpMarker) m).anyMatch(m -> m == marker)); - - final var term = transformationManager.toTerm(assertion); - add(marker, term); - } - - protected abstract String add(final ItpMarker marker, final String term); - - @Override - public abstract Interpolant getInterpolant(ItpPattern pattern); - - // Delegate - - @Override - public Collection getMarkers() { - return markers.toCollection(); - } - - @Override - public void add(Expr assertion) { - solver.add(assertion); - } - - @Override - public SolverStatus check() { - return solver.check(); - } - - @Override - public void push() { - markers.push(); - for (final var marker : markers) { - marker.push(); - } - solver.push(); - } - - @Override - public void pop(final int n) { - markers.pop(n); - for (final var marker : markers) { - marker.pop(n); - } - solver.pop(n); - } - - @Override - public void reset() { - solver.reset(); - } - - @Override - public SolverStatus getStatus() { - return solver.getStatus(); - } - - @Override - public Valuation getModel() { - return solver.getModel(); - } - - @Override - public Collection> getAssertions() { - return solver.getAssertions(); - } - - -} From 262ecce7d5c7758e74a9a17ad06ef451cae3b3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 15 Sep 2020 11:32:47 +0200 Subject: [PATCH 59/99] Add interpolation capabilities to Z3 in solver-smtlib --- .../solver/smtlib/z3/Z3SmtLibItpMarker.java | 23 +++ .../solver/smtlib/z3/Z3SmtLibItpPattern.java | 94 +++++++++ .../solver/smtlib/z3/Z3SmtLibItpSolver.java | 194 ++++++++++++++++++ 3 files changed, 311 insertions(+) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpPattern.java create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java new file mode 100644 index 0000000000..78d7f0e4c7 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java @@ -0,0 +1,23 @@ +package hu.bme.mit.theta.solver.smtlib.z3; + +import hu.bme.mit.theta.solver.smtlib.SmtLibItpMarker; + +public class Z3SmtLibItpMarker extends SmtLibItpMarker { + private static final String markerPattern = "_z3_marker_%d"; + private static long markerCount = 0; + + static void resetMarkerCount() { + markerCount = 0; + } + + private final String markerName; + + public Z3SmtLibItpMarker() { + super(); + markerName = String.format(markerPattern, markerCount++); + } + + public String getMarkerName() { + return markerName; + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpPattern.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpPattern.java new file mode 100644 index 0000000000..2f175c89fb --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpPattern.java @@ -0,0 +1,94 @@ +package hu.bme.mit.theta.solver.smtlib.z3; + +import com.google.common.collect.Lists; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; +import hu.bme.mit.theta.solver.ItpPattern; + +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +public class Z3SmtLibItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { + final ItpMarkerTree markerTree; + + Z3SmtLibItpPattern(final ItpMarkerTree markerTree) { + this.markerTree = markerTree; + } + + @SuppressWarnings("unchecked") + static Z3SmtLibItpPattern of(final ItpMarkerTree markerTree) { + final var list = new ArrayList>(); + list.add(markerTree); + while(!list.isEmpty()) { + final var node = list.get(0); + list.remove(0); + + checkArgument(node.getMarker() instanceof Z3SmtLibItpMarker); + + list.addAll(node.getChildren()); + } + + return new Z3SmtLibItpPattern((ItpMarkerTree) markerTree); + } + + @Override + public Z3SmtLibItpMarker getA() { + checkState(isBinary()); + return markerTree.getChild(0).getMarker(); + } + + @Override + public Z3SmtLibItpMarker getB() { + checkState(isBinary()); + return markerTree.getMarker(); + } + + @Override + public List getSequence() { + checkState(isSequence()); + final var markerList = new ArrayList(); + + var current = markerTree; + while(current.getChildrenNumber() > 0) { + markerList.add(current.getMarker()); + current = current.getChild(0); + } + markerList.add(current.getMarker()); + + return Lists.reverse(markerList); + } + + @Override + public ItpMarkerTree getRoot() { + return markerTree; + } + + @Override + public E visit(ItpPatternVisitor visitor) { + return visitor.visitTreePattern(this); + } + + private boolean isBinary() { + return + markerTree != null && + markerTree.getChildrenNumber() == 1 && + markerTree.getChild(0) != null && + markerTree.getChild(0).getChildrenNumber() == 0; + } + + private boolean isSequence() { + var current = markerTree; + while(current.getChildrenNumber() > 0) { + if(current.getChildrenNumber() > 1) { + return false; + } + else { + current = current.getChild(0); + } + } + return true; + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java new file mode 100644 index 0000000000..7d50884bdb --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java @@ -0,0 +1,194 @@ +package hu.bme.mit.theta.solver.smtlib.z3; + +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolExprs; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.solver.Interpolant; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; +import hu.bme.mit.theta.solver.ItpPattern; +import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.smtlib.BaseSmtLibItpSolver; +import hu.bme.mit.theta.solver.smtlib.SmtLibInterpolant; +import hu.bme.mit.theta.solver.smtlib.SmtLibModel; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.parser.GeneralResponse; +import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.misc.Interval; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.False; + +public final class Z3SmtLibItpSolver extends BaseSmtLibItpSolver { + private boolean topMostContainsAssertions = false; + + public Z3SmtLibItpSolver( + final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, + final SmtLibTermTransformer termTransformer, final SmtLibSolverBinary solverBinary + ) { + super(symbolTable, transformationManager, termTransformer, solverBinary); + } + + @Override + public ItpPattern createTreePattern(final ItpMarkerTree root) { + checkNotNull(root); + return Z3SmtLibItpPattern.of(root); + } + + @Override + public Z3SmtLibItpMarker createMarker() { + final var marker = new Z3SmtLibItpMarker(); + markers.add(marker); + return marker; + } + + @Override + public void add(ItpMarker marker, Expr assertion) { + if(topMostContainsAssertions) { + issueGeneralCommand("(pop 1)"); // Topmost frame contains marker assertions + topMostContainsAssertions = false; + } + super.add(marker, assertion); + } + + @Override + protected void add(final ItpMarker marker, final Expr assertion, final Set> consts, final String term) { + consts.stream().map(symbolTable::getDeclaration).forEach(this::issueGeneralCommand); + } + + @Override + public SolverStatus check() { + if(topMostContainsAssertions) { + issueGeneralCommand("(pop 1)"); // Topmost frame contains marker assertions + topMostContainsAssertions = false; + } + Z3SmtLibItpMarker.resetMarkerCount(); + issueGeneralCommand("(push 1)"); // Topmost frame contains marker assertions + topMostContainsAssertions = true; + + for(final var marker : markers.toCollection()) { + final var term = String.format("(and %s)", String.join(" ", marker.getTerms().stream().map(Tuple2::get2).collect(Collectors.toUnmodifiableList()))); + + issueGeneralCommand(String.format("(assert (! %s :named %s))", term, marker.getMarkerName())); + } + + return super.check(); + } + + @Override + public void pop(int n) { + if(topMostContainsAssertions) { + issueGeneralCommand("(pop 1)"); // Topmost frame contains marker assertions + topMostContainsAssertions = false; + } + super.pop(n); // Topmost frame contains marker assertions + } + + @Override + public Interpolant getInterpolant(final ItpPattern pattern) { + checkState(getStatus() == SolverStatus.UNSAT, "Cannot get interpolant if status is not UNSAT."); + checkArgument(pattern instanceof Z3SmtLibItpPattern); + final var z3ItpPattern = (Z3SmtLibItpPattern) pattern; + + final var term = patternToTerm(z3ItpPattern.getRoot()); + final var markerCount = getMarkerCount(z3ItpPattern.getRoot()); + + final List> itpList = new LinkedList<>(); + + solverBinary.issueCommand(String.format("(get-interpolant %s)", term)); + for(var i = 0; i < markerCount - 1; i++) { + final var res = parseItpResponse(solverBinary.readResponse()); + itpList.add(termTransformer.toExpr(res, BoolExprs.Bool(), new SmtLibModel(Collections.emptyMap()))); + } + itpList.add(False()); + + final Map> itpMap = new HashMap<>(); + buildItpMapFormList(z3ItpPattern.getRoot(), itpList, itpMap); + + return new SmtLibInterpolant(itpMap); + } + + private String patternToTerm(final ItpMarkerTree markerTree) { + final Collection opTerms = new LinkedList<>(); + + final Z3SmtLibItpMarker marker = markerTree.getMarker(); + opTerms.add(marker.getMarkerName()); + //opTerms.addAll(marker.getTerms().stream().map(Tuple2::get2).collect(Collectors.toUnmodifiableList())); + + for (final var child : markerTree.getChildren()) { + final var childTerm = patternToTerm(child); + opTerms.add(childTerm); + } + + return String.format("(interp (and %s))", String.join(" ", opTerms)); + } + + private void buildItpMapFormList(final ItpMarkerTree pattern, final List> itpList, + final Map> itpMap) { + for (final ItpMarkerTree child : pattern.getChildren()) { + buildItpMapFormList(child, itpList, itpMap); + } + final ItpMarker marker = pattern.getMarker(); + final Expr itpExpr = itpList.get(0); + itpMap.put(marker, itpExpr); + itpList.remove(0); + } + + private int getMarkerCount(final ItpMarkerTree markerTree) { + return 1 + markerTree.getChildren().stream().mapToInt(this::getMarkerCount).sum(); + } + + @Override + protected void init() { + issueGeneralCommand("(set-option :print-success true)"); + issueGeneralCommand("(set-option :produce-interpolants true)"); + super.init(); + issueGeneralCommand("(push 1)"); // Topmost frame contains marker assertions + } + + private String parseItpResponse(final String response) { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(response)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + try { + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + return extractString(parser.term()); + } + catch (Exception e) { + try { + throw new SmtLibSolverException(parser.response().general_response_error().reason.getText()); + } + catch(Exception ex) { + throw new SmtLibSolverException("Could not parse solver output: " + response, e); + } + } + } + + private static String extractString(final ParserRuleContext ctx) { + return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex())); + } +} From 2e7f6bf74e36517cdd1cc858447151ccb89b1318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 15 Sep 2020 11:33:04 +0200 Subject: [PATCH 60/99] Add dedicated solver factory for Z3 --- .../smtlib/z3/Z3SmtLibSolverFactory.java | 57 +++++++++++++++++++ .../smtlib/z3/Z3SmtLibSolverInstaller.java | 2 +- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java new file mode 100644 index 0000000000..2c834261a5 --- /dev/null +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java @@ -0,0 +1,57 @@ +package hu.bme.mit.theta.solver.smtlib.z3; + +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolver; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTransformationManager; + +import java.nio.file.Path; + +public class Z3SmtLibSolverFactory implements SolverFactory { + private final Path solverPath; + private final String[] args; + + private Z3SmtLibSolverFactory(Path solverPath, String[] args) { + this.solverPath = solverPath; + this.args = args; + } + + public static Z3SmtLibSolverFactory create(Path solverPath, String[] args) { + return new Z3SmtLibSolverFactory(solverPath, args); + } + + @Override + public Solver createSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); + } + + @Override + public UCSolver createUCSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); + } + + @Override + public ItpSolver createItpSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new Z3SmtLibItpSolver(symbolTable, transformationManager, termTransformer, solverBinary); + } +} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java index 7baed63787..e90d139aa4 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java +++ b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java @@ -147,7 +147,7 @@ public SolverFactory getSolverFactory(final Path home, final String version) thr final var solverArgsPath = argsFile(installDir); final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); - return GenericSmtLibSolverFactory.create(solverFilePath, solverArgs); + return Z3SmtLibSolverFactory.create(solverFilePath, solverArgs); } catch (IOException e) { throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); From cd547daaa2cabef9dab73e365b2dcfa8714f15aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 15 Sep 2020 11:33:29 +0200 Subject: [PATCH 61/99] Add interpolation tests for Z3SmtLibItpSolver --- .../solver/smtlib/SmtLibItpSolverTest.java | 277 ++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java new file mode 100644 index 0000000000..e6a1af3113 --- /dev/null +++ b/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java @@ -0,0 +1,277 @@ +/* + * Copyright 2017 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hu.bme.mit.theta.solver.smtlib; + +import com.google.common.collect.ImmutableList; +import hu.bme.mit.theta.common.logging.NullLogger; +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.decl.ParamDecl; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.core.type.functype.FuncType; +import hu.bme.mit.theta.core.type.inttype.IntType; +import hu.bme.mit.theta.core.utils.ExprUtils; +import hu.bme.mit.theta.solver.Interpolant; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpPattern; +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static hu.bme.mit.theta.core.decl.Decls.Const; +import static hu.bme.mit.theta.core.decl.Decls.Param; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Forall; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Imply; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; +import static hu.bme.mit.theta.core.type.functype.FuncExprs.App; +import static hu.bme.mit.theta.core.type.functype.FuncExprs.Func; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Add; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Eq; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Mul; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Neq; +import static hu.bme.mit.theta.solver.ItpMarkerTree.Leaf; +import static hu.bme.mit.theta.solver.ItpMarkerTree.Subtree; +import static hu.bme.mit.theta.solver.ItpMarkerTree.Tree; + +public final class SmtLibItpSolverTest { + private static SmtLibSolverManager solverManager; + private static SolverFactory solverFactory; + + @BeforeClass + public static void init() throws SmtLibSolverInstallerException, IOException { + Path home = Files.createTempDirectory("theta-solver"); + + solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); + solverManager.install("z3", "4.5.0", "4.5.0", false); + + solverFactory = solverManager.getSolverFactory("z3", "latest"); + } + + @AfterClass + public static void destroy() throws SmtLibSolverInstallerException { + solverManager.uninstall("z3", "latest"); + } + + ItpSolver solver; + + Expr a; + Expr b; + Expr c; + Expr d; + Expr e; + Expr> f; + Expr> g; + + @Before + public void initialize() { + solver = solverFactory.createItpSolver(); + + final ConstDecl ad = Const("a", Int()); + final ConstDecl bd = Const("b", Int()); + final ConstDecl cd = Const("c", Int()); + final ConstDecl dd = Const("d", Int()); + final ConstDecl ed = Const("e", Int()); + final ConstDecl> fd = Const("f", Func(Int(), Int())); + final ConstDecl> gd = Const("g", Func(Int(), Int())); + + a = ad.getRef(); + b = bd.getRef(); + c = cd.getRef(); + d = dd.getRef(); + e = ed.getRef(); + f = fd.getRef(); + g = gd.getRef(); + } + + @Test + public void testBinaryInterpolation() { + final ItpMarker A = solver.createMarker(); + final ItpMarker B = solver.createMarker(); + final ItpPattern pattern = solver.createBinPattern(A, B); + + solver.add(A, Eq(a, b)); + solver.add(A, Eq(a, c)); + solver.add(B, Eq(b, d)); + solver.add(B, Neq(c, d)); + + solver.check(); + Assert.assertEquals(SolverStatus.UNSAT, solver.getStatus()); + final Interpolant itp = solver.getInterpolant(pattern); + + System.out.println(itp.eval(A)); + System.out.println("----------"); + Assert.assertTrue(ExprUtils.getVars(itp.eval(A)).size() <= 3); + } + + @Test + public void testSequenceInterpolation() { + final ItpMarker I1 = solver.createMarker(); + final ItpMarker I2 = solver.createMarker(); + final ItpMarker I3 = solver.createMarker(); + final ItpMarker I4 = solver.createMarker(); + final ItpMarker I5 = solver.createMarker(); + final ItpPattern pattern = solver.createSeqPattern(ImmutableList.of(I1, I2, I3, I4, I5)); + + solver.add(I1, Eq(a, Int(0))); + solver.add(I2, Eq(a, b)); + solver.add(I3, Eq(c, d)); + solver.add(I4, Eq(d, Int(1))); + solver.add(I5, Eq(b, c)); + + solver.check(); + Assert.assertEquals(SolverStatus.UNSAT, solver.getStatus()); + final Interpolant itp = solver.getInterpolant(pattern); + + System.out.println(itp.eval(I1)); + System.out.println(itp.eval(I2)); + System.out.println(itp.eval(I3)); + System.out.println(itp.eval(I4)); + System.out.println(itp.eval(I5)); + System.out.println("----------"); + } + + @Test + public void testTreeInterpolation() { + final ItpMarker I1 = solver.createMarker(); + final ItpMarker I2 = solver.createMarker(); + final ItpMarker I3 = solver.createMarker(); + final ItpMarker I4 = solver.createMarker(); + final ItpMarker I5 = solver.createMarker(); + final ItpPattern pattern = solver.createTreePattern(Tree(I3, Subtree(I1, Leaf(I4), Leaf(I5)), Leaf(I2))); + + solver.add(I1, Eq(a, Int(0))); + solver.add(I2, Eq(a, b)); + solver.add(I3, Eq(c, d)); + solver.add(I4, Eq(d, Int(1))); + solver.add(I5, Eq(b, c)); + + solver.check(); + Assert.assertEquals(SolverStatus.UNSAT, solver.getStatus()); + final Interpolant itp = solver.getInterpolant(pattern); + + System.out.println(itp.eval(I1)); + System.out.println(itp.eval(I2)); + System.out.println(itp.eval(I3)); + System.out.println(itp.eval(I4)); + System.out.println(itp.eval(I5)); + System.out.println("----------"); + } + + @Test + public void testEUF() { + final ItpMarker A = solver.createMarker(); + final ItpMarker B = solver.createMarker(); + final ItpPattern pattern = solver.createBinPattern(A, B); + + solver.add(A, Eq(App(f, a), c)); + solver.add(A, Eq(App(f, b), d)); + solver.add(B, Eq(a, b)); + solver.add(B, Neq(App(g, c), App(g, d))); + + solver.check(); + Assert.assertEquals(SolverStatus.UNSAT, solver.getStatus()); + final Interpolant itp = solver.getInterpolant(pattern); + + System.out.println(itp.eval(A)); + System.out.println("----------"); + } + + @Test + public void testLIA() { + final ItpMarker A = solver.createMarker(); + final ItpMarker B = solver.createMarker(); + final ItpPattern pattern = solver.createBinPattern(A, B); + + solver.add(A, Eq(b, Mul(ImmutableList.of(Int(2), a)))); + solver.add(B, Eq(b, Add(ImmutableList.of(Mul(ImmutableList.of(Int(2), c)), Int(1))))); + + solver.check(); + Assert.assertEquals(SolverStatus.UNSAT, solver.getStatus()); + final Interpolant itp = solver.getInterpolant(pattern); + + System.out.println(itp.eval(A)); + System.out.println("----------"); + } + + @Test + public void testQuantifiers() { + final ItpMarker A = solver.createMarker(); + final ItpMarker B = solver.createMarker(); + final ItpPattern pattern = solver.createBinPattern(A, B); + + final ConstDecl id = Const("i", Int()); + final ConstDecl> pd = Const("p", Func(Int(), Bool())); + final ConstDecl> qd = Const("q", Func(Int(), Bool())); + final ParamDecl x1d = Param("x", Int()); + final ParamDecl x2d = Param("x", Int()); + + final Expr i = id.getRef(); + final Expr> p = pd.getRef(); + final Expr> q = qd.getRef(); + final Expr x1 = x1d.getRef(); + final Expr x2 = x2d.getRef(); + + solver.add(A, Forall(ImmutableList.of(x1d), Imply(App(q, x1), App(p, x1)))); + solver.add(A, Forall(ImmutableList.of(x2d), Not(App(p, x2)))); + solver.add(B, App(q, i)); + + solver.check(); + Assert.assertEquals(SolverStatus.UNSAT, solver.getStatus()); + final Interpolant itp = solver.getInterpolant(pattern); + + System.out.println(itp.eval(A)); + System.out.println("----------"); + } + + @Test + public void testPushPop() { + final ItpMarker A = solver.createMarker(); + final ItpMarker B = solver.createMarker(); + final ItpPattern pattern = solver.createBinPattern(A, B); + + solver.add(A, Eq(a, b)); + solver.add(B, Eq(b, c)); + + solver.push(); + + solver.add(A, Neq(a, c)); + solver.check(); + Assert.assertEquals(SolverStatus.UNSAT, solver.getStatus()); + + solver.pop(); + + solver.add(B, Neq(a, c)); + solver.check(); + Assert.assertEquals(SolverStatus.UNSAT, solver.getStatus()); + final Interpolant itp = solver.getInterpolant(pattern); + + System.out.println(itp.eval(A)); + System.out.println("----------"); + } + +} From 84644c0dc4d12e2916e21b750e9fb29d72f8953c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sun, 20 Dec 2020 15:14:17 +0100 Subject: [PATCH 62/99] Add solver-smtlib documentation --- subprojects/solver-smtlib-cli/README.md | 74 ++++++++++++++++++++++++- subprojects/solver-smtlib/README.md | 55 +++++++++++++++++- 2 files changed, 127 insertions(+), 2 deletions(-) diff --git a/subprojects/solver-smtlib-cli/README.md b/subprojects/solver-smtlib-cli/README.md index 227a82f08b..8173a66f6f 100644 --- a/subprojects/solver-smtlib-cli/README.md +++ b/subprojects/solver-smtlib-cli/README.md @@ -1 +1,73 @@ -This project is a cli tool for installing, managing the SMT-LIB compatible solvers. \ No newline at end of file +## Overview + +The `solver-smtlib-cli` project is an executable (command line) tool for managing the SMT-LIB compatible solvers. +For more information about the SMT-LIB compatibility in Theta, take a look at the [`solver-smtlib`](../solver-smtlib/README.md) project. + +### Related projects + +* [`solver`](../solver/README.md): Contains the generic utilities and solver interface of Theta. +* [`solver-smtlib`](../solver-smtlib/README.md): Implements Theta's solver interface to support SMT-LIB compatible solvers. + +## Using the tool + +1. First, get the tool. + * The easiest way is to download a [pre-built release](https://github.com/ftsrg/theta/releases). + * You can also [build](../../doc/Build.md) the tool yourself. The runnable jar file will appear under _build/libs/_ with the name _theta-solver-smtlib-cli-\-all.jar_, you can simply rename it to _theta-solver-smtlib-cli.jar_.. +2. Running the tool requires Java (JRE) 11. +3. The tool can be executed with `java -jar theta-solver-smtlib-cli.jar [MAIN ARGUMENTS] [COMMAND] [ARGUMENTS]`. + * If no arguments are given, a help screen is displayed about the arguments and their possible values. + More information can also be found below. + +## Arguments + +The tool supports the following main arguments. These are all optional: +* `--home`: Sets the path of the solver registry. It defaults to a folder named _.theta_ in the home folder of the current user. +* `--help`: Prints the help message. + +The tool supports the following commands and their arguments: + +* `install :`: Installs a solver with the given name and version to the current solver registry. The __ identifies the driver (a.k.a. the type) of the solver, while the __ identifies the version of the solver to install. (See the list of supported solvers and their versions with `list-supported`) + * `--name`: Install the solver version under this custom name (:), instead of the default (:) + * `--tempt-murphy`: Enables the installation of unsupported solver versions. If you enable this, you can expect things to break, as these solvers were not tested with Theta at all! +* `install-generic`: Installs an SMT-LIB compatible solver with the generic driver. For more information see the [Generic driver](#Generic-driver) section. + * `--solver-path` **[required]**: Denotes the path to the binary of the solver. + * `--solver-args`: The command line arguments to pass to the generic solver. + * `--name` **[required]**: Install the solver under this custom name (generic:) +* `uninstall :`: Uninstalls a solver with the given name and version from the current solver registry. (See the list of installed solvers and their versions with `list-installed`) +* `reinstall :`: Reinstalls a solver with the given name and version in the current solver registry. (See the list of installed solvers and their versions with `list-installed`.) **Note**: This command is not available for solvers installed with the generic driver. +* `get-info :`: Gets the stored information about the solver with the given name and version in the current solver registry. (See the list of installed solvers and their versions with `list-installed`) +* `edit-args :`: Edits the command line arguments of the solver with the given name and version. The command opens a txt file that stores the command line arguments to edit with the default editor, or prints the path of the file to edit if the default editor is not applicable (e.g. CLI). (See the list of installed solvers and their versions with `list-installed`) + * `--print`: If given, the path of the file to edit will be printed instead of opening. +* `list-installed []`: Lists the installed solvers and their versions. If the __ is given, only the versions of that solver will be listed. +* `list-supported []`: Lists the supported solvers and their versions. If the __ is given, only the versions of that solver will be listed. + +### For developer usage + +The following main arguments are targeted for developers: + +| Flag | Description | +|---|---| +| `--stacktrace` | Print full stack trace for exceptions. | +| `--loglevel` | `--loglevel`: Detailedness of logging. Possible values (from the least to the most detailed): `RESULT`, `MAINSTEP`, `SUBSTEP` (default), `INFO`, `DETAIL`, `VERBOSE` | + +## Generic driver + +It is possible to integrate any fully SMT-LIB compatible solvers with Theta using the generic driver. To do this, the following information is needed: + +* The path to the binary of the solver. If the solver does not have a binary (e.g. it is Java based), then a bash script should be created that serves as an entry point for the solver. +* The command line arguments to pass to the solver. These arguments should configure the solver for the following behavior: + * It must read its input from the standard input. + * It must write its output to the standard output. Moreover, it should flush the standard output after every line. + * It **must not** write anything else to the standard output that is not part of the SMT-LIB standard. The first command the driver issues is the `(set-option :print-success true)`, so the first characters the binary outputs should be the result of this command! + +For more information see the default configurations of the supported solvers. + +## Supported solvers + +Currently, the following solvers are supported. + +* Z3 + * `4.4.0` - `4.6.0`: Supported with interpolation. + * `4.7.1` - `4.8.9`: Supported without interpolation. Interpolation was removed in `4.7.0`. +* CVC4 + * `1.0` - `1.8`: Supported. \ No newline at end of file diff --git a/subprojects/solver-smtlib/README.md b/subprojects/solver-smtlib/README.md index 709f60bec0..0945f8e2d1 100644 --- a/subprojects/solver-smtlib/README.md +++ b/subprojects/solver-smtlib/README.md @@ -1 +1,54 @@ -This project wraps a generic solver that supports the SMT-LIB2 interface into our common interfaces for solvers (located in the [solver](../solver) project). \ No newline at end of file +## Overview + +This project wraps a generic solver that supports the SMT-LIB2 interface into our common interfaces for solvers (located in the [solver](../solver) project). + +### Related projects + +* [`solver`](../solver/README.md): Contains the generic utilities and solver interface of Theta. +* [`solver-smtlib-cli`](../solver-smtlib-cli/README.md): Command line tool for managing the SMT-LIB compatible solvers. + +## SMT-LIB2 + +The [SMT-LIB2 standard](http://smtlib.cs.uiowa.edu/) is an international initiative, whose goal is to partly provide a common input and output language for SMT solvers. The standard is adapted by many SMT solvers, such as Z3, MathSAT, CVC4, etc... + +However, there are some limitation to this standard, both in terms of its content and its practical application by the solvers that support it: + +- There are no standard way of denoting an array literal in SMT-LIB. Each solver that support the said theory used to come up with a solution of their own in this matter. This lead to the creation of the `as-array` (Z3), and the `as const` (CVC4, MathSAT) constructs. Nowadays, solvers tend to support the `as const` construct (event the newer versions of Z3). +- There are no standard way of denoting interpolation. Solvers that support interpolation (Z3, SMTInterpol, MathSAT) have their own extension added to SMT-LIB to support this feature. +- The support for the standard tends to be loose in some solvers. For example, MathSAT expects a numeric argument to `push` and `pop`, does not default to 1, like the standard. Moreover, MathSAT uses a custom output language when outputting models, that is not part of the standard. + +This list is unfortunately far from being complete, so one has to be careful when integrating a new solver with SMT-LIB support. + +## Architecture + +The issues of compatibility described in the earlier section warranted to be considered in the architecture. The component is designed to be a composite of subcomponents along well-defined interfaced that make it possible to replace complete subcomponents if for the sake of a solver. + +### Generic architecture interface + +In general, to have an SMT-LIB supporting solver, components implementing the following interfaces has to be developed: + +- `SmtLibTransformationManager`: Transforms anything in Theta to their SMT-LIB counterpart. It uses further components for this feature: + - `SmtLibTypeTransformer`: Transforms a Theta type to and SMT-LIB type. + - `SmtLibDeclTransformer`: Transforms a Theta declaration to an SMT-LIB declaration. + - `SmtLibExprTransformer`: Transforms a Theta expression to an SMT-LIB expression. + - `SmtLibSymbolTable`: Caches the Theta declarations and their SMT-LIB counterpart. +- `SmtLibTermTransformer`: Transforms an SMT-LIB expression to a Theta expression. It provides methods that ensure type-safety. +- `SmtLibSolverBinary`: Provides an interface to communicate with the binary of the solver. +- `SmtLibSolverInstaller`: An interface to support installation scripts and solver management. + +The SMT-LIB grammar that the component supports is defined using ANTLR. The ANTLR grammar can be found in the source folder (`SMTLIBv2.g4`). + +The components above are integrated into a working solver implementation with Theta's solver interface by the followin classes: +- `SmtLibSolver`: Provides a solver implementing Theta's `Solver` and `UCSolver` interface supporting basic satisfiability checks, model querying and unsat core querying. +- `BaseSmtLibItpSolver`: Provides a solver implementinf Theta`s `ItpSolver` interface supporting interpolating solvers. **Note**: As interpolation is not part of the SMT-LIB standard, this class is abstract. Each solver supporting interpolation has to extend this class and configure it properly. + +### Generic interface implementation + +The interfaces above have a default, generic implementation that works with solvers that follow the SMT-LIB standard fully. These generic classes can be found in the `hu.bme.mit.theta.solver.smtlib.generic` package. + +### Solver specific implementations + +Right now, the solver-smtlib subproject supports the following solvers. Each package contains the specialization of the interfaces above that communicate with the said solver: + +- **Z3** (`hu.bme.mit.theta.solver.smtlib.z3`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors, functions), and supports interpolation as well (binary, sequential and tree interpolation) up to version 4.7. +- **CVC4** (`hu.bme.mit.theta.solver.smtlib.cvc4`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). \ No newline at end of file From e5c9bf683012b1fb0fab2da5827969e163a4cf91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 19 Feb 2021 11:44:20 +0100 Subject: [PATCH 63/99] Modify project structure to match that of #101. --- settings.gradle.kts | 9 +- .../refinement/ExprTraceNewtonChecker.java | 607 ------------------ .../expr/refinement/ExprTraceUCBChecker.java | 277 -------- .../expr/refinement/ExprTraceUCBChecker.java | 22 +- .../hu/bme/mit/theta/common/QuadFunction.java | 0 .../bme/mit/theta/common/QuintFunction.java | 0 .../java/hu/bme/mit/theta/common/SemVer.java | 0 .../bme/mit/theta/core/utils/ExprUtils.java | 2 + .../mit/theta/solver/impl/ItpPatternImpl.java | 64 -- .../solver/smtlib/z3/Z3SmtLibItpPattern.java | 94 --- .../{ => solver}/solver-smtlib-cli/README.md | 2 +- .../solver-smtlib-cli}/bin/.gitignore | 0 .../solver-smtlib-cli/build.gradle.kts | 0 .../theta/solver/smtlib/cli/SmtLibCli.java | 0 .../{ => solver}/solver-smtlib/README.md | 2 +- .../solver-smtlib}/bin/.gitignore | 0 .../solver-smtlib/build.gradle.kts | 0 .../solver-smtlib/src/main/antlr/SMTLIBv2.g4 | 0 .../solver/smtlib/BaseSmtLibItpSolver.java | 0 .../smtlib/BaseSmtLibSolverInstaller.java | 0 .../solver/smtlib/SmtLibDeclTransformer.java | 0 .../solver/smtlib/SmtLibExprTransformer.java | 0 .../solver/smtlib/SmtLibInterpolant.java | 0 .../theta/solver/smtlib/SmtLibItpMarker.java | 0 .../mit/theta/solver/smtlib/SmtLibModel.java | 0 .../mit/theta/solver/smtlib/SmtLibSolver.java | 0 .../solver/smtlib/SmtLibSolverBinary.java | 0 .../smtlib/SmtLibSolverBinaryException.java | 0 .../solver/smtlib/SmtLibSolverException.java | 0 .../solver/smtlib/SmtLibSolverInstaller.java | 0 .../SmtLibSolverInstallerException.java | 0 .../solver/smtlib/SmtLibSymbolTable.java | 0 .../solver/smtlib/SmtLibTermTransformer.java | 0 .../smtlib/SmtLibTransformationManager.java | 0 .../solver/smtlib/SmtLibTypeTransformer.java | 0 .../theta/solver/smtlib/SmtLibValuation.java | 0 .../cvc4/CVC4SmtLibSolverInstaller.java | 0 .../generic/GenericSmtLibDeclTransformer.java | 0 .../generic/GenericSmtLibExprTransformer.java | 0 .../generic/GenericSmtLibSolverBinary.java | 0 .../generic/GenericSmtLibSolverFactory.java | 0 .../generic/GenericSmtLibSolverInstaller.java | 0 .../generic/GenericSmtLibSymbolTable.java | 0 .../generic/GenericSmtLibTermTransformer.java | 2 +- .../GenericSmtLibTransformationManager.java | 0 .../generic/GenericSmtLibTypeTransformer.java | 0 .../smtlib/manager/SmtLibSolverManager.java | 0 .../smtlib/parser/CheckSatResponse.java | 0 .../solver/smtlib/parser/GeneralResponse.java | 0 .../smtlib/parser/GetModelResponse.java | 0 .../smtlib/parser/GetUnsatCoreResponse.java | 0 .../smtlib/parser/SpecificResponse.java | 0 .../parser/ThrowExceptionErrorListener.java | 0 .../solver/smtlib/z3/Z3SmtLibItpMarker.java | 0 .../solver/smtlib/z3/Z3SmtLibItpSolver.java | 1 - .../smtlib/z3/Z3SmtLibSolverFactory.java | 0 .../smtlib/z3/Z3SmtLibSolverInstaller.java | 0 .../solver/smtlib/SmtLibItpSolverTest.java | 0 .../solver/smtlib/SmtLibSolverBVTest.java | 0 .../theta/solver/smtlib/SmtLibSolverTest.java | 2 +- .../{common => solver}/solver-z3/README.md | 0 .../solver-z3}/bin/.gitignore | 0 .../solver-z3/build.gradle.kts | 0 .../theta/solver/z3/Z3DeclTransformer.java | 0 .../theta/solver/z3/Z3ExprTransformer.java | 0 .../mit/theta/solver/z3/Z3Interpolant.java | 0 .../bme/mit/theta/solver/z3/Z3ItpMarker.java | 0 .../bme/mit/theta/solver/z3/Z3ItpPattern.java | 0 .../bme/mit/theta/solver/z3/Z3ItpSolver.java | 0 .../hu/bme/mit/theta/solver/z3/Z3Solver.java | 0 .../mit/theta/solver/z3/Z3SolverFactory.java | 0 .../mit/theta/solver/z3/Z3SymbolTable.java | 0 .../theta/solver/z3/Z3TermTransformer.java | 0 .../solver/z3/Z3TransformationManager.java | 0 .../theta/solver/z3/Z3TypeTransformer.java | 0 .../bme/mit/theta/solver/z3/package-info.java | 0 .../mit/theta/solver/z3/SolverUtilsTest.java | 0 .../mit/theta/solver/z3/Z3ItpSolverTest.java | 0 .../bme/mit/theta/solver/z3/Z3ModelTest.java | 0 .../mit/theta/solver/z3/Z3SolverBVTest.java | 0 .../bme/mit/theta/solver/z3/Z3SolverTest.java | 1 + .../{common => solver}/solver/README.md | 0 .../solver}/bin/.gitignore | 0 .../solver/build.gradle.kts | 0 .../hu/bme/mit/theta/solver/Interpolant.java | 0 .../hu/bme/mit/theta/solver/ItpMarker.java | 0 .../bme/mit/theta/solver/ItpMarkerTree.java | 0 .../hu/bme/mit/theta/solver/ItpPattern.java | 0 .../hu/bme/mit/theta/solver/ItpSolver.java | 0 .../java/hu/bme/mit/theta/solver/Solver.java | 59 +- .../hu/bme/mit/theta/solver/SolverBase.java | 0 .../bme/mit/theta/solver/SolverFactory.java | 0 .../hu/bme/mit/theta/solver/SolverStatus.java | 0 .../java/hu/bme/mit/theta/solver/Stack.java | 0 .../hu/bme/mit/theta/solver/UCSolver.java | 0 .../solver/UnknownSolverStatusException.java | 0 .../bme/mit/theta/solver/impl/NullSolver.java | 0 .../bme/mit/theta/solver/impl/StackImpl.java | 0 .../hu/bme/mit/theta/solver/package-info.java | 0 .../mit/theta/solver/utils/SolverUtils.java | 0 .../mit/theta/solver/utils/WithPushPop.java | 0 .../hu/bme/mit/theta/solver/SolverStub.java | 0 .../hu/bme/mit/theta/solver/StackTest.java | 0 .../bme/mit/theta/solver/WithPushPopTest.java | 0 104 files changed, 25 insertions(+), 1119 deletions(-) delete mode 100644 subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java delete mode 100644 subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java rename subprojects/common/{ => common}/src/main/java/hu/bme/mit/theta/common/QuadFunction.java (100%) rename subprojects/common/{ => common}/src/main/java/hu/bme/mit/theta/common/QuintFunction.java (100%) rename subprojects/common/{ => common}/src/main/java/hu/bme/mit/theta/common/SemVer.java (100%) delete mode 100644 subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/ItpPatternImpl.java delete mode 100644 subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpPattern.java rename subprojects/{ => solver}/solver-smtlib-cli/README.md (95%) rename subprojects/{common/solver-z3 => solver/solver-smtlib-cli}/bin/.gitignore (100%) rename subprojects/{ => solver}/solver-smtlib-cli/build.gradle.kts (100%) rename subprojects/{ => solver}/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java (100%) rename subprojects/{ => solver}/solver-smtlib/README.md (99%) rename subprojects/{common/solver => solver/solver-smtlib}/bin/.gitignore (100%) rename subprojects/{ => solver}/solver-smtlib/build.gradle.kts (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/antlr/SMTLIBv2.g4 (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinaryException.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java (99%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java (99%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java (100%) rename subprojects/{ => solver}/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java (99%) rename subprojects/{common => solver}/solver-z3/README.md (100%) rename subprojects/{solver-smtlib-cli => solver/solver-z3}/bin/.gitignore (100%) rename subprojects/{common => solver}/solver-z3/build.gradle.kts (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3DeclTransformer.java (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ExprTransformer.java (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Interpolant.java (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpMarker.java (100%) rename subprojects/{ => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpPattern.java (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverFactory.java (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SymbolTable.java (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TermTransformer.java (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TransformationManager.java (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TypeTransformer.java (100%) rename subprojects/{common => solver}/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/package-info.java (100%) rename subprojects/{common => solver}/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/SolverUtilsTest.java (100%) rename subprojects/{common => solver}/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ItpSolverTest.java (100%) rename subprojects/{common => solver}/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ModelTest.java (100%) rename subprojects/{common => solver}/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverBVTest.java (100%) rename subprojects/{common => solver}/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java (99%) rename subprojects/{common => solver}/solver/README.md (100%) rename subprojects/{solver-smtlib => solver/solver}/bin/.gitignore (100%) rename subprojects/{common => solver}/solver/build.gradle.kts (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/Interpolant.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarker.java (100%) rename subprojects/solver/{ => solver}/src/main/java/hu/bme/mit/theta/solver/ItpMarkerTree.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java (57%) rename subprojects/solver/{ => solver}/src/main/java/hu/bme/mit/theta/solver/SolverBase.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/SolverStatus.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/Stack.java (100%) rename subprojects/solver/{ => solver}/src/main/java/hu/bme/mit/theta/solver/UCSolver.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/UnknownSolverStatusException.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/impl/StackImpl.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/package-info.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/utils/SolverUtils.java (100%) rename subprojects/{common => solver}/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java (100%) rename subprojects/{common => solver}/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java (100%) rename subprojects/{common => solver}/solver/src/test/java/hu/bme/mit/theta/solver/StackTest.java (100%) rename subprojects/{common => solver}/solver/src/test/java/hu/bme/mit/theta/solver/WithPushPopTest.java (100%) diff --git a/settings.gradle.kts b/settings.gradle.kts index 856b94e54f..04f191d083 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,8 +4,6 @@ include( "common/analysis", "common/common", "common/core", - "common/solver", - "common/solver-z3", "cfa/cfa", "cfa/cfa-analysis", @@ -21,7 +19,12 @@ include( "xsts/xsts", "xsts/xsts-analysis", - "xsts/xsts-cli" + "xsts/xsts-cli", + + "solver/solver", + "solver/solver-z3", + "solver/solver-smtlib", + "solver/solver-smtlib-cli" ) for (project in rootProject.children) { diff --git a/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java b/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java deleted file mode 100644 index 349a83fb9b..0000000000 --- a/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java +++ /dev/null @@ -1,607 +0,0 @@ -package hu.bme.mit.theta.analysis.expr.refinement; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import hu.bme.mit.theta.analysis.Trace; -import hu.bme.mit.theta.analysis.expr.ExprAction; -import hu.bme.mit.theta.analysis.expr.ExprState; -import hu.bme.mit.theta.analysis.expr.ExprTraceUtils; -import hu.bme.mit.theta.analysis.expr.StmtAction; -import hu.bme.mit.theta.common.Tuple2; -import hu.bme.mit.theta.common.Utils; -import hu.bme.mit.theta.core.decl.VarDecl; -import hu.bme.mit.theta.core.model.BasicSubstitution; -import hu.bme.mit.theta.core.model.ImmutableValuation; -import hu.bme.mit.theta.core.model.Valuation; -import hu.bme.mit.theta.core.stmt.AssignStmt; -import hu.bme.mit.theta.core.stmt.AssumeStmt; -import hu.bme.mit.theta.core.stmt.HavocStmt; -import hu.bme.mit.theta.core.stmt.SkipStmt; -import hu.bme.mit.theta.core.stmt.Stmt; -import hu.bme.mit.theta.core.stmt.StmtVisitor; -import hu.bme.mit.theta.core.type.Expr; -import hu.bme.mit.theta.core.type.Type; -import hu.bme.mit.theta.core.type.booltype.BoolType; -import hu.bme.mit.theta.core.utils.ExprSimplifier; -import hu.bme.mit.theta.core.utils.ExprUtils; -import hu.bme.mit.theta.core.utils.PathUtils; -import hu.bme.mit.theta.core.utils.SpState; -import hu.bme.mit.theta.core.utils.StmtUtils; -import hu.bme.mit.theta.core.utils.VarIndexing; -import hu.bme.mit.theta.core.utils.WpState; -import hu.bme.mit.theta.solver.Solver; -import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.utils.WithPushPop; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import static com.google.common.base.Preconditions.checkNotNull; -import static hu.bme.mit.theta.core.decl.Decls.Param; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Exists; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Forall; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toUnmodifiableMap; - -/** - * An ExprTraceChecker that generates new predicates based on the Newton-style algorithms described in - * Daniel Dietsch, Matthias Heizmann, Betim Musa, Alexander Nutz, and Andreas Podelski. 2017. - * Craig vs. Newton in software model checking. In Proceedings of the 2017 11th Joint Meeting on Foundations - * of Software Engineering (ESEC/FSE 2017). Association for Computing Machinery, New York, NY, USA, - * 487–497. DOI:https://doi.org/10.1145/3106237.3106307 - */ -public class ExprTraceNewtonChecker implements ExprTraceChecker { - private enum AssertionGeneratorMethod { SP, WP } - - private final UCSolver solver; - private final Expr init; - private final Expr target; - - private final boolean IT; // Whether to abstract the trace or not - private final AssertionGeneratorMethod SPorWP; // Whether to use pre- or postconditions - private final boolean LV; // Whether to project the assertions to live variables - - private ExprTraceNewtonChecker( - final Expr init, final Expr target, final UCSolver solver, - boolean it, AssertionGeneratorMethod sPorWP, boolean lv - ) { - this.solver = checkNotNull(solver); - this.init = checkNotNull(init); - this.target = checkNotNull(target); - this.IT = it; - this.SPorWP = checkNotNull(sPorWP); - this.LV = lv; - } - - public static ExprTraceNewtonCheckerITBuilder create( - final Expr init, final Expr target, final UCSolver solver - ) { - return new ExprTraceNewtonCheckerITBuilder(solver, init, target); - } - - @SuppressWarnings("unchecked") - @Override - public ExprTraceStatus check(final Trace trace) { - checkNotNull(trace); - try { - return check2((Trace) trace); - } - catch(ClassCastException e) { - throw new UnsupportedOperationException("Actions must be of type StmtAction", e); - } - } - - private ExprTraceStatus check2(final Trace trace) { - var ftrace = flattenTrace(trace); // Moves the expressions in the states to the corresponting actions as assumptions - - final int stateCount = ftrace.getStates().size(); - final List indexings = new ArrayList<>(stateCount); - indexings.add(VarIndexing.all(0)); - - final Valuation model; - final Collection> unsatCore; - final boolean concretizable; - - try (WithPushPop wpp = new WithPushPop(solver)) { - for (int i = 1; i < stateCount; ++i) { - var curIndexing = indexings.get(i - 1); - for(var stmt : ftrace.getAction(i - 1).getStmts()) { - var stmtUnfoldResult = StmtUtils.toExpr(stmt, VarIndexing.all(0)); - solver.track(PathUtils.unfold(stmtUnfoldResult.getExprs().iterator().next(), curIndexing)); - curIndexing = curIndexing.add(stmtUnfoldResult.getIndexing()); - } - indexings.add(curIndexing); - } - - concretizable = solver.check().isSat(); - - if (concretizable) { - model = solver.getModel(); - unsatCore = null; - } else { - model = null; - unsatCore = solver.getUnsatCore(); - } - } - - if (concretizable) { - checkNotNull(model); - return createCounterexample(model, indexings, trace); - } else { - checkNotNull(unsatCore); - return createRefinement(unsatCore, indexings, ftrace); - } - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - private Trace flattenTrace(final Trace trace) { - final var stateCount = trace.getStates().size(); - final var flattenedActions = new ArrayList(stateCount - 1); - - for(var i = 1; i < stateCount; i++) { - var initStream = - (i == 1) - ? ExprUtils.getConjuncts(init).stream().map(AssumeStmt::of) - : Stream.empty(); - - var stateStream = ExprUtils.getConjuncts(trace.getState(i - 1).toExpr()).stream().map(AssumeStmt::of); - - var actionStream = trace.getAction(i - 1).getStmts().stream(); - - var targetStream = - (i == stateCount - 1) - ? Stream.concat( - ExprUtils.getConjuncts(trace.getState(i).toExpr()).stream().map(AssumeStmt::of), - ExprUtils.getConjuncts(target).stream().map(AssumeStmt::of) - ) - : Stream.empty(); - - flattenedActions.add( - NewtonAction.of( - Stream.of(initStream, stateStream, actionStream, targetStream).flatMap(e -> e).collect(toList()) - ) - ); - } - - return ExprTraceUtils.traceFrom(flattenedActions); - } - - private ExprTraceStatus.Feasible createCounterexample( - final Valuation model, - final List indexings, - final Trace trace - ) { - final ImmutableList.Builder builder = ImmutableList.builder(); - for (final VarIndexing indexing : indexings) { - builder.add(PathUtils.extractValuation(model, indexing)); - } - return ExprTraceStatus.feasible(Trace.of(builder.build(), trace.getActions())); - } - - private ExprTraceStatus.Infeasible createRefinement( - final Collection> unsatCore, - final List indexings, - Trace trace - ) { - if(IT) { - trace = computeAbstractTrace(unsatCore, trace); - } - - final List> assertions; - if(SPorWP == AssertionGeneratorMethod.SP) { - assertions = computeAssertionsFromTraceWithStrongestPostcondition(trace); - } - else if(SPorWP == AssertionGeneratorMethod.WP) { - assertions = computeAssertionsFromTraceWithWeakestPrecondition(trace); - } - else { - throw new AssertionError("There should be no other option"); - } - - return ExprTraceStatus.infeasible(ItpRefutation.sequence(assertions)); - } - - /* - * State abstraction - */ - - private Trace computeAbstractTrace( - final Collection> unsatCore, - final Trace trace - ) { - final var stateCount = trace.getStates().size(); - var curIndexing = VarIndexing.all(0); - - final var actions = new ArrayList(); - - for (int i = 1; i < stateCount; ++i) { - final var stmts = new ArrayList(); - for(final var stmt : trace.getAction(i - 1).getStmts()) { - final var stmtUnfoldResult = StmtUtils.toExpr(stmt, VarIndexing.all(0)); - final var stmtExpr = PathUtils.unfold(stmtUnfoldResult.getExprs().iterator().next(), curIndexing); - - if(unsatCore.contains(stmtExpr)) { - stmts.add(stmt); - } - else { - stmts.add(computeAbstractStmt(stmt)); - } - - curIndexing = curIndexing.add(stmtUnfoldResult.getIndexing()); - } - actions.add(NewtonAction.of(stmts)); - } - - return Trace.of(trace.getStates(), actions); - } - - private Stmt computeAbstractStmt(Stmt stmt) { - return stmt.accept(new StmtVisitor() { - @Override - public Stmt visit(SkipStmt stmt, Void param) { - return SkipStmt.getInstance(); - } - - @Override - public Stmt visit(AssumeStmt stmt, Void param) { - return AssumeStmt.of(True()); - } - - @Override - public Stmt visit(AssignStmt stmt, Void param) { - return HavocStmt.of(stmt.getVarDecl()); - } - - @Override - public Stmt visit(HavocStmt stmt, Void param) { - return HavocStmt.of(stmt.getVarDecl()); - } - }, null); - } - - /* - * Assertion computation - */ - - private List> computeAssertionsFromTraceWithStrongestPostcondition( - final Trace trace - ) { - final int stateCount = trace.getStates().size(); - final List> assertions = new ArrayList<>(stateCount); - - assertions.add(True()); - var constCount = 0; - for(var i = 1; i < stateCount; i++) { - var spState = SpState.of(assertions.get(i - 1), constCount); - for(var stmt : trace.getAction(i - 1).getStmts()) { - spState = spState.sp(stmt); - } - assertions.add(ExprSimplifier.simplify(spState.getExpr(), ImmutableValuation.empty())); - constCount = spState.getConstCount(); - } - - if(LV) { - var allVariables = collectVariablesInTrace(trace); - var futureLiveVariables = collectFutureLiveVariablesForTrace(trace); - return IntStream.range(0, assertions.size()) - .mapToObj(i -> existentialProjection(assertions.get(i), futureLiveVariables.get(i), allVariables)) - .collect(Collectors.toUnmodifiableList()); - } - else { - return assertions; - } - } - - private List> computeAssertionsFromTraceWithWeakestPrecondition( - final Trace trace - ) { - final int stateCount = trace.getStates().size(); - final List> assertions = new ArrayList<>(Collections.nCopies(stateCount, null)); - - assertions.set(stateCount - 1, True()); - var constCount = 0; - for(var i = stateCount - 2; i >= 0; i--) { - var wpState = WpState.of(assertions.get(i + 1), constCount); - for(var stmt : Lists.reverse(trace.getAction(i).getStmts())) { - wpState = wpState.wep(stmt); - } - assertions.set(i, ExprSimplifier.simplify(wpState.getExpr(), ImmutableValuation.empty())); - constCount = wpState.getConstCount(); - } - - if(LV) { - var allVariables = collectVariablesInTrace(trace); - var pastLiveVariables = collectPastLiveVariablesForTrace(trace); - return IntStream.range(0, assertions.size()) - .mapToObj(i -> universalProjection(assertions.get(i), pastLiveVariables.get(i), allVariables)) - .collect(Collectors.toUnmodifiableList()); - } - else { - return assertions; - } - } - - /* - * Live variable collection - */ - - private Collection> collectVariablesInTrace(final Trace trace) { - var variables = new HashSet>(); - - for(var state : trace.getStates()) { - ExprUtils.collectVars(state.toExpr(), variables); - } - for(var action : trace.getActions()) { - ExprUtils.collectVars(action.toExpr(), variables); - } - - return variables; - } - - private Collection> stmtReadsVariables(final Stmt stmt) { - return stmt.accept(new StmtVisitor>>() { - @Override - public Collection> visit(SkipStmt stmt, Void param) { - return Collections.emptySet(); - } - - @Override - public Collection> visit(AssumeStmt stmt, Void param) { - return ExprUtils.getVars(stmt.getCond()); - } - - @Override - public Collection> visit(AssignStmt stmt, Void param) { - return ExprUtils.getVars(stmt.getExpr()); - } - - @Override - public Collection> visit(HavocStmt stmt, Void param) { - return Collections.emptySet(); - } - }, null); - } - - private Collection> stmtWritesVariables(final Stmt stmt) { - return stmt.accept(new StmtVisitor>>() { - @Override - public Collection> visit(SkipStmt stmt, Void param) { - return Collections.emptySet(); - } - - @Override - public Collection> visit(AssumeStmt stmt, Void param) { - return Collections.emptySet(); - } - - @Override - public Collection> visit(AssignStmt stmt, Void param) { - return Collections.singletonList(stmt.getVarDecl()); - } - - @Override - public Collection> visit(HavocStmt stmt, Void param) { - return Collections.emptySet(); - } - }, null); - } - - private Collection> stmtHavocsVariables(final Stmt stmt) { - return stmt.accept(new StmtVisitor>>() { - @Override - public Collection> visit(SkipStmt stmt, Void param) { - return Collections.emptySet(); - } - - @Override - public Collection> visit(AssumeStmt stmt, Void param) { - return Collections.emptySet(); - } - - @Override - public Collection> visit(AssignStmt stmt, Void param) { - return Collections.emptySet(); - } - - @Override - public Collection> visit(HavocStmt stmt, Void param) { - return Collections.singletonList(stmt.getVarDecl()); - } - }, null); - } - - private Collection> actionReadsVariables(final StmtAction action) { - return action.getStmts().stream().flatMap(stmt -> stmtReadsVariables(stmt).stream()).collect(Collectors.toUnmodifiableSet()); - } - - private Collection> actionWritesVariables(final StmtAction action) { - return action.getStmts().stream().flatMap(stmt -> stmtWritesVariables(stmt).stream()).collect(Collectors.toUnmodifiableSet()); - } - - private Collection> actionHavocsVariables(final StmtAction action) { - return action.getStmts().stream().flatMap(stmt -> stmtHavocsVariables(stmt).stream()).collect(Collectors.toUnmodifiableSet()); - } - - private List>> collectFutureLiveVariablesForTrace(final Trace trace) { - final var stateCount = trace.getStates().size(); - final var futureLiveVariables = new ArrayList>>(Collections.nCopies(stateCount, null)); - - futureLiveVariables.set(stateCount - 1, Collections.emptySet()); - for(var i = stateCount - 2; i >= 0; i--) { - var vars = new HashSet<>(futureLiveVariables.get(i + 1)); - vars.addAll(actionReadsVariables(trace.getAction(i))); - vars.removeAll(actionWritesVariables(trace.getAction(i))); - vars.removeAll(actionHavocsVariables(trace.getAction(i))); - futureLiveVariables.set(i, vars); - } - - return futureLiveVariables; - } - - private List>> collectPastLiveVariablesForTrace(final Trace trace) { - final var stateCount = trace.getStates().size(); - final var pastLiveVariables = new ArrayList>>(Collections.nCopies(stateCount, null)); - - pastLiveVariables.set(0, Collections.emptySet()); - for(var i = 1; i < stateCount; i++) { - var vars = new HashSet<>(pastLiveVariables.get(i - 1)); - vars.addAll(actionReadsVariables(trace.getAction(i - 1))); - vars.addAll(actionWritesVariables(trace.getAction(i - 1))); - vars.removeAll(actionHavocsVariables(trace.getAction(i - 1))); - pastLiveVariables.set(i, vars); - } - - return pastLiveVariables; - } - - /* - * Projection to live variables - */ - - private Expr existentialProjection( - final Expr expr, - final Collection> variables, - final Collection> allVariables - ) { - var params = allVariables.stream() - .filter(e -> !variables.contains(e)) - .map(e -> Tuple2.of(e, Param(e.getName(), e.getType()))) - .collect(Collectors.toUnmodifiableSet()); - - var substitution = BasicSubstitution.builder() - .putAll(params.stream().collect(toUnmodifiableMap(Tuple2::get1, e -> e.get2().getRef()))) - .build(); - - return params.size() > 0 - ? Exists(params.stream().map(Tuple2::get2).collect(toList()), substitution.apply(expr)) - : expr; - } - - private Expr universalProjection( - final Expr expr, - final Collection> variables, - final Collection> allVariables - ) { - var params = allVariables.stream() - .filter(e -> !variables.contains(e)) - .map(e -> Tuple2.of(e, Param(e.getName(), e.getType()))) - .collect(Collectors.toUnmodifiableSet()); - - var substitution = BasicSubstitution.builder() - .putAll(params.stream().collect(toUnmodifiableMap(Tuple2::get1, e -> e.get2().getRef()))) - .build(); - - return params.size() > 0 - ? Forall(params.stream().map(Tuple2::get2).collect(toList()), substitution.apply(expr)) - : expr; - } - - /* - * Builder for ExprTraceNewtonChecker - */ - - public static class ExprTraceNewtonCheckerITBuilder { - private final UCSolver solver; - private final Expr init; - private final Expr target; - - public ExprTraceNewtonCheckerITBuilder(UCSolver solver, Expr init, Expr target) { - this.solver = solver; - this.init = init; - this.target = target; - } - - public ExprTraceNewtonCheckerAssertBuilder withIT() { - return new ExprTraceNewtonCheckerAssertBuilder(solver, init, target, true); - } - - public ExprTraceNewtonCheckerAssertBuilder withoutIT() { - return new ExprTraceNewtonCheckerAssertBuilder(solver, init, target, false); - } - } - - public static class ExprTraceNewtonCheckerAssertBuilder { - private final UCSolver solver; - private final Expr init; - private final Expr target; - - private final boolean IT; - - public ExprTraceNewtonCheckerAssertBuilder(UCSolver solver, Expr init, Expr target, boolean it) { - this.solver = solver; - this.init = init; - this.target = target; - this.IT = it; - } - - public ExprTraceNewtonCheckerLVBuilder withSP() { - return new ExprTraceNewtonCheckerLVBuilder(solver, init, target, IT, AssertionGeneratorMethod.SP); - } - - public ExprTraceNewtonCheckerLVBuilder withWP() { - return new ExprTraceNewtonCheckerLVBuilder(solver, init, target, IT, AssertionGeneratorMethod.WP); - } - } - - public static class ExprTraceNewtonCheckerLVBuilder { - private final UCSolver solver; - private final Expr init; - private final Expr target; - - private final boolean IT; - private final AssertionGeneratorMethod SPorWP; - - public ExprTraceNewtonCheckerLVBuilder(UCSolver solver, Expr init, Expr target, boolean it, AssertionGeneratorMethod sPorWP) { - this.solver = solver; - this.init = init; - this.target = target; - this.IT = it; - this.SPorWP = sPorWP; - } - - public ExprTraceNewtonChecker withLV() { - return new ExprTraceNewtonChecker(init, target, solver, IT, SPorWP, true); - } - - public ExprTraceNewtonChecker withoutLV() { - return new ExprTraceNewtonChecker(init, target, solver, IT, SPorWP, false); - } - } - - /* - * Custom StmtAction to use when constructing helper traces - */ - - private static class NewtonAction extends StmtAction { - private final List stmts; - - private NewtonAction(List stmts) { - this.stmts = stmts; - } - - public static NewtonAction of(List stmts) { - return new NewtonAction(stmts); - } - - @Override - public List getStmts() { - return stmts; - } - - @Override - public String toString() { - return Utils.lispStringBuilder(getClass().getSimpleName()).body().addAll(stmts).toString(); - } - } -} diff --git a/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java b/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java deleted file mode 100644 index 5107976f6b..0000000000 --- a/subprojects/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java +++ /dev/null @@ -1,277 +0,0 @@ -package hu.bme.mit.theta.analysis.expr.refinement; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import hu.bme.mit.theta.analysis.Trace; -import hu.bme.mit.theta.analysis.expr.ExprAction; -import hu.bme.mit.theta.analysis.expr.ExprState; -import hu.bme.mit.theta.analysis.expr.ExprTraceUtils; -import hu.bme.mit.theta.analysis.expr.StmtAction; -import hu.bme.mit.theta.common.Utils; -import hu.bme.mit.theta.core.model.ImmutableValuation; -import hu.bme.mit.theta.core.model.Valuation; -import hu.bme.mit.theta.core.stmt.AssumeStmt; -import hu.bme.mit.theta.core.stmt.Stmt; -import hu.bme.mit.theta.core.type.Expr; -import hu.bme.mit.theta.core.type.booltype.BoolType; -import hu.bme.mit.theta.core.utils.ExprSimplifier; -import hu.bme.mit.theta.core.utils.ExprUtils; -import hu.bme.mit.theta.core.utils.PathUtils; -import hu.bme.mit.theta.core.utils.SpState; -import hu.bme.mit.theta.core.utils.VarIndexing; -import hu.bme.mit.theta.core.utils.WpState; -import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.utils.WithPushPop; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import static com.google.common.base.Preconditions.checkNotNull; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; -import static hu.bme.mit.theta.core.type.booltype.SmartBoolExprs.And; -import static hu.bme.mit.theta.core.type.booltype.SmartBoolExprs.Not; -import static java.util.stream.Collectors.toList; - -/** - * An ExprTraceChecker that generates new predicates based on the UCB algorithm by - * Leucker, Martin & Markin, Grigory & Neuhäußer, Martin. (2015). A New Refinement - * Strategy for CEGAR-Based Industrial Model Checking. 155-170. 10.1007/978-3-319-26287-1_10. - */ -public class ExprTraceUCBChecker implements ExprTraceChecker { - - private final UCSolver solver; - private final Expr init; - private final Expr target; - - private ExprTraceUCBChecker(final Expr init, final Expr target, final UCSolver solver) { - this.solver = checkNotNull(solver); - this.init = checkNotNull(init); - this.target = checkNotNull(target); - } - - public static ExprTraceUCBChecker create( - final Expr init, final Expr target, final UCSolver solver - ) { - return new ExprTraceUCBChecker(init, target, solver); - } - - @SuppressWarnings("unchecked") - @Override - public ExprTraceStatus check(final Trace trace) { - checkNotNull(trace); - try { - return check2((Trace) trace); - } - catch(ClassCastException e) { - throw new UnsupportedOperationException("Actions must be of type StmtAction", e); - } - } - -private ExprTraceStatus check2(final Trace trace) { - final var ftrace = flattenTrace(trace); - final int stateCount = trace.getStates().size(); - - final List indexings = new ArrayList<>(stateCount); - indexings.add(VarIndexing.all(0)); - - final Valuation model; - final Collection> unsatCore; - final boolean concretizable; - - try (WithPushPop wpp = new WithPushPop(solver)) { - for (int i = 1; i < stateCount; ++i) { - indexings.add(indexings.get(i - 1).add(trace.getAction(i - 1).nextIndexing())); - solver.track( - ExprUtils.getConjuncts( - PathUtils.unfold(trace.getAction(i - 1).toExpr(), indexings.get(i - 1)) - ) - ); - } - - concretizable = solver.check().isSat(); - - if (concretizable) { - model = solver.getModel(); - unsatCore = null; - } else { - model = null; - unsatCore = solver.getUnsatCore(); - } - } - - if (concretizable) { - checkNotNull(model); - return createCounterexample(model, indexings, trace); - } else { - checkNotNull(unsatCore); - return createRefinement(unsatCore, indexings, ftrace); - } - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - - private ExprTraceStatus.Feasible createCounterexample( - final Valuation model, - final List indexings, - final Trace trace - ) { - final ImmutableList.Builder builder = ImmutableList.builder(); - for (final VarIndexing indexing : indexings) { - builder.add(PathUtils.extractValuation(model, indexing)); - } - return ExprTraceStatus.feasible(Trace.of(builder.build(), trace.getActions())); - } - - private ExprTraceStatus.Infeasible createRefinement( - final Collection> unsatCore, - final List indexings, - final Trace trace - ) { - final int stateCount = trace.getStates().size(); - final List> wps = calculateWpStates(trace, indexings); - - final List> predicates = new ArrayList<>(); - - var constCount = 0; - for(var i = 0; i < stateCount; i++) { - try(final var wpp = new WithPushPop(solver)) { - final List> dataRegion = new ArrayList<>(); - - /* Calculate SP */ - if (i == 0) { - solver.track(True()); - dataRegion.add(True()); - } else /* i > 0 */ { - var spState = SpState.of(PathUtils.foldin(predicates.get(i - 1), indexings.get(i - 1)), constCount); - for(var stmt : trace.getAction(i - 1).getStmts()) { - spState = spState.sp(stmt); - } - - final var expr = PathUtils.unfold(spState.getExpr(), indexings.get(i)); - constCount = spState.getConstCount(); - solver.track(ExprUtils.getConjuncts(expr)); - dataRegion.addAll(ExprUtils.getConjuncts(expr)); - } - - /* Add wp */ - solver.track(ExprUtils.getConjuncts(wps.get(i))); - - solver.check(); - assert solver.check().isUnsat(); // It must be unsat - Collection> uc = solver.getUnsatCore(); - - /* Keep only those expressions from uc that are not in the data region */ - final Collection> predicate = new ArrayList<>(); - for (var ucExpr : uc) { - if (!dataRegion.contains(ucExpr)) { - predicate.add(ucExpr); - } - } - - /* Add the negated of the above expression as the new predicate */ - predicates.add( - ExprSimplifier.simplify( - Not(And(new HashSet<>(predicate))), - ImmutableValuation.empty() - ) - ); - } - } - return ExprTraceStatus.infeasible( - ItpRefutation.sequence( - IntStream.range(0, predicates.size()) - .mapToObj(i -> PathUtils.foldin(predicates.get(i), indexings.get(i))) - .collect(Collectors.toUnmodifiableList()) - ) - ); - } - - private List> calculateWpStates( - final Trace trace, - final List indexings - ) { - final int stateCount = trace.getStates().size(); - final List> wps = new ArrayList<>(Collections.nCopies(stateCount, null)); - - var wpstate = WpState.of(target); - wps.set(stateCount - 1, target); - for(var i = stateCount - 1; i > 0; i--) { - var action = trace.getAction(i - 1); - - for(var stmt : Lists.reverse(action.getStmts())) { - wpstate = wpstate.wep(stmt); - } - - wps.set(i - 1, PathUtils.unfold(wpstate.getExpr(), indexings.get(i - 1))); - } - - return wps; - } - - private Trace flattenTrace(final Trace trace) { - final var stateCount = trace.getStates().size(); - final var flattenedActions = new ArrayList(stateCount - 1); - - for(var i = 1; i < stateCount; i++) { - var initStream = - (i == 1) - ? ExprUtils.getConjuncts(init).stream().map(AssumeStmt::of) - : Stream.empty(); - - var stateStream = ExprUtils.getConjuncts(trace.getState(i - 1).toExpr()).stream().map(AssumeStmt::of); - - var actionStream = trace.getAction(i - 1).getStmts().stream(); - - var targetStream = - (i == stateCount - 1) - ? Stream.concat( - ExprUtils.getConjuncts(trace.getState(i).toExpr()).stream().map(AssumeStmt::of), - ExprUtils.getConjuncts(target).stream().map(AssumeStmt::of) - ) - : Stream.empty(); - - flattenedActions.add( - UCBAction.of( - Stream.of(initStream, stateStream, actionStream, targetStream).flatMap(e -> e).collect(toList()) - ) - ); - } - - return ExprTraceUtils.traceFrom(flattenedActions); - } - - /* - * Custom StmtAction to use when constructing helper traces - */ - - private static class UCBAction extends StmtAction { - private final List stmts; - - private UCBAction(List stmts) { - this.stmts = stmts; - } - - public static UCBAction of(List stmts) { - return new UCBAction(stmts); - } - - @Override - public List getStmts() { - return stmts; - } - - @Override - public String toString() { - return Utils.lispStringBuilder(getClass().getSimpleName()).body().addAll(stmts).toString(); - } - } -} diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java index e1a9737537..74941b1a2f 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceUCBChecker.java @@ -20,13 +20,13 @@ import hu.bme.mit.theta.core.utils.SpState; import hu.bme.mit.theta.core.utils.VarIndexing; import hu.bme.mit.theta.core.utils.WpState; -import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.utils.WithPushPop; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import hu.bme.mit.theta.common.container.Containers; +import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -45,18 +45,18 @@ */ public class ExprTraceUCBChecker implements ExprTraceChecker { - private final Solver solver; + private final UCSolver solver; private final Expr init; private final Expr target; - private ExprTraceUCBChecker(final Expr init, final Expr target, final Solver solver) { + private ExprTraceUCBChecker(final Expr init, final Expr target, final UCSolver solver) { this.solver = checkNotNull(solver); this.init = checkNotNull(init); this.target = checkNotNull(target); } public static ExprTraceUCBChecker create( - final Expr init, final Expr target, final Solver solver + final Expr init, final Expr target, final UCSolver solver ) { return new ExprTraceUCBChecker(init, target, solver); } @@ -73,7 +73,7 @@ public ExprTraceStatus check(final Trace check2(final Trace trace) { + private ExprTraceStatus check2(final Trace trace) { final var ftrace = flattenTrace(trace); final int stateCount = trace.getStates().size(); @@ -180,7 +180,7 @@ private ExprTraceStatus.Infeasible createRefinement( /* Add the negated of the above expression as the new predicate */ predicates.add( ExprSimplifier.simplify( - Not(And(Containers.createSet(predicate))), + Not(And(new HashSet<>(predicate))), ImmutableValuation.empty() ) ); @@ -224,8 +224,8 @@ private List> calculateWpStates( for(var i = 1; i < stateCount; i++) { var initStream = (i == 1) - ? ExprUtils.getConjuncts(init).stream().map(AssumeStmt::of) - : Stream.empty(); + ? ExprUtils.getConjuncts(init).stream().map(AssumeStmt::of) + : Stream.empty(); var stateStream = ExprUtils.getConjuncts(trace.getState(i - 1).toExpr()).stream().map(AssumeStmt::of); @@ -233,11 +233,11 @@ private List> calculateWpStates( var targetStream = (i == stateCount - 1) - ? Stream.concat( + ? Stream.concat( ExprUtils.getConjuncts(trace.getState(i).toExpr()).stream().map(AssumeStmt::of), ExprUtils.getConjuncts(target).stream().map(AssumeStmt::of) ) - : Stream.empty(); + : Stream.empty(); flattenedActions.add( UCBAction.of( diff --git a/subprojects/common/src/main/java/hu/bme/mit/theta/common/QuadFunction.java b/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/QuadFunction.java similarity index 100% rename from subprojects/common/src/main/java/hu/bme/mit/theta/common/QuadFunction.java rename to subprojects/common/common/src/main/java/hu/bme/mit/theta/common/QuadFunction.java diff --git a/subprojects/common/src/main/java/hu/bme/mit/theta/common/QuintFunction.java b/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/QuintFunction.java similarity index 100% rename from subprojects/common/src/main/java/hu/bme/mit/theta/common/QuintFunction.java rename to subprojects/common/common/src/main/java/hu/bme/mit/theta/common/QuintFunction.java diff --git a/subprojects/common/src/main/java/hu/bme/mit/theta/common/SemVer.java b/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/SemVer.java similarity index 100% rename from subprojects/common/src/main/java/hu/bme/mit/theta/common/SemVer.java rename to subprojects/common/common/src/main/java/hu/bme/mit/theta/common/SemVer.java diff --git a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/ExprUtils.java b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/ExprUtils.java index 4e5f8f9907..ac3bbf7345 100644 --- a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/ExprUtils.java +++ b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/ExprUtils.java @@ -21,6 +21,8 @@ import java.util.Collection; import java.util.Collections; import hu.bme.mit.theta.common.container.Containers; + +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/ItpPatternImpl.java b/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/ItpPatternImpl.java deleted file mode 100644 index 7f91ffb180..0000000000 --- a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/ItpPatternImpl.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2017 Budapest University of Technology and Economics - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package hu.bme.mit.theta.solver.impl; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - -import hu.bme.mit.theta.solver.ItpMarker; -import hu.bme.mit.theta.solver.ItpPattern; - -public class ItpPatternImpl implements ItpPattern { - - private ItpPattern parent; - private final List children; - - private final ItpMarker marker; - - public ItpPatternImpl(final ItpMarker marker) { - this.marker = checkNotNull(marker); - children = new LinkedList<>(); - } - - @Override - public ItpMarker getMarker() { - return marker; - } - - @Override - public ItpPattern getParent() { - return parent; - } - - @Override - public Collection getChildren() { - return Collections.unmodifiableCollection(children); - } - - @Override - public ItpPattern createChild(final ItpMarker marker) { - checkNotNull(marker); - final ItpPatternImpl child = new ItpPatternImpl(marker); - children.add(child); - child.parent = this; - return child; - } - -} diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpPattern.java b/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpPattern.java deleted file mode 100644 index 2f175c89fb..0000000000 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpPattern.java +++ /dev/null @@ -1,94 +0,0 @@ -package hu.bme.mit.theta.solver.smtlib.z3; - -import com.google.common.collect.Lists; -import hu.bme.mit.theta.solver.ItpMarker; -import hu.bme.mit.theta.solver.ItpMarkerTree; -import hu.bme.mit.theta.solver.ItpPattern; - -import java.util.ArrayList; -import java.util.List; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; - -public class Z3SmtLibItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { - final ItpMarkerTree markerTree; - - Z3SmtLibItpPattern(final ItpMarkerTree markerTree) { - this.markerTree = markerTree; - } - - @SuppressWarnings("unchecked") - static Z3SmtLibItpPattern of(final ItpMarkerTree markerTree) { - final var list = new ArrayList>(); - list.add(markerTree); - while(!list.isEmpty()) { - final var node = list.get(0); - list.remove(0); - - checkArgument(node.getMarker() instanceof Z3SmtLibItpMarker); - - list.addAll(node.getChildren()); - } - - return new Z3SmtLibItpPattern((ItpMarkerTree) markerTree); - } - - @Override - public Z3SmtLibItpMarker getA() { - checkState(isBinary()); - return markerTree.getChild(0).getMarker(); - } - - @Override - public Z3SmtLibItpMarker getB() { - checkState(isBinary()); - return markerTree.getMarker(); - } - - @Override - public List getSequence() { - checkState(isSequence()); - final var markerList = new ArrayList(); - - var current = markerTree; - while(current.getChildrenNumber() > 0) { - markerList.add(current.getMarker()); - current = current.getChild(0); - } - markerList.add(current.getMarker()); - - return Lists.reverse(markerList); - } - - @Override - public ItpMarkerTree getRoot() { - return markerTree; - } - - @Override - public E visit(ItpPatternVisitor visitor) { - return visitor.visitTreePattern(this); - } - - private boolean isBinary() { - return - markerTree != null && - markerTree.getChildrenNumber() == 1 && - markerTree.getChild(0) != null && - markerTree.getChild(0).getChildrenNumber() == 0; - } - - private boolean isSequence() { - var current = markerTree; - while(current.getChildrenNumber() > 0) { - if(current.getChildrenNumber() > 1) { - return false; - } - else { - current = current.getChild(0); - } - } - return true; - } -} diff --git a/subprojects/solver-smtlib-cli/README.md b/subprojects/solver/solver-smtlib-cli/README.md similarity index 95% rename from subprojects/solver-smtlib-cli/README.md rename to subprojects/solver/solver-smtlib-cli/README.md index 8173a66f6f..a0a2683e1f 100644 --- a/subprojects/solver-smtlib-cli/README.md +++ b/subprojects/solver/solver-smtlib-cli/README.md @@ -12,7 +12,7 @@ For more information about the SMT-LIB compatibility in Theta, take a look at th 1. First, get the tool. * The easiest way is to download a [pre-built release](https://github.com/ftsrg/theta/releases). - * You can also [build](../../doc/Build.md) the tool yourself. The runnable jar file will appear under _build/libs/_ with the name _theta-solver-smtlib-cli-\-all.jar_, you can simply rename it to _theta-solver-smtlib-cli.jar_.. + * You can also [build](../../../doc/Build.md) the tool yourself. The runnable jar file will appear under _build/libs/_ with the name _theta-solver-smtlib-cli-\-all.jar_, you can simply rename it to _theta-solver-smtlib-cli.jar_.. 2. Running the tool requires Java (JRE) 11. 3. The tool can be executed with `java -jar theta-solver-smtlib-cli.jar [MAIN ARGUMENTS] [COMMAND] [ARGUMENTS]`. * If no arguments are given, a help screen is displayed about the arguments and their possible values. diff --git a/subprojects/common/solver-z3/bin/.gitignore b/subprojects/solver/solver-smtlib-cli/bin/.gitignore similarity index 100% rename from subprojects/common/solver-z3/bin/.gitignore rename to subprojects/solver/solver-smtlib-cli/bin/.gitignore diff --git a/subprojects/solver-smtlib-cli/build.gradle.kts b/subprojects/solver/solver-smtlib-cli/build.gradle.kts similarity index 100% rename from subprojects/solver-smtlib-cli/build.gradle.kts rename to subprojects/solver/solver-smtlib-cli/build.gradle.kts diff --git a/subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java similarity index 100% rename from subprojects/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java rename to subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java diff --git a/subprojects/solver-smtlib/README.md b/subprojects/solver/solver-smtlib/README.md similarity index 99% rename from subprojects/solver-smtlib/README.md rename to subprojects/solver/solver-smtlib/README.md index 0945f8e2d1..7783d4a4b4 100644 --- a/subprojects/solver-smtlib/README.md +++ b/subprojects/solver/solver-smtlib/README.md @@ -1,6 +1,6 @@ ## Overview -This project wraps a generic solver that supports the SMT-LIB2 interface into our common interfaces for solvers (located in the [solver](../solver) project). +This project wraps a generic solver that supports the SMT-LIB2 interface into our common interfaces for solvers (located in the [solver](..) project). ### Related projects diff --git a/subprojects/common/solver/bin/.gitignore b/subprojects/solver/solver-smtlib/bin/.gitignore similarity index 100% rename from subprojects/common/solver/bin/.gitignore rename to subprojects/solver/solver-smtlib/bin/.gitignore diff --git a/subprojects/solver-smtlib/build.gradle.kts b/subprojects/solver/solver-smtlib/build.gradle.kts similarity index 100% rename from subprojects/solver-smtlib/build.gradle.kts rename to subprojects/solver/solver-smtlib/build.gradle.kts diff --git a/subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 b/subprojects/solver/solver-smtlib/src/main/antlr/SMTLIBv2.g4 similarity index 100% rename from subprojects/solver-smtlib/src/main/antlr/SMTLIBv2.g4 rename to subprojects/solver/solver-smtlib/src/main/antlr/SMTLIBv2.g4 diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinaryException.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinaryException.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinaryException.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinaryException.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java similarity index 99% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java index cfe9f62b2b..03da1f21d0 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java @@ -239,7 +239,7 @@ private Expr toExpr(final String term, final SmtLibModel model) { @Override public LitExpr toLitExpr(final String litImpl, final T type, final SmtLibModel model) { - final var litExpr = toExpr(litImpl, model); + final var litExpr = toLitExpr(litImpl, model); if(litExpr == null) { return null; diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java similarity index 99% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java index 7d50884bdb..54760d637c 100644 --- a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java @@ -20,7 +20,6 @@ import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; -import hu.bme.mit.theta.solver.smtlib.parser.GeneralResponse; import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java diff --git a/subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java similarity index 100% rename from subprojects/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java similarity index 100% rename from subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java rename to subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java similarity index 100% rename from subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java rename to subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java diff --git a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java similarity index 99% rename from subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java rename to subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index 4af13d2a9e..42652c2a94 100644 --- a/subprojects/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -79,7 +79,7 @@ public void test() { symbolTable.put(x, "x", "(declare-fun x () (_ BitVec 4))"); final var expr = termTransformer.toExpr( - "z () Bool (forall ((y (Array (_ BitVec 4) Int))) (= (select y x) 0))", + "(forall ((y (Array (_ BitVec 4) Int))) (= (select y x) 0))", BoolExprs.Bool(), new SmtLibModel(Map.of()) ); assertNotNull(expr); diff --git a/subprojects/common/solver-z3/README.md b/subprojects/solver/solver-z3/README.md similarity index 100% rename from subprojects/common/solver-z3/README.md rename to subprojects/solver/solver-z3/README.md diff --git a/subprojects/solver-smtlib-cli/bin/.gitignore b/subprojects/solver/solver-z3/bin/.gitignore similarity index 100% rename from subprojects/solver-smtlib-cli/bin/.gitignore rename to subprojects/solver/solver-z3/bin/.gitignore diff --git a/subprojects/common/solver-z3/build.gradle.kts b/subprojects/solver/solver-z3/build.gradle.kts similarity index 100% rename from subprojects/common/solver-z3/build.gradle.kts rename to subprojects/solver/solver-z3/build.gradle.kts diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3DeclTransformer.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3DeclTransformer.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3DeclTransformer.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3DeclTransformer.java diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ExprTransformer.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ExprTransformer.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ExprTransformer.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ExprTransformer.java diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Interpolant.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Interpolant.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Interpolant.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Interpolant.java diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpMarker.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpMarker.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpMarker.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpMarker.java diff --git a/subprojects/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpPattern.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpPattern.java similarity index 100% rename from subprojects/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpPattern.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpPattern.java diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverFactory.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverFactory.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverFactory.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverFactory.java diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SymbolTable.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SymbolTable.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SymbolTable.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SymbolTable.java diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TermTransformer.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TermTransformer.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TermTransformer.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TermTransformer.java diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TransformationManager.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TransformationManager.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TransformationManager.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TransformationManager.java diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TypeTransformer.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TypeTransformer.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TypeTransformer.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3TypeTransformer.java diff --git a/subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/package-info.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/package-info.java similarity index 100% rename from subprojects/common/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/package-info.java rename to subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/package-info.java diff --git a/subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/SolverUtilsTest.java b/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/SolverUtilsTest.java similarity index 100% rename from subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/SolverUtilsTest.java rename to subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/SolverUtilsTest.java diff --git a/subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ItpSolverTest.java b/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ItpSolverTest.java similarity index 100% rename from subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ItpSolverTest.java rename to subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ItpSolverTest.java diff --git a/subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ModelTest.java b/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ModelTest.java similarity index 100% rename from subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ModelTest.java rename to subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3ModelTest.java diff --git a/subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverBVTest.java b/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverBVTest.java similarity index 100% rename from subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverBVTest.java rename to subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverBVTest.java diff --git a/subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java b/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java similarity index 99% rename from subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java rename to subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java index c4b6651c86..6088e4ba22 100644 --- a/subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java +++ b/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java @@ -95,6 +95,7 @@ public void testSimple() { @Test public void testTrack() { + final UCSolver solver = Z3SolverFactory.getInstance().createUCSolver(); final ConstDecl ca = Const("a", BoolExprs.Bool()); final Expr expr = BoolExprs.And(ca.getRef(), True()); diff --git a/subprojects/common/solver/README.md b/subprojects/solver/solver/README.md similarity index 100% rename from subprojects/common/solver/README.md rename to subprojects/solver/solver/README.md diff --git a/subprojects/solver-smtlib/bin/.gitignore b/subprojects/solver/solver/bin/.gitignore similarity index 100% rename from subprojects/solver-smtlib/bin/.gitignore rename to subprojects/solver/solver/bin/.gitignore diff --git a/subprojects/common/solver/build.gradle.kts b/subprojects/solver/solver/build.gradle.kts similarity index 100% rename from subprojects/common/solver/build.gradle.kts rename to subprojects/solver/solver/build.gradle.kts diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/Interpolant.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/Interpolant.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/Interpolant.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/Interpolant.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarker.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarker.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarker.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarker.java diff --git a/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarkerTree.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarkerTree.java similarity index 100% rename from subprojects/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarkerTree.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpMarkerTree.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java similarity index 57% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java index 65d5848f8a..8ea8851771 100644 --- a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java +++ b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java @@ -31,7 +31,7 @@ * * The solver can also support incremental solving by {@link #push()} and {@link #pop()}. */ -public interface Solver { +public interface Solver extends SolverBase { /** * Add an expression to the solver. @@ -50,61 +50,4 @@ default void add(final Iterable> assertions) { add(assertion); } } - - /** - * Check if the currently added expressions are satisfiable. - * - * @return Status - */ - SolverStatus check(); - - /** - * Push the current solver state. When calling {@link #pop()}, all expressions added after - * the last push will be removed. - */ - void push(); - - /** - * Remove expressions added after the previous n {@link #push()} calls. - * - * @param n - */ - void pop(final int n); - - /** - * Remove expressions added after the previous {@link #push()} call. - */ - default void pop() { - pop(1); - } - - /** - * Reset the solver state. It should be only used as a last resort. Try using - * {@link #push()} and {@link #pop()} instead. See also {@link hu.bme.mit.theta.solver.utils.WithPushPop} - * which implements try with resources pattern. - */ - void reset(); - - /** - * Get the current status of the solver. - * - * @return Status - */ - SolverStatus getStatus(); - - /** - * Get the satisfying assignment for the currently added expressions. - * Should only be called if {@link #check()} was already called and - * the result is SAT. - * - * @return Satisfying assignment - */ - Valuation getModel(); - - /** - * Get the currently added expressions. - * - * @return Expressions - */ - Collection> getAssertions(); } diff --git a/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java similarity index 100% rename from subprojects/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/SolverStatus.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverStatus.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/SolverStatus.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverStatus.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/Stack.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/Stack.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/Stack.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/Stack.java diff --git a/subprojects/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java similarity index 100% rename from subprojects/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/UCSolver.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/UnknownSolverStatusException.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/UnknownSolverStatusException.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/UnknownSolverStatusException.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/UnknownSolverStatusException.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/StackImpl.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/impl/StackImpl.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/impl/StackImpl.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/impl/StackImpl.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/package-info.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/package-info.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/package-info.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/package-info.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/utils/SolverUtils.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/utils/SolverUtils.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/utils/SolverUtils.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/utils/SolverUtils.java diff --git a/subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java similarity index 100% rename from subprojects/common/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java rename to subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java diff --git a/subprojects/common/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java b/subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java similarity index 100% rename from subprojects/common/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java rename to subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java diff --git a/subprojects/common/solver/src/test/java/hu/bme/mit/theta/solver/StackTest.java b/subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/StackTest.java similarity index 100% rename from subprojects/common/solver/src/test/java/hu/bme/mit/theta/solver/StackTest.java rename to subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/StackTest.java diff --git a/subprojects/common/solver/src/test/java/hu/bme/mit/theta/solver/WithPushPopTest.java b/subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/WithPushPopTest.java similarity index 100% rename from subprojects/common/solver/src/test/java/hu/bme/mit/theta/solver/WithPushPopTest.java rename to subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/WithPushPopTest.java From 012fd0ea1dbd8383c184c3bf932d750b8ffbd56f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 25 Feb 2021 13:58:50 +0100 Subject: [PATCH 64/99] Add basic MathSAT support for newer versions --- .../java/hu/bme/mit/theta/common/SemVer.java | 86 --------- .../solver/solver-smtlib/build.gradle.kts | 1 + .../smtlib/BaseSmtLibSolverInstaller.java | 26 +++ .../cvc4/CVC4SmtLibSolverInstaller.java | 26 +-- .../generic/GenericSmtLibSolverInstaller.java | 14 +- .../generic/GenericSmtLibTermTransformer.java | 5 + .../smtlib/manager/SmtLibSolverManager.java | 2 + .../mathsat/MathSATSmtLibSolverInstaller.java | 174 ++++++++++++++++++ .../theta/solver/smtlib/utils/Compress.java | 49 +++++ .../mit/theta/solver/smtlib/utils/SemVer.java | 142 ++++++++++++++ .../smtlib/z3/Z3SmtLibSolverInstaller.java | 120 ++---------- 11 files changed, 420 insertions(+), 225 deletions(-) delete mode 100644 subprojects/common/common/src/main/java/hu/bme/mit/theta/common/SemVer.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/Compress.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/SemVer.java diff --git a/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/SemVer.java b/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/SemVer.java deleted file mode 100644 index d3ea250acf..0000000000 --- a/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/SemVer.java +++ /dev/null @@ -1,86 +0,0 @@ -package hu.bme.mit.theta.common; - -import java.util.Arrays; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -public class SemVer implements Comparable { - private final int[] version; - - private SemVer(final String version) { - checkNotNull(version); - checkArgument(version.matches("[0-9]+(\\.[0-9]+)*")); - - this.version = Arrays.stream(version.split("\\.")).mapToInt(Integer::parseInt).toArray(); - } - - public static SemVer of(final String version) { - return new SemVer(version); - } - - public boolean hasMajor() { - return version.length > 0; - } - - public int getMajor() { - return version[0]; - } - - public boolean hasMinor() { - return version.length > 1; - } - - public int getMinor() { - return version[1]; - } - - public boolean hasPatch() { - return version.length > 2; - } - - public int getPatch() { - return version[2]; - } - - public int[] getAll() { - return version; - } - - @Override - public int compareTo(final SemVer that) { - if(that == null) { - return 1; - } - - for(int i = 0; i < Math.max(this.version.length, that.version.length); i++) { - final var thisVer = i < this.version.length ? this.version[i] : 0; - final var thatVer = i < that.version.length ? that.version[i] : 0; - - if(thisVer < thatVer) { - return -1; - } - else if(thisVer > thatVer) { - return 1; - } - else { - continue; - } - } - - return 0; - } - - @Override - public boolean equals(Object obj) { - if(obj == null) { - return false; - } - else if(obj instanceof SemVer) { - return this.compareTo((SemVer) obj) == 0; - } - else { - return false; - } - } -} diff --git a/subprojects/solver/solver-smtlib/build.gradle.kts b/subprojects/solver/solver-smtlib/build.gradle.kts index e959b56575..92ad3fa008 100644 --- a/subprojects/solver/solver-smtlib/build.gradle.kts +++ b/subprojects/solver/solver-smtlib/build.gradle.kts @@ -7,4 +7,5 @@ dependencies { compile(project(":theta-common")) compile(project(":theta-core")) compile(project(":theta-solver")) + compile("org.apache.commons:commons-compress:1.20") } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java index 826a340ecc..ec950e0d60 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java @@ -1,9 +1,12 @@ package hu.bme.mit.theta.solver.smtlib; import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibSolverFactory; import java.io.File; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -119,6 +122,28 @@ public void reinstall(Path home, String version) throws SmtLibSolverInstallerExc install(home, solverVersion, version); } + @Override + public final SolverFactory getSolverFactory(final Path home, final String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final var installDir = home.resolve(version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + try { + final var solverArgsPath = argsFile(installDir); + final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); + + return getSolverFactory(installDir, version, solverArgs); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + @Override public final String getInfo(Path home, String version) throws SmtLibSolverInstallerException { checkNotNull(home); @@ -176,6 +201,7 @@ public final List getInstalledVersions(Path home) throws SmtLibSolverIns protected abstract String getSolverName() throws SmtLibSolverInstallerException; protected abstract void installSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException; protected abstract void uninstallSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException; + protected abstract SolverFactory getSolverFactory(final Path installDir, final String version, final String[] args) throws SmtLibSolverInstallerException; protected abstract String[] getDefaultSolverArgs(final String version) throws SmtLibSolverInstallerException; protected final void checkName(final String version) throws SmtLibSolverInstallerException { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java index cca24fac80..a4b9f243cb 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java @@ -1,12 +1,13 @@ package hu.bme.mit.theta.solver.smtlib.cvc4; import hu.bme.mit.theta.common.OsHelper; -import hu.bme.mit.theta.common.SemVer; +import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.smtlib.BaseSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; +import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibSolverFactory; import java.io.FileOutputStream; import java.io.IOException; @@ -69,26 +70,9 @@ protected String[] getDefaultSolverArgs(String version) { } @Override - public SolverFactory getSolverFactory(Path home, String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkVersion(version); - - final var installDir = home.resolve(version); - if(!Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("The version is not installed"); - } - - try { - final var solverFilePath = installDir.resolve(getSolverBinaryName()); - final var solverArgsPath = argsFile(installDir); - final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); - - return GenericSmtLibSolverFactory.create(solverFilePath, solverArgs); - } - catch (IOException e) { - throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); - } + public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); + return GenericSmtLibSolverFactory.create(solverFilePath, solverArgs); } @Override diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java index fd11044336..e49e5a8054 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java @@ -77,22 +77,10 @@ public void reinstall(final Path home, final String version) throws SmtLibSolver } @Override - public SolverFactory getSolverFactory(final Path home, final String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkVersion(version); - - final var installDir = home.resolve(version); - if(!Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("The version is not installed"); - } - + public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { try { final var solverFilePath = solverFile(installDir); final var solverPathStr = Files.readAllLines(solverFilePath, StandardCharsets.UTF_8).get(0); - final var solverArgsPath = argsFile(installDir); - final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); - return GenericSmtLibSolverFactory.create(Path.of(solverPathStr), solverArgs); } catch (IOException e) { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java index 03da1f21d0..32748c0e06 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java @@ -480,6 +480,11 @@ protected Expr transformIdentifier(final IdentifierContext ctx, final SmtLibM final var funcLit = (FuncLitExpr) toFuncLitExpr(model.getTerm(name), model); return funcLit.getResult(); } + else if(ctx.symbol().getText().startsWith("bv")) { + final var value = ctx.symbol().getText().substring(2); + final var bvSize = Integer.parseInt(ctx.index().get(0).getText()); + return BvUtils.bigIntegerToNeutralBvLitExpr(new BigInteger(value), bvSize); + } else { return transformSymbol(ctx.symbol(), model, vars); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java index 85d749e237..ca986461c3 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java @@ -8,6 +8,7 @@ import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; import hu.bme.mit.theta.solver.smtlib.cvc4.CVC4SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.mathsat.MathSATSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibSolverInstaller; import java.io.IOException; @@ -40,6 +41,7 @@ public static void registerGenericInsta static { registerInstaller("z3", Z3SmtLibSolverInstaller.class); registerInstaller("cvc4", CVC4SmtLibSolverInstaller.class); + registerInstaller("mathsat", MathSATSmtLibSolverInstaller.class); registerGenericInstaller("generic", GenericSmtLibSolverInstaller.class); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java new file mode 100644 index 0000000000..a22e0084e3 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java @@ -0,0 +1,174 @@ +package hu.bme.mit.theta.solver.smtlib.mathsat; + +import hu.bme.mit.theta.common.OsHelper; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; +import hu.bme.mit.theta.solver.smtlib.utils.Compress; +import hu.bme.mit.theta.solver.smtlib.utils.SemVer; +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.BaseSmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibSolverFactory; +import org.apache.commons.compress.utils.IOUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.zip.ZipInputStream; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; +import static hu.bme.mit.theta.common.OsHelper.Architecture.X86; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.MAC; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; + +public class MathSATSmtLibSolverInstaller extends BaseSmtLibSolverInstaller { + private final List versions; + + public MathSATSmtLibSolverInstaller(final Logger logger) { + super(logger); + + versions = new ArrayList<>(); + versions.add(SemVer.VersionDecoder.create(SemVer.of("5.5.0")) + .addString(LINUX, X64, "linux-x86_64") + .addString(MAC, X64, "darwin-libcxx-x86_64") + .addString(WINDOWS, X64, "win64-msvc") + .build() + ); + versions.add(SemVer.VersionDecoder.create(SemVer.of("5.3.6")) + .addString(LINUX, X64, "linux-x86_64") + .addString(LINUX, X86, "linux-x86") + .addString(MAC, X64, "darwin-libcxx-x86_64") + .addString(WINDOWS, X64, "win64-msvc") + .addString(WINDOWS, X86, "win32-msvc") + .build() + ); + versions.add(SemVer.VersionDecoder.create(SemVer.of("5.2.12")) + .addString(LINUX, X64, "linux-x86_64") + .addString(LINUX, X86, "linux-x86") + .addString(MAC, X64, "darwin-libcxx-x86_64") + .addString(WINDOWS, X64, "win64-msvc18") + .addString(WINDOWS, X86, "win32-msvc18") + .build() + ); + versions.add(SemVer.VersionDecoder.create(SemVer.of("5.2.9")) + .addString(LINUX, X64, "linux-x86_64") + .addString(LINUX, X86, "linux-x86") + .addString(MAC, X64, "darwin-libcxx-x86_64") + .addString(WINDOWS, X64, "win64-msvc") + .addString(WINDOWS, X86, "win32-msvc") + .build() + ); + versions.add(SemVer.VersionDecoder.create(SemVer.of("5.2.6")) + .addString(LINUX, X64, "linux-x86_64") + .addString(LINUX, X86, "linux-x86") + .addString(MAC, X64, "darwin-x86_64") + .addString(WINDOWS, X64, "win64-msvc") + .addString(WINDOWS, X86, "win32-msvc") + .build() + ); + versions.add(SemVer.VersionDecoder.create(SemVer.of("5.1.10")) + .addString(LINUX, X64, "linux-x86_64") + .addString(LINUX, X86, "linux-x86") + .addString(MAC, X64, "darwin-x86_64") + .build() + ); + versions.add(SemVer.VersionDecoder.create(SemVer.of("5.1.1")) + .addString(LINUX, X64, "linux-x86_64") + .addString(LINUX, X86, "linux-x86") + .build() + ); + } + + @Override + protected String getSolverName() { + return "mathsat"; + } + + @Override + protected void installSolver(Path installDir, String version) throws SmtLibSolverInstallerException { + final var semVer = SemVer.of(version); + String archStr = null; + + for(final var versionDecoder : versions) { + if(semVer.compareTo(versionDecoder.getVersion()) >= 0) { + archStr = versionDecoder.getOsArchString(OsHelper.getOs(), OsHelper.getArch()); + break; + } + } + if(archStr == null) { + throw new SmtLibSolverInstallerException(String.format("MathSAT on operating system %s and architecture %s is not supported", OsHelper.getOs(), OsHelper.getArch())); + } + + final var downloadUrl = URI.create(String.format( + "https://mathsat.fbk.eu/download.php?file=mathsat-%s-%s.%s", + version, archStr, OsHelper.getOs().equals(WINDOWS) ? "zip" : "tar.gz" + )); + + logger.write(Logger.Level.MAINSTEP, "Starting download (%s)...\n", downloadUrl.toString()); + + try(final var inputStream = downloadUrl.toURL().openStream()) { + if(OsHelper.getOs().equals(WINDOWS)) { + Compress.extract(inputStream, installDir, Compress.CompressionType.ZIP); + } + else { + Compress.extract(inputStream, installDir, Compress.CompressionType.TARGZ); + } + installDir.resolve("bin").resolve(getSolverBinaryName()).toFile().setExecutable(true, true); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(e); + } + + logger.write(Logger.Level.MAINSTEP, "Download finished\n"); + } + + @Override + protected void uninstallSolver(Path installDir, String version) { } + + @Override + protected String[] getDefaultSolverArgs(String version) throws SmtLibSolverInstallerException { + return new String[] { }; + } + + @Override + public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); + return GenericSmtLibSolverFactory.create(solverFilePath, solverArgs); + } + + @Override + public List getSupportedVersions() { + return Arrays.asList( + "5.6.5", "5.6.4", "5.6.3", "5.6.2", "5.6.1", "5.6.0", + "5.5.4", "5.5.3", "5.5.2", "5.5.1", "5.5.0", + "5.4.1", "5.4.0", + "5.3.14", "5.3.13", "5.3.12", "5.3.11", "5.3.10", "5.3.9", "5.3.8", "5.3.7", "5.3.6", "5.3.5", "5.3.4", "5.3.3", "5.3.2", "5.3.1", + "5.2.12", "5.2.11", "5.2.10", "5.2.9", "5.2.8", "5.2.7", "5.2.6", "5.2.5", "5.2.4", "5.2.3", "5.2.2", "5.2.1", + "5.1.12", "5.1.11", "5.1.10", "5.1.9", "5.1.8", "5.1.7", "5.1.6", "5.1.5", "5.1.4", "5.1.3", "5.1.2", "5.1.1" + ); + } + + private String getSolverBinaryName() { + switch(OsHelper.getOs()) { + case WINDOWS: + return "mathsat.exe"; + case LINUX: + return "mathsat"; + case MAC: + return "mathsat.dmg"; + default: + throw new AssertionError(); + } + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/Compress.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/Compress.java new file mode 100644 index 0000000000..0de0b7d885 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/Compress.java @@ -0,0 +1,49 @@ +package hu.bme.mit.theta.solver.smtlib.utils; + +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.ArchiveInputStream; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +public class Compress { + private Compress() {} + + public enum CompressionType { + ZIP, TARGZ + } + + public static void extract(final InputStream inputStream, final Path extractDir, final CompressionType compressionType) throws IOException { + switch (compressionType) { + case ZIP: + extract(new ZipArchiveInputStream(inputStream), extractDir); + break; + case TARGZ: + extract(new TarArchiveInputStream(new GzipCompressorInputStream(new BufferedInputStream(inputStream))), extractDir); + break; + } + } + + private static void extract(final ArchiveInputStream archiveInputStream, final Path extractDir) throws IOException { + for(ArchiveEntry entry = archiveInputStream.getNextEntry(); entry != null; entry = archiveInputStream.getNextEntry()) { + final var entryPath = Path.of(entry.getName()); + if(entry.isDirectory()) { + if(entryPath.getNameCount() > 1) { + final var entryResolvedPath = extractDir.resolve(entryPath.subpath(1, entryPath.getNameCount())); + Files.createDirectories(entryResolvedPath); + } + } + else { + final var entryResolvedPath = extractDir.resolve(entryPath.subpath(1, entryPath.getNameCount())); + Files.createDirectories(entryResolvedPath.getParent()); + Files.copy(archiveInputStream, entryResolvedPath); + } + } + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/SemVer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/SemVer.java new file mode 100644 index 0000000000..7b15a060d3 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/SemVer.java @@ -0,0 +1,142 @@ +package hu.bme.mit.theta.solver.smtlib.utils; + +import hu.bme.mit.theta.common.OsHelper; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public class SemVer implements Comparable { + private final int[] version; + + private SemVer(final String version) { + checkNotNull(version); + checkArgument(version.matches("[0-9]+(\\.[0-9]+)*")); + + this.version = Arrays.stream(version.split("\\.")).mapToInt(Integer::parseInt).toArray(); + } + + public static SemVer of(final String version) { + return new SemVer(version); + } + + public boolean hasMajor() { + return version.length > 0; + } + + public int getMajor() { + return version[0]; + } + + public boolean hasMinor() { + return version.length > 1; + } + + public int getMinor() { + return version[1]; + } + + public boolean hasPatch() { + return version.length > 2; + } + + public int getPatch() { + return version[2]; + } + + public int[] getAll() { + return version; + } + + @Override + public int compareTo(final SemVer that) { + if(that == null) { + return 1; + } + + for(int i = 0; i < Math.max(this.version.length, that.version.length); i++) { + final var thisVer = i < this.version.length ? this.version[i] : 0; + final var thatVer = i < that.version.length ? that.version[i] : 0; + + if(thisVer < thatVer) { + return -1; + } + else if(thisVer > thatVer) { + return 1; + } + else { + continue; + } + } + + return 0; + } + + @Override + public boolean equals(Object obj) { + if(obj == null) { + return false; + } + else if(obj instanceof SemVer) { + return this.compareTo((SemVer) obj) == 0; + } + else { + return false; + } + } + + public static class VersionDecoder { + private final SemVer version; + private final Map> string; + + private VersionDecoder(final SemVer version, final Map> string) { + this.version = version; + this.string = string; + } + + public static VersionDecoder.Builder create(final SemVer version) { + return new VersionDecoder.Builder(version); + } + + public SemVer getVersion() { + return version; + } + + public String getOsArchString(final OsHelper.OperatingSystem os, final OsHelper.Architecture arch) { + if(!string.containsKey(os)) { + throw new UnsupportedOperationException(String.format("Operating system %s is not supported by z3", os)); + } + else if(!string.get(os).containsKey(arch)) { + throw new UnsupportedOperationException(String.format("Architecture %s on operating system %s is not supported by z3", arch, os)); + } + else { + return string.get(os).get(arch); + } + } + + public static class Builder { + private final SemVer version; + private final Map> string; + + private Builder(final SemVer version) { + this.version = version; + this.string = new HashMap<>(); + } + + public VersionDecoder.Builder addString(final OsHelper.OperatingSystem os, final OsHelper.Architecture arch, final String string) { + if(!this.string.containsKey(os)) { + this.string.put(os, new HashMap<>()); + } + this.string.get(os).put(arch, string); + return this; + } + + public VersionDecoder build() { + return new VersionDecoder(version, string); + } + } + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java index e90d139aa4..dd84248971 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java @@ -1,12 +1,12 @@ package hu.bme.mit.theta.solver.smtlib.z3; import hu.bme.mit.theta.common.OsHelper; -import hu.bme.mit.theta.common.SemVer; +import hu.bme.mit.theta.solver.smtlib.utils.Compress; +import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.smtlib.BaseSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; import java.io.IOException; import java.net.URI; @@ -15,9 +15,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -30,48 +28,48 @@ import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; public class Z3SmtLibSolverInstaller extends BaseSmtLibSolverInstaller { - private final List versions; + private final List versions; public Z3SmtLibSolverInstaller(final Logger logger) { super(logger); versions = new ArrayList<>(); - versions.add(VersionDecoder.create(SemVer.of("4.8.5")) + versions.add(SemVer.VersionDecoder.create(SemVer.of("4.8.5")) .addString(LINUX, X64, "x64-ubuntu-16.04") .addString(WINDOWS, X64, "x64-win") .addString(WINDOWS, X86, "x86-win") .addString(MAC, X64, "x64-osx-10.14.6") .build() ); - versions.add(VersionDecoder.create(SemVer.of("4.8.5")) + versions.add(SemVer.VersionDecoder.create(SemVer.of("4.8.5")) .addString(LINUX, X64, "x64-ubuntu-16.04") .addString(WINDOWS, X64, "x64-win") .addString(WINDOWS, X86, "x86-win") .addString(MAC, X64, "x64-osx-10.14.2") .build() ); - versions.add(VersionDecoder.create(SemVer.of("4.8.4")) + versions.add(SemVer.VersionDecoder.create(SemVer.of("4.8.4")) .addString(LINUX, X64, "x64-ubuntu-16.04") .addString(WINDOWS, X64, "x64-win") .addString(WINDOWS, X86, "x86-win") .addString(MAC, X64, "x64-osx-10.14.1") .build() ); - versions.add(VersionDecoder.create(SemVer.of("4.8.3")) + versions.add(SemVer.VersionDecoder.create(SemVer.of("4.8.3")) .addString(LINUX, X64, "x64-ubuntu-16.04") .addString(WINDOWS, X64, "x64-win") .addString(WINDOWS, X86, "x86-win") .addString(MAC, X64, "x64-osx-10.13.6") .build() ); - versions.add(VersionDecoder.create(SemVer.of("4.6.0")) + versions.add(SemVer.VersionDecoder.create(SemVer.of("4.6.0")) .addString(LINUX, X64, "x64-ubuntu-16.04") .addString(WINDOWS, X64, "x64-win") .addString(WINDOWS, X86, "x86-win") .addString(MAC, X64, "x64-osx-10.11.6") .build() ); - versions.add(VersionDecoder.create(SemVer.of("4.4.0")) + versions.add(SemVer.VersionDecoder.create(SemVer.of("4.4.0")) .addString(LINUX, X64, "x64-ubuntu-14.04") .addString(LINUX, X86, "x86-ubuntu-14.04") .addString(WINDOWS, X64, "x64-win") @@ -79,7 +77,7 @@ public Z3SmtLibSolverInstaller(final Logger logger) { .addString(MAC, X64, "x64-osx-10.11.6") .build() ); - versions.add(VersionDecoder.create(SemVer.of("4.3.2")) + versions.add(SemVer.VersionDecoder.create(SemVer.of("4.3.2")) .addString(WINDOWS, X64, "x64-win") .addString(WINDOWS, X86, "x86-win") .build() @@ -112,8 +110,8 @@ protected void installSolver(final Path installDir, final String version) throws )); logger.write(Logger.Level.MAINSTEP, "Starting download (%s)...\n", downloadUrl.toString()); - try(final var zipInputStream = new ZipInputStream(downloadUrl.toURL().openStream())) { - unzip(zipInputStream, installDir); + try(final var inputStream = downloadUrl.toURL().openStream()) { + Compress.extract(inputStream, installDir, Compress.CompressionType.ZIP); installDir.resolve("bin").resolve(getSolverBinaryName()).toFile().setExecutable(true, true); } catch (IOException e) { @@ -132,26 +130,9 @@ protected String[] getDefaultSolverArgs(String version) { } @Override - public SolverFactory getSolverFactory(final Path home, final String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkVersion(version); - - final var installDir = home.resolve(version); - if(!Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("The version is not installed"); - } - - try { - final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); - final var solverArgsPath = argsFile(installDir); - final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); - - return Z3SmtLibSolverFactory.create(solverFilePath, solverArgs); - } - catch (IOException e) { - throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); - } + public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); + return Z3SmtLibSolverFactory.create(solverFilePath, solverArgs); } @Override @@ -174,75 +155,4 @@ private String getSolverBinaryName() { throw new AssertionError(); } } - - private static void unzip(final ZipInputStream zipInputStream, final Path installDir) throws SmtLibSolverInstallerException { - try { - for(ZipEntry entry = zipInputStream.getNextEntry(); entry != null; entry = zipInputStream.getNextEntry()) { - final var entryPath = Path.of(entry.getName()); - final var entryResolvedPath = installDir.resolve(entryPath.subpath(1, entryPath.getNameCount())); - if(entry.isDirectory()) { - Files.createDirectories(entryResolvedPath); - } - else { - Files.createDirectories(entryResolvedPath.getParent()); - Files.copy(zipInputStream, entryResolvedPath); - } - } - } - catch(IOException e) { - throw new SmtLibSolverInstallerException(e.getMessage(), e); - } - } - - private static class VersionDecoder { - private final SemVer version; - private final Map> string; - - private VersionDecoder(final SemVer version, final Map> string) { - this.version = version; - this.string = string; - } - - public static Builder create(final SemVer version) { - return new Builder(version); - } - - public SemVer getVersion() { - return version; - } - - public String getOsArchString(final OsHelper.OperatingSystem os, final OsHelper.Architecture arch) throws SmtLibSolverInstallerException { - if(!string.containsKey(os)) { - throw new SmtLibSolverInstallerException(String.format("Operating system %s is not supported by z3", os)); - } - else if(!string.get(os).containsKey(arch)) { - throw new SmtLibSolverInstallerException(String.format("Architecture %s on operating system %s is not supported by z3", arch, os)); - } - else { - return string.get(os).get(arch); - } - } - - public static class Builder { - private final SemVer version; - private final Map> string; - - private Builder(final SemVer version) { - this.version = version; - this.string = new HashMap<>(); - } - - public Builder addString(final OsHelper.OperatingSystem os, final OsHelper.Architecture arch, final String string) { - if(!this.string.containsKey(os)) { - this.string.put(os, new HashMap<>()); - } - this.string.get(os).put(arch, string); - return this; - } - - public VersionDecoder build() { - return new VersionDecoder(version, string); - } - } - } } From c2c536d5386cc653f839532d113664660aa06b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 2 Mar 2021 15:09:03 +0100 Subject: [PATCH 65/99] Add basic MathSAT interpolation support for newer versions --- .../solver/smtlib/BaseSmtLibItpSolver.java | 9 +- .../generic/GenericSmtLibTermTransformer.java | 2 +- .../mathsat/MathSATSmtLibItpMarker.java | 23 ++++ .../mathsat/MathSATSmtLibItpPattern.java | 94 +++++++++++++ .../mathsat/MathSATSmtLibItpSolver.java | 125 ++++++++++++++++++ .../mathsat/MathSATSmtLibSolverFactory.java | 58 ++++++++ .../mathsat/MathSATSmtLibSolverInstaller.java | 2 +- .../solver/smtlib/z3/Z3SmtLibItpSolver.java | 2 +- 8 files changed, 308 insertions(+), 7 deletions(-) create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpMarker.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpPattern.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpSolver.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverFactory.java diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java index 9ef122cf24..1a5b96b9c4 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java @@ -73,27 +73,28 @@ public Collection getMarkers() { return markers.toCollection(); } + @SuppressWarnings("unchecked") @Override public void add(final ItpMarker marker, final Expr assertion) { checkNotNull(marker); checkNotNull(assertion); - checkArgument(marker instanceof SmtLibItpMarker); + checkNotNull((T) marker); checkArgument(markers.toCollection().contains(marker)); final var consts = ExprUtils.getConstants(assertion); consts.removeAll(declarationStack.toCollection()); declarationStack.add(consts); - final var itpMarker = (SmtLibItpMarker) marker; + final var itpMarker = (T) marker; final var term = transformationManager.toTerm(assertion); itpMarker.add(assertion, term); - add(marker, assertion, consts, term); + add(itpMarker, assertion, consts, term); clearState(); } - protected abstract void add(final ItpMarker marker, final Expr assertion, final Set> consts, final String term); + protected abstract void add(final T marker, final Expr assertion, final Set> consts, final String term); @Override public SolverStatus check() { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java index 32748c0e06..ac51b25e92 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java @@ -411,7 +411,7 @@ protected Expr transformGenericTerm(final Generic_termContext ctx, final SmtL } else if (funAppTransformer.containsKey(funName)) { // known function application return funAppTransformer.get(funName).apply(funParams, funAppParams, model, vars); } else { // custom function application - checkArgument(funParams.size() == 0, "Custom unary function application cannot vahe parameter"); + checkArgument(funParams.size() == 0, "Custom unary function application cannot have parameter"); checkArgument(funAppParams.size() == 1, "Only unary functions are supported"); return createFuncAppExpr(funName, funAppParams.get(0), model, vars); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpMarker.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpMarker.java new file mode 100644 index 0000000000..027dad79d7 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpMarker.java @@ -0,0 +1,23 @@ +package hu.bme.mit.theta.solver.smtlib.mathsat; + +import hu.bme.mit.theta.solver.smtlib.SmtLibItpMarker; + +public class MathSATSmtLibItpMarker extends SmtLibItpMarker { + private static final String markerPattern = "_mathsat_marker_%d"; + private static long markerCount = 0; + + static void resetMarkerCount() { + markerCount = 0; + } + + private final String markerName; + + public MathSATSmtLibItpMarker() { + super(); + markerName = String.format(markerPattern, markerCount++); + } + + public String getMarkerName() { + return markerName; + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpPattern.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpPattern.java new file mode 100644 index 0000000000..882521a393 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpPattern.java @@ -0,0 +1,94 @@ +package hu.bme.mit.theta.solver.smtlib.mathsat; + +import com.google.common.collect.Lists; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; +import hu.bme.mit.theta.solver.ItpPattern; + +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +public class MathSATSmtLibItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { + final ItpMarkerTree markerTree; + + MathSATSmtLibItpPattern(final ItpMarkerTree markerTree) { + this.markerTree = markerTree; + } + + @SuppressWarnings("unchecked") + static MathSATSmtLibItpPattern of(final ItpMarkerTree markerTree) { + final var list = new ArrayList>(); + list.add(markerTree); + while(!list.isEmpty()) { + final var node = list.get(0); + list.remove(0); + + checkArgument(node.getMarker() instanceof MathSATSmtLibItpMarker); + + list.addAll(node.getChildren()); + } + + return new MathSATSmtLibItpPattern((ItpMarkerTree) markerTree); + } + + @Override + public MathSATSmtLibItpMarker getA() { + checkState(isBinary()); + return markerTree.getChild(0).getMarker(); + } + + @Override + public MathSATSmtLibItpMarker getB() { + checkState(isBinary()); + return markerTree.getMarker(); + } + + @Override + public List getSequence() { + checkState(isSequence()); + final var markerList = new ArrayList(); + + var current = markerTree; + while(current.getChildrenNumber() > 0) { + markerList.add(current.getMarker()); + current = current.getChild(0); + } + markerList.add(current.getMarker()); + + return Lists.reverse(markerList); + } + + @Override + public ItpMarkerTree getRoot() { + return markerTree; + } + + @Override + public E visit(ItpPatternVisitor visitor) { + return visitor.visitTreePattern(this); + } + + private boolean isBinary() { + return + markerTree != null && + markerTree.getChildrenNumber() == 1 && + markerTree.getChild(0) != null && + markerTree.getChild(0).getChildrenNumber() == 0; + } + + private boolean isSequence() { + var current = markerTree; + while(current.getChildrenNumber() > 0) { + if(current.getChildrenNumber() > 1) { + return false; + } + else { + current = current.getChild(0); + } + } + return true; + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpSolver.java new file mode 100644 index 0000000000..dbef64e60a --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpSolver.java @@ -0,0 +1,125 @@ +package hu.bme.mit.theta.solver.smtlib.mathsat; + +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolExprs; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.solver.Interpolant; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; +import hu.bme.mit.theta.solver.ItpPattern; +import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.Stack; +import hu.bme.mit.theta.solver.impl.StackImpl; +import hu.bme.mit.theta.solver.smtlib.BaseSmtLibItpSolver; +import hu.bme.mit.theta.solver.smtlib.SmtLibInterpolant; +import hu.bme.mit.theta.solver.smtlib.SmtLibModel; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.misc.Interval; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public class MathSATSmtLibItpSolver extends BaseSmtLibItpSolver { + + public MathSATSmtLibItpSolver( + final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, + final SmtLibTermTransformer termTransformer, final SmtLibSolverBinary solverBinary + ) { + super(symbolTable, transformationManager, termTransformer, solverBinary); + } + + @Override + public ItpPattern createTreePattern(final ItpMarkerTree root) { + checkNotNull(root); + return MathSATSmtLibItpPattern.of(root); + } + + @Override + public MathSATSmtLibItpMarker createMarker() { + final var marker = new MathSATSmtLibItpMarker(); + markers.add(marker); + return marker; + } + + @Override + protected void add(final MathSATSmtLibItpMarker marker, final Expr assertion, final Set> consts, final String term) { + consts.stream().map(symbolTable::getDeclaration).forEach(this::issueGeneralCommand); + issueGeneralCommand(String.format("(assert (! %s :interpolation-group %s))", term, marker.getMarkerName())); + } + + @Override + public Interpolant getInterpolant(final ItpPattern pattern) { + checkState(getStatus() == SolverStatus.UNSAT, "Cannot get interpolant if status is not UNSAT."); + checkArgument(pattern instanceof MathSATSmtLibItpPattern); + final var mathsatItpPattern = (MathSATSmtLibItpPattern) pattern; + + final Map> itpMap = new HashMap<>(); + buildItpMapFromTree(mathsatItpPattern.getRoot(), itpMap); + + return new SmtLibInterpolant(itpMap); + } + + @Override + protected void init() { + super.init(); + issueGeneralCommand("(set-option :produce-interpolants true)"); + } + + private List buildItpMapFromTree(final ItpMarkerTree pattern, final Map> itpMap) { + final List markers = new ArrayList<>(); + for(final var child : pattern.getChildren()) { + markers.addAll(buildItpMapFromTree(child, itpMap)); + } + markers.add(pattern.getMarker()); + + solverBinary.issueCommand(String.format("(get-interpolant (%s))", markers.stream().map(MathSATSmtLibItpMarker::getMarkerName).collect(Collectors.joining(" ")))); + final var res = parseItpResponse(solverBinary.readResponse()); + itpMap.put(pattern.getMarker(), termTransformer.toExpr(res, BoolExprs.Bool(), new SmtLibModel(Collections.emptyMap()))); + + return markers; + } + + private String parseItpResponse(final String response) { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(response)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + try { + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + return extractString(parser.term()); + } + catch (Exception e) { + try { + throw new SmtLibSolverException(parser.response().general_response_error().reason.getText()); + } + catch(Exception ex) { + throw new SmtLibSolverException("Could not parse solver output: " + response, e); + } + } + } + + private static String extractString(final ParserRuleContext ctx) { + return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex())); + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverFactory.java new file mode 100644 index 0000000000..773023d23d --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverFactory.java @@ -0,0 +1,58 @@ +package hu.bme.mit.theta.solver.smtlib.mathsat; + +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolver; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibItpSolver; + +import java.nio.file.Path; + +public class MathSATSmtLibSolverFactory implements SolverFactory { + private final Path solverPath; + private final String[] args; + + private MathSATSmtLibSolverFactory(Path solverPath, String[] args) { + this.solverPath = solverPath; + this.args = args; + } + + public static MathSATSmtLibSolverFactory create(Path solverPath, String[] args) { + return new MathSATSmtLibSolverFactory(solverPath, args); + } + + @Override + public Solver createSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); + } + + @Override + public UCSolver createUCSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); + } + + @Override + public ItpSolver createItpSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new MathSATSmtLibItpSolver(symbolTable, transformationManager, termTransformer, solverBinary); + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java index a22e0084e3..2c7f5cf6fd 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java @@ -144,7 +144,7 @@ protected String[] getDefaultSolverArgs(String version) throws SmtLibSolverInsta @Override public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); - return GenericSmtLibSolverFactory.create(solverFilePath, solverArgs); + return MathSATSmtLibSolverFactory.create(solverFilePath, solverArgs); } @Override diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java index 54760d637c..c557028a24 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java @@ -73,7 +73,7 @@ public void add(ItpMarker marker, Expr assertion) { } @Override - protected void add(final ItpMarker marker, final Expr assertion, final Set> consts, final String term) { + protected void add(final Z3SmtLibItpMarker marker, final Expr assertion, final Set> consts, final String term) { consts.stream().map(symbolTable::getDeclaration).forEach(this::issueGeneralCommand); } From 21fbee5a343ef88a564862b895b18c4f15246516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 5 Mar 2021 15:35:15 +0100 Subject: [PATCH 66/99] Add MathSAT support for older versions --- .../solver/solver-smtlib/src/main/antlr/SMTLIBv2.g4 | 5 +++++ .../smtlib/mathsat/MathSATSmtLibSolverInstaller.java | 2 +- .../theta/solver/smtlib/parser/GetModelResponse.java | 12 ++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/subprojects/solver/solver-smtlib/src/main/antlr/SMTLIBv2.g4 b/subprojects/solver/solver-smtlib/src/main/antlr/SMTLIBv2.g4 index a8163165c6..bb7936d6bc 100644 --- a/subprojects/solver/solver-smtlib/src/main/antlr/SMTLIBv2.g4 +++ b/subprojects/solver/solver-smtlib/src/main/antlr/SMTLIBv2.g4 @@ -74,6 +74,7 @@ model_response : model_response_fun | model_response_fun_rec | model_response_funs_rec + | model_response_mathsat ; model_response_fun @@ -88,6 +89,10 @@ model_response_funs_rec : ParOpen CMD_DefineFunsRec ParOpen function_dec+ ParClose ParOpen term+ ParClose ParClose ; +model_response_mathsat + : ParOpen symbol term ParClose + ; + function_def : symbol ParOpen sorted_var* ParClose sort term ; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java index 2c7f5cf6fd..d635fba1b8 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java @@ -155,7 +155,7 @@ public List getSupportedVersions() { "5.4.1", "5.4.0", "5.3.14", "5.3.13", "5.3.12", "5.3.11", "5.3.10", "5.3.9", "5.3.8", "5.3.7", "5.3.6", "5.3.5", "5.3.4", "5.3.3", "5.3.2", "5.3.1", "5.2.12", "5.2.11", "5.2.10", "5.2.9", "5.2.8", "5.2.7", "5.2.6", "5.2.5", "5.2.4", "5.2.3", "5.2.2", "5.2.1", - "5.1.12", "5.1.11", "5.1.10", "5.1.9", "5.1.8", "5.1.7", "5.1.6", "5.1.5", "5.1.4", "5.1.3", "5.1.2", "5.1.1" + "5.1.12", "5.1.11", "5.1.10", "5.1.9", "5.1.8", "5.1.7", "5.1.6", "5.1.5", "5.1.4", "5.1.3" ); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java index 0d63f2a981..d3616c9b8d 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java @@ -3,6 +3,8 @@ import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.solver.smtlib.SmtLibModel; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Model_response_mathsatContext; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.misc.Interval; @@ -28,6 +30,16 @@ public Tuple2 visitModel_response_fun(Model_response_funContext return Tuple2.of(extractString(ctx.function_def().symbol()), extractString(ctx.function_def())); } + @Override + public Tuple2 visitModel_response_mathsat(Model_response_mathsatContext ctx) { + final var functionDef = String.format( + "%s () (_ theta_type unknown) %s", + extractString(ctx.symbol()), + extractString(ctx.term()) + ); + return Tuple2.of(extractString(ctx.symbol()), functionDef); + } + @Override public Tuple2 visitModel_response_fun_rec(Model_response_fun_recContext ctx) { throw new UnsupportedOperationException(); From ca7c1af211772ea847a1a900eed53645e1f70614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 8 Mar 2021 15:47:42 +0100 Subject: [PATCH 67/99] Add version guard to MathSAT and Z3 solver factories --- .../mathsat/MathSATSmtLibSolverFactory.java | 24 ++++++++++++------- .../mathsat/MathSATSmtLibSolverInstaller.java | 2 +- .../smtlib/z3/Z3SmtLibSolverFactory.java | 23 +++++++++++------- .../smtlib/z3/Z3SmtLibSolverInstaller.java | 2 +- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverFactory.java index 773023d23d..d9669ae7db 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverFactory.java @@ -9,21 +9,22 @@ import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSymbolTable; import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTermTransformer; import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTransformationManager; -import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibItpSolver; import java.nio.file.Path; public class MathSATSmtLibSolverFactory implements SolverFactory { private final Path solverPath; private final String[] args; + private final boolean itpSupported; - private MathSATSmtLibSolverFactory(Path solverPath, String[] args) { + private MathSATSmtLibSolverFactory(Path solverPath, String[] args, boolean itpSupported) { this.solverPath = solverPath; this.args = args; + this.itpSupported = itpSupported; } - public static MathSATSmtLibSolverFactory create(Path solverPath, String[] args) { - return new MathSATSmtLibSolverFactory(solverPath, args); + public static MathSATSmtLibSolverFactory create(Path solverPath, String[] args, boolean itpSupported) { + return new MathSATSmtLibSolverFactory(solverPath, args, itpSupported); } @Override @@ -48,11 +49,16 @@ public UCSolver createUCSolver() { @Override public ItpSolver createItpSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + if(itpSupported) { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - return new MathSATSmtLibItpSolver(symbolTable, transformationManager, termTransformer, solverBinary); + return new MathSATSmtLibItpSolver(symbolTable, transformationManager, termTransformer, solverBinary); + } + else { + throw new UnsupportedOperationException("MathSAT interpolation supported above 5.4.0"); + } } } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java index d635fba1b8..d6d49b1681 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java @@ -144,7 +144,7 @@ protected String[] getDefaultSolverArgs(String version) throws SmtLibSolverInsta @Override public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); - return MathSATSmtLibSolverFactory.create(solverFilePath, solverArgs); + return MathSATSmtLibSolverFactory.create(solverFilePath, solverArgs, SemVer.of(version).compareTo(SemVer.of("5.4.0")) >= 0); } @Override diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java index 2c834261a5..ed7f108e99 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java @@ -15,14 +15,16 @@ public class Z3SmtLibSolverFactory implements SolverFactory { private final Path solverPath; private final String[] args; + private final boolean itpSupported; - private Z3SmtLibSolverFactory(Path solverPath, String[] args) { + private Z3SmtLibSolverFactory(Path solverPath, String[] args, boolean itpSupported) { this.solverPath = solverPath; this.args = args; + this.itpSupported = itpSupported; } - public static Z3SmtLibSolverFactory create(Path solverPath, String[] args) { - return new Z3SmtLibSolverFactory(solverPath, args); + public static Z3SmtLibSolverFactory create(Path solverPath, String[] args, boolean itpSupported) { + return new Z3SmtLibSolverFactory(solverPath, args, itpSupported); } @Override @@ -47,11 +49,16 @@ public UCSolver createUCSolver() { @Override public ItpSolver createItpSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + if(itpSupported) { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - return new Z3SmtLibItpSolver(symbolTable, transformationManager, termTransformer, solverBinary); + return new Z3SmtLibItpSolver(symbolTable, transformationManager, termTransformer, solverBinary); + } + else { + throw new UnsupportedOperationException("Z3 interpolation supported below 4.5.0"); + } } } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java index dd84248971..5e3ca64a44 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java @@ -132,7 +132,7 @@ protected String[] getDefaultSolverArgs(String version) { @Override public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); - return Z3SmtLibSolverFactory.create(solverFilePath, solverArgs); + return Z3SmtLibSolverFactory.create(solverFilePath, solverArgs, SemVer.of(version).compareTo(SemVer.of("4.5.0")) <= 0); } @Override From dc11e4679abe48007e569067b7fe11fb8979b525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 8 Mar 2021 15:48:08 +0100 Subject: [PATCH 68/99] Add dedicated solver factory for CVC4 --- .../smtlib/cvc4/CVC4SmtLibSolverFactory.java | 52 +++++++++++++++++++ .../cvc4/CVC4SmtLibSolverInstaller.java | 2 +- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverFactory.java diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverFactory.java new file mode 100644 index 0000000000..fa57fe93d8 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverFactory.java @@ -0,0 +1,52 @@ +package hu.bme.mit.theta.solver.smtlib.cvc4; + +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolver; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTransformationManager; + +import java.nio.file.Path; + +public class CVC4SmtLibSolverFactory implements SolverFactory { + private final Path solverPath; + private final String[] args; + + private CVC4SmtLibSolverFactory(Path solverPath, String[] args) { + this.solverPath = solverPath; + this.args = args; + } + + public static CVC4SmtLibSolverFactory create(Path solverPath, String[] args) { + return new CVC4SmtLibSolverFactory(solverPath, args); + } + + @Override + public Solver createSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); + } + + @Override + public UCSolver createUCSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); + } + + @Override + public ItpSolver createItpSolver() { + throw new UnsupportedOperationException("CVC4 does not support interpolation"); + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java index a4b9f243cb..74b9b5aa1c 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java @@ -72,7 +72,7 @@ protected String[] getDefaultSolverArgs(String version) { @Override public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); - return GenericSmtLibSolverFactory.create(solverFilePath, solverArgs); + return CVC4SmtLibSolverFactory.create(solverFilePath, solverArgs); } @Override From 3eefa8ddcc60194bb8b7f4b17ba8005a29b87c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 15 Mar 2021 16:12:08 +0100 Subject: [PATCH 69/99] Refactor smtlib project structure --- .../theta/solver/smtlib/cli/SmtLibCli.java | 4 +- subprojects/solver/solver-smtlib/README.md | 6 +- .../smtlib/BaseSmtLibSolverInstaller.java | 241 ---------------- .../solver/smtlib/SmtLibSolverInstaller.java | 24 -- .../{manager => }/SmtLibSolverManager.java | 14 +- .../cvc4/CVC4SmtLibSolverFactory.java | 12 +- .../cvc4/CVC4SmtLibSolverInstaller.java | 12 +- .../generic/GenericSmtLibDeclTransformer.java | 8 +- .../generic/GenericSmtLibExprTransformer.java | 6 +- .../generic/GenericSmtLibSolverBinary.java | 7 +- .../generic/GenericSmtLibSolverFactory.java | 4 +- .../generic/GenericSmtLibSolverInstaller.java | 8 +- .../generic/GenericSmtLibSymbolTable.java | 4 +- .../generic/GenericSmtLibTermTransformer.java | 12 +- .../GenericSmtLibTransformationManager.java | 12 +- .../generic/GenericSmtLibTypeTransformer.java | 6 +- .../mathsat/MathSATSmtLibItpMarker.java | 4 +- .../mathsat/MathSATSmtLibItpPattern.java | 2 +- .../mathsat/MathSATSmtLibItpSolver.java | 24 +- .../mathsat/MathSATSmtLibSolverFactory.java | 12 +- .../mathsat/MathSATSmtLibSolverInstaller.java | 19 +- .../{ => impl}/z3/Z3SmtLibItpMarker.java | 4 +- .../smtlib/impl/z3/Z3SmtLibItpPattern.java | 94 +++++++ .../{ => impl}/z3/Z3SmtLibItpSolver.java | 22 +- .../{ => impl}/z3/Z3SmtLibSolverFactory.java | 12 +- .../z3/Z3SmtLibSolverInstaller.java | 12 +- .../SmtLibItpSolver.java} | 20 +- .../smtlib/{ => solver}/SmtLibSolver.java | 17 +- .../{ => solver}/SmtLibSolverException.java | 2 +- .../binary}/SmtLibSolverBinary.java | 2 +- .../binary}/SmtLibSolverBinaryException.java | 4 +- .../installer/SmtLibSolverInstaller.java | 258 ++++++++++++++++++ .../SmtLibSolverInstallerException.java | 2 +- .../interpolation}/SmtLibInterpolant.java | 2 +- .../interpolation}/SmtLibItpMarker.java | 2 +- .../{ => solver/model}/SmtLibModel.java | 2 +- .../{ => solver/model}/SmtLibValuation.java | 5 +- .../{ => solver}/parser/CheckSatResponse.java | 4 +- .../{ => solver}/parser/GeneralResponse.java | 3 +- .../{ => solver}/parser/GetModelResponse.java | 5 +- .../parser/GetUnsatCoreResponse.java | 3 +- .../{ => solver}/parser/SpecificResponse.java | 2 +- .../parser/ThrowExceptionErrorListener.java | 4 +- .../transformer}/SmtLibDeclTransformer.java | 2 +- .../transformer}/SmtLibExprTransformer.java | 2 +- .../transformer}/SmtLibSymbolTable.java | 2 +- .../transformer}/SmtLibTermTransformer.java | 3 +- .../SmtLibTransformationManager.java | 2 +- .../transformer}/SmtLibTypeTransformer.java | 2 +- 49 files changed, 509 insertions(+), 426 deletions(-) delete mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java delete mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{manager => }/SmtLibSolverManager.java (94%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/cvc4/CVC4SmtLibSolverFactory.java (80%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/cvc4/CVC4SmtLibSolverInstaller.java (90%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/generic/GenericSmtLibDeclTransformer.java (92%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/generic/GenericSmtLibExprTransformer.java (99%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/generic/GenericSmtLibSolverBinary.java (93%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/generic/GenericSmtLibSolverFactory.java (94%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/generic/GenericSmtLibSolverInstaller.java (92%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/generic/GenericSmtLibSymbolTable.java (93%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/generic/GenericSmtLibTermTransformer.java (98%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/generic/GenericSmtLibTransformationManager.java (78%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/generic/GenericSmtLibTypeTransformer.java (90%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/mathsat/MathSATSmtLibItpMarker.java (78%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/mathsat/MathSATSmtLibItpPattern.java (98%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/mathsat/MathSATSmtLibItpSolver.java (85%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/mathsat/MathSATSmtLibSolverFactory.java (84%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/mathsat/MathSATSmtLibSolverInstaller.java (91%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/z3/Z3SmtLibItpMarker.java (79%) create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpPattern.java rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/z3/Z3SmtLibItpSolver.java (90%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/z3/Z3SmtLibSolverFactory.java (84%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => impl}/z3/Z3SmtLibSolverInstaller.java (93%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{BaseSmtLibItpSolver.java => solver/SmtLibItpSolver.java} (88%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver}/SmtLibSolver.java (91%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver}/SmtLibSolverException.java (95%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/binary}/SmtLibSolverBinary.java (66%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/binary}/SmtLibSolverBinaryException.java (88%) create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/installer}/SmtLibSolverInstallerException.java (94%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/interpolation}/SmtLibInterpolant.java (95%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/interpolation}/SmtLibItpMarker.java (93%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/model}/SmtLibModel.java (88%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/model}/SmtLibValuation.java (94%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver}/parser/CheckSatResponse.java (91%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver}/parser/GeneralResponse.java (95%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver}/parser/GetModelResponse.java (94%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver}/parser/GetUnsatCoreResponse.java (87%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver}/parser/SpecificResponse.java (95%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver}/parser/ThrowExceptionErrorListener.java (81%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/transformer}/SmtLibDeclTransformer.java (73%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/transformer}/SmtLibExprTransformer.java (66%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/transformer}/SmtLibSymbolTable.java (87%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/transformer}/SmtLibTermTransformer.java (87%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/transformer}/SmtLibTransformationManager.java (82%) rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{ => solver/transformer}/SmtLibTypeTransformer.java (66%) diff --git a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java index d95e5520ea..1d07a55af2 100644 --- a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java +++ b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java @@ -8,8 +8,8 @@ import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.common.logging.ConsoleLogger; import hu.bme.mit.theta.common.logging.Logger; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; -import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverManager; import java.awt.Desktop; import java.io.IOException; diff --git a/subprojects/solver/solver-smtlib/README.md b/subprojects/solver/solver-smtlib/README.md index 7783d4a4b4..2aadbdd189 100644 --- a/subprojects/solver/solver-smtlib/README.md +++ b/subprojects/solver/solver-smtlib/README.md @@ -44,11 +44,11 @@ The components above are integrated into a working solver implementation with Th ### Generic interface implementation -The interfaces above have a default, generic implementation that works with solvers that follow the SMT-LIB standard fully. These generic classes can be found in the `hu.bme.mit.theta.solver.smtlib.generic` package. +The interfaces above have a default, generic implementation that works with solvers that follow the SMT-LIB standard fully. These generic classes can be found in the `hu.bme.mit.theta.solver.smtlib.impl.generic` package. ### Solver specific implementations Right now, the solver-smtlib subproject supports the following solvers. Each package contains the specialization of the interfaces above that communicate with the said solver: -- **Z3** (`hu.bme.mit.theta.solver.smtlib.z3`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors, functions), and supports interpolation as well (binary, sequential and tree interpolation) up to version 4.7. -- **CVC4** (`hu.bme.mit.theta.solver.smtlib.cvc4`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). \ No newline at end of file +- **Z3** (`hu.bme.mit.theta.solver.smtlib.impl.z3`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors, functions), and supports interpolation as well (binary, sequential and tree interpolation) up to version 4.7. +- **CVC4** (`hu.bme.mit.theta.solver.smtlib.impl.cvc4`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). \ No newline at end of file diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java deleted file mode 100644 index ec950e0d60..0000000000 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibSolverInstaller.java +++ /dev/null @@ -1,241 +0,0 @@ -package hu.bme.mit.theta.solver.smtlib; - -import hu.bme.mit.theta.common.logging.Logger; -import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibSolverFactory; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -public abstract class BaseSmtLibSolverInstaller implements SmtLibSolverInstaller { - protected final Logger logger; - - public BaseSmtLibSolverInstaller(final Logger logger) { - this.logger = logger; - } - - @Override - public final void install(Path home, String version, String name) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkVersion(version); - checkName(name); - - final var installDir = getInstallDir(home, name); - if(Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("There is already a solver instance with this name installed"); - } - - try { - logger.write(Logger.Level.MAINSTEP, "Beginning installation...\n"); - - Files.createDirectory(installDir); - - installSolver(installDir, version); - - final var solverArgsPath = argsFile(installDir); - Files.writeString(solverArgsPath, String.join("\n", getDefaultSolverArgs(version)), StandardCharsets.UTF_8); - - final var solverInfoPath = infoFile(installDir); - Files.writeString( - solverInfoPath, - String.format("solver=%s\n", getSolverName()) + - String.format("version=%s\n", version) + - String.format("name=%s\n", name), - StandardCharsets.UTF_8 - ); - - logger.write(Logger.Level.MAINSTEP, "Installation finished\n"); - } - catch (SmtLibSolverInstallerException e) { - uninstall(home, version); - throw e; - } - catch (IOException e) { - throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); - } - } - - @Override - public final void uninstall(Path home, String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkName(version); - - final var installDir = getInstallDir(home, version); - if(!Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("The version is not installed"); - } - - try { - logger.write(Logger.Level.MAINSTEP, "Beginning uninstallation...\n"); - - uninstallSolver(installDir, version); - - deleteDirectory(installDir.toFile()); - - logger.write(Logger.Level.MAINSTEP, "Uninstallation finished\n"); - } - catch (IOException e) { - throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); - } - } - - @Override - public void reinstall(Path home, String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkName(version); - - final String solverVersion; - try { - final var installDir = getInstallDir(home, version); - final var solverInfoPath = infoFile(installDir); - final var solverInfo = Files - .readAllLines(solverInfoPath, StandardCharsets.UTF_8).stream() - .filter(l -> l.startsWith("version=")) - .map(l -> l.substring("version=".length())) - .findAny(); - - if(solverInfo.isPresent()) { - solverVersion = solverInfo.get(); - } - else { - throw new SmtLibSolverInstallerException("The solver installation is corrupted"); - } - } - catch (IOException e) { - throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); - } - - uninstall(home, version); - install(home, solverVersion, version); - } - - @Override - public final SolverFactory getSolverFactory(final Path home, final String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkVersion(version); - - final var installDir = home.resolve(version); - if(!Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("The version is not installed"); - } - - try { - final var solverArgsPath = argsFile(installDir); - final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); - - return getSolverFactory(installDir, version, solverArgs); - } - catch (IOException e) { - throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); - } - } - - @Override - public final String getInfo(Path home, String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkName(version); - - final var installDir = getInstallDir(home, version); - if(!Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("The version is not installed"); - } - - try { - final var solverInfoPath = infoFile(installDir); - final var solverInfoStr = Files.readString(solverInfoPath, StandardCharsets.UTF_8); - final var solverArgsPath = argsFile(installDir); - final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); - - return solverInfoStr + String.format("args=%s\n", String.join(" ", solverArgs)); - } - catch (IOException e) { - throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); - } - } - - @Override - public final Path getArgsFile(Path home, String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkName(version); - - final var installDir = home.resolve(version); - if(!Files.exists(installDir)) { - throw new SmtLibSolverInstallerException("The version is not installed"); - } - - return argsFile(installDir); - } - - @Override - public final List getInstalledVersions(Path home) throws SmtLibSolverInstallerException { - checkNotNull(home); - - if(Files.exists(home)) { - final var installedDirs = home.toFile() - .list((current, name) -> new File(current, name).isDirectory()); - - assert installedDirs != null; - return Arrays.asList(installedDirs); - } - else { - return Collections.emptyList(); - } - } - - protected abstract String getSolverName() throws SmtLibSolverInstallerException; - protected abstract void installSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException; - protected abstract void uninstallSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException; - protected abstract SolverFactory getSolverFactory(final Path installDir, final String version, final String[] args) throws SmtLibSolverInstallerException; - protected abstract String[] getDefaultSolverArgs(final String version) throws SmtLibSolverInstallerException; - - protected final void checkName(final String version) throws SmtLibSolverInstallerException { - if(!version.matches("^[a-zA-Z0-9_.-]+$")) { - throw new SmtLibSolverInstallerException("Unsupported name format: " + version); - } - } - - protected final void checkVersion(final String version) throws SmtLibSolverInstallerException { - if(!version.matches("^[0-9]+(\\.[0-9]+)*$")) { - throw new SmtLibSolverInstallerException("Unsupported version format: " + version); - } - } - - protected final Path getInstallDir(final Path home, final String version) { - return home.resolve(version); - } - - protected final Path argsFile(final Path installDir) { - return installDir.resolve("solver-args.txt"); - } - - protected final Path infoFile(final Path installDir) { - return installDir.resolve("solver-info.txt"); - } - - private void deleteDirectory(File directoryToBeDeleted) throws IOException { - File[] allContents = directoryToBeDeleted.listFiles(); - if (allContents != null) { - for (File file : allContents) { - deleteDirectory(file); - } - } - - Files.delete(directoryToBeDeleted.toPath()); - } -} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java deleted file mode 100644 index 973f6ef70f..0000000000 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstaller.java +++ /dev/null @@ -1,24 +0,0 @@ -package hu.bme.mit.theta.solver.smtlib; - -import hu.bme.mit.theta.solver.SolverFactory; - -import java.nio.file.Path; -import java.util.List; - -public interface SmtLibSolverInstaller { - void install(Path home, String version, String name) throws SmtLibSolverInstallerException; - - void uninstall(Path home, String version) throws SmtLibSolverInstallerException; - - void reinstall(Path home, String version) throws SmtLibSolverInstallerException; - - String getInfo(Path home, String version) throws SmtLibSolverInstallerException; - - Path getArgsFile(Path home, String version) throws SmtLibSolverInstallerException; - - SolverFactory getSolverFactory(Path home, String version) throws SmtLibSolverInstallerException; - - List getSupportedVersions() throws SmtLibSolverInstallerException; - - List getInstalledVersions(Path home) throws SmtLibSolverInstallerException; -} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java similarity index 94% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java index ca986461c3..9475eeac46 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/manager/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java @@ -1,15 +1,15 @@ -package hu.bme.mit.theta.solver.smtlib.manager; +package hu.bme.mit.theta.solver.smtlib; import com.google.common.collect.ImmutableList; import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstaller; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; -import hu.bme.mit.theta.solver.smtlib.cvc4.CVC4SmtLibSolverInstaller; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverInstaller; -import hu.bme.mit.theta.solver.smtlib.mathsat.MathSATSmtLibSolverInstaller; -import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.impl.cvc4.CVC4SmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.impl.mathsat.MathSATSmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.impl.z3.Z3SmtLibSolverInstaller; import java.io.IOException; import java.lang.reflect.InvocationTargetException; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverFactory.java similarity index 80% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverFactory.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverFactory.java index fa57fe93d8..c7e7348e7f 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverFactory.java @@ -1,14 +1,14 @@ -package hu.bme.mit.theta.solver.smtlib.cvc4; +package hu.bme.mit.theta.solver.smtlib.impl.cvc4; import hu.bme.mit.theta.solver.ItpSolver; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolver; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverBinary; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTermTransformer; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; import java.nio.file.Path; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java similarity index 90% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java index 74b9b5aa1c..d3facf2c2c 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/cvc4/CVC4SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java @@ -1,13 +1,11 @@ -package hu.bme.mit.theta.solver.smtlib.cvc4; +package hu.bme.mit.theta.solver.smtlib.impl.cvc4; import hu.bme.mit.theta.common.OsHelper; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.smtlib.BaseSmtLibSolverInstaller; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; -import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibSolverFactory; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import java.io.FileOutputStream; import java.io.IOException; @@ -15,8 +13,6 @@ import java.net.URI; import java.net.URL; import java.nio.channels.Channels; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.List; @@ -27,7 +23,7 @@ import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; -public class CVC4SmtLibSolverInstaller extends BaseSmtLibSolverInstaller { +public class CVC4SmtLibSolverInstaller extends SmtLibSolverInstaller.Default { public CVC4SmtLibSolverInstaller(final Logger logger) { super(logger); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibDeclTransformer.java similarity index 92% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibDeclTransformer.java index 5fbd6af3ac..310bd869bc 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibDeclTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibDeclTransformer.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib.generic; +package hu.bme.mit.theta.solver.smtlib.impl.generic; import com.google.common.collect.ImmutableList; import hu.bme.mit.theta.common.Tuple2; @@ -6,9 +6,9 @@ import hu.bme.mit.theta.core.decl.Decl; import hu.bme.mit.theta.core.type.Type; import hu.bme.mit.theta.core.type.functype.FuncType; -import hu.bme.mit.theta.solver.smtlib.SmtLibDeclTransformer; -import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibDeclTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; import java.util.List; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibExprTransformer.java similarity index 99% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibExprTransformer.java index 4ee3a52d6a..93c429998f 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibExprTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibExprTransformer.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib.generic; +package hu.bme.mit.theta.solver.smtlib.impl.generic; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -95,8 +95,8 @@ import hu.bme.mit.theta.core.type.rattype.RatPosExpr; import hu.bme.mit.theta.core.type.rattype.RatSubExpr; import hu.bme.mit.theta.core.utils.BvUtils; -import hu.bme.mit.theta.solver.smtlib.SmtLibExprTransformer; -import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibExprTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; import java.math.BigInteger; import java.util.Arrays; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverBinary.java similarity index 93% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverBinary.java index 0b5e6f1118..8ff838ce1b 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverBinary.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverBinary.java @@ -1,6 +1,7 @@ -package hu.bme.mit.theta.solver.smtlib.generic; +package hu.bme.mit.theta.solver.smtlib.impl.generic; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverBinaryException; +import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinaryException; +import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; import java.io.IOException; import java.io.InputStreamReader; @@ -13,7 +14,7 @@ import static com.google.common.base.Preconditions.checkState; -public final class GenericSmtLibSolverBinary implements hu.bme.mit.theta.solver.smtlib.SmtLibSolverBinary { +public final class GenericSmtLibSolverBinary implements SmtLibSolverBinary { private final Process solverProcess; private final PrintWriter solverInput; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverFactory.java similarity index 94% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverFactory.java index d172e1bc29..a7ebd3b501 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverFactory.java @@ -1,10 +1,10 @@ -package hu.bme.mit.theta.solver.smtlib.generic; +package hu.bme.mit.theta.solver.smtlib.impl.generic; import hu.bme.mit.theta.solver.ItpSolver; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolver; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; import java.nio.file.Path; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java similarity index 92% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java index e49e5a8054..e889d3b42f 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java @@ -1,9 +1,9 @@ -package hu.bme.mit.theta.solver.smtlib.generic; +package hu.bme.mit.theta.solver.smtlib.impl.generic; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.smtlib.BaseSmtLibSolverInstaller; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -16,7 +16,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -public final class GenericSmtLibSolverInstaller extends BaseSmtLibSolverInstaller { +public final class GenericSmtLibSolverInstaller extends SmtLibSolverInstaller.Default { private Path solverPath; private String[] solverArgs; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSymbolTable.java similarity index 93% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSymbolTable.java index 3f3ff1c10c..cbe1671866 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibSymbolTable.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSymbolTable.java @@ -1,10 +1,10 @@ -package hu.bme.mit.theta.solver.smtlib.generic; +package hu.bme.mit.theta.solver.smtlib.impl.generic; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.Maps; import hu.bme.mit.theta.core.decl.ConstDecl; -import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java similarity index 98% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java index ac51b25e92..3512b6ee17 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTermTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib.generic; +package hu.bme.mit.theta.solver.smtlib.impl.generic; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; @@ -70,13 +70,13 @@ import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; import hu.bme.mit.theta.core.utils.BvUtils; import hu.bme.mit.theta.core.utils.ExprUtils; -import hu.bme.mit.theta.solver.smtlib.SmtLibModel; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverException; -import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; -import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; +import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTransformationManager.java similarity index 78% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTransformationManager.java index 3c2981a9cb..6c2cb0ff42 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTransformationManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTransformationManager.java @@ -1,13 +1,13 @@ -package hu.bme.mit.theta.solver.smtlib.generic; +package hu.bme.mit.theta.solver.smtlib.impl.generic; import hu.bme.mit.theta.core.decl.Decl; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.Type; -import hu.bme.mit.theta.solver.smtlib.SmtLibDeclTransformer; -import hu.bme.mit.theta.solver.smtlib.SmtLibExprTransformer; -import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; -import hu.bme.mit.theta.solver.smtlib.SmtLibTypeTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibDeclTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibExprTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTypeTransformer; public class GenericSmtLibTransformationManager implements SmtLibTransformationManager { private final SmtLibTypeTransformer typeTransformer; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTypeTransformer.java similarity index 90% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTypeTransformer.java index fe3e3c96f4..613876454e 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/generic/GenericSmtLibTypeTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTypeTransformer.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib.generic; +package hu.bme.mit.theta.solver.smtlib.impl.generic; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -9,8 +9,8 @@ import hu.bme.mit.theta.core.type.bvtype.BvType; import hu.bme.mit.theta.core.type.inttype.IntType; import hu.bme.mit.theta.core.type.rattype.RatType; -import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; -import hu.bme.mit.theta.solver.smtlib.SmtLibTypeTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTypeTransformer; import java.util.concurrent.ExecutionException; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpMarker.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpMarker.java similarity index 78% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpMarker.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpMarker.java index 027dad79d7..1d1a8bc94e 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpMarker.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpMarker.java @@ -1,6 +1,6 @@ -package hu.bme.mit.theta.solver.smtlib.mathsat; +package hu.bme.mit.theta.solver.smtlib.impl.mathsat; -import hu.bme.mit.theta.solver.smtlib.SmtLibItpMarker; +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibItpMarker; public class MathSATSmtLibItpMarker extends SmtLibItpMarker { private static final String markerPattern = "_mathsat_marker_%d"; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpPattern.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpPattern.java similarity index 98% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpPattern.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpPattern.java index 882521a393..84fa95ff03 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpPattern.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpPattern.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib.mathsat; +package hu.bme.mit.theta.solver.smtlib.impl.mathsat; import com.google.common.collect.Lists; import hu.bme.mit.theta.solver.ItpMarker; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpSolver.java similarity index 85% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpSolver.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpSolver.java index dbef64e60a..e80c01f1d7 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpSolver.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib.mathsat; +package hu.bme.mit.theta.solver.smtlib.impl.mathsat; import hu.bme.mit.theta.core.decl.ConstDecl; import hu.bme.mit.theta.core.type.Expr; @@ -9,19 +9,17 @@ import hu.bme.mit.theta.solver.ItpMarkerTree; import hu.bme.mit.theta.solver.ItpPattern; import hu.bme.mit.theta.solver.SolverStatus; -import hu.bme.mit.theta.solver.Stack; -import hu.bme.mit.theta.solver.impl.StackImpl; -import hu.bme.mit.theta.solver.smtlib.BaseSmtLibItpSolver; -import hu.bme.mit.theta.solver.smtlib.SmtLibInterpolant; -import hu.bme.mit.theta.solver.smtlib.SmtLibModel; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverBinary; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverException; -import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.SmtLibTermTransformer; -import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibItpSolver; +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibInterpolant; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; +import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; -import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; +import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.ParserRuleContext; @@ -39,7 +37,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -public class MathSATSmtLibItpSolver extends BaseSmtLibItpSolver { +public class MathSATSmtLibItpSolver extends SmtLibItpSolver { public MathSATSmtLibItpSolver( final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverFactory.java similarity index 84% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverFactory.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverFactory.java index d9669ae7db..218acbd5f7 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverFactory.java @@ -1,14 +1,14 @@ -package hu.bme.mit.theta.solver.smtlib.mathsat; +package hu.bme.mit.theta.solver.smtlib.impl.mathsat; import hu.bme.mit.theta.solver.ItpSolver; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolver; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverBinary; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTermTransformer; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; import java.nio.file.Path; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java similarity index 91% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java index d6d49b1681..066ab35317 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/mathsat/MathSATSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java @@ -1,28 +1,19 @@ -package hu.bme.mit.theta.solver.smtlib.mathsat; +package hu.bme.mit.theta.solver.smtlib.impl.mathsat; import hu.bme.mit.theta.common.OsHelper; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.utils.Compress; import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.smtlib.BaseSmtLibSolverInstaller; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; -import hu.bme.mit.theta.solver.smtlib.z3.Z3SmtLibSolverFactory; -import org.apache.commons.compress.utils.IOUtils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; + import java.io.IOException; import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.zip.ZipInputStream; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -32,7 +23,7 @@ import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.MAC; import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; -public class MathSATSmtLibSolverInstaller extends BaseSmtLibSolverInstaller { +public class MathSATSmtLibSolverInstaller extends SmtLibSolverInstaller.Default { private final List versions; public MathSATSmtLibSolverInstaller(final Logger logger) { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpMarker.java similarity index 79% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpMarker.java index 78d7f0e4c7..55acc34080 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpMarker.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpMarker.java @@ -1,6 +1,6 @@ -package hu.bme.mit.theta.solver.smtlib.z3; +package hu.bme.mit.theta.solver.smtlib.impl.z3; -import hu.bme.mit.theta.solver.smtlib.SmtLibItpMarker; +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibItpMarker; public class Z3SmtLibItpMarker extends SmtLibItpMarker { private static final String markerPattern = "_z3_marker_%d"; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpPattern.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpPattern.java new file mode 100644 index 0000000000..6d91f326d5 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpPattern.java @@ -0,0 +1,94 @@ +package hu.bme.mit.theta.solver.smtlib.impl.z3; + +import com.google.common.collect.Lists; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; +import hu.bme.mit.theta.solver.ItpPattern; + +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +public class Z3SmtLibItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { + final ItpMarkerTree markerTree; + + Z3SmtLibItpPattern(final ItpMarkerTree markerTree) { + this.markerTree = markerTree; + } + + @SuppressWarnings("unchecked") + static Z3SmtLibItpPattern of(final ItpMarkerTree markerTree) { + final var list = new ArrayList>(); + list.add(markerTree); + while(!list.isEmpty()) { + final var node = list.get(0); + list.remove(0); + + checkArgument(node.getMarker() instanceof Z3SmtLibItpMarker); + + list.addAll(node.getChildren()); + } + + return new Z3SmtLibItpPattern((ItpMarkerTree) markerTree); + } + + @Override + public Z3SmtLibItpMarker getA() { + checkState(isBinary()); + return markerTree.getChild(0).getMarker(); + } + + @Override + public Z3SmtLibItpMarker getB() { + checkState(isBinary()); + return markerTree.getMarker(); + } + + @Override + public List getSequence() { + checkState(isSequence()); + final var markerList = new ArrayList(); + + var current = markerTree; + while(current.getChildrenNumber() > 0) { + markerList.add(current.getMarker()); + current = current.getChild(0); + } + markerList.add(current.getMarker()); + + return Lists.reverse(markerList); + } + + @Override + public ItpMarkerTree getRoot() { + return markerTree; + } + + @Override + public E visit(ItpPatternVisitor visitor) { + return visitor.visitTreePattern(this); + } + + private boolean isBinary() { + return + markerTree != null && + markerTree.getChildrenNumber() == 1 && + markerTree.getChild(0) != null && + markerTree.getChild(0).getChildrenNumber() == 0; + } + + private boolean isSequence() { + var current = markerTree; + while(current.getChildrenNumber() > 0) { + if(current.getChildrenNumber() > 1) { + return false; + } + else { + current = current.getChild(0); + } + } + return true; + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpSolver.java similarity index 90% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpSolver.java index c557028a24..0d15c0d1bf 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpSolver.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib.z3; +package hu.bme.mit.theta.solver.smtlib.impl.z3; import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.core.decl.ConstDecl; @@ -10,17 +10,17 @@ import hu.bme.mit.theta.solver.ItpMarkerTree; import hu.bme.mit.theta.solver.ItpPattern; import hu.bme.mit.theta.solver.SolverStatus; -import hu.bme.mit.theta.solver.smtlib.BaseSmtLibItpSolver; -import hu.bme.mit.theta.solver.smtlib.SmtLibInterpolant; -import hu.bme.mit.theta.solver.smtlib.SmtLibModel; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverBinary; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverException; -import hu.bme.mit.theta.solver.smtlib.SmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.SmtLibTermTransformer; -import hu.bme.mit.theta.solver.smtlib.SmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibItpSolver; +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibInterpolant; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; +import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; -import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; +import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.ParserRuleContext; @@ -40,7 +40,7 @@ import static com.google.common.base.Preconditions.checkState; import static hu.bme.mit.theta.core.type.booltype.BoolExprs.False; -public final class Z3SmtLibItpSolver extends BaseSmtLibItpSolver { +public final class Z3SmtLibItpSolver extends SmtLibItpSolver { private boolean topMostContainsAssertions = false; public Z3SmtLibItpSolver( diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverFactory.java similarity index 84% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverFactory.java index ed7f108e99..e15012671f 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverFactory.java @@ -1,14 +1,14 @@ -package hu.bme.mit.theta.solver.smtlib.z3; +package hu.bme.mit.theta.solver.smtlib.impl.z3; import hu.bme.mit.theta.solver.ItpSolver; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolver; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverBinary; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTermTransformer; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; import java.nio.file.Path; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java similarity index 93% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java index 5e3ca64a44..eb09fafc56 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/z3/Z3SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java @@ -1,23 +1,19 @@ -package hu.bme.mit.theta.solver.smtlib.z3; +package hu.bme.mit.theta.solver.smtlib.impl.z3; import hu.bme.mit.theta.common.OsHelper; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.utils.Compress; import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.smtlib.BaseSmtLibSolverInstaller; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import java.io.IOException; import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -27,7 +23,7 @@ import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.MAC; import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; -public class Z3SmtLibSolverInstaller extends BaseSmtLibSolverInstaller { +public class Z3SmtLibSolverInstaller extends SmtLibSolverInstaller.Default { private final List versions; public Z3SmtLibSolverInstaller(final Logger logger) { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java similarity index 88% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java index 1a5b96b9c4..d1d0d7b48d 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/BaseSmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver; import hu.bme.mit.theta.core.decl.ConstDecl; import hu.bme.mit.theta.core.model.Valuation; @@ -16,10 +16,16 @@ import hu.bme.mit.theta.solver.impl.StackImpl; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; -import hu.bme.mit.theta.solver.smtlib.parser.CheckSatResponse; -import hu.bme.mit.theta.solver.smtlib.parser.GeneralResponse; -import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; -import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; +import hu.bme.mit.theta.solver.smtlib.solver.parser.CheckSatResponse; +import hu.bme.mit.theta.solver.smtlib.solver.parser.GeneralResponse; +import hu.bme.mit.theta.solver.smtlib.solver.parser.GetModelResponse; +import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; +import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibItpMarker; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibValuation; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; @@ -30,7 +36,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -public abstract class BaseSmtLibItpSolver implements ItpSolver { +public abstract class SmtLibItpSolver implements ItpSolver { protected final SmtLibSymbolTable symbolTable; protected final SmtLibTransformationManager transformationManager; protected final SmtLibTermTransformer termTransformer; @@ -45,7 +51,7 @@ public abstract class BaseSmtLibItpSolver implements private SolverStatus status; - public BaseSmtLibItpSolver( + public SmtLibItpSolver( final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, final SmtLibTermTransformer termTransformer, final SmtLibSolverBinary solverBinary ) { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java similarity index 91% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java index 29600c7371..a8374c5fe5 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver; import hu.bme.mit.theta.core.decl.ConstDecl; import hu.bme.mit.theta.core.model.Valuation; @@ -13,11 +13,16 @@ import hu.bme.mit.theta.solver.impl.StackImpl; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; -import hu.bme.mit.theta.solver.smtlib.parser.CheckSatResponse; -import hu.bme.mit.theta.solver.smtlib.parser.GeneralResponse; -import hu.bme.mit.theta.solver.smtlib.parser.GetModelResponse; -import hu.bme.mit.theta.solver.smtlib.parser.GetUnsatCoreResponse; -import hu.bme.mit.theta.solver.smtlib.parser.ThrowExceptionErrorListener; +import hu.bme.mit.theta.solver.smtlib.solver.parser.CheckSatResponse; +import hu.bme.mit.theta.solver.smtlib.solver.parser.GeneralResponse; +import hu.bme.mit.theta.solver.smtlib.solver.parser.GetModelResponse; +import hu.bme.mit.theta.solver.smtlib.solver.parser.GetUnsatCoreResponse; +import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; +import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibValuation; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolverException.java similarity index 95% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolverException.java index f02b1f1210..fecf6a7d83 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverException.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolverException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver; public class SmtLibSolverException extends RuntimeException { private static final long serialVersionUID = -7472824180590829943L; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/binary/SmtLibSolverBinary.java similarity index 66% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/binary/SmtLibSolverBinary.java index ed96597888..141a5b6252 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinary.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/binary/SmtLibSolverBinary.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.binary; public interface SmtLibSolverBinary { void issueCommand(String command); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinaryException.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/binary/SmtLibSolverBinaryException.java similarity index 88% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinaryException.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/binary/SmtLibSolverBinaryException.java index 59f9b819ef..dbb9506aa7 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBinaryException.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/binary/SmtLibSolverBinaryException.java @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.binary; + +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; public class SmtLibSolverBinaryException extends SmtLibSolverException { private static final long serialVersionUID = -7472824180590829943L; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java new file mode 100644 index 0000000000..f2c038a470 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java @@ -0,0 +1,258 @@ +package hu.bme.mit.theta.solver.smtlib.solver.installer; + +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public interface SmtLibSolverInstaller { + + void install(Path home, String version, String name) throws SmtLibSolverInstallerException; + + void uninstall(Path home, String version) throws SmtLibSolverInstallerException; + + void reinstall(Path home, String version) throws SmtLibSolverInstallerException; + + String getInfo(Path home, String version) throws SmtLibSolverInstallerException; + + Path getArgsFile(Path home, String version) throws SmtLibSolverInstallerException; + + SolverFactory getSolverFactory(Path home, String version) throws SmtLibSolverInstallerException; + + List getSupportedVersions() throws SmtLibSolverInstallerException; + + List getInstalledVersions(Path home) throws SmtLibSolverInstallerException; + + abstract class Default implements SmtLibSolverInstaller { + protected final Logger logger; + + public Default(final Logger logger) { + this.logger = logger; + } + + @Override + public final void install(Path home, String version, String name) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + checkName(name); + + final var installDir = getInstallDir(home, name); + if(Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("There is already a solver instance with this name installed"); + } + + try { + logger.write(Logger.Level.MAINSTEP, "Beginning installation...\n"); + + Files.createDirectory(installDir); + + installSolver(installDir, version); + + final var solverArgsPath = argsFile(installDir); + Files.writeString(solverArgsPath, String.join("\n", getDefaultSolverArgs(version)), StandardCharsets.UTF_8); + + final var solverInfoPath = infoFile(installDir); + Files.writeString( + solverInfoPath, + String.format("solver=%s\n", getSolverName()) + + String.format("version=%s\n", version) + + String.format("name=%s\n", name), + StandardCharsets.UTF_8 + ); + + logger.write(Logger.Level.MAINSTEP, "Installation finished\n"); + } + catch (SmtLibSolverInstallerException e) { + uninstall(home, version); + throw e; + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public final void uninstall(Path home, String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkName(version); + + final var installDir = getInstallDir(home, version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + try { + logger.write(Logger.Level.MAINSTEP, "Beginning uninstallation...\n"); + + uninstallSolver(installDir, version); + + deleteDirectory(installDir.toFile()); + + logger.write(Logger.Level.MAINSTEP, "Uninstallation finished\n"); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public void reinstall(Path home, String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkName(version); + + final String solverVersion; + try { + final var installDir = getInstallDir(home, version); + final var solverInfoPath = infoFile(installDir); + final var solverInfo = Files + .readAllLines(solverInfoPath, StandardCharsets.UTF_8).stream() + .filter(l -> l.startsWith("version=")) + .map(l -> l.substring("version=".length())) + .findAny(); + + if(solverInfo.isPresent()) { + solverVersion = solverInfo.get(); + } + else { + throw new SmtLibSolverInstallerException("The solver installation is corrupted"); + } + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + + uninstall(home, version); + install(home, solverVersion, version); + } + + @Override + public final SolverFactory getSolverFactory(final Path home, final String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + + final var installDir = home.resolve(version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + try { + final var solverArgsPath = argsFile(installDir); + final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); + + return getSolverFactory(installDir, version, solverArgs); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public final String getInfo(Path home, String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkName(version); + + final var installDir = getInstallDir(home, version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + try { + final var solverInfoPath = infoFile(installDir); + final var solverInfoStr = Files.readString(solverInfoPath, StandardCharsets.UTF_8); + final var solverArgsPath = argsFile(installDir); + final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); + + return solverInfoStr + String.format("args=%s\n", String.join(" ", solverArgs)); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); + } + } + + @Override + public final Path getArgsFile(Path home, String version) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkName(version); + + final var installDir = home.resolve(version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + return argsFile(installDir); + } + + @Override + public final List getInstalledVersions(Path home) throws SmtLibSolverInstallerException { + checkNotNull(home); + + if(Files.exists(home)) { + final var installedDirs = home.toFile() + .list((current, name) -> new File(current, name).isDirectory()); + + assert installedDirs != null; + return Arrays.asList(installedDirs); + } + else { + return Collections.emptyList(); + } + } + + protected abstract String getSolverName() throws SmtLibSolverInstallerException; + protected abstract void installSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException; + protected abstract void uninstallSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException; + protected abstract SolverFactory getSolverFactory(final Path installDir, final String version, final String[] args) throws SmtLibSolverInstallerException; + protected abstract String[] getDefaultSolverArgs(final String version) throws SmtLibSolverInstallerException; + + protected final void checkName(final String version) throws SmtLibSolverInstallerException { + if(!version.matches("^[a-zA-Z0-9_.-]+$")) { + throw new SmtLibSolverInstallerException("Unsupported name format: " + version); + } + } + + protected final void checkVersion(final String version) throws SmtLibSolverInstallerException { + if(!version.matches("^[0-9]+(\\.[0-9]+)*$")) { + throw new SmtLibSolverInstallerException("Unsupported version format: " + version); + } + } + + protected final Path getInstallDir(final Path home, final String version) { + return home.resolve(version); + } + + protected final Path argsFile(final Path installDir) { + return installDir.resolve("solver-args.txt"); + } + + protected final Path infoFile(final Path installDir) { + return installDir.resolve("solver-info.txt"); + } + + private void deleteDirectory(File directoryToBeDeleted) throws IOException { + File[] allContents = directoryToBeDeleted.listFiles(); + if (allContents != null) { + for (File file : allContents) { + deleteDirectory(file); + } + } + + Files.delete(directoryToBeDeleted.toPath()); + } + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstallerException.java similarity index 94% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstallerException.java index 2b0fd262ff..734344a284 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverInstallerException.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstallerException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.installer; public class SmtLibSolverInstallerException extends Exception { private static final long serialVersionUID = -7472824180590329943L; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/interpolation/SmtLibInterpolant.java similarity index 95% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/interpolation/SmtLibInterpolant.java index 87fe02bc9d..38681d69c5 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibInterpolant.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/interpolation/SmtLibInterpolant.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.interpolation; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.booltype.BoolType; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/interpolation/SmtLibItpMarker.java similarity index 93% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/interpolation/SmtLibItpMarker.java index 2b854210f0..0ca2a1f7eb 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpMarker.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/interpolation/SmtLibItpMarker.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.interpolation; import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.core.type.Expr; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/model/SmtLibModel.java similarity index 88% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/model/SmtLibModel.java index ca8c5f1346..c9f5d2028a 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibModel.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/model/SmtLibModel.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.model; import java.util.Collection; import java.util.Map; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/model/SmtLibValuation.java similarity index 94% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/model/SmtLibValuation.java index 172657ce5e..a6647dbccc 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibValuation.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/model/SmtLibValuation.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.model; import com.google.common.collect.ImmutableList; import hu.bme.mit.theta.core.decl.ConstDecl; @@ -9,6 +9,9 @@ import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.bvtype.BvType; import hu.bme.mit.theta.core.type.functype.FuncType; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; import java.util.Collection; import java.util.Collections; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/CheckSatResponse.java similarity index 91% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/CheckSatResponse.java index af49c39305..5ad50589d9 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/CheckSatResponse.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/CheckSatResponse.java @@ -1,6 +1,6 @@ -package hu.bme.mit.theta.solver.smtlib.parser; +package hu.bme.mit.theta.solver.smtlib.solver.parser; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Check_sat_responseContext; import static hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.PS_Sat; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GeneralResponse.java similarity index 95% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GeneralResponse.java index 6973f32822..c4383125dc 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GeneralResponse.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GeneralResponse.java @@ -1,7 +1,6 @@ -package hu.bme.mit.theta.solver.smtlib.parser; +package hu.bme.mit.theta.solver.smtlib.solver.parser; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; -import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.General_response_errorContext; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.General_response_successContext; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.General_response_unsupportedContext; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GetModelResponse.java similarity index 94% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GetModelResponse.java index d3616c9b8d..2ce48a129f 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetModelResponse.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GetModelResponse.java @@ -1,9 +1,8 @@ -package hu.bme.mit.theta.solver.smtlib.parser; +package hu.bme.mit.theta.solver.smtlib.solver.parser; import hu.bme.mit.theta.common.Tuple2; -import hu.bme.mit.theta.solver.smtlib.SmtLibModel; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; -import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Model_response_mathsatContext; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.misc.Interval; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GetUnsatCoreResponse.java similarity index 87% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GetUnsatCoreResponse.java index cf704e5fb8..fc691de4ec 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/GetUnsatCoreResponse.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GetUnsatCoreResponse.java @@ -1,6 +1,5 @@ -package hu.bme.mit.theta.solver.smtlib.parser; +package hu.bme.mit.theta.solver.smtlib.solver.parser; -import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser.Get_unsat_core_responseContext; import org.antlr.v4.runtime.RuleContext; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/SpecificResponse.java similarity index 95% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/SpecificResponse.java index 0315811f91..997efe55f4 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/SpecificResponse.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/SpecificResponse.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib.parser; +package hu.bme.mit.theta.solver.smtlib.solver.parser; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2BaseVisitor; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/ThrowExceptionErrorListener.java similarity index 81% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/ThrowExceptionErrorListener.java index 9f69d4c8d7..69b5de7641 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/parser/ThrowExceptionErrorListener.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/ThrowExceptionErrorListener.java @@ -1,6 +1,6 @@ -package hu.bme.mit.theta.solver.smtlib.parser; +package hu.bme.mit.theta.solver.smtlib.solver.parser; -import hu.bme.mit.theta.solver.smtlib.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; import org.antlr.v4.runtime.ANTLRErrorListener; import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.RecognitionException; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibDeclTransformer.java similarity index 73% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibDeclTransformer.java index b80f851252..b6bc85ffce 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibDeclTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibDeclTransformer.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.transformer; import hu.bme.mit.theta.core.decl.Decl; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibExprTransformer.java similarity index 66% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibExprTransformer.java index 717650fded..2ac8b5cbbc 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibExprTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibExprTransformer.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.transformer; import hu.bme.mit.theta.core.type.Expr; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibSymbolTable.java similarity index 87% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibSymbolTable.java index b6a4d2ccae..5095bd13f4 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSymbolTable.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibSymbolTable.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.transformer; import hu.bme.mit.theta.core.decl.ConstDecl; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibTermTransformer.java similarity index 87% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibTermTransformer.java index cc1dff40de..faa52597b0 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTermTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibTermTransformer.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.transformer; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.LitExpr; @@ -6,6 +6,7 @@ import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.bvtype.BvType; import hu.bme.mit.theta.core.type.functype.FuncType; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; public interface SmtLibTermTransformer {

LitExpr> toFuncLitExpr(String funcLitImpl, FuncType type, SmtLibModel model); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibTransformationManager.java similarity index 82% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibTransformationManager.java index 009501e6a9..400f991354 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTransformationManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibTransformationManager.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.transformer; import hu.bme.mit.theta.core.decl.Decl; import hu.bme.mit.theta.core.type.Expr; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibTypeTransformer.java similarity index 66% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibTypeTransformer.java index f9e583080d..7e07025adb 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibTypeTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/transformer/SmtLibTypeTransformer.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib; +package hu.bme.mit.theta.solver.smtlib.solver.transformer; import hu.bme.mit.theta.core.type.Type; From 098af5f8660b4e53efcb5f473d14e4fceaa9de06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 17 Mar 2021 17:56:01 +0100 Subject: [PATCH 70/99] Add support for Yices2 --- .../solver/smtlib/SmtLibSolverManager.java | 2 + .../impl/yices2/Yices2SmtLibSolver.java | 92 +++++++++++++ .../yices2/Yices2SmtLibSolverFactory.java | 51 +++++++ .../yices2/Yices2SmtLibSolverInstaller.java | 125 ++++++++++++++++++ .../solver/parser/GetModelResponse.java | 2 +- 5 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolver.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverFactory.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverInstaller.java diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java index 9475eeac46..5e896e34b0 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java @@ -4,6 +4,7 @@ import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.impl.yices2.Yices2SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import hu.bme.mit.theta.solver.smtlib.impl.cvc4.CVC4SmtLibSolverInstaller; @@ -42,6 +43,7 @@ public static void registerGenericInsta registerInstaller("z3", Z3SmtLibSolverInstaller.class); registerInstaller("cvc4", CVC4SmtLibSolverInstaller.class); registerInstaller("mathsat", MathSATSmtLibSolverInstaller.class); + registerInstaller("yices2", Yices2SmtLibSolverInstaller.class); registerGenericInstaller("generic", GenericSmtLibSolverInstaller.class); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolver.java new file mode 100644 index 0000000000..7b84ca093e --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolver.java @@ -0,0 +1,92 @@ +package hu.bme.mit.theta.solver.smtlib.impl.yices2; + +import hu.bme.mit.theta.common.Tuple2; +import hu.bme.mit.theta.core.model.Valuation; +import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibValuation; +import hu.bme.mit.theta.solver.smtlib.solver.parser.GetModelResponse; +import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; + +import java.util.HashMap; + +import static com.google.common.base.Preconditions.checkState; + +public class Yices2SmtLibSolver extends SmtLibSolver { + private Valuation model; + private SolverStatus status; + + public Yices2SmtLibSolver( + final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, + final SmtLibTermTransformer termTransformer, final SmtLibSolverBinary solverBinary, + final boolean unsatCoreEnabled + ) { + super(symbolTable, transformationManager, termTransformer, solverBinary, unsatCoreEnabled); + } + + @Override + public SolverStatus check() { + return status = super.check(); + } + + @Override + public Valuation getModel() { + checkState(status == SolverStatus.SAT, "Cannot get model if status is not SAT."); + + if (model == null) { + model = extractModel(); + } + + return model; + } + + private Valuation extractModel() { + assert status == SolverStatus.SAT; + assert model == null; + + solverBinary.issueCommand("(get-model)"); + + final var modelValues = new HashMap(); + for(final var ignored : declarationStack.toCollection()) { + final var value = parseModelResponse(solverBinary.readResponse()); + modelValues.put(value.get1(), value.get2()); + } + + return new SmtLibValuation(symbolTable, transformationManager, termTransformer, new SmtLibModel(modelValues)); + } + + private Tuple2 parseModelResponse(final String response) { + try { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(response)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + + final var term = parser.term().generic_term(); + final var id = GetModelResponse.extractString(term.qual_identifier()); + final var variable = GetModelResponse.extractString(term.term(0)); + final var value = GetModelResponse.extractString(term.term(1)); + + if(id.equals("=")) { + return Tuple2.of(variable, String.format("%s () (_ theta_type unknown) %s", variable, value)); + } + + throw new SmtLibSolverException("Could not parse solver output: " + response); + } + catch (Exception e) { + throw new SmtLibSolverException("Could not parse solver output: " + response, e); + } + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverFactory.java new file mode 100644 index 0000000000..79c1dfb17f --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverFactory.java @@ -0,0 +1,51 @@ +package hu.bme.mit.theta.solver.smtlib.impl.yices2; + +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; + +import java.nio.file.Path; + +public class Yices2SmtLibSolverFactory implements SolverFactory { + private final Path solverPath; + private final String[] args; + + private Yices2SmtLibSolverFactory(Path solverPath, String[] args) { + this.solverPath = solverPath; + this.args = args; + } + + public static Yices2SmtLibSolverFactory create(Path solverPath, String[] args) { + return new Yices2SmtLibSolverFactory(solverPath, args); + } + + @Override + public Solver createSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new Yices2SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); + } + + @Override + public UCSolver createUCSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new Yices2SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); + } + + @Override + public ItpSolver createItpSolver() { + throw new UnsupportedOperationException("Yices2 does not support interpolation"); + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverInstaller.java new file mode 100644 index 0000000000..efd1cd8a5b --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverInstaller.java @@ -0,0 +1,125 @@ +package hu.bme.mit.theta.solver.smtlib.impl.yices2; + +import hu.bme.mit.theta.common.OsHelper; +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.utils.Compress; +import hu.bme.mit.theta.solver.smtlib.utils.SemVer; + +import java.io.IOException; +import java.net.URI; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.MAC; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; + +public class Yices2SmtLibSolverInstaller extends SmtLibSolverInstaller.Default { + private final List versions; + + public Yices2SmtLibSolverInstaller(final Logger logger) { + super(logger); + + versions = new ArrayList<>(); + versions.add(SemVer.VersionDecoder.create(SemVer.of("2.6.2")) + .addString(LINUX, X64, "x86_64-pc-linux-gnu-static-gmp") + .addString(MAC, X64, "x86_64-apple-darwin18.7.0-static-gmp") + .addString(WINDOWS, X64, "x86_64-pc-mingw32-static-gmp") + .build() + ); + versions.add(SemVer.VersionDecoder.create(SemVer.of("2.5.4")) + .addString(LINUX, X64, "x86_64-pc-linux-gnu-static-gmp") + .addString(MAC, X64, "x86_64-apple-darwin16.7.0-static-gmp") + .addString(WINDOWS, X64, "x86_64-pc-mingw32-static-gmp") + .build() + ); + versions.add(SemVer.VersionDecoder.create(SemVer.of("2.5.3")) + .addString(LINUX, X64, "x86_64-unknown-linux-gnu-static-gmp") + .addString(MAC, X64, "x86_64-apple-darwin16.7.0-static-gmp") + .addString(WINDOWS, X64, "x86_64-pc-mingw32-static-gmp") + .build() + ); + } + + @Override + protected String getSolverName() { + return "yices2"; + } + + @Override + protected void installSolver(Path installDir, String version) throws SmtLibSolverInstallerException { + final var semVer = SemVer.of(version); + String archStr = null; + + for(final var versionDecoder : versions) { + if(semVer.compareTo(versionDecoder.getVersion()) >= 0) { + archStr = versionDecoder.getOsArchString(OsHelper.getOs(), OsHelper.getArch()); + break; + } + } + if(archStr == null) { + throw new SmtLibSolverInstallerException(String.format("Yices2 on operating system %s and architecture %s is not supported", OsHelper.getOs(), OsHelper.getArch())); + } + + final var downloadUrl = URI.create(String.format( + "https://yices.csl.sri.com/releases/%s/yices-%s-%s.%s", + version, version, archStr, OsHelper.getOs().equals(WINDOWS) ? "zip" : "tar.gz" + )); + + logger.write(Logger.Level.MAINSTEP, "Starting download (%s)...\n", downloadUrl.toString()); + + try(final var inputStream = downloadUrl.toURL().openStream()) { + if(OsHelper.getOs().equals(WINDOWS)) { + Compress.extract(inputStream, installDir, Compress.CompressionType.ZIP); + } + else { + Compress.extract(inputStream, installDir, Compress.CompressionType.TARGZ); + } + installDir.resolve("bin").resolve(getSolverBinaryName()).toFile().setExecutable(true, true); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(e); + } + + logger.write(Logger.Level.MAINSTEP, "Download finished\n"); + } + + @Override + protected void uninstallSolver(Path installDir, String version) { } + + @Override + protected String[] getDefaultSolverArgs(String version) { + return new String[] { "--incremental" }; + } + + @Override + public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); + return Yices2SmtLibSolverFactory.create(solverFilePath, solverArgs); + } + + @Override + public List getSupportedVersions() { + return Arrays.asList( + "2.6.2", "2.6.1", "2.6.0" + ); + } + + private String getSolverBinaryName() { + switch(OsHelper.getOs()) { + case WINDOWS: + return "yices-smt2.exe"; + case LINUX: + case MAC: + return "yices-smt2"; + default: + throw new AssertionError(); + } + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GetModelResponse.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GetModelResponse.java index 2ce48a129f..e2d7d604f3 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GetModelResponse.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/parser/GetModelResponse.java @@ -55,7 +55,7 @@ public SmtLibModel getModel() { return model; } - private static String extractString(final ParserRuleContext ctx) { + public static String extractString(final ParserRuleContext ctx) { return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex())); } } From 99849b8e09f98e2234466c3690788944d77ce48f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 18 Mar 2021 22:19:45 +0100 Subject: [PATCH 71/99] Add boolector support --- .../solver/smtlib/SmtLibSolverManager.java | 3 + .../BoolectorSmtLibSolverInstaller.java | 123 ++++++++++++++++++ .../generic/GenericSmtLibTermTransformer.java | 12 +- .../installer/SmtLibSolverInstaller.java | 6 +- 4 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java index 5e896e34b0..8238332ac9 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java @@ -4,6 +4,8 @@ import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.impl.boolector.BoolectorSmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.impl.smtinterpol.SMTInterpolSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.impl.yices2.Yices2SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; @@ -44,6 +46,7 @@ public static void registerGenericInsta registerInstaller("cvc4", CVC4SmtLibSolverInstaller.class); registerInstaller("mathsat", MathSATSmtLibSolverInstaller.class); registerInstaller("yices2", Yices2SmtLibSolverInstaller.class); + registerInstaller("boolector", BoolectorSmtLibSolverInstaller.class); registerGenericInstaller("generic", GenericSmtLibSolverInstaller.class); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java new file mode 100644 index 0000000000..1ea9a8ca18 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java @@ -0,0 +1,123 @@ +package hu.bme.mit.theta.solver.smtlib.impl.boolector; + +import hu.bme.mit.theta.common.OsHelper; +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.impl.cvc4.CVC4SmtLibSolverFactory; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.utils.Compress; +import hu.bme.mit.theta.solver.smtlib.utils.SemVer; + +import java.io.BufferedReader; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; + +public class BoolectorSmtLibSolverInstaller extends SmtLibSolverInstaller.Default { + + public BoolectorSmtLibSolverInstaller(final Logger logger) { + super(logger); + } + + @Override + protected String getSolverName() { + return "boolector"; + } + + @Override + protected void installSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException { + final var downloadUrl = URI.create(String.format( + "https://github.com/Boolector/boolector/archive/refs/tags/%s.tar.gz", + version + )); + + logger.write(Logger.Level.MAINSTEP, "Starting download (%s)...\n", downloadUrl.toString()); + + try(final var inputStream = downloadUrl.toURL().openStream()) { + Compress.extract(inputStream, installDir, Compress.CompressionType.TARGZ); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(e); + } + + logger.write(Logger.Level.MAINSTEP, "Download finished\n"); + + logger.write(Logger.Level.MAINSTEP, "Starting compilation\n"); + + installDir.resolve("contrib").resolve("setup-lingeling.sh").toFile().setExecutable(true, true); + executeCommand(installDir, "alias nproc=\"echo 1\" && ./contrib/setup-lingeling.sh"); + + installDir.resolve("contrib").resolve("setup-btor2tools.sh").toFile().setExecutable(true, true); + executeCommand(installDir, "alias nproc=\"echo 1\" && ./contrib/setup-btor2tools.sh"); + + installDir.resolve("configure.sh").toFile().setExecutable(true, true); + executeCommand(installDir, "./configure.sh"); + executeCommand(installDir.resolve("build"), "make"); + installDir.resolve("build").resolve("bin").resolve(getSolverBinaryName()).toFile().setExecutable(true, true); + + logger.write(Logger.Level.MAINSTEP, "Finished compilation\n"); + } + + @Override + protected void uninstallSolver(final Path installDir, final String version) { } + + @Override + protected String[] getDefaultSolverArgs(String version) { + return new String[] { + "--smt2", + "--smt2-model", + "-i" + }; + } + + @Override + public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = installDir.resolve("build").resolve("bin").resolve(getSolverBinaryName()); + return CVC4SmtLibSolverFactory.create(solverFilePath, solverArgs); + } + + @Override + public List getSupportedVersions() { + return Arrays.asList("3.2.1", "3.2.0", "3.1.0", "3.0.0"); + } + + private String getSolverBinaryName() { + switch(OsHelper.getOs()) { + case LINUX: + return "boolector"; + default: + throw new AssertionError(); + } + } + + private void executeCommand(final Path workingPath, final String command) throws SmtLibSolverInstallerException { + try { + logger.write(Logger.Level.SUBSTEP, "Execute command: %s\n", command); + final var process = new ProcessBuilder() + .command("bash", "-c", command) + .directory(workingPath.toFile()) + .redirectOutput(ProcessBuilder.Redirect.INHERIT) + .redirectError(ProcessBuilder.Redirect.INHERIT) + .start(); + + if(process.waitFor() != 0) { + throw new SmtLibSolverInstallerException(String.format("Error executing command: %s", command)); + } + } + catch (IOException | InterruptedException e) { + throw new SmtLibSolverInstallerException(String.format("Error executing command: %s", command), e); + } + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java index 3512b6ee17..519efbca57 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java @@ -260,7 +260,17 @@ private Expr toLitExpr(final String litImpl, final SmtLibModel model) { parser.removeErrorListeners(); parser.addErrorListener(new ThrowExceptionErrorListener()); - return transformTerm(parser.function_def().term(), model, HashBiMap.create()); + final var funcDef = parser.function_def(); + final var paramDecls = funcDef.sorted_var().stream() + .map(sv -> Param(sv.symbol().getText(), transformSort(sv.sort()))) + .collect(toList()); + + final var vars = HashBiMap., String>create(); + pushParams(paramDecls, vars); + final var expr = transformTerm(funcDef.term(), model, vars); + popParams(paramDecls, vars); + + return expr; } @Override diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java index f2c038a470..d2d32b6b88 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java @@ -57,8 +57,6 @@ public final void install(Path home, String version, String name) throws SmtLibS Files.createDirectory(installDir); - installSolver(installDir, version); - final var solverArgsPath = argsFile(installDir); Files.writeString(solverArgsPath, String.join("\n", getDefaultSolverArgs(version)), StandardCharsets.UTF_8); @@ -71,6 +69,8 @@ public final void install(Path home, String version, String name) throws SmtLibS StandardCharsets.UTF_8 ); + installSolver(installDir, version); + logger.write(Logger.Level.MAINSTEP, "Installation finished\n"); } catch (SmtLibSolverInstallerException e) { @@ -227,7 +227,7 @@ protected final void checkName(final String version) throws SmtLibSolverInstalle } protected final void checkVersion(final String version) throws SmtLibSolverInstallerException { - if(!version.matches("^[0-9]+(\\.[0-9]+)*$")) { + if(!version.matches("^[a-zA-Z0-9_.-]+$")) { throw new SmtLibSolverInstallerException("Unsupported version format: " + version); } } From 9ffad78e711262a6b44317249412a6daea3d088d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Fri, 19 Mar 2021 22:20:49 +0100 Subject: [PATCH 72/99] Add basic SMTInterpol support --- .../solver/smtlib/SmtLibSolverManager.java | 1 + .../SMTInterpolSmtLibSolverFactory.java | 66 ++++++++++++++ .../SMTInterpolSmtLibSolverInstaller.java | 90 +++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverFactory.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java index 8238332ac9..8381f2f0cb 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java @@ -47,6 +47,7 @@ public static void registerGenericInsta registerInstaller("mathsat", MathSATSmtLibSolverInstaller.class); registerInstaller("yices2", Yices2SmtLibSolverInstaller.class); registerInstaller("boolector", BoolectorSmtLibSolverInstaller.class); + registerInstaller("smtinterpol", SMTInterpolSmtLibSolverInstaller.class); registerGenericInstaller("generic", GenericSmtLibSolverInstaller.class); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverFactory.java new file mode 100644 index 0000000000..28778348a2 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverFactory.java @@ -0,0 +1,66 @@ +package hu.bme.mit.theta.solver.smtlib.impl.smtinterpol; + +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; + +import java.nio.file.Path; + +public class SMTInterpolSmtLibSolverFactory implements SolverFactory { + private final Path solverPath; + private final String[] args; + + private SMTInterpolSmtLibSolverFactory(Path solverPath, String[] args) { + this.solverPath = solverPath; + this.args = args; + } + + public static SMTInterpolSmtLibSolverFactory create(Path solverPath, String[] args) { + return new SMTInterpolSmtLibSolverFactory(solverPath, args); + } + + @Override + public Solver createSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(getJavaBinary(), getSolverArgs()); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); + } + + @Override + public UCSolver createUCSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(getJavaBinary(), getSolverArgs()); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); + } + + @Override + public ItpSolver createItpSolver() { + throw new UnsupportedOperationException("CVC4 does not support interpolation"); + } + + private Path getJavaBinary() { + return Path.of(System.getProperty("java.home")).resolve("bin").resolve("java"); + } + + private String[] getSolverArgs() { + final var solverArgs = new String[args.length + 2]; + solverArgs[0] = "-jar"; + solverArgs[1] = solverPath.toAbsolutePath().toString(); + for(var i = 0; i < args.length; i++) { + solverArgs[i + 2] = args[i]; + } + return solverArgs; + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java new file mode 100644 index 0000000000..251ce5762b --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java @@ -0,0 +1,90 @@ +package hu.bme.mit.theta.solver.smtlib.impl.smtinterpol; + +import hu.bme.mit.theta.common.OsHelper; +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.impl.cvc4.CVC4SmtLibSolverFactory; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.utils.SemVer; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; + +public class SMTInterpolSmtLibSolverInstaller extends SmtLibSolverInstaller.Default { + + public SMTInterpolSmtLibSolverInstaller(final Logger logger) { + super(logger); + } + + @Override + protected String getSolverName() { + return "smtinterpol"; + } + + @Override + protected void installSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException { + + try( + final var inputChannel = Channels.newChannel(getDownloadUrl(version).openStream()); + final var outputChannel = new FileOutputStream(installDir.resolve(getSolverBinaryName(version)).toAbsolutePath().toString()).getChannel() + ) { + logger.write(Logger.Level.MAINSTEP, "Starting download (%s)...\n", getDownloadUrl(version).toString()); + outputChannel.transferFrom(inputChannel, 0, Long.MAX_VALUE); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(e); + } + + logger.write(Logger.Level.MAINSTEP, "Download finished\n"); + } + + @Override + protected void uninstallSolver(final Path installDir, final String version) { } + + @Override + protected String[] getDefaultSolverArgs(String version) { + return new String[] { "-smt2" }; + } + + @Override + public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = installDir.resolve(getSolverBinaryName(version)); + return SMTInterpolSmtLibSolverFactory.create(solverFilePath, solverArgs); + } + + @Override + public List getSupportedVersions() { + return Arrays.asList("2.5-663", "2.5-479", "2.5-7"); + } + + private URL getDownloadUrl(final String version) throws SmtLibSolverInstallerException, MalformedURLException { + final String fileName; + switch (version) { + case "2.5-663": fileName = "2.5-663-gf15aa217"; break; + case "2.5-479": fileName = "2.5-479-ga49e50b1"; break; + case "2.5-7": fileName = "2.5-7-g64ec65d"; break; + default: throw new SmtLibSolverInstallerException("Unsupported solver version."); + } + + return URI.create(String.format( + "https://ultimate.informatik.uni-freiburg.de/smtinterpol/smtinterpol-%s.jar", + fileName + )).toURL(); + } + + private String getSolverBinaryName(final String version) { + return String.format("smtinterpol-%s.jar", version); + } +} From 632dafe633f883e7381c03366235da64caae91ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 22 Mar 2021 22:57:15 +0100 Subject: [PATCH 73/99] Allow local installation of known solvers (instead of download) --- .../theta/solver/smtlib/cli/SmtLibCli.java | 7 ++- .../solver/smtlib/SmtLibSolverManager.java | 9 +++- .../BoolectorSmtLibSolverInstaller.java | 19 ++----- .../impl/cvc4/CVC4SmtLibSolverInstaller.java | 4 +- .../generic/GenericSmtLibSolverInstaller.java | 13 ++--- .../mathsat/MathSATSmtLibSolverInstaller.java | 4 +- .../SMTInterpolSmtLibSolverInstaller.java | 4 +- .../yices2/Yices2SmtLibSolverInstaller.java | 4 +- .../impl/z3/Z3SmtLibSolverInstaller.java | 4 +- .../installer/SmtLibSolverInstaller.java | 50 ++++++++++++++++--- 10 files changed, 73 insertions(+), 45 deletions(-) diff --git a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java index 1d07a55af2..7071c8b791 100644 --- a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java +++ b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java @@ -48,6 +48,9 @@ static class InstallCommand { @Parameter(names = "--name", description = "Install the solver version under this custom name (:), instead of the default (:)") String name; + @Parameter(names = "--solver-path", description = "The path of the solver to install. The solver will not be downloaded, instead the binary on this path will be used. Caveat emptor: the version must be specified correctly, there is no automatic detection.") + String solverPath; + @Parameter(names = "--tempt-murphy", description = "Allows the installation of unsupported solver version") boolean temptMurphy = false; } @@ -185,10 +188,10 @@ private void run() { } if(installCommand.name != null) { - smtLibSolverManager.install(solver.get1(), solver.get2(), installCommand.name, installCommand.temptMurphy); + smtLibSolverManager.install(solver.get1(), solver.get2(), installCommand.name, installCommand.solverPath != null ? Path.of(installCommand.solverPath) : null, installCommand.temptMurphy); } else { - smtLibSolverManager.install(solver.get1(), solver.get2(), solver.get2(), installCommand.temptMurphy); + smtLibSolverManager.install(solver.get1(), solver.get2(), solver.get2(), installCommand.solverPath != null ? Path.of(installCommand.solverPath) : null, installCommand.temptMurphy); } return; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java index 8381f2f0cb..500151d9de 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java @@ -95,7 +95,7 @@ public String getGenericInstallerName() { return genericInstaller.get1(); } - public void install(final String solver, final String version, final String name, final boolean installUnsupported) throws SmtLibSolverInstallerException { + public void install(final String solver, final String version, final String name, final Path solverPath, final boolean installUnsupported) throws SmtLibSolverInstallerException { checkArgument(!solver.equals(genericInstaller.get1())); if(!installers.containsKey(solver)) { @@ -114,7 +114,12 @@ else if(!getSupportedVersions(solver).contains(getVersionString(solver, version, throw new SmtLibSolverInstallerException(e); } - installers.get(solver).install(installDir, getVersionString(solver, version, false), getVersionString(solver, name, false)); + if(solverPath != null) { + installers.get(solver).install(installDir, getVersionString(solver, version, false), getVersionString(solver, name, false), solverPath); + } + else { + installers.get(solver).install(installDir, getVersionString(solver, version, false), getVersionString(solver, name, false)); + } } public void installGeneric(final String version, final Path solverPath, final String[] args) throws SmtLibSolverInstallerException { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java index 1ea9a8ca18..52f14b0f47 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java @@ -3,28 +3,17 @@ import hu.bme.mit.theta.common.OsHelper; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.smtlib.impl.cvc4.CVC4SmtLibSolverFactory; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverFactory; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import hu.bme.mit.theta.solver.smtlib.utils.Compress; -import hu.bme.mit.theta.solver.smtlib.utils.SemVer; -import java.io.BufferedReader; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStreamReader; -import java.net.MalformedURLException; import java.net.URI; -import java.net.URL; -import java.nio.channels.Channels; import java.nio.file.Path; import java.util.Arrays; import java.util.List; -import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; -import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; -import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; - public class BoolectorSmtLibSolverInstaller extends SmtLibSolverInstaller.Default { public BoolectorSmtLibSolverInstaller(final Logger logger) { @@ -83,9 +72,9 @@ protected String[] getDefaultSolverArgs(String version) { } @Override - public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { - final var solverFilePath = installDir.resolve("build").resolve("bin").resolve(getSolverBinaryName()); - return CVC4SmtLibSolverFactory.create(solverFilePath, solverArgs); + public SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = solverPath != null ? solverPath : installDir.resolve("build").resolve("bin").resolve(getSolverBinaryName()); + return GenericSmtLibSolverFactory.create(solverFilePath, solverArgs); } @Override diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java index d3facf2c2c..c98426c895 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java @@ -66,8 +66,8 @@ protected String[] getDefaultSolverArgs(String version) { } @Override - public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { - final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); + public SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = solverPath != null ? solverPath : installDir.resolve("bin").resolve(getSolverBinaryName()); return CVC4SmtLibSolverFactory.create(solverFilePath, solverArgs); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java index e889d3b42f..71a6519d7c 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java @@ -32,7 +32,7 @@ protected String getSolverName() { public void install(final Path home, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { this.solverPath = solverPath; this.solverArgs = solverArgs; - super.install(home, version, version); + super.install(home, version, version, solverPath); } @Override @@ -77,15 +77,8 @@ public void reinstall(final Path home, final String version) throws SmtLibSolver } @Override - public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { - try { - final var solverFilePath = solverFile(installDir); - final var solverPathStr = Files.readAllLines(solverFilePath, StandardCharsets.UTF_8).get(0); - return GenericSmtLibSolverFactory.create(Path.of(solverPathStr), solverArgs); - } - catch (IOException e) { - throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); - } + public SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] solverArgs) { + return GenericSmtLibSolverFactory.create(solverPath, solverArgs); } @Override diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java index 066ab35317..4326acfa46 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java @@ -133,8 +133,8 @@ protected String[] getDefaultSolverArgs(String version) throws SmtLibSolverInsta } @Override - public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { - final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); + public SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = solverPath != null ? solverPath : installDir.resolve("bin").resolve(getSolverBinaryName()); return MathSATSmtLibSolverFactory.create(solverFilePath, solverArgs, SemVer.of(version).compareTo(SemVer.of("5.4.0")) >= 0); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java index 251ce5762b..894926db84 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java @@ -59,8 +59,8 @@ protected String[] getDefaultSolverArgs(String version) { } @Override - public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { - final var solverFilePath = installDir.resolve(getSolverBinaryName(version)); + public SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = solverPath != null ? solverPath : installDir.resolve(getSolverBinaryName(version)); return SMTInterpolSmtLibSolverFactory.create(solverFilePath, solverArgs); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverInstaller.java index efd1cd8a5b..4483dc8222 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverInstaller.java @@ -99,8 +99,8 @@ protected String[] getDefaultSolverArgs(String version) { } @Override - public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { - final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); + public SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = solverPath != null ? solverPath : installDir.resolve("bin").resolve(getSolverBinaryName()); return Yices2SmtLibSolverFactory.create(solverFilePath, solverArgs); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java index eb09fafc56..6efaec73df 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java @@ -126,8 +126,8 @@ protected String[] getDefaultSolverArgs(String version) { } @Override - public SolverFactory getSolverFactory(final Path installDir, final String version, final String[] solverArgs) throws SmtLibSolverInstallerException { - final var solverFilePath = installDir.resolve("bin").resolve(getSolverBinaryName()); + public SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = solverPath != null ? solverPath : installDir.resolve("bin").resolve(getSolverBinaryName()); return Z3SmtLibSolverFactory.create(solverFilePath, solverArgs, SemVer.of(version).compareTo(SemVer.of("4.5.0")) <= 0); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java index d2d32b6b88..6e91e8f47d 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java @@ -19,6 +19,8 @@ public interface SmtLibSolverInstaller { void install(Path home, String version, String name) throws SmtLibSolverInstallerException; + void install(Path home, String version, String name, Path solverPath) throws SmtLibSolverInstallerException; + void uninstall(Path home, String version) throws SmtLibSolverInstallerException; void reinstall(Path home, String version) throws SmtLibSolverInstallerException; @@ -41,12 +43,27 @@ public Default(final Logger logger) { } @Override - public final void install(Path home, String version, String name) throws SmtLibSolverInstallerException { + public final void install(final Path home, final String version, final String name) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + checkName(name); + + doInstall(home, version, name, null); + } + + @Override + public final void install(final Path home, final String version, final String name, final Path solverPath) throws SmtLibSolverInstallerException { checkNotNull(home); checkArgument(Files.exists(home)); checkVersion(version); checkName(name); + checkNotNull(solverPath); + + doInstall(home, version, name, solverPath); + } + private void doInstall(final Path home, final String version, final String name, final Path solverPath) throws SmtLibSolverInstallerException { final var installDir = getInstallDir(home, name); if(Files.exists(installDir)) { throw new SmtLibSolverInstallerException("There is already a solver instance with this name installed"); @@ -57,6 +74,11 @@ public final void install(Path home, String version, String name) throws SmtLibS Files.createDirectory(installDir); + if(solverPath != null) { + final var solverFilePath = solverFile(installDir); + Files.writeString(solverFilePath, solverPath.toAbsolutePath().toString(), StandardCharsets.UTF_8); + } + final var solverArgsPath = argsFile(installDir); Files.writeString(solverArgsPath, String.join("\n", getDefaultSolverArgs(version)), StandardCharsets.UTF_8); @@ -64,12 +86,15 @@ public final void install(Path home, String version, String name) throws SmtLibS Files.writeString( solverInfoPath, String.format("solver=%s\n", getSolverName()) + - String.format("version=%s\n", version) + - String.format("name=%s\n", name), + String.format("version=%s\n", version) + + String.format("name=%s\n", name) + + (solverPath != null ? String.format("binary=%s\n", solverPath.toAbsolutePath().toString()) : ""), StandardCharsets.UTF_8 ); - installSolver(installDir, version); + if(solverPath == null) { + installSolver(installDir, version); + } logger.write(Logger.Level.MAINSTEP, "Installation finished\n"); } @@ -150,10 +175,19 @@ public final SolverFactory getSolverFactory(final Path home, final String versio } try { + final Path solverPath; + final var solverFilePath = solverFile(installDir); + if(Files.exists(solverFilePath)) { + solverPath = Path.of(Files.readAllLines(solverFilePath, StandardCharsets.UTF_8).get(0)); + } + else { + solverPath = null; + } + final var solverArgsPath = argsFile(installDir); final var solverArgs = Files.readAllLines(solverArgsPath, StandardCharsets.UTF_8).toArray(String[]::new); - return getSolverFactory(installDir, version, solverArgs); + return getSolverFactory(installDir, version, solverPath, solverArgs); } catch (IOException e) { throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); @@ -217,7 +251,7 @@ public final List getInstalledVersions(Path home) throws SmtLibSolverIns protected abstract String getSolverName() throws SmtLibSolverInstallerException; protected abstract void installSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException; protected abstract void uninstallSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException; - protected abstract SolverFactory getSolverFactory(final Path installDir, final String version, final String[] args) throws SmtLibSolverInstallerException; + protected abstract SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] args) throws SmtLibSolverInstallerException; protected abstract String[] getDefaultSolverArgs(final String version) throws SmtLibSolverInstallerException; protected final void checkName(final String version) throws SmtLibSolverInstallerException { @@ -236,6 +270,10 @@ protected final Path getInstallDir(final Path home, final String version) { return home.resolve(version); } + private Path solverFile(final Path installDir) { + return installDir.resolve("solver.txt"); + } + protected final Path argsFile(final Path installDir) { return installDir.resolve("solver-args.txt"); } From de3cbf7abea70a0fdd0601e9d1f074fa7a4be539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 27 Mar 2021 23:00:13 +0100 Subject: [PATCH 74/99] Remove reinstall feature --- .../theta/solver/smtlib/cli/SmtLibCli.java | 15 -------- .../solver/smtlib/SmtLibSolverManager.java | 8 ----- .../generic/GenericSmtLibSolverInstaller.java | 8 ----- .../installer/SmtLibSolverInstaller.java | 35 +------------------ 4 files changed, 1 insertion(+), 65 deletions(-) diff --git a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java index 7071c8b791..84db69dca4 100644 --- a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java +++ b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java @@ -77,14 +77,6 @@ static class UninstallCommand { String solver; } - @Parameters(commandDescription = "Reinstalls the solver") - static class ReinstallCommand { - static final String COMMAND = "reinstall"; - - @Parameter(description = "The solver to reinstall (:)", validateWith = SolverNameAndVersionValidator.class, required = true) - String solver; - } - @Parameters(commandDescription = "Prints info about the solver") static class GetInfoCommand { static final String COMMAND = "get-info"; @@ -134,7 +126,6 @@ private void run() { final var installCommand = new InstallCommand(); final var installGenericCommand = new InstallGenericCommand(); final var uninstallCommand = new UninstallCommand(); - final var reinstallCommand = new ReinstallCommand(); final var getInfoCommand = new GetInfoCommand(); final var editArgsCommand = new EditArgsCommand(); final var listInstalledCommand = new ListInstalledCommand(); @@ -145,7 +136,6 @@ private void run() { .addCommand(InstallCommand.COMMAND, installCommand) .addCommand(InstallGenericCommand.COMMAND, installGenericCommand) .addCommand(UninstallCommand.COMMAND, uninstallCommand) - .addCommand(ReinstallCommand.COMMAND, reinstallCommand) .addCommand(GetInfoCommand.COMMAND, getInfoCommand) .addCommand(EditArgsCommand.COMMAND, editArgsCommand) .addCommand(ListInstalledCommand.COMMAND, listInstalledCommand) @@ -209,11 +199,6 @@ private void run() { smtLibSolverManager.uninstall(solver.get1(), solver.get2()); return; } - case ReinstallCommand.COMMAND: { - final var solver = decodeVersionString(reinstallCommand.solver); - smtLibSolverManager.reinstall(solver.get1(), solver.get2()); - return; - } case GetInfoCommand.COMMAND: { final var solver = decodeVersionString(getInfoCommand.solver); final var info = smtLibSolverManager.getInfo(solver.get1(), solver.get2()); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java index 500151d9de..1966d1ddc4 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java @@ -142,14 +142,6 @@ public void uninstall(final String solver, final String version) throws SmtLibSo installers.get(solver).uninstall(home.resolve(solver), getVersionString(solver, version, true)); } - public void reinstall(final String solver, final String version) throws SmtLibSolverInstallerException { - if(!installers.containsKey(solver)) { - throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); - } - - installers.get(solver).reinstall(home.resolve(solver), getVersionString(solver, version, true)); - } - public String getInfo(final String solver, final String version) throws SmtLibSolverInstallerException { if(!installers.containsKey(solver)) { throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java index 71a6519d7c..f4124852cd 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java @@ -68,14 +68,6 @@ protected void uninstallSolver(Path installDir, String version) throws SmtLibSol } } - @Override - public void reinstall(final Path home, final String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkVersion(version); - throw new SmtLibSolverInstallerException("Unsupported operation for generic solvers"); - } - @Override public SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] solverArgs) { return GenericSmtLibSolverFactory.create(solverPath, solverArgs); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java index 6e91e8f47d..cc4020956b 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java @@ -23,8 +23,6 @@ public interface SmtLibSolverInstaller { void uninstall(Path home, String version) throws SmtLibSolverInstallerException; - void reinstall(Path home, String version) throws SmtLibSolverInstallerException; - String getInfo(Path home, String version) throws SmtLibSolverInstallerException; Path getArgsFile(Path home, String version) throws SmtLibSolverInstallerException; @@ -132,37 +130,6 @@ public final void uninstall(Path home, String version) throws SmtLibSolverInstal } } - @Override - public void reinstall(Path home, String version) throws SmtLibSolverInstallerException { - checkNotNull(home); - checkArgument(Files.exists(home)); - checkName(version); - - final String solverVersion; - try { - final var installDir = getInstallDir(home, version); - final var solverInfoPath = infoFile(installDir); - final var solverInfo = Files - .readAllLines(solverInfoPath, StandardCharsets.UTF_8).stream() - .filter(l -> l.startsWith("version=")) - .map(l -> l.substring("version=".length())) - .findAny(); - - if(solverInfo.isPresent()) { - solverVersion = solverInfo.get(); - } - else { - throw new SmtLibSolverInstallerException("The solver installation is corrupted"); - } - } - catch (IOException e) { - throw new SmtLibSolverInstallerException(String.format("Error: %s", e.getMessage()), e); - } - - uninstall(home, version); - install(home, solverVersion, version); - } - @Override public final SolverFactory getSolverFactory(final Path home, final String version) throws SmtLibSolverInstallerException { checkNotNull(home); @@ -233,7 +200,7 @@ public final Path getArgsFile(Path home, String version) throws SmtLibSolverInst } @Override - public final List getInstalledVersions(Path home) throws SmtLibSolverInstallerException { + public final List getInstalledVersions(Path home) { checkNotNull(home); if(Files.exists(home)) { From dc423be98e0a4a27e6731248807a02f87ea8a058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 27 Mar 2021 23:15:21 +0100 Subject: [PATCH 75/99] Add rename command to rename already installed solvers --- .../theta/solver/smtlib/cli/SmtLibCli.java | 18 ++++++++++ .../solver/smtlib/SmtLibSolverManager.java | 11 +++++- .../installer/SmtLibSolverInstaller.java | 35 +++++++++++++++++-- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java index 84db69dca4..4888685296 100644 --- a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java +++ b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java @@ -77,6 +77,17 @@ static class UninstallCommand { String solver; } + @Parameters(commandDescription = "Renames one installed solver version") + static class RenameCommand { + static final String COMMAND = "rename"; + + @Parameter(description = "The solver to reinstall (:)", validateWith = SolverNameAndVersionValidator.class, required = true) + String solver; + + @Parameter(names = "--name", description = "Rename the solver version to this custom name (:).", required = true) + String name; + } + @Parameters(commandDescription = "Prints info about the solver") static class GetInfoCommand { static final String COMMAND = "get-info"; @@ -126,6 +137,7 @@ private void run() { final var installCommand = new InstallCommand(); final var installGenericCommand = new InstallGenericCommand(); final var uninstallCommand = new UninstallCommand(); + final var renameCommand = new RenameCommand(); final var getInfoCommand = new GetInfoCommand(); final var editArgsCommand = new EditArgsCommand(); final var listInstalledCommand = new ListInstalledCommand(); @@ -136,6 +148,7 @@ private void run() { .addCommand(InstallCommand.COMMAND, installCommand) .addCommand(InstallGenericCommand.COMMAND, installGenericCommand) .addCommand(UninstallCommand.COMMAND, uninstallCommand) + .addCommand(RenameCommand.COMMAND, renameCommand) .addCommand(GetInfoCommand.COMMAND, getInfoCommand) .addCommand(EditArgsCommand.COMMAND, editArgsCommand) .addCommand(ListInstalledCommand.COMMAND, listInstalledCommand) @@ -199,6 +212,11 @@ private void run() { smtLibSolverManager.uninstall(solver.get1(), solver.get2()); return; } + case RenameCommand.COMMAND: { + final var solver = decodeVersionString(renameCommand.solver); + smtLibSolverManager.rename(solver.get1(), solver.get2(), renameCommand.name); + return; + } case GetInfoCommand.COMMAND: { final var solver = decodeVersionString(getInfoCommand.solver); final var info = smtLibSolverManager.getInfo(solver.get1(), solver.get2()); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java index 1966d1ddc4..35025c91ef 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java @@ -142,6 +142,14 @@ public void uninstall(final String solver, final String version) throws SmtLibSo installers.get(solver).uninstall(home.resolve(solver), getVersionString(solver, version, true)); } + public void rename(final String solver, final String version, final String name) throws SmtLibSolverInstallerException { + if(!installers.containsKey(solver)) { + throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); + } + + installers.get(solver).rename(home.resolve(solver), getVersionString(solver, version, true), name); + } + public String getInfo(final String solver, final String version) throws SmtLibSolverInstallerException { if(!installers.containsKey(solver)) { throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); @@ -211,7 +219,8 @@ private String getVersionString(final String solver, final String version, final return version; } else { - final var versions = installed ? getInstalledVersions(solver) : getSupportedVersions(solver); + final var supportedVersions = getSupportedVersions(solver); + final var versions = installed ? getInstalledVersions(solver).stream().filter(supportedVersions::contains).collect(Collectors.toList()) : supportedVersions; if(versions.size() > 0) { return versions.get(0); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java index cc4020956b..5648b9963d 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java @@ -6,8 +6,10 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.nio.file.CopyOption; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -23,6 +25,8 @@ public interface SmtLibSolverInstaller { void uninstall(Path home, String version) throws SmtLibSolverInstallerException; + void rename(Path home, String version, String name) throws SmtLibSolverInstallerException; + String getInfo(Path home, String version) throws SmtLibSolverInstallerException; Path getArgsFile(Path home, String version) throws SmtLibSolverInstallerException; @@ -130,6 +134,31 @@ public final void uninstall(Path home, String version) throws SmtLibSolverInstal } } + @Override + public void rename(final Path home, final String version, final String name) throws SmtLibSolverInstallerException { + checkNotNull(home); + checkArgument(Files.exists(home)); + checkVersion(version); + checkName(name); + + final var installDir = getInstallDir(home, version); + if(!Files.exists(installDir)) { + throw new SmtLibSolverInstallerException("The version is not installed"); + } + + final var newInstallDir = getInstallDir(home, name); + if(Files.exists(newInstallDir)) { + throw new SmtLibSolverInstallerException("The chosen name is already used"); + } + + try { + Files.move(installDir, newInstallDir); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(String.format("Error renaming solver: %s", e.getMessage()), e); + } + } + @Override public final SolverFactory getSolverFactory(final Path home, final String version) throws SmtLibSolverInstallerException { checkNotNull(home); @@ -221,9 +250,9 @@ public final List getInstalledVersions(Path home) { protected abstract SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] args) throws SmtLibSolverInstallerException; protected abstract String[] getDefaultSolverArgs(final String version) throws SmtLibSolverInstallerException; - protected final void checkName(final String version) throws SmtLibSolverInstallerException { - if(!version.matches("^[a-zA-Z0-9_.-]+$")) { - throw new SmtLibSolverInstallerException("Unsupported name format: " + version); + protected final void checkName(final String name) throws SmtLibSolverInstallerException { + if(!name.matches("^[a-zA-Z0-9_.-]+$") || name.matches("latest")) { + throw new SmtLibSolverInstallerException("Unsupported name format: " + name); } } From 58a7de42eca15302fae2998de2b101a7fc6ff94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Sat, 27 Mar 2021 23:36:59 +0100 Subject: [PATCH 76/99] Modify tests to fit the project structure. --- .../mit/theta/solver/smtlib/SmtLibItpSolverTest.java | 4 ++-- .../mit/theta/solver/smtlib/SmtLibSolverBVTest.java | 6 ++---- .../bme/mit/theta/solver/smtlib/SmtLibSolverTest.java | 11 ++++++----- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java index e6a1af3113..50b4cf54d2 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java @@ -30,7 +30,7 @@ import hu.bme.mit.theta.solver.ItpSolver; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.SolverStatus; -import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; @@ -67,7 +67,7 @@ public static void init() throws SmtLibSolverInstallerException, IOException { Path home = Files.createTempDirectory("theta-solver"); solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); - solverManager.install("z3", "4.5.0", "4.5.0", false); + solverManager.install("z3", "4.5.0", "4.5.0", null, false); solverFactory = solverManager.getSolverFactory("z3", "latest"); } diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java index 1d8b6445e4..b670039ca2 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java @@ -5,10 +5,8 @@ import hu.bme.mit.theta.core.type.abstracttype.EqExpr; import hu.bme.mit.theta.core.utils.BvTestUtils; import hu.bme.mit.theta.solver.Solver; -import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.SolverStatus; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSolverFactory; -import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -45,7 +43,7 @@ public static void init() throws SmtLibSolverInstallerException, IOException { Path home = Files.createTempDirectory("theta-solver"); solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); - solverManager.install("z3", "latest", "latest", false); + solverManager.install("z3", "latest", "latest", null, false); } @AfterClass diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index 42652c2a94..800922a1d5 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -22,9 +22,10 @@ import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.generic.GenericSmtLibTermTransformer; -import hu.bme.mit.theta.solver.smtlib.manager.SmtLibSolverManager; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -60,7 +61,7 @@ public static void init() throws SmtLibSolverInstallerException, IOException { Path home = Files.createTempDirectory("theta-solver"); solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); - solverManager.install("z3", "latest", "latest", false); + solverManager.install("z3", "latest", "latest", null, false); solverFactory = solverManager.getSolverFactory("z3", "latest"); } @@ -219,7 +220,7 @@ public void testArray() { final Expr> val = optVal.get(); assertTrue(val instanceof ArrayLitExpr); var valLit = (ArrayLitExpr)val; - assertEquals(2, valLit.getElements().size()); + assertTrue(2 <= valLit.getElements().size()); assertEquals(Int(1), Read(valLit, Int(0)).eval(ImmutableValuation.empty())); assertEquals(Int(2), Read(valLit, Int(1)).eval(ImmutableValuation.empty())); } From f801d0caecc23c47f952267eba9a0b6724e443c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 30 Mar 2021 16:39:18 +0200 Subject: [PATCH 77/99] Add SMTInterpol interpolation support --- .../solver-smtlib/src/main/antlr/SMTLIBv2.g4 | 5 + .../SMTInterpolSmtLibItpMarker.java | 6 + .../SMTInterpolSmtLibItpPattern.java | 94 ++++++++++ .../SMTInterpolSmtLibItpSolver.java | 171 ++++++++++++++++++ .../SMTInterpolSmtLibSolverFactory.java | 7 +- 5 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpMarker.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpPattern.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpSolver.java diff --git a/subprojects/solver/solver-smtlib/src/main/antlr/SMTLIBv2.g4 b/subprojects/solver/solver-smtlib/src/main/antlr/SMTLIBv2.g4 index bb7936d6bc..0e5543397d 100644 --- a/subprojects/solver/solver-smtlib/src/main/antlr/SMTLIBv2.g4 +++ b/subprojects/solver/solver-smtlib/src/main/antlr/SMTLIBv2.g4 @@ -54,6 +54,7 @@ specific_success_response : check_sat_response | get_unsat_core_response | get_model_response + | get_interpolants_response_smtinterpol ; check_sat_response @@ -101,6 +102,10 @@ function_dec : ParOpen symbol ParOpen sorted_var* ParClose sort ParClose ; +get_interpolants_response_smtinterpol + : ParOpen term* ParClose + ; + // Parser Rules End // Parser Rules Start diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpMarker.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpMarker.java new file mode 100644 index 0000000000..04fbe9a68a --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpMarker.java @@ -0,0 +1,6 @@ +package hu.bme.mit.theta.solver.smtlib.impl.smtinterpol; + +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibItpMarker; + +public class SMTInterpolSmtLibItpMarker extends SmtLibItpMarker { +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpPattern.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpPattern.java new file mode 100644 index 0000000000..5aeb443e6c --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpPattern.java @@ -0,0 +1,94 @@ +package hu.bme.mit.theta.solver.smtlib.impl.smtinterpol; + +import com.google.common.collect.Lists; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; +import hu.bme.mit.theta.solver.ItpPattern; + +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +public class SMTInterpolSmtLibItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { + final ItpMarkerTree markerTree; + + SMTInterpolSmtLibItpPattern(final ItpMarkerTree markerTree) { + this.markerTree = markerTree; + } + + @SuppressWarnings("unchecked") + static SMTInterpolSmtLibItpPattern of(final ItpMarkerTree markerTree) { + final var list = new ArrayList>(); + list.add(markerTree); + while(!list.isEmpty()) { + final var node = list.get(0); + list.remove(0); + + checkArgument(node.getMarker() instanceof SMTInterpolSmtLibItpMarker); + + list.addAll(node.getChildren()); + } + + return new SMTInterpolSmtLibItpPattern((ItpMarkerTree) markerTree); + } + + @Override + public SMTInterpolSmtLibItpMarker getA() { + checkState(isBinary()); + return markerTree.getChild(0).getMarker(); + } + + @Override + public SMTInterpolSmtLibItpMarker getB() { + checkState(isBinary()); + return markerTree.getMarker(); + } + + @Override + public List getSequence() { + checkState(isSequence()); + final var markerList = new ArrayList(); + + var current = markerTree; + while(current.getChildrenNumber() > 0) { + markerList.add(current.getMarker()); + current = current.getChild(0); + } + markerList.add(current.getMarker()); + + return Lists.reverse(markerList); + } + + @Override + public ItpMarkerTree getRoot() { + return markerTree; + } + + @Override + public E visit(ItpPatternVisitor visitor) { + return visitor.visitTreePattern(this); + } + + private boolean isBinary() { + return + markerTree != null && + markerTree.getChildrenNumber() == 1 && + markerTree.getChild(0) != null && + markerTree.getChild(0).getChildrenNumber() == 0; + } + + private boolean isSequence() { + var current = markerTree; + while(current.getChildrenNumber() > 0) { + if(current.getChildrenNumber() > 1) { + return false; + } + else { + current = current.getChild(0); + } + } + return true; + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpSolver.java new file mode 100644 index 0000000000..790095f709 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpSolver.java @@ -0,0 +1,171 @@ +package hu.bme.mit.theta.solver.smtlib.impl.smtinterpol; + +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolExprs; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.solver.Interpolant; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; +import hu.bme.mit.theta.solver.ItpPattern; +import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibItpSolver; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibInterpolant; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; +import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.misc.Interval; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.False; + +public final class SMTInterpolSmtLibItpSolver extends SmtLibItpSolver { + private final Map, String> assertionNames = new HashMap<>(); + private static final String assertionNamePattern = "_smtinterpol_assertion_%d"; + private static long assertionCount = 0; + + public SMTInterpolSmtLibItpSolver( + final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, + final SmtLibTermTransformer termTransformer, final SmtLibSolverBinary solverBinary + ) { + super(symbolTable, transformationManager, termTransformer, solverBinary); + } + + @Override + public ItpPattern createTreePattern(final ItpMarkerTree root) { + checkNotNull(root); + return SMTInterpolSmtLibItpPattern.of(root); + } + + @Override + public SMTInterpolSmtLibItpMarker createMarker() { + final var marker = new SMTInterpolSmtLibItpMarker(); + markers.add(marker); + return marker; + } + + @Override + protected void add(final SMTInterpolSmtLibItpMarker marker, final Expr assertion, final Set> consts, final String term) { + consts.stream().map(symbolTable::getDeclaration).forEach(this::issueGeneralCommand); + + final var name = String.format(assertionNamePattern, assertionCount++); + assertionNames.put(assertion, name); + issueGeneralCommand(String.format("(assert (! %s :named %s))", term, name)); + } + + @Override + public Interpolant getInterpolant(final ItpPattern pattern) { + checkState(getStatus() == SolverStatus.UNSAT, "Cannot get interpolant if status is not UNSAT."); + checkArgument(pattern instanceof SMTInterpolSmtLibItpPattern); + final var smtInterpolItpPattern = (SMTInterpolSmtLibItpPattern) pattern; + + final var term = patternToTerm(smtInterpolItpPattern.getRoot()); + + final List> itpList = new LinkedList<>(); + + solverBinary.issueCommand(String.format("(get-interpolants %s)", term)); + for(final var itp : parseItpResponse(solverBinary.readResponse())) { + itpList.add(termTransformer.toExpr(itp, BoolExprs.Bool(), new SmtLibModel(Collections.emptyMap()))); + } + itpList.add(False()); + + final Map> itpMap = new HashMap<>(); + buildItpMapFormList(smtInterpolItpPattern.getRoot(), itpList, itpMap); + + return new SmtLibInterpolant(itpMap); + } + + private String patternToTerm(final ItpMarkerTree markerTree) { + String term; + + final var marker = markerTree.getMarker(); + final var terms = marker.getTerms(); + if(terms.size() == 1) { + term = assertionNames.get(terms.iterator().next().get1()); + } + else { + term = String.format("(and %s)", terms.stream().map(t -> assertionNames.get(t.get1())).collect(Collectors.joining(" "))); + } + + final var children = markerTree.getChildren(); + for(var i = children.size() - 1; i >= 0; i--) { + if(i == 0) { + term = String.format("%s %s", patternToTerm(children.get(i)), term); + } + else { + term = String.format("(%s) %s", patternToTerm(children.get(i)), term); + } + } + + return term; + } + + private void buildItpMapFormList(final ItpMarkerTree pattern, final List> itpList, final Map> itpMap) { + for (final ItpMarkerTree child : pattern.getChildren()) { + buildItpMapFormList(child, itpList, itpMap); + } + final ItpMarker marker = pattern.getMarker(); + final Expr itpExpr = itpList.get(0); + itpMap.put(marker, itpExpr); + itpList.remove(0); + } + + @Override + protected void init() { + issueGeneralCommand("(set-option :print-success true)"); + issueGeneralCommand("(set-option :produce-models true)"); + issueGeneralCommand("(set-option :produce-interpolants true)"); + issueGeneralCommand("(set-logic ALL)"); + } + + private List parseItpResponse(final String response) { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(response)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + try { + final var interpolants = new ArrayList(); + + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + + for(final var term : parser.get_interpolants_response_smtinterpol().term()) { + interpolants.add(extractString(term)); + } + + return interpolants; + } + catch (Exception e) { + try { + throw new SmtLibSolverException(parser.response().general_response_error().reason.getText()); + } + catch(Exception ex) { + throw new SmtLibSolverException("Could not parse solver output: " + response, e); + } + } + } + + private static String extractString(final ParserRuleContext ctx) { + return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex())); + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverFactory.java index 28778348a2..ea4fd088ea 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverFactory.java @@ -47,7 +47,12 @@ public UCSolver createUCSolver() { @Override public ItpSolver createItpSolver() { - throw new UnsupportedOperationException("CVC4 does not support interpolation"); + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(getJavaBinary(), getSolverArgs()); + + return new SMTInterpolSmtLibItpSolver(symbolTable, transformationManager, termTransformer, solverBinary); } private Path getJavaBinary() { From cdaadcc09559f06940c90c0469833ad2bed048cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 30 Mar 2021 18:38:16 +0200 Subject: [PATCH 78/99] Add Princess solver support --- .../solver/smtlib/SmtLibSolverManager.java | 2 + .../princess/PrincessSmtLibItpMarker.java | 6 + .../princess/PrincessSmtLibItpPattern.java | 94 ++++++++++ .../princess/PrincessSmtLibItpSolver.java | 173 ++++++++++++++++++ .../princess/PrincessSmtLibSolverFactory.java | 57 ++++++ .../PrincessSmtLibSolverInstaller.java | 95 ++++++++++ 6 files changed, 427 insertions(+) create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpMarker.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpPattern.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpSolver.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverFactory.java create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java index 35025c91ef..c3d095946e 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java @@ -5,6 +5,7 @@ import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.smtlib.impl.boolector.BoolectorSmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.impl.princess.PrincessSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.impl.smtinterpol.SMTInterpolSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.impl.yices2.Yices2SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; @@ -48,6 +49,7 @@ public static void registerGenericInsta registerInstaller("yices2", Yices2SmtLibSolverInstaller.class); registerInstaller("boolector", BoolectorSmtLibSolverInstaller.class); registerInstaller("smtinterpol", SMTInterpolSmtLibSolverInstaller.class); + registerInstaller("princess", PrincessSmtLibSolverInstaller.class); registerGenericInstaller("generic", GenericSmtLibSolverInstaller.class); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpMarker.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpMarker.java new file mode 100644 index 0000000000..141ecdf2bb --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpMarker.java @@ -0,0 +1,6 @@ +package hu.bme.mit.theta.solver.smtlib.impl.princess; + +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibItpMarker; + +public class PrincessSmtLibItpMarker extends SmtLibItpMarker { +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpPattern.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpPattern.java new file mode 100644 index 0000000000..01a1a178d2 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpPattern.java @@ -0,0 +1,94 @@ +package hu.bme.mit.theta.solver.smtlib.impl.princess; + +import com.google.common.collect.Lists; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; +import hu.bme.mit.theta.solver.ItpPattern; + +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +public class PrincessSmtLibItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { + final ItpMarkerTree markerTree; + + PrincessSmtLibItpPattern(final ItpMarkerTree markerTree) { + this.markerTree = markerTree; + } + + @SuppressWarnings("unchecked") + static PrincessSmtLibItpPattern of(final ItpMarkerTree markerTree) { + final var list = new ArrayList>(); + list.add(markerTree); + while(!list.isEmpty()) { + final var node = list.get(0); + list.remove(0); + + checkArgument(node.getMarker() instanceof PrincessSmtLibItpMarker); + + list.addAll(node.getChildren()); + } + + return new PrincessSmtLibItpPattern((ItpMarkerTree) markerTree); + } + + @Override + public PrincessSmtLibItpMarker getA() { + checkState(isBinary()); + return markerTree.getChild(0).getMarker(); + } + + @Override + public PrincessSmtLibItpMarker getB() { + checkState(isBinary()); + return markerTree.getMarker(); + } + + @Override + public List getSequence() { + checkState(isSequence()); + final var markerList = new ArrayList(); + + var current = markerTree; + while(current.getChildrenNumber() > 0) { + markerList.add(current.getMarker()); + current = current.getChild(0); + } + markerList.add(current.getMarker()); + + return Lists.reverse(markerList); + } + + @Override + public ItpMarkerTree getRoot() { + return markerTree; + } + + @Override + public E visit(ItpPatternVisitor visitor) { + return visitor.visitTreePattern(this); + } + + public boolean isBinary() { + return + markerTree != null && + markerTree.getChildrenNumber() == 1 && + markerTree.getChild(0) != null && + markerTree.getChild(0).getChildrenNumber() == 0; + } + + public boolean isSequence() { + var current = markerTree; + while(current.getChildrenNumber() > 0) { + if(current.getChildrenNumber() > 1) { + return false; + } + else { + current = current.getChild(0); + } + } + return true; + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpSolver.java new file mode 100644 index 0000000000..cf22650e5b --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpSolver.java @@ -0,0 +1,173 @@ +package hu.bme.mit.theta.solver.smtlib.impl.princess; + +import hu.bme.mit.theta.core.decl.ConstDecl; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolExprs; +import hu.bme.mit.theta.core.type.booltype.BoolType; +import hu.bme.mit.theta.solver.Interpolant; +import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; +import hu.bme.mit.theta.solver.ItpPattern; +import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.impl.smtinterpol.SMTInterpolSmtLibItpMarker; +import hu.bme.mit.theta.solver.smtlib.impl.smtinterpol.SMTInterpolSmtLibItpPattern; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibItpSolver; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibInterpolant; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; +import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.misc.Interval; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.False; + +public final class PrincessSmtLibItpSolver extends SmtLibItpSolver { + private final Map, String> assertionNames = new HashMap<>(); + private static final String assertionNamePattern = "_smtinterpol_assertion_%d"; + private static long assertionCount = 0; + + public PrincessSmtLibItpSolver( + final SmtLibSymbolTable symbolTable, final SmtLibTransformationManager transformationManager, + final SmtLibTermTransformer termTransformer, final SmtLibSolverBinary solverBinary + ) { + super(symbolTable, transformationManager, termTransformer, solverBinary); + } + + @Override + public ItpPattern createTreePattern(final ItpMarkerTree root) { + checkNotNull(root); + return PrincessSmtLibItpPattern.of(root); + } + + @Override + public PrincessSmtLibItpMarker createMarker() { + final var marker = new PrincessSmtLibItpMarker(); + markers.add(marker); + return marker; + } + + @Override + protected void add(final PrincessSmtLibItpMarker marker, final Expr assertion, final Set> consts, final String term) { + consts.stream().map(symbolTable::getDeclaration).forEach(this::issueGeneralCommand); + + final var name = String.format(assertionNamePattern, assertionCount++); + assertionNames.put(assertion, name); + issueGeneralCommand(String.format("(assert (! %s :named %s))", term, name)); + } + + @Override + public Interpolant getInterpolant(final ItpPattern pattern) { + checkState(getStatus() == SolverStatus.UNSAT, "Cannot get interpolant if status is not UNSAT."); + checkArgument(pattern instanceof PrincessSmtLibItpPattern); + final var princessItpPattern = (PrincessSmtLibItpPattern) pattern; + + final var term = patternToTerm(princessItpPattern.getRoot()); + + final List> itpList = new LinkedList<>(); + + solverBinary.issueCommand(String.format("(get-interpolants %s)", term)); + for(final var itp : parseItpResponse(solverBinary.readResponse())) { + itpList.add(termTransformer.toExpr(itp, BoolExprs.Bool(), new SmtLibModel(Collections.emptyMap()))); + } + itpList.add(False()); + + final Map> itpMap = new HashMap<>(); + buildItpMapFormList(princessItpPattern.getRoot(), itpList, itpMap); + + return new SmtLibInterpolant(itpMap); + } + + private String patternToTerm(final ItpMarkerTree markerTree) { + String term; + + final var marker = markerTree.getMarker(); + final var terms = marker.getTerms(); + if(terms.size() == 1) { + term = assertionNames.get(terms.iterator().next().get1()); + } + else { + term = String.format("(and %s)", terms.stream().map(t -> assertionNames.get(t.get1())).collect(Collectors.joining(" "))); + } + + final var children = markerTree.getChildren(); + for(var i = children.size() - 1; i >= 0; i--) { + if(i == 0) { + term = String.format("%s %s", patternToTerm(children.get(i)), term); + } + else { + term = String.format("(%s) %s", patternToTerm(children.get(i)), term); + } + } + + return term; + } + + private void buildItpMapFormList(final ItpMarkerTree pattern, final List> itpList, final Map> itpMap) { + for (final ItpMarkerTree child : pattern.getChildren()) { + buildItpMapFormList(child, itpList, itpMap); + } + final ItpMarker marker = pattern.getMarker(); + final Expr itpExpr = itpList.get(0); + itpMap.put(marker, itpExpr); + itpList.remove(0); + } + + @Override + protected void init() { + issueGeneralCommand("(set-option :print-success true)"); + issueGeneralCommand("(set-option :produce-models true)"); + issueGeneralCommand("(set-option :produce-interpolants true)"); + issueGeneralCommand("(set-logic ALL)"); + } + + private List parseItpResponse(final String response) { + final var lexer = new SMTLIBv2Lexer(CharStreams.fromString(response)); + final var parser = new SMTLIBv2Parser(new CommonTokenStream(lexer)); + try { + final var interpolants = new ArrayList(); + + lexer.removeErrorListeners(); + lexer.addErrorListener(new ThrowExceptionErrorListener()); + parser.removeErrorListeners(); + parser.addErrorListener(new ThrowExceptionErrorListener()); + + for(final var term : parser.get_interpolants_response_smtinterpol().term()) { + interpolants.add(extractString(term)); + } + + return interpolants; + } + catch (Exception e) { + try { + throw new SmtLibSolverException(parser.response().general_response_error().reason.getText()); + } + catch(Exception ex) { + throw new SmtLibSolverException("Could not parse solver output: " + response, e); + } + } + } + + private static String extractString(final ParserRuleContext ctx) { + return ctx.start.getInputStream().getText(new Interval(ctx.start.getStartIndex(), ctx.stop.getStopIndex())); + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverFactory.java new file mode 100644 index 0000000000..aa470f1e22 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverFactory.java @@ -0,0 +1,57 @@ +package hu.bme.mit.theta.solver.smtlib.impl.princess; + +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; + +import java.nio.file.Path; + +public class PrincessSmtLibSolverFactory implements SolverFactory { + private final Path solverPath; + private final String[] args; + + private PrincessSmtLibSolverFactory(Path solverPath, String[] args) { + this.solverPath = solverPath; + this.args = args; + } + + public static PrincessSmtLibSolverFactory create(Path solverPath, String[] args) { + return new PrincessSmtLibSolverFactory(solverPath, args); + } + + @Override + public Solver createSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); + } + + @Override + public UCSolver createUCSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); + } + + @Override + public ItpSolver createItpSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new PrincessSmtLibItpSolver(symbolTable, transformationManager, termTransformer, solverBinary); + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java new file mode 100644 index 0000000000..db3e76de23 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java @@ -0,0 +1,95 @@ +package hu.bme.mit.theta.solver.smtlib.impl.princess; + +import hu.bme.mit.theta.common.OsHelper; +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.impl.cvc4.CVC4SmtLibSolverFactory; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.utils.Compress; +import hu.bme.mit.theta.solver.smtlib.utils.SemVer; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; +import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; + +public class PrincessSmtLibSolverInstaller extends SmtLibSolverInstaller.Default { + + public PrincessSmtLibSolverInstaller(final Logger logger) { + super(logger); + } + + @Override + protected String getSolverName() { + return "princess"; + } + + @Override + protected void installSolver(final Path installDir, final String version) throws SmtLibSolverInstallerException { + + final var downloadUrl = URI.create(String.format( + "http://www.philipp.ruemmer.org/princess/princess-bin-%s.zip", + version + )); + + logger.write(Logger.Level.MAINSTEP, "Starting download (%s)...\n", downloadUrl.toString()); + + try(final var inputStream = downloadUrl.toURL().openStream()) { + Compress.extract(inputStream, installDir, Compress.CompressionType.ZIP); + installDir.resolve(getSolverBinaryName()).toFile().setExecutable(true, true); + } + catch (IOException e) { + throw new SmtLibSolverInstallerException(e); + } + + logger.write(Logger.Level.MAINSTEP, "Download finished\n"); + } + + @Override + protected void uninstallSolver(final Path installDir, final String version) { } + + @Override + protected String[] getDefaultSolverArgs(String version) { + return new String[] { + "+stdin", + "+incremental", + "+quiet" + }; + } + + @Override + public SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { + final var solverFilePath = solverPath != null ? solverPath : installDir.resolve(getSolverBinaryName()); + return PrincessSmtLibSolverFactory.create(solverFilePath, solverArgs); + } + + @Override + public List getSupportedVersions() { + return Arrays.asList( + "2021-03-10", "2020-03-12", "2019-10-02", "2019-07-24", + "2018-10-26", "2018-05-25", "2018-01-27", "2017-12-06", "2017-07-17" + ); + } + + private String getSolverBinaryName() { + switch(OsHelper.getOs()) { + case WINDOWS: + return "princess.bat"; + case MAC: + case LINUX: + return "princess"; + default: + throw new AssertionError(); + } + } +} From 55edca87ebbee43e3628e8ede89ba1712e41d1c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 30 Mar 2021 18:50:53 +0200 Subject: [PATCH 79/99] Add boolector specific solver factory --- .../BoolectorSmtLibSolverFactory.java | 52 +++++++++++++++++++ .../BoolectorSmtLibSolverInstaller.java | 3 +- 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java new file mode 100644 index 0000000000..e86d5ae088 --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java @@ -0,0 +1,52 @@ +package hu.bme.mit.theta.solver.smtlib.impl.boolector; + +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.UCSolver; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; + +import java.nio.file.Path; + +public class BoolectorSmtLibSolverFactory implements SolverFactory { + private final Path solverPath; + private final String[] args; + + private BoolectorSmtLibSolverFactory(Path solverPath, String[] args) { + this.solverPath = solverPath; + this.args = args; + } + + public static BoolectorSmtLibSolverFactory create(Path solverPath, String[] args) { + return new BoolectorSmtLibSolverFactory(solverPath, args); + } + + @Override + public Solver createSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); + } + + @Override + public UCSolver createUCSolver() { + final var symbolTable = new GenericSmtLibSymbolTable(); + final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); + final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); + final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); + + return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); + } + + @Override + public ItpSolver createItpSolver() { + throw new UnsupportedOperationException("Boolector does not support interpolation"); + } +} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java index 52f14b0f47..cfc80e4808 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java @@ -3,7 +3,6 @@ import hu.bme.mit.theta.common.OsHelper; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverFactory; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import hu.bme.mit.theta.solver.smtlib.utils.Compress; @@ -74,7 +73,7 @@ protected String[] getDefaultSolverArgs(String version) { @Override public SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { final var solverFilePath = solverPath != null ? solverPath : installDir.resolve("build").resolve("bin").resolve(getSolverBinaryName()); - return GenericSmtLibSolverFactory.create(solverFilePath, solverArgs); + return BoolectorSmtLibSolverFactory.create(solverFilePath, solverArgs); } @Override From 7f0d689f646a7dd04423dfa7cdaad4a768ed9bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 30 Mar 2021 18:52:04 +0200 Subject: [PATCH 80/99] Remove solver specific interpolation patterns --- .../impl/mathsat/MathSATSmtLibItpPattern.java | 94 ------------------- .../impl/mathsat/MathSATSmtLibItpSolver.java | 8 +- .../princess/PrincessSmtLibItpPattern.java | 94 ------------------- .../princess/PrincessSmtLibItpSolver.java | 10 +- .../SMTInterpolSmtLibItpPattern.java | 94 ------------------- .../SMTInterpolSmtLibItpSolver.java | 8 +- .../smtlib/impl/z3/Z3SmtLibItpSolver.java | 8 +- .../interpolation/SmtLibItpPattern.java} | 24 ++--- 8 files changed, 32 insertions(+), 308 deletions(-) delete mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpPattern.java delete mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpPattern.java delete mode 100644 subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpPattern.java rename subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/{impl/z3/Z3SmtLibItpPattern.java => solver/interpolation/SmtLibItpPattern.java} (70%) diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpPattern.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpPattern.java deleted file mode 100644 index 84fa95ff03..0000000000 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpPattern.java +++ /dev/null @@ -1,94 +0,0 @@ -package hu.bme.mit.theta.solver.smtlib.impl.mathsat; - -import com.google.common.collect.Lists; -import hu.bme.mit.theta.solver.ItpMarker; -import hu.bme.mit.theta.solver.ItpMarkerTree; -import hu.bme.mit.theta.solver.ItpPattern; - -import java.util.ArrayList; -import java.util.List; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; - -public class MathSATSmtLibItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { - final ItpMarkerTree markerTree; - - MathSATSmtLibItpPattern(final ItpMarkerTree markerTree) { - this.markerTree = markerTree; - } - - @SuppressWarnings("unchecked") - static MathSATSmtLibItpPattern of(final ItpMarkerTree markerTree) { - final var list = new ArrayList>(); - list.add(markerTree); - while(!list.isEmpty()) { - final var node = list.get(0); - list.remove(0); - - checkArgument(node.getMarker() instanceof MathSATSmtLibItpMarker); - - list.addAll(node.getChildren()); - } - - return new MathSATSmtLibItpPattern((ItpMarkerTree) markerTree); - } - - @Override - public MathSATSmtLibItpMarker getA() { - checkState(isBinary()); - return markerTree.getChild(0).getMarker(); - } - - @Override - public MathSATSmtLibItpMarker getB() { - checkState(isBinary()); - return markerTree.getMarker(); - } - - @Override - public List getSequence() { - checkState(isSequence()); - final var markerList = new ArrayList(); - - var current = markerTree; - while(current.getChildrenNumber() > 0) { - markerList.add(current.getMarker()); - current = current.getChild(0); - } - markerList.add(current.getMarker()); - - return Lists.reverse(markerList); - } - - @Override - public ItpMarkerTree getRoot() { - return markerTree; - } - - @Override - public E visit(ItpPatternVisitor visitor) { - return visitor.visitTreePattern(this); - } - - private boolean isBinary() { - return - markerTree != null && - markerTree.getChildrenNumber() == 1 && - markerTree.getChild(0) != null && - markerTree.getChild(0).getChildrenNumber() == 0; - } - - private boolean isSequence() { - var current = markerTree; - while(current.getChildrenNumber() > 0) { - if(current.getChildrenNumber() > 1) { - return false; - } - else { - current = current.getChild(0); - } - } - return true; - } -} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpSolver.java index e80c01f1d7..d407919f31 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibItpSolver.java @@ -11,6 +11,7 @@ import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.smtlib.solver.SmtLibItpSolver; import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibInterpolant; +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibItpPattern; import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; @@ -49,7 +50,7 @@ public MathSATSmtLibItpSolver( @Override public ItpPattern createTreePattern(final ItpMarkerTree root) { checkNotNull(root); - return MathSATSmtLibItpPattern.of(root); + return SmtLibItpPattern.of(root); } @Override @@ -68,8 +69,9 @@ protected void add(final MathSATSmtLibItpMarker marker, final Expr ass @Override public Interpolant getInterpolant(final ItpPattern pattern) { checkState(getStatus() == SolverStatus.UNSAT, "Cannot get interpolant if status is not UNSAT."); - checkArgument(pattern instanceof MathSATSmtLibItpPattern); - final var mathsatItpPattern = (MathSATSmtLibItpPattern) pattern; + checkArgument(pattern instanceof SmtLibItpPattern); + @SuppressWarnings("unchecked") + final var mathsatItpPattern = (SmtLibItpPattern) pattern; final Map> itpMap = new HashMap<>(); buildItpMapFromTree(mathsatItpPattern.getRoot(), itpMap); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpPattern.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpPattern.java deleted file mode 100644 index 01a1a178d2..0000000000 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpPattern.java +++ /dev/null @@ -1,94 +0,0 @@ -package hu.bme.mit.theta.solver.smtlib.impl.princess; - -import com.google.common.collect.Lists; -import hu.bme.mit.theta.solver.ItpMarker; -import hu.bme.mit.theta.solver.ItpMarkerTree; -import hu.bme.mit.theta.solver.ItpPattern; - -import java.util.ArrayList; -import java.util.List; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; - -public class PrincessSmtLibItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { - final ItpMarkerTree markerTree; - - PrincessSmtLibItpPattern(final ItpMarkerTree markerTree) { - this.markerTree = markerTree; - } - - @SuppressWarnings("unchecked") - static PrincessSmtLibItpPattern of(final ItpMarkerTree markerTree) { - final var list = new ArrayList>(); - list.add(markerTree); - while(!list.isEmpty()) { - final var node = list.get(0); - list.remove(0); - - checkArgument(node.getMarker() instanceof PrincessSmtLibItpMarker); - - list.addAll(node.getChildren()); - } - - return new PrincessSmtLibItpPattern((ItpMarkerTree) markerTree); - } - - @Override - public PrincessSmtLibItpMarker getA() { - checkState(isBinary()); - return markerTree.getChild(0).getMarker(); - } - - @Override - public PrincessSmtLibItpMarker getB() { - checkState(isBinary()); - return markerTree.getMarker(); - } - - @Override - public List getSequence() { - checkState(isSequence()); - final var markerList = new ArrayList(); - - var current = markerTree; - while(current.getChildrenNumber() > 0) { - markerList.add(current.getMarker()); - current = current.getChild(0); - } - markerList.add(current.getMarker()); - - return Lists.reverse(markerList); - } - - @Override - public ItpMarkerTree getRoot() { - return markerTree; - } - - @Override - public E visit(ItpPatternVisitor visitor) { - return visitor.visitTreePattern(this); - } - - public boolean isBinary() { - return - markerTree != null && - markerTree.getChildrenNumber() == 1 && - markerTree.getChild(0) != null && - markerTree.getChild(0).getChildrenNumber() == 0; - } - - public boolean isSequence() { - var current = markerTree; - while(current.getChildrenNumber() > 0) { - if(current.getChildrenNumber() > 1) { - return false; - } - else { - current = current.getChild(0); - } - } - return true; - } -} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpSolver.java index cf22650e5b..bec80fa9ef 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibItpSolver.java @@ -11,12 +11,11 @@ import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; -import hu.bme.mit.theta.solver.smtlib.impl.smtinterpol.SMTInterpolSmtLibItpMarker; -import hu.bme.mit.theta.solver.smtlib.impl.smtinterpol.SMTInterpolSmtLibItpPattern; import hu.bme.mit.theta.solver.smtlib.solver.SmtLibItpSolver; import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibInterpolant; +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibItpPattern; import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; @@ -56,7 +55,7 @@ public PrincessSmtLibItpSolver( @Override public ItpPattern createTreePattern(final ItpMarkerTree root) { checkNotNull(root); - return PrincessSmtLibItpPattern.of(root); + return SmtLibItpPattern.of(root); } @Override @@ -78,8 +77,9 @@ protected void add(final PrincessSmtLibItpMarker marker, final Expr as @Override public Interpolant getInterpolant(final ItpPattern pattern) { checkState(getStatus() == SolverStatus.UNSAT, "Cannot get interpolant if status is not UNSAT."); - checkArgument(pattern instanceof PrincessSmtLibItpPattern); - final var princessItpPattern = (PrincessSmtLibItpPattern) pattern; + checkArgument(pattern instanceof SmtLibItpPattern); + @SuppressWarnings("unchecked") + final var princessItpPattern = (SmtLibItpPattern) pattern; final var term = patternToTerm(princessItpPattern.getRoot()); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpPattern.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpPattern.java deleted file mode 100644 index 5aeb443e6c..0000000000 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpPattern.java +++ /dev/null @@ -1,94 +0,0 @@ -package hu.bme.mit.theta.solver.smtlib.impl.smtinterpol; - -import com.google.common.collect.Lists; -import hu.bme.mit.theta.solver.ItpMarker; -import hu.bme.mit.theta.solver.ItpMarkerTree; -import hu.bme.mit.theta.solver.ItpPattern; - -import java.util.ArrayList; -import java.util.List; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; - -public class SMTInterpolSmtLibItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { - final ItpMarkerTree markerTree; - - SMTInterpolSmtLibItpPattern(final ItpMarkerTree markerTree) { - this.markerTree = markerTree; - } - - @SuppressWarnings("unchecked") - static SMTInterpolSmtLibItpPattern of(final ItpMarkerTree markerTree) { - final var list = new ArrayList>(); - list.add(markerTree); - while(!list.isEmpty()) { - final var node = list.get(0); - list.remove(0); - - checkArgument(node.getMarker() instanceof SMTInterpolSmtLibItpMarker); - - list.addAll(node.getChildren()); - } - - return new SMTInterpolSmtLibItpPattern((ItpMarkerTree) markerTree); - } - - @Override - public SMTInterpolSmtLibItpMarker getA() { - checkState(isBinary()); - return markerTree.getChild(0).getMarker(); - } - - @Override - public SMTInterpolSmtLibItpMarker getB() { - checkState(isBinary()); - return markerTree.getMarker(); - } - - @Override - public List getSequence() { - checkState(isSequence()); - final var markerList = new ArrayList(); - - var current = markerTree; - while(current.getChildrenNumber() > 0) { - markerList.add(current.getMarker()); - current = current.getChild(0); - } - markerList.add(current.getMarker()); - - return Lists.reverse(markerList); - } - - @Override - public ItpMarkerTree getRoot() { - return markerTree; - } - - @Override - public E visit(ItpPatternVisitor visitor) { - return visitor.visitTreePattern(this); - } - - private boolean isBinary() { - return - markerTree != null && - markerTree.getChildrenNumber() == 1 && - markerTree.getChild(0) != null && - markerTree.getChild(0).getChildrenNumber() == 0; - } - - private boolean isSequence() { - var current = markerTree; - while(current.getChildrenNumber() > 0) { - if(current.getChildrenNumber() > 1) { - return false; - } - else { - current = current.getChild(0); - } - } - return true; - } -} diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpSolver.java index 790095f709..b02fd7aec8 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibItpSolver.java @@ -15,6 +15,7 @@ import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibInterpolant; +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibItpPattern; import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; @@ -54,7 +55,7 @@ public SMTInterpolSmtLibItpSolver( @Override public ItpPattern createTreePattern(final ItpMarkerTree root) { checkNotNull(root); - return SMTInterpolSmtLibItpPattern.of(root); + return SmtLibItpPattern.of(root); } @Override @@ -76,8 +77,9 @@ protected void add(final SMTInterpolSmtLibItpMarker marker, final Expr @Override public Interpolant getInterpolant(final ItpPattern pattern) { checkState(getStatus() == SolverStatus.UNSAT, "Cannot get interpolant if status is not UNSAT."); - checkArgument(pattern instanceof SMTInterpolSmtLibItpPattern); - final var smtInterpolItpPattern = (SMTInterpolSmtLibItpPattern) pattern; + checkArgument(pattern instanceof SmtLibItpPattern); + @SuppressWarnings("unchecked") + final var smtInterpolItpPattern = (SmtLibItpPattern) pattern; final var term = patternToTerm(smtInterpolItpPattern.getRoot()); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpSolver.java index 0d15c0d1bf..ec74b25e0e 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpSolver.java @@ -12,6 +12,7 @@ import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.smtlib.solver.SmtLibItpSolver; import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibInterpolant; +import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibItpPattern; import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; @@ -53,7 +54,7 @@ public Z3SmtLibItpSolver( @Override public ItpPattern createTreePattern(final ItpMarkerTree root) { checkNotNull(root); - return Z3SmtLibItpPattern.of(root); + return SmtLibItpPattern.of(root); } @Override @@ -108,8 +109,9 @@ public void pop(int n) { @Override public Interpolant getInterpolant(final ItpPattern pattern) { checkState(getStatus() == SolverStatus.UNSAT, "Cannot get interpolant if status is not UNSAT."); - checkArgument(pattern instanceof Z3SmtLibItpPattern); - final var z3ItpPattern = (Z3SmtLibItpPattern) pattern; + checkArgument(pattern instanceof SmtLibItpPattern); + @SuppressWarnings("unchecked") + final var z3ItpPattern = (SmtLibItpPattern) pattern; final var term = patternToTerm(z3ItpPattern.getRoot()); final var markerCount = getMarkerCount(z3ItpPattern.getRoot()); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpPattern.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/interpolation/SmtLibItpPattern.java similarity index 70% rename from subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpPattern.java rename to subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/interpolation/SmtLibItpPattern.java index 6d91f326d5..07908bcd2f 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpPattern.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/interpolation/SmtLibItpPattern.java @@ -1,4 +1,4 @@ -package hu.bme.mit.theta.solver.smtlib.impl.z3; +package hu.bme.mit.theta.solver.smtlib.solver.interpolation; import com.google.common.collect.Lists; import hu.bme.mit.theta.solver.ItpMarker; @@ -11,45 +11,45 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; -public class Z3SmtLibItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { - final ItpMarkerTree markerTree; +public class SmtLibItpPattern implements ItpPattern.Binary, ItpPattern.Sequence, ItpPattern.Tree { + final ItpMarkerTree markerTree; - Z3SmtLibItpPattern(final ItpMarkerTree markerTree) { + SmtLibItpPattern(final ItpMarkerTree markerTree) { this.markerTree = markerTree; } @SuppressWarnings("unchecked") - static Z3SmtLibItpPattern of(final ItpMarkerTree markerTree) { + public static SmtLibItpPattern of(final ItpMarkerTree markerTree) { final var list = new ArrayList>(); list.add(markerTree); while(!list.isEmpty()) { final var node = list.get(0); list.remove(0); - checkArgument(node.getMarker() instanceof Z3SmtLibItpMarker); + checkArgument(node.getMarker() instanceof SmtLibItpMarker); list.addAll(node.getChildren()); } - return new Z3SmtLibItpPattern((ItpMarkerTree) markerTree); + return new SmtLibItpPattern<>((ItpMarkerTree) markerTree); } @Override - public Z3SmtLibItpMarker getA() { + public T getA() { checkState(isBinary()); return markerTree.getChild(0).getMarker(); } @Override - public Z3SmtLibItpMarker getB() { + public T getB() { checkState(isBinary()); return markerTree.getMarker(); } @Override - public List getSequence() { + public List getSequence() { checkState(isSequence()); - final var markerList = new ArrayList(); + final var markerList = new ArrayList(); var current = markerTree; while(current.getChildrenNumber() > 0) { @@ -62,7 +62,7 @@ public List getSequence() { } @Override - public ItpMarkerTree getRoot() { + public ItpMarkerTree getRoot() { return markerTree; } From 0928d017ed0472f0f0e3d69086af0b075efc1629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 30 Mar 2021 19:01:48 +0200 Subject: [PATCH 81/99] Refactor to remove code duplication --- .../BoolectorSmtLibSolverFactory.java | 37 ++----------------- .../impl/cvc4/CVC4SmtLibSolverFactory.java | 37 ++----------------- .../generic/GenericSmtLibSolverFactory.java | 8 ++-- .../mathsat/MathSATSmtLibSolverFactory.java | 32 ++-------------- .../princess/PrincessSmtLibSolverFactory.java | 33 ++--------------- .../yices2/Yices2SmtLibSolverFactory.java | 35 ++---------------- .../smtlib/impl/z3/Z3SmtLibSolverFactory.java | 32 ++-------------- 7 files changed, 22 insertions(+), 192 deletions(-) diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java index e86d5ae088..60cdb93007 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java @@ -1,50 +1,19 @@ package hu.bme.mit.theta.solver.smtlib.impl.boolector; import hu.bme.mit.theta.solver.ItpSolver; -import hu.bme.mit.theta.solver.Solver; -import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; -import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverFactory; import java.nio.file.Path; -public class BoolectorSmtLibSolverFactory implements SolverFactory { - private final Path solverPath; - private final String[] args; - +public class BoolectorSmtLibSolverFactory extends GenericSmtLibSolverFactory { private BoolectorSmtLibSolverFactory(Path solverPath, String[] args) { - this.solverPath = solverPath; - this.args = args; + super(solverPath, args); } public static BoolectorSmtLibSolverFactory create(Path solverPath, String[] args) { return new BoolectorSmtLibSolverFactory(solverPath, args); } - @Override - public Solver createSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); - } - - @Override - public UCSolver createUCSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); - } - @Override public ItpSolver createItpSolver() { throw new UnsupportedOperationException("Boolector does not support interpolation"); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverFactory.java index c7e7348e7f..c540d3653a 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverFactory.java @@ -1,50 +1,19 @@ package hu.bme.mit.theta.solver.smtlib.impl.cvc4; import hu.bme.mit.theta.solver.ItpSolver; -import hu.bme.mit.theta.solver.Solver; -import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverFactory; import java.nio.file.Path; -public class CVC4SmtLibSolverFactory implements SolverFactory { - private final Path solverPath; - private final String[] args; - +public class CVC4SmtLibSolverFactory extends GenericSmtLibSolverFactory { private CVC4SmtLibSolverFactory(Path solverPath, String[] args) { - this.solverPath = solverPath; - this.args = args; + super(solverPath, args); } public static CVC4SmtLibSolverFactory create(Path solverPath, String[] args) { return new CVC4SmtLibSolverFactory(solverPath, args); } - @Override - public Solver createSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); - } - - @Override - public UCSolver createUCSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); - } - @Override public ItpSolver createItpSolver() { throw new UnsupportedOperationException("CVC4 does not support interpolation"); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverFactory.java index a7ebd3b501..370ec3b1e2 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverFactory.java @@ -9,10 +9,10 @@ import java.nio.file.Path; public class GenericSmtLibSolverFactory implements SolverFactory { - private final Path solverPath; - private final String[] args; + protected final Path solverPath; + protected final String[] args; - private GenericSmtLibSolverFactory(Path solverPath, String[] args) { + protected GenericSmtLibSolverFactory(Path solverPath, String[] args) { this.solverPath = solverPath; this.args = args; } @@ -43,6 +43,6 @@ public UCSolver createUCSolver() { @Override public ItpSolver createItpSolver() { - throw new UnsupportedOperationException("GenericSmtLibSolver does not support interpolation"); + throw new UnsupportedOperationException("The generic driver does not support interpolation"); } } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverFactory.java index 218acbd5f7..91f4101bb1 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverFactory.java @@ -1,25 +1,19 @@ package hu.bme.mit.theta.solver.smtlib.impl.mathsat; import hu.bme.mit.theta.solver.ItpSolver; -import hu.bme.mit.theta.solver.Solver; -import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverFactory; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; import java.nio.file.Path; -public class MathSATSmtLibSolverFactory implements SolverFactory { - private final Path solverPath; - private final String[] args; +public class MathSATSmtLibSolverFactory extends GenericSmtLibSolverFactory { private final boolean itpSupported; private MathSATSmtLibSolverFactory(Path solverPath, String[] args, boolean itpSupported) { - this.solverPath = solverPath; - this.args = args; + super(solverPath, args); this.itpSupported = itpSupported; } @@ -27,26 +21,6 @@ public static MathSATSmtLibSolverFactory create(Path solverPath, String[] args, return new MathSATSmtLibSolverFactory(solverPath, args, itpSupported); } - @Override - public Solver createSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); - } - - @Override - public UCSolver createUCSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); - } - @Override public ItpSolver createItpSolver() { if(itpSupported) { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverFactory.java index aa470f1e22..5d61eb15c2 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverFactory.java @@ -1,50 +1,23 @@ package hu.bme.mit.theta.solver.smtlib.impl.princess; import hu.bme.mit.theta.solver.ItpSolver; -import hu.bme.mit.theta.solver.Solver; -import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverFactory; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; -import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; import java.nio.file.Path; -public class PrincessSmtLibSolverFactory implements SolverFactory { - private final Path solverPath; - private final String[] args; - +public class PrincessSmtLibSolverFactory extends GenericSmtLibSolverFactory { private PrincessSmtLibSolverFactory(Path solverPath, String[] args) { - this.solverPath = solverPath; - this.args = args; + super(solverPath, args); } public static PrincessSmtLibSolverFactory create(Path solverPath, String[] args) { return new PrincessSmtLibSolverFactory(solverPath, args); } - @Override - public Solver createSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); - } - - @Override - public UCSolver createUCSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); - } - @Override public ItpSolver createItpSolver() { final var symbolTable = new GenericSmtLibSymbolTable(); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverFactory.java index 79c1dfb17f..b2c1712ecb 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/yices2/Yices2SmtLibSolverFactory.java @@ -1,49 +1,20 @@ package hu.bme.mit.theta.solver.smtlib.impl.yices2; import hu.bme.mit.theta.solver.ItpSolver; -import hu.bme.mit.theta.solver.Solver; -import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; -import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverFactory; import java.nio.file.Path; -public class Yices2SmtLibSolverFactory implements SolverFactory { - private final Path solverPath; - private final String[] args; +public class Yices2SmtLibSolverFactory extends GenericSmtLibSolverFactory { private Yices2SmtLibSolverFactory(Path solverPath, String[] args) { - this.solverPath = solverPath; - this.args = args; + super(solverPath, args); } public static Yices2SmtLibSolverFactory create(Path solverPath, String[] args) { return new Yices2SmtLibSolverFactory(solverPath, args); } - @Override - public Solver createSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new Yices2SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); - } - - @Override - public UCSolver createUCSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new Yices2SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); - } - @Override public ItpSolver createItpSolver() { throw new UnsupportedOperationException("Yices2 does not support interpolation"); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverFactory.java index e15012671f..ec580ed951 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverFactory.java @@ -1,25 +1,19 @@ package hu.bme.mit.theta.solver.smtlib.impl.z3; import hu.bme.mit.theta.solver.ItpSolver; -import hu.bme.mit.theta.solver.Solver; -import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.UCSolver; -import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolver; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverFactory; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSymbolTable; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTermTransformer; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibTransformationManager; import java.nio.file.Path; -public class Z3SmtLibSolverFactory implements SolverFactory { - private final Path solverPath; - private final String[] args; +public class Z3SmtLibSolverFactory extends GenericSmtLibSolverFactory { private final boolean itpSupported; private Z3SmtLibSolverFactory(Path solverPath, String[] args, boolean itpSupported) { - this.solverPath = solverPath; - this.args = args; + super(solverPath, args); this.itpSupported = itpSupported; } @@ -27,26 +21,6 @@ public static Z3SmtLibSolverFactory create(Path solverPath, String[] args, boole return new Z3SmtLibSolverFactory(solverPath, args, itpSupported); } - @Override - public Solver createSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, false); - } - - @Override - public UCSolver createUCSolver() { - final var symbolTable = new GenericSmtLibSymbolTable(); - final var transformationManager = new GenericSmtLibTransformationManager(symbolTable); - final var termTransformer = new GenericSmtLibTermTransformer(symbolTable); - final var solverBinary = new GenericSmtLibSolverBinary(solverPath, args); - - return new SmtLibSolver(symbolTable, transformationManager, termTransformer, solverBinary, true); - } - @Override public ItpSolver createItpSolver() { if(itpSupported) { From ab32da3203f2b7950a7355f07afd9bedc84ab993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 30 Mar 2021 22:35:26 +0200 Subject: [PATCH 82/99] Add solver parameter to cfa-cli --- .../cfa/analysis/config/CfaConfigBuilder.java | 165 ++++++++------- .../impact/CfaPredImpactCheckerTest.java | 10 +- .../java/hu/bme/mit/theta/cfa/cli/CfaCli.java | 53 ++++- .../analysis/config/XstsConfigBuilder.java | 195 +++++++++++------- 4 files changed, 268 insertions(+), 155 deletions(-) diff --git a/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/config/CfaConfigBuilder.java b/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/config/CfaConfigBuilder.java index 08ead09daf..7a3d402a47 100644 --- a/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/config/CfaConfigBuilder.java +++ b/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/config/CfaConfigBuilder.java @@ -15,8 +15,6 @@ */ package hu.bme.mit.theta.cfa.analysis.config; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; - import hu.bme.mit.theta.analysis.Action; import hu.bme.mit.theta.analysis.Analysis; import hu.bme.mit.theta.analysis.Prec; @@ -36,7 +34,20 @@ import hu.bme.mit.theta.analysis.expl.ItpRefToExplPrec; import hu.bme.mit.theta.analysis.expl.VarsRefToExplPrec; import hu.bme.mit.theta.analysis.expr.ExprState; -import hu.bme.mit.theta.analysis.expr.refinement.*; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceBwBinItpChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceFwBinItpChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceNewtonChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceSeqItpChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceUCBChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceUnsatCoreChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ItpRefutation; +import hu.bme.mit.theta.analysis.expr.refinement.MultiExprTraceRefiner; +import hu.bme.mit.theta.analysis.expr.refinement.PrecRefiner; +import hu.bme.mit.theta.analysis.expr.refinement.PruneStrategy; +import hu.bme.mit.theta.analysis.expr.refinement.Refutation; +import hu.bme.mit.theta.analysis.expr.refinement.RefutationToPrec; +import hu.bme.mit.theta.analysis.expr.refinement.SingleExprTraceRefiner; import hu.bme.mit.theta.analysis.pred.ExprSplitters; import hu.bme.mit.theta.analysis.pred.ExprSplitters.ExprSplitter; import hu.bme.mit.theta.analysis.pred.ItpRefToPredPrec; @@ -47,7 +58,12 @@ import hu.bme.mit.theta.analysis.pred.PredState; import hu.bme.mit.theta.analysis.waitlist.PriorityWaitlist; import hu.bme.mit.theta.cfa.CFA; -import hu.bme.mit.theta.cfa.analysis.*; +import hu.bme.mit.theta.cfa.analysis.CfaAction; +import hu.bme.mit.theta.cfa.analysis.CfaAnalysis; +import hu.bme.mit.theta.cfa.analysis.CfaInitPrecs; +import hu.bme.mit.theta.cfa.analysis.CfaPrec; +import hu.bme.mit.theta.cfa.analysis.CfaState; +import hu.bme.mit.theta.cfa.analysis.DistToErrComparator; import hu.bme.mit.theta.cfa.analysis.lts.CfaCachedLts; import hu.bme.mit.theta.cfa.analysis.lts.CfaLbeLts; import hu.bme.mit.theta.cfa.analysis.lts.CfaLts; @@ -58,9 +74,11 @@ import hu.bme.mit.theta.cfa.analysis.prec.LocalCfaPrecRefiner; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.common.logging.NullLogger; -import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverFactory; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; + public class CfaConfigBuilder { public enum Domain { EXPL, PRED_BOOL, PRED_CART, PRED_SPLIT @@ -120,7 +138,7 @@ public

CfaPrec

createPrec(final P innerPrec) { @Override public PrecRefiner, A, CfaPrec

, R> createRefiner( - final RefutationToPrec refToPrec) { + final RefutationToPrec refToPrec) { return GlobalCfaPrecRefiner.create(refToPrec); } }, @@ -133,7 +151,7 @@ public

CfaPrec

createPrec(final P innerPrec) { @Override public PrecRefiner, A, CfaPrec

, R> createRefiner( - final RefutationToPrec refToPrec) { + final RefutationToPrec refToPrec) { return LocalCfaPrecRefiner.create(refToPrec); } }; @@ -141,7 +159,7 @@ public CfaPrec

createPrec(P innerPrec); public abstract PrecRefiner, A, CfaPrec

, R> createRefiner( - RefutationToPrec refToPrec); + RefutationToPrec refToPrec); } public enum Encoding { @@ -167,7 +185,8 @@ public enum InitPrec { } private Logger logger = NullLogger.getInstance(); - private final SolverFactory solverFactory; + private final SolverFactory abstractionSolverFactory; + private final SolverFactory refinementSolverFactory; private final Domain domain; private final Refinement refinement; private Search search = Search.BFS; @@ -181,7 +200,15 @@ public enum InitPrec { public CfaConfigBuilder(final Domain domain, final Refinement refinement, final SolverFactory solverFactory) { this.domain = domain; this.refinement = refinement; - this.solverFactory = solverFactory; + this.abstractionSolverFactory = solverFactory; + this.refinementSolverFactory = solverFactory; + } + + public CfaConfigBuilder(final Domain domain, final Refinement refinement, final SolverFactory abstractionSolverFactory, final SolverFactory refinementSolverFactory) { + this.domain = domain; + this.refinement = refinement; + this.abstractionSolverFactory = abstractionSolverFactory; + this.refinementSolverFactory = refinementSolverFactory; } public CfaConfigBuilder logger(final Logger logger) { @@ -225,50 +252,49 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { } public CfaConfig build(final CFA cfa, final CFA.Loc errLoc) { - final ItpSolver solver = solverFactory.createItpSolver(); final CfaLts lts = encoding.getLts(errLoc); if (domain == Domain.EXPL) { final Analysis, CfaAction, CfaPrec> analysis = CfaAnalysis - .create(cfa.getInitLoc(), ExplStmtAnalysis.create(solver, True(), maxEnum)); + .create(cfa.getInitLoc(), ExplStmtAnalysis.create(abstractionSolverFactory.createSolver(), True(), maxEnum)); final ArgBuilder, CfaAction, CfaPrec> argBuilder = ArgBuilder.create(lts, - analysis, s -> s.getLoc().equals(errLoc), true); + analysis, s -> s.getLoc().equals(errLoc), true); final Abstractor, CfaAction, CfaPrec> abstractor = BasicAbstractor - .builder(argBuilder).projection(CfaState::getLoc) - .waitlist(PriorityWaitlist.create(search.getComp(cfa, errLoc))) - .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() - : StopCriterions.firstCex()).logger(logger).build(); + .builder(argBuilder).projection(CfaState::getLoc) + .waitlist(PriorityWaitlist.create(search.getComp(cfa, errLoc))) + .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() + : StopCriterions.firstCex()).logger(logger).build(); Refiner, CfaAction, CfaPrec> refiner; switch (refinement) { case FW_BIN_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceFwBinItpChecker.create(True(), True(), solver), - precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceFwBinItpChecker.create(True(), True(), refinementSolverFactory.createItpSolver()), + precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger); break; case BW_BIN_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceBwBinItpChecker.create(True(), True(), solver), - precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceBwBinItpChecker.create(True(), True(), refinementSolverFactory.createItpSolver()), + precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger); break; case SEQ_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceSeqItpChecker.create(True(), True(), solver), - precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceSeqItpChecker.create(True(), True(), refinementSolverFactory.createItpSolver()), + precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger); break; case MULTI_SEQ: - refiner = MultiExprTraceRefiner.create(ExprTraceSeqItpChecker.create(True(), True(), solver), - precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = MultiExprTraceRefiner.create(ExprTraceSeqItpChecker.create(True(), True(), refinementSolverFactory.createItpSolver()), + precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger); break; case UNSAT_CORE: - refiner = SingleExprTraceRefiner.create(ExprTraceUnsatCoreChecker.create(True(), True(), solver), - precGranularity.createRefiner(new VarsRefToExplPrec()), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceUnsatCoreChecker.create(True(), True(), refinementSolverFactory.createUCSolver()), + precGranularity.createRefiner(new VarsRefToExplPrec()), pruneStrategy, logger); break; case UCB: - refiner = SingleExprTraceRefiner.create(ExprTraceUCBChecker.create(True(), True(), solver), - precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceUCBChecker.create(True(), True(), refinementSolverFactory.createUCSolver()), + precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger); break; case NWT_SP: refiner = SingleExprTraceRefiner.create( - ExprTraceNewtonChecker.create(True(), True(), solver).withoutIT().withSP().withoutLV(), + ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withoutIT().withSP().withoutLV(), precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger @@ -276,7 +302,7 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { break; case NWT_WP: refiner = SingleExprTraceRefiner.create( - ExprTraceNewtonChecker.create(True(), True(), solver).withoutIT().withWP().withoutLV(), + ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withoutIT().withWP().withoutLV(), precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger @@ -284,7 +310,7 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { break; case NWT_SP_LV: refiner = SingleExprTraceRefiner.create( - ExprTraceNewtonChecker.create(True(), True(), solver).withoutIT().withSP().withLV(), + ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withoutIT().withSP().withLV(), precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger @@ -292,7 +318,7 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { break; case NWT_WP_LV: refiner = SingleExprTraceRefiner.create( - ExprTraceNewtonChecker.create(True(), True(), solver).withoutIT().withWP().withLV(), + ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withoutIT().withWP().withLV(), precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger @@ -300,7 +326,7 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { break; case NWT_IT_SP: refiner = SingleExprTraceRefiner.create( - ExprTraceNewtonChecker.create(True(), True(), solver).withIT().withSP().withoutLV(), + ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withIT().withSP().withoutLV(), precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger @@ -308,7 +334,7 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { break; case NWT_IT_WP: refiner = SingleExprTraceRefiner.create( - ExprTraceNewtonChecker.create(True(), True(), solver).withIT().withWP().withoutLV(), + ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withIT().withWP().withoutLV(), precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger @@ -316,7 +342,7 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { break; case NWT_IT_SP_LV: refiner = SingleExprTraceRefiner.create( - ExprTraceNewtonChecker.create(True(), True(), solver).withIT().withSP().withLV(), + ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withIT().withSP().withLV(), precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger @@ -324,7 +350,7 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { break; case NWT_IT_WP_LV: refiner = SingleExprTraceRefiner.create( - ExprTraceNewtonChecker.create(True(), True(), solver).withIT().withWP().withLV(), + ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withIT().withWP().withLV(), precGranularity.createRefiner(new ItpRefToExplPrec()), pruneStrategy, logger @@ -332,11 +358,11 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { break; default: throw new UnsupportedOperationException( - domain + " domain does not support " + refinement + " refinement."); + domain + " domain does not support " + refinement + " refinement."); } final SafetyChecker, CfaAction, CfaPrec> checker = CegarChecker - .create(abstractor, refiner, logger); + .create(abstractor, refiner, logger); CfaPrec prec; @@ -349,94 +375,95 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { break; default: throw new UnsupportedOperationException(initPrec + " initial precision is not supported with " + - domain + " domain"); + domain + " domain"); } return CfaConfig.create(checker, prec); } else if (domain == Domain.PRED_BOOL || domain == Domain.PRED_CART || domain == Domain.PRED_SPLIT) { + final Solver analysisSolver = abstractionSolverFactory.createSolver(); PredAbstractor predAbstractor; switch (domain) { case PRED_BOOL: - predAbstractor = PredAbstractors.booleanAbstractor(solver); + predAbstractor = PredAbstractors.booleanAbstractor(analysisSolver); break; case PRED_SPLIT: - predAbstractor = PredAbstractors.booleanSplitAbstractor(solver); + predAbstractor = PredAbstractors.booleanSplitAbstractor(analysisSolver); break; case PRED_CART: - predAbstractor = PredAbstractors.cartesianAbstractor(solver); + predAbstractor = PredAbstractors.cartesianAbstractor(analysisSolver); break; default: throw new UnsupportedOperationException(domain + " domain is not supported."); } final Analysis, CfaAction, CfaPrec> analysis = CfaAnalysis - .create(cfa.getInitLoc(), PredAnalysis.create(solver, predAbstractor, True())); + .create(cfa.getInitLoc(), PredAnalysis.create(analysisSolver, predAbstractor, True())); final ArgBuilder, CfaAction, CfaPrec> argBuilder = ArgBuilder.create(lts, - analysis, s -> s.getLoc().equals(errLoc), true); + analysis, s -> s.getLoc().equals(errLoc), true); final Abstractor, CfaAction, CfaPrec> abstractor = BasicAbstractor - .builder(argBuilder).projection(CfaState::getLoc) - .waitlist(PriorityWaitlist.create(search.getComp(cfa, errLoc))) - .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() - : StopCriterions.firstCex()).logger(logger).build(); + .builder(argBuilder).projection(CfaState::getLoc) + .waitlist(PriorityWaitlist.create(search.getComp(cfa, errLoc))) + .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() + : StopCriterions.firstCex()).logger(logger).build(); ExprTraceChecker exprTraceChecker; switch (refinement) { case FW_BIN_ITP: - exprTraceChecker = ExprTraceFwBinItpChecker.create(True(), True(), solver); + exprTraceChecker = ExprTraceFwBinItpChecker.create(True(), True(), refinementSolverFactory.createItpSolver()); break; case BW_BIN_ITP: - exprTraceChecker = ExprTraceBwBinItpChecker.create(True(), True(), solver); + exprTraceChecker = ExprTraceBwBinItpChecker.create(True(), True(), refinementSolverFactory.createItpSolver()); break; case SEQ_ITP: - exprTraceChecker = ExprTraceSeqItpChecker.create(True(), True(), solver); + exprTraceChecker = ExprTraceSeqItpChecker.create(True(), True(), refinementSolverFactory.createItpSolver()); break; case MULTI_SEQ: - exprTraceChecker = ExprTraceSeqItpChecker.create(True(), True(), solver); + exprTraceChecker = ExprTraceSeqItpChecker.create(True(), True(), refinementSolverFactory.createItpSolver()); break; case UCB: - exprTraceChecker = ExprTraceUCBChecker.create(True(), True(), solver); + exprTraceChecker = ExprTraceUCBChecker.create(True(), True(), refinementSolverFactory.createUCSolver()); break; case NWT_SP: - exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), solver).withoutIT().withSP().withoutLV(); + exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withoutIT().withSP().withoutLV(); break; case NWT_WP: - exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), solver).withoutIT().withWP().withoutLV(); + exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withoutIT().withWP().withoutLV(); break; case NWT_SP_LV: - exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), solver).withoutIT().withSP().withLV(); + exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withoutIT().withSP().withLV(); break; case NWT_WP_LV: - exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), solver).withoutIT().withWP().withLV(); + exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withoutIT().withWP().withLV(); break; case NWT_IT_SP: - exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), solver).withIT().withSP().withoutLV(); + exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withIT().withSP().withoutLV(); break; case NWT_IT_WP: - exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), solver).withIT().withWP().withoutLV(); + exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withIT().withWP().withoutLV(); break; case NWT_IT_SP_LV: - exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), solver).withIT().withSP().withLV(); + exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withIT().withSP().withLV(); break; case NWT_IT_WP_LV: - exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), solver).withIT().withWP().withLV(); + exprTraceChecker = ExprTraceNewtonChecker.create(True(), True(), refinementSolverFactory.createUCSolver()).withIT().withWP().withLV(); break; default: throw new UnsupportedOperationException( - domain + " domain does not support " + refinement + " refinement."); + domain + " domain does not support " + refinement + " refinement."); } final ItpRefToPredPrec refToPrec = new ItpRefToPredPrec(predSplit.splitter); Refiner, CfaAction, CfaPrec> refiner; if (refinement == Refinement.MULTI_SEQ) { refiner = MultiExprTraceRefiner.create(exprTraceChecker, - precGranularity.createRefiner(refToPrec), pruneStrategy, logger); + precGranularity.createRefiner(refToPrec), pruneStrategy, logger); } else { refiner = SingleExprTraceRefiner.create(exprTraceChecker, - precGranularity.createRefiner(refToPrec), pruneStrategy, logger); + precGranularity.createRefiner(refToPrec), pruneStrategy, logger); } final SafetyChecker, CfaAction, CfaPrec> checker = CegarChecker - .create(abstractor, refiner, logger); + .create(abstractor, refiner, logger); CfaPrec prec; @@ -454,12 +481,12 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { break; default: throw new UnsupportedOperationException(precGranularity + - " precision granularity is not supported with " + domain + " domain"); + " precision granularity is not supported with " + domain + " domain"); } break; default: throw new UnsupportedOperationException(initPrec + " initial precision is not supported with " + - domain + " domain"); + domain + " domain"); } return CfaConfig.create(checker, prec); @@ -468,4 +495,4 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { throw new UnsupportedOperationException(domain + " domain is not supported."); } } -} +} \ No newline at end of file diff --git a/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/impact/CfaPredImpactCheckerTest.java b/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/impact/CfaPredImpactCheckerTest.java index 6bf6f0275e..3ff359bc93 100644 --- a/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/impact/CfaPredImpactCheckerTest.java +++ b/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/impact/CfaPredImpactCheckerTest.java @@ -21,6 +21,7 @@ import java.io.FileNotFoundException; import java.io.IOException; +import hu.bme.mit.theta.solver.Solver; import org.junit.Test; import hu.bme.mit.theta.analysis.algorithm.ARG; @@ -44,10 +45,11 @@ public void test() throws FileNotFoundException, IOException { // Arrange final CFA cfa = CfaDslManager.createCfa(new FileInputStream("src/test/resources/counter5_true.cfa")); - final ItpSolver solver = Z3SolverFactory.getInstance().createItpSolver(); + final Solver abstractionSolver = Z3SolverFactory.getInstance().createSolver(); + final ItpSolver refinementSolver = Z3SolverFactory.getInstance().createItpSolver(); final PredImpactChecker checker = PredImpactChecker.create(CfaLbeLts.of(cfa.getErrorLoc().get()), cfa.getInitLoc(), - l -> l.equals(cfa.getErrorLoc().get()), solver); + l -> l.equals(cfa.getErrorLoc().get()), abstractionSolver, refinementSolver); // Act final SafetyResult status = checker.check(UnitPrec.getInstance()); @@ -58,9 +60,9 @@ public void test() throws FileNotFoundException, IOException { final ARG arg = status.getArg(); arg.minimize(); - final ArgChecker argChecker = ArgChecker.create(solver); + final ArgChecker argChecker = ArgChecker.create(abstractionSolver); assertTrue(argChecker.isWellLabeled(arg)); System.out.println(GraphvizWriter.getInstance().writeString(ArgVisualizer.getDefault().visualize(arg))); } -} +} \ No newline at end of file diff --git a/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java b/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java index 8e1bc8e738..cd3c64978e 100644 --- a/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java +++ b/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java @@ -21,6 +21,7 @@ import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; +import java.nio.file.Path; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; @@ -59,6 +60,8 @@ import hu.bme.mit.theta.common.table.TableWriter; import hu.bme.mit.theta.common.visualization.Graph; import hu.bme.mit.theta.common.visualization.writer.GraphvizWriter; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverManager; import hu.bme.mit.theta.solver.z3.Z3SolverFactory; import static com.google.common.base.Preconditions.checkNotNull; @@ -83,6 +86,18 @@ public class CfaCli { @Parameter(names = "--predsplit", description = "Predicate splitting (for predicate abstraction)") PredSplit predSplit = PredSplit.WHOLE; + @Parameter(names = "--solver", description = "Sets the underlying SMT solver to use for both the abstraction and the refinement process. Enter in format :, see theta-smtlib-cli.jar for more details. Enter \"Z3\" to use the legacy z3 solver.") + String solver = "Z3"; + + @Parameter(names = "--abstraction-solver", description = "Sets the underlying SMT solver to use for the abstraction process. Enter in format :, see theta-smtlib-cli.jar for more details. Enter \"Z3\" to use the legacy z3 solver.") + String abstractionSolver; + + @Parameter(names = "--refinement-solver", description = "Sets the underlying SMT solver to use for the refinement process. Enter in format :, see theta-smtlib-cli.jar for more details. Enter \"Z3\" to use the legacy z3 solver.") + String refinementSolver; + + @Parameter(names = "--home", description = "The path of the solver registry") + String home = Path.of(System.getProperty("user.home"), ".theta").toAbsolutePath().toString(); + @Parameter(names = "--model", description = "Path of the input CFA model", required = true) String model; @@ -162,6 +177,9 @@ private void run() { } try { + final var homePath = Path.of(home); + final var smtLibSolverManager = SmtLibSolverManager.create(homePath, logger); + final Stopwatch sw = Stopwatch.createStarted(); final CFA cfa = loadModel(); @@ -189,9 +207,36 @@ private void run() { } checkNotNull(errLoc, "Location '" + errorLoc + "' not found in CFA"); } - checkNotNull(errLoc, "Error location must be specified in CFA or as argument"); - final CfaConfig configuration = buildConfiguration(cfa, errLoc); + + final SolverFactory abstractionSolverFactory; + if(abstractionSolver != null && !abstractionSolver.equals("Z3")) { + final var s = abstractionSolver.split("\\."); + abstractionSolverFactory = smtLibSolverManager.getSolverFactory(s[0], s[1]); + } + else if(!solver.equals("Z3")) { + final var s = solver.split("\\."); + abstractionSolverFactory = smtLibSolverManager.getSolverFactory(s[0], s[1]); + } + else { + abstractionSolverFactory = Z3SolverFactory.getInstance(); + } + + + final SolverFactory refinementSolverFactory; + if(refinementSolver != null && !refinementSolver.equals("Z3")) { + final var s = refinementSolver.split("\\."); + refinementSolverFactory = smtLibSolverManager.getSolverFactory(s[0], s[1]); + } + else if(!solver.equals("Z3")) { + final var s = solver.split("\\."); + refinementSolverFactory = smtLibSolverManager.getSolverFactory(s[0], s[1]); + } + else { + refinementSolverFactory = Z3SolverFactory.getInstance(); + } + + final CfaConfig configuration = buildConfiguration(cfa, errLoc, abstractionSolverFactory, refinementSolverFactory); final SafetyResult status = check(configuration); sw.stop(); printResult(status, sw.elapsed(TimeUnit.MILLISECONDS)); @@ -220,9 +265,9 @@ private CFA loadModel() throws Exception { } } - private CfaConfig buildConfiguration(final CFA cfa, final CFA.Loc errLoc) throws Exception { + private CfaConfig buildConfiguration(final CFA cfa, final CFA.Loc errLoc, final SolverFactory abstractionSolverFactory, final SolverFactory refinementSolverFactory) throws Exception { try { - return new CfaConfigBuilder(domain, refinement, Z3SolverFactory.getInstance()) + return new CfaConfigBuilder(domain, refinement, abstractionSolverFactory, refinementSolverFactory) .precGranularity(precGranularity).search(search) .predSplit(predSplit).encoding(encoding).maxEnum(maxEnum).initPrec(initPrec) .pruneStrategy(pruneStrategy).logger(logger).build(cfa, errLoc); diff --git a/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/config/XstsConfigBuilder.java b/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/config/XstsConfigBuilder.java index 2091f97ed6..8bea2a8fa6 100644 --- a/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/config/XstsConfigBuilder.java +++ b/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/config/XstsConfigBuilder.java @@ -1,6 +1,10 @@ package hu.bme.mit.theta.xsts.analysis.config; -import hu.bme.mit.theta.analysis.*; +import hu.bme.mit.theta.analysis.Action; +import hu.bme.mit.theta.analysis.Analysis; +import hu.bme.mit.theta.analysis.LTS; +import hu.bme.mit.theta.analysis.Prec; +import hu.bme.mit.theta.analysis.State; import hu.bme.mit.theta.analysis.algorithm.ArgBuilder; import hu.bme.mit.theta.analysis.algorithm.ArgNodeComparators; import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; @@ -9,10 +13,33 @@ import hu.bme.mit.theta.analysis.algorithm.cegar.CegarChecker; import hu.bme.mit.theta.analysis.algorithm.cegar.Refiner; import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterions; -import hu.bme.mit.theta.analysis.expl.*; +import hu.bme.mit.theta.analysis.expl.ExplAnalysis; +import hu.bme.mit.theta.analysis.expl.ExplPrec; +import hu.bme.mit.theta.analysis.expl.ExplState; +import hu.bme.mit.theta.analysis.expl.ExplStatePredicate; +import hu.bme.mit.theta.analysis.expl.ExplStmtAnalysis; +import hu.bme.mit.theta.analysis.expl.ExplStmtOptimizer; +import hu.bme.mit.theta.analysis.expl.ItpRefToExplPrec; +import hu.bme.mit.theta.analysis.expl.VarsRefToExplPrec; import hu.bme.mit.theta.analysis.expr.ExprStatePredicate; -import hu.bme.mit.theta.analysis.expr.refinement.*; -import hu.bme.mit.theta.analysis.pred.*; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceBwBinItpChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceFwBinItpChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceSeqItpChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceUnsatCoreChecker; +import hu.bme.mit.theta.analysis.expr.refinement.ItpRefutation; +import hu.bme.mit.theta.analysis.expr.refinement.JoiningPrecRefiner; +import hu.bme.mit.theta.analysis.expr.refinement.MultiExprTraceRefiner; +import hu.bme.mit.theta.analysis.expr.refinement.PruneStrategy; +import hu.bme.mit.theta.analysis.expr.refinement.RefutationToPrec; +import hu.bme.mit.theta.analysis.expr.refinement.SingleExprTraceRefiner; +import hu.bme.mit.theta.analysis.pred.ExprSplitters; +import hu.bme.mit.theta.analysis.pred.ItpRefToPredPrec; +import hu.bme.mit.theta.analysis.pred.PredAbstractors; +import hu.bme.mit.theta.analysis.pred.PredAnalysis; +import hu.bme.mit.theta.analysis.pred.PredPrec; +import hu.bme.mit.theta.analysis.pred.PredState; +import hu.bme.mit.theta.analysis.pred.PredStmtOptimizer; import hu.bme.mit.theta.analysis.prod2.Prod2Analysis; import hu.bme.mit.theta.analysis.prod2.Prod2Prec; import hu.bme.mit.theta.analysis.prod2.Prod2State; @@ -24,12 +51,24 @@ import hu.bme.mit.theta.core.decl.VarDecl; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.booltype.BoolType; -import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.xsts.XSTS; -import hu.bme.mit.theta.xsts.analysis.*; -import hu.bme.mit.theta.xsts.analysis.autoexpl.*; -import hu.bme.mit.theta.xsts.analysis.initprec.*; +import hu.bme.mit.theta.xsts.analysis.XstsAction; +import hu.bme.mit.theta.xsts.analysis.XstsAnalysis; +import hu.bme.mit.theta.xsts.analysis.XstsLts; +import hu.bme.mit.theta.xsts.analysis.XstsState; +import hu.bme.mit.theta.xsts.analysis.XstsStatePredicate; +import hu.bme.mit.theta.xsts.analysis.XstsStmtOptimizer; +import hu.bme.mit.theta.xsts.analysis.autoexpl.XstsAutoExpl; +import hu.bme.mit.theta.xsts.analysis.autoexpl.XstsNewAtomsAutoExpl; +import hu.bme.mit.theta.xsts.analysis.autoexpl.XstsNewOperandsAutoExpl; +import hu.bme.mit.theta.xsts.analysis.autoexpl.XstsStaticAutoExpl; +import hu.bme.mit.theta.xsts.analysis.initprec.XstsAllVarsInitPrec; +import hu.bme.mit.theta.xsts.analysis.initprec.XstsCtrlInitPrec; +import hu.bme.mit.theta.xsts.analysis.initprec.XstsEmptyInitPrec; +import hu.bme.mit.theta.xsts.analysis.initprec.XstsInitPrec; +import hu.bme.mit.theta.xsts.analysis.initprec.XstsPropInitPrec; import java.util.Set; import java.util.function.Predicate; @@ -165,56 +204,56 @@ public XstsConfigBuilder autoExpl(final AutoExpl autoExpl) { } public XstsConfig build(final XSTS xsts) { - final ItpSolver solver = solverFactory.createItpSolver(); + final Solver abstractionSolver = solverFactory.createSolver(); final Expr negProp = Not(xsts.getProp()); if (domain == Domain.EXPL) { final LTS, XstsAction> lts; if(optimizeStmts == OptimizeStmts.ON){ - lts = XstsLts.create(xsts,XstsStmtOptimizer.create(ExplStmtOptimizer.getInstance())); + lts = XstsLts.create(xsts, XstsStmtOptimizer.create(ExplStmtOptimizer.getInstance())); } else { lts = XstsLts.create(xsts, XstsStmtOptimizer.create(DefaultStmtOptimizer.create())); } - final Predicate> target = new XstsStatePredicate(new ExplStatePredicate(negProp, solver)); - final Analysis, XstsAction, ExplPrec> analysis = XstsAnalysis.create(ExplStmtAnalysis.create(solver, xsts.getInitFormula(), maxEnum)); + final Predicate> target = new XstsStatePredicate(new ExplStatePredicate(negProp, abstractionSolver)); + final Analysis, XstsAction, ExplPrec> analysis = XstsAnalysis.create(ExplStmtAnalysis.create(abstractionSolver, xsts.getInitFormula(), maxEnum)); final ArgBuilder, XstsAction, ExplPrec> argBuilder = ArgBuilder.create(lts, analysis, target, - true); + true); final Abstractor, XstsAction, ExplPrec> abstractor = BasicAbstractor.builder(argBuilder) - .waitlist(PriorityWaitlist.create(search.comparator)) - .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() - : StopCriterions.firstCex()) - .logger(logger).build(); + .waitlist(PriorityWaitlist.create(search.comparator)) + .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() + : StopCriterions.firstCex()) + .logger(logger).build(); Refiner, XstsAction, ExplPrec> refiner = null; switch (refinement) { case FW_BIN_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceFwBinItpChecker.create(xsts.getInitFormula(), negProp, solver), - JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceFwBinItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); break; case BW_BIN_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceBwBinItpChecker.create(xsts.getInitFormula(), negProp, solver), - JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceBwBinItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); break; case SEQ_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solver), - JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); break; case MULTI_SEQ: - refiner = MultiExprTraceRefiner.create(ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solver), - JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = MultiExprTraceRefiner.create(ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); break; case UNSAT_CORE: - refiner = SingleExprTraceRefiner.create(ExprTraceUnsatCoreChecker.create(xsts.getInitFormula(), negProp, solver), - JoiningPrecRefiner.create(new VarsRefToExplPrec()), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceUnsatCoreChecker.create(xsts.getInitFormula(), negProp, solverFactory.createUCSolver()), + JoiningPrecRefiner.create(new VarsRefToExplPrec()), pruneStrategy, logger); break; default: throw new UnsupportedOperationException(domain + " domain does not support " + refinement + " refinement."); } final SafetyChecker, XstsAction, ExplPrec> checker = CegarChecker.create(abstractor, refiner, - logger); + logger); final ExplPrec prec = initPrec.builder.createExpl(xsts); return XstsConfig.create(checker, prec); @@ -222,13 +261,13 @@ public XstsConfigBuilder autoExpl(final AutoExpl autoExpl) { PredAbstractors.PredAbstractor predAbstractor = null; switch (domain) { case PRED_BOOL: - predAbstractor = PredAbstractors.booleanAbstractor(solver); + predAbstractor = PredAbstractors.booleanAbstractor(abstractionSolver); break; case PRED_SPLIT: - predAbstractor = PredAbstractors.booleanSplitAbstractor(solver); + predAbstractor = PredAbstractors.booleanSplitAbstractor(abstractionSolver); break; case PRED_CART: - predAbstractor = PredAbstractors.cartesianAbstractor(solver); + predAbstractor = PredAbstractors.cartesianAbstractor(abstractionSolver); break; default: throw new UnsupportedOperationException(domain + " domain is not supported."); @@ -241,46 +280,46 @@ public XstsConfigBuilder autoExpl(final AutoExpl autoExpl) { lts = XstsLts.create(xsts, XstsStmtOptimizer.create(DefaultStmtOptimizer.create())); } - final Predicate> target = new XstsStatePredicate(new ExprStatePredicate(negProp, solver)); - final Analysis, XstsAction, PredPrec> analysis = XstsAnalysis.create(PredAnalysis.create(solver, predAbstractor, - xsts.getInitFormula())); + final Predicate> target = new XstsStatePredicate(new ExprStatePredicate(negProp, abstractionSolver)); + final Analysis, XstsAction, PredPrec> analysis = XstsAnalysis.create(PredAnalysis.create(abstractionSolver, predAbstractor, + xsts.getInitFormula())); final ArgBuilder, XstsAction, PredPrec> argBuilder = ArgBuilder.create(lts, analysis, target, - true); + true); final Abstractor, XstsAction, PredPrec> abstractor = BasicAbstractor.builder(argBuilder) - .waitlist(PriorityWaitlist.create(search.comparator)) - .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() - : StopCriterions.firstCex()) - .logger(logger).build(); + .waitlist(PriorityWaitlist.create(search.comparator)) + .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() + : StopCriterions.firstCex()) + .logger(logger).build(); ExprTraceChecker exprTraceChecker = null; switch (refinement) { case FW_BIN_ITP: - exprTraceChecker = ExprTraceFwBinItpChecker.create(xsts.getInitFormula(), negProp, solver); + exprTraceChecker = ExprTraceFwBinItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()); break; case BW_BIN_ITP: - exprTraceChecker = ExprTraceBwBinItpChecker.create(xsts.getInitFormula(), negProp, solver); + exprTraceChecker = ExprTraceBwBinItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()); break; case SEQ_ITP: - exprTraceChecker = ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solver); + exprTraceChecker = ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()); break; case MULTI_SEQ: - exprTraceChecker = ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solver); + exprTraceChecker = ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()); break; default: throw new UnsupportedOperationException( - domain + " domain does not support " + refinement + " refinement."); + domain + " domain does not support " + refinement + " refinement."); } Refiner, XstsAction, PredPrec> refiner; if (refinement == Refinement.MULTI_SEQ) { refiner = MultiExprTraceRefiner.create(exprTraceChecker, - JoiningPrecRefiner.create(new ItpRefToPredPrec(predSplit.splitter)), pruneStrategy, logger); + JoiningPrecRefiner.create(new ItpRefToPredPrec(predSplit.splitter)), pruneStrategy, logger); } else { refiner = SingleExprTraceRefiner.create(exprTraceChecker, - JoiningPrecRefiner.create(new ItpRefToPredPrec(predSplit.splitter)), pruneStrategy, logger); + JoiningPrecRefiner.create(new ItpRefToPredPrec(predSplit.splitter)), pruneStrategy, logger); } final SafetyChecker, XstsAction, PredPrec> checker = CegarChecker.create(abstractor, refiner, - logger); + logger); final PredPrec prec = initPrec.builder.createPred(xsts); return XstsConfig.create(checker, prec); @@ -288,52 +327,52 @@ public XstsConfigBuilder autoExpl(final AutoExpl autoExpl) { final LTS>, XstsAction> lts; if(optimizeStmts == OptimizeStmts.ON){ lts = XstsLts.create(xsts,XstsStmtOptimizer.create( - Prod2ExplPredStmtOptimizer.create( - ExplStmtOptimizer.getInstance() - ))); + Prod2ExplPredStmtOptimizer.create( + ExplStmtOptimizer.getInstance() + ))); } else { lts = XstsLts.create(xsts, XstsStmtOptimizer.create(DefaultStmtOptimizer.create())); } final Analysis,XstsAction,Prod2Prec> prod2Analysis; - final Predicate>> target = new XstsStatePredicate>(new ExprStatePredicate(negProp, solver)); + final Predicate>> target = new XstsStatePredicate>(new ExprStatePredicate(negProp, abstractionSolver)); if(domain == Domain.EXPL_PRED_BOOL || domain == Domain.EXPL_PRED_CART || domain == Domain.EXPL_PRED_SPLIT){ final PredAbstractors.PredAbstractor predAbstractor; switch (domain) { case EXPL_PRED_BOOL: - predAbstractor = PredAbstractors.booleanAbstractor(solver); + predAbstractor = PredAbstractors.booleanAbstractor(abstractionSolver); break; case EXPL_PRED_SPLIT: - predAbstractor = PredAbstractors.booleanSplitAbstractor(solver); + predAbstractor = PredAbstractors.booleanSplitAbstractor(abstractionSolver); break; case EXPL_PRED_CART: - predAbstractor = PredAbstractors.cartesianAbstractor(solver); + predAbstractor = PredAbstractors.cartesianAbstractor(abstractionSolver); break; default: throw new UnsupportedOperationException(domain + " domain is not supported."); } prod2Analysis = Prod2Analysis.create( - ExplStmtAnalysis.create(solver, xsts.getInitFormula(), maxEnum), - PredAnalysis.create(solver, predAbstractor, xsts.getInitFormula()), - Prod2ExplPredPreStrengtheningOperator.create(), - Prod2ExplPredStrengtheningOperator.create(solver)); + ExplStmtAnalysis.create(abstractionSolver, xsts.getInitFormula(), maxEnum), + PredAnalysis.create(abstractionSolver, predAbstractor, xsts.getInitFormula()), + Prod2ExplPredPreStrengtheningOperator.create(), + Prod2ExplPredStrengtheningOperator.create(abstractionSolver)); } else { - final Prod2ExplPredAbstractors.Prod2ExplPredAbstractor prodAbstractor = Prod2ExplPredAbstractors.booleanAbstractor(solver); + final Prod2ExplPredAbstractors.Prod2ExplPredAbstractor prodAbstractor = Prod2ExplPredAbstractors.booleanAbstractor(abstractionSolver); prod2Analysis = Prod2ExplPredAnalysis.create( - ExplAnalysis.create(solver, xsts.getInitFormula()), - PredAnalysis.create(solver, PredAbstractors.booleanAbstractor(solver), xsts.getInitFormula()), - Prod2ExplPredStrengtheningOperator.create(solver), - prodAbstractor); + ExplAnalysis.create(abstractionSolver, xsts.getInitFormula()), + PredAnalysis.create(abstractionSolver, PredAbstractors.booleanAbstractor(abstractionSolver), xsts.getInitFormula()), + Prod2ExplPredStrengtheningOperator.create(abstractionSolver), + prodAbstractor); } final Analysis>, XstsAction, Prod2Prec> analysis = XstsAnalysis.create(prod2Analysis); final ArgBuilder>, XstsAction, Prod2Prec> argBuilder = ArgBuilder.create(lts, analysis, target, - true); + true); final Abstractor>, XstsAction, Prod2Prec> abstractor = BasicAbstractor.builder(argBuilder) - .waitlist(PriorityWaitlist.create(search.comparator)) - .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() - : StopCriterions.firstCex()) - .logger(logger).build(); + .waitlist(PriorityWaitlist.create(search.comparator)) + .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() + : StopCriterions.firstCex()) + .logger(logger).build(); Refiner>, XstsAction, Prod2Prec> refiner = null; @@ -342,28 +381,28 @@ public XstsConfigBuilder autoExpl(final AutoExpl autoExpl) { switch (refinement) { case FW_BIN_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceFwBinItpChecker.create(xsts.getInitFormula(), negProp, solver), - JoiningPrecRefiner.create(precRefiner), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceFwBinItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(precRefiner), pruneStrategy, logger); break; case BW_BIN_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceBwBinItpChecker.create(xsts.getInitFormula(), negProp, solver), - JoiningPrecRefiner.create(precRefiner), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceBwBinItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(precRefiner), pruneStrategy, logger); break; case SEQ_ITP: - refiner = SingleExprTraceRefiner.create(ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solver), - JoiningPrecRefiner.create(precRefiner), pruneStrategy, logger); + refiner = SingleExprTraceRefiner.create(ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(precRefiner), pruneStrategy, logger); break; case MULTI_SEQ: - refiner = MultiExprTraceRefiner.create(ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solver), - JoiningPrecRefiner.create(precRefiner), pruneStrategy, logger); + refiner = MultiExprTraceRefiner.create(ExprTraceSeqItpChecker.create(xsts.getInitFormula(), negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(precRefiner), pruneStrategy, logger); break; default: throw new UnsupportedOperationException( - domain + " domain does not support " + refinement + " refinement."); + domain + " domain does not support " + refinement + " refinement."); } final SafetyChecker>, XstsAction, Prod2Prec> checker = CegarChecker.create(abstractor, refiner, - logger); + logger); final Prod2Prec prec = initPrec.builder.createProd2ExplPred(xsts); return XstsConfig.create(checker, prec); } else { From d320ab18b0013820f604cefd3798335230290f8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 30 Mar 2021 22:36:12 +0200 Subject: [PATCH 83/99] Fix solver integration issues --- subprojects/cfa/cfa-analysis/build.gradle.kts | 1 + subprojects/cfa/cfa-cli/build.gradle.kts | 1 + .../solver/smtlib/SmtLibSolverManager.java | 10 +- .../impl/cvc4/CVC4SmtLibSolverInstaller.java | 2 +- .../generic/GenericSmtLibExprTransformer.java | 145 ++++++++++++++---- .../generic/GenericSmtLibSymbolTable.java | 9 +- .../generic/GenericSmtLibTermTransformer.java | 1 + .../mathsat/MathSATSmtLibSolverInstaller.java | 2 +- .../smtlib/impl/z3/Z3SmtLibItpSolver.java | 37 +++-- .../solver/smtlib/solver/SmtLibItpSolver.java | 2 +- 10 files changed, 166 insertions(+), 44 deletions(-) diff --git a/subprojects/cfa/cfa-analysis/build.gradle.kts b/subprojects/cfa/cfa-analysis/build.gradle.kts index fbfc58a323..6ba5f600e6 100644 --- a/subprojects/cfa/cfa-analysis/build.gradle.kts +++ b/subprojects/cfa/cfa-analysis/build.gradle.kts @@ -8,4 +8,5 @@ dependencies { compile(project(":theta-common")) compile(project(":theta-core")) testImplementation(project(":theta-solver-z3")) + testImplementation(project(":theta-solver-smtlib")) } diff --git a/subprojects/cfa/cfa-cli/build.gradle.kts b/subprojects/cfa/cfa-cli/build.gradle.kts index 2d7a900bde..81d0bb182c 100644 --- a/subprojects/cfa/cfa-cli/build.gradle.kts +++ b/subprojects/cfa/cfa-cli/build.gradle.kts @@ -7,6 +7,7 @@ dependencies { compile(project(":theta-cfa")) compile(project(":theta-cfa-analysis")) compile(project(":theta-solver-z3")) + compile(project(":theta-solver-smtlib")) } application { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java index c3d095946e..5e3d8b6b72 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java @@ -89,7 +89,8 @@ private SmtLibSolverManager(final Path home, final Logger logger) { } - public static SmtLibSolverManager create(final Path home, final Logger logger) { + public static SmtLibSolverManager create(final Path home, final Logger logger) throws IOException { + createIfNotExists(home); return new SmtLibSolverManager(home, logger); } @@ -231,4 +232,11 @@ private String getVersionString(final String solver, final String version, final } } } + + private static Path createIfNotExists(final Path path) throws IOException { + if(!Files.exists(path)) { + Files.createDirectory(path); + } + return path; + } } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java index c98426c895..05654c9731 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java @@ -67,7 +67,7 @@ protected String[] getDefaultSolverArgs(String version) { @Override public SolverFactory getSolverFactory(final Path installDir, final String version, final Path solverPath, final String[] solverArgs) throws SmtLibSolverInstallerException { - final var solverFilePath = solverPath != null ? solverPath : installDir.resolve("bin").resolve(getSolverBinaryName()); + final var solverFilePath = solverPath != null ? solverPath : installDir.resolve(getSolverBinaryName()); return CVC4SmtLibSolverFactory.create(solverFilePath, solverArgs); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibExprTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibExprTransformer.java index 93c429998f..43b5fdbf75 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibExprTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibExprTransformer.java @@ -361,19 +361,35 @@ protected String transformXor(final XorExpr expr) { } protected String transformAnd(final AndExpr expr) { - final String[] opTerms = expr.getOps().stream() - .map(this::toTerm) - .toArray(String[]::new); + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return "true"; + } + else { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); - return String.format("(and %s)", String.join(" ", opTerms)); + return String.format("(and %s)", String.join(" ", opTerms)); + } } protected String transformOr(final OrExpr expr) { - final String[] opTerms = expr.getOps().stream() + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return "false"; + } + else { + final String[] opTerms = expr.getOps().stream() .map(this::toTerm) .toArray(String[]::new); - return String.format("(or %s)", String.join(" ", opTerms)); + return String.format("(or %s)", String.join(" ", opTerms)); + } } protected String transformExists(final ExistsExpr expr) { @@ -424,11 +440,19 @@ protected String transformRatLit(final RatLitExpr expr) { } protected String transformRatAdd(final RatAddExpr expr) { - final String[] opTerms = expr.getOps().stream() + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return "0.0"; + } + else { + final String[] opTerms = expr.getOps().stream() .map(this::toTerm) .toArray(String[]::new); - return String.format("(+ %s)", String.join(" ", opTerms)); + return String.format("(+ %s)", String.join(" ", opTerms)); + } } protected String transformRatSub(final RatSubExpr expr) { @@ -444,11 +468,19 @@ protected String transformRatNeg(final RatNegExpr expr) { } protected String transformRatMul(final RatMulExpr expr) { - final String[] opTerms = expr.getOps().stream() + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return "1.0"; + } + else { + final String[] opTerms = expr.getOps().stream() .map(this::toTerm) .toArray(String[]::new); - return String.format("(* %s)", String.join(" ", opTerms)); + return String.format("(* %s)", String.join(" ", opTerms)); + } } protected String transformRatDiv(final RatDivExpr expr) { @@ -484,15 +516,28 @@ protected String transformRatLt(final RatLtExpr expr) { */ protected String transformIntLit(final IntLitExpr expr) { - return expr.getValue().toString(); + if(expr.getValue().compareTo(BigInteger.ZERO) < 0) { + return String.format("(- %s)", expr.getValue().abs().toString()); + } + else { + return expr.getValue().toString(); + } } protected String transformIntAdd(final IntAddExpr expr) { - final String[] opTerms = expr.getOps().stream() + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return "0"; + } + else { + final String[] opTerms = expr.getOps().stream() .map(this::toTerm) .toArray(String[]::new); - return String.format("(+ %s)", String.join(" ", opTerms)); + return String.format("(+ %s)", String.join(" ", opTerms)); + } } protected String transformIntSub(final IntSubExpr expr) { @@ -508,15 +553,23 @@ protected String transformIntNeg(final IntNegExpr expr) { } protected String transformIntMul(final IntMulExpr expr) { - final String[] opTerms = expr.getOps().stream() + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return "1"; + } + else { + final String[] opTerms = expr.getOps().stream() .map(this::toTerm) .toArray(String[]::new); - return String.format("(* %s)", String.join(" ", opTerms)); + return String.format("(* %s)", String.join(" ", opTerms)); + } } protected String transformIntDiv(final IntDivExpr expr) { - return String.format("(/ %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + return String.format("(div %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } protected String transformIntMod(final IntModExpr expr) { @@ -597,11 +650,19 @@ protected String transformBvSExt(final BvSExtExpr expr) { } protected String transformBvAdd(final BvAddExpr expr) { - final String[] opTerms = expr.getOps().stream() + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return toTerm(BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, expr.getType().getSize())); + } + else { + final String[] opTerms = expr.getOps().stream() .map(this::toTerm) .toArray(String[]::new); - return String.format("(bvadd %s)", String.join(" ", opTerms)); + return String.format("(bvadd %s)", String.join(" ", opTerms)); + } } protected String transformBvSub(final BvSubExpr expr) { @@ -617,11 +678,19 @@ protected String transformBvNeg(final BvNegExpr expr) { } protected String transformBvMul(final BvMulExpr expr) { - final String[] opTerms = expr.getOps().stream() + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return toTerm(BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ONE, expr.getType().getSize())); + } + else { + final String[] opTerms = expr.getOps().stream() .map(this::toTerm) .toArray(String[]::new); - return String.format("(bvmul %s)", String.join(" ", opTerms)); + return String.format("(bvmul %s)", String.join(" ", opTerms)); + } } protected String transformBvUDiv(final BvUDivExpr expr) { @@ -645,27 +714,51 @@ protected String transformBvSRem(final BvSRemExpr expr) { } protected String transformBvAnd(final BvAndExpr expr) { - final String[] opTerms = expr.getOps().stream() + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return toTerm(BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.TWO.pow(expr.getType().getSize()).subtract(BigInteger.ONE), expr.getType().getSize())); + } + else { + final String[] opTerms = expr.getOps().stream() .map(this::toTerm) .toArray(String[]::new); - return String.format("(bvand %s)", String.join(" ", opTerms)); + return String.format("(bvand %s)", String.join(" ", opTerms)); + } } protected String transformBvOr(final BvOrExpr expr) { - final String[] opTerms = expr.getOps().stream() + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return toTerm(BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, expr.getType().getSize())); + } + else { + final String[] opTerms = expr.getOps().stream() .map(this::toTerm) .toArray(String[]::new); - return String.format("(bvor %s)", String.join(" ", opTerms)); + return String.format("(bvor %s)", String.join(" ", opTerms)); + } } protected String transformBvXor(final BvXorExpr expr) { - final String[] opTerms = expr.getOps().stream() + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return toTerm(BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, expr.getType().getSize())); + } + else { + final String[] opTerms = expr.getOps().stream() .map(this::toTerm) .toArray(String[]::new); - return String.format("(bvxor %s)", String.join(" ", opTerms)); + return String.format("(bvxor %s)", String.join(" ", opTerms)); + } } protected String transformBvNot(final BvNotExpr expr) { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSymbolTable.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSymbolTable.java index cbe1671866..d0903ccf00 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSymbolTable.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSymbolTable.java @@ -11,6 +11,9 @@ import static com.google.common.base.Preconditions.checkState; public class GenericSmtLibSymbolTable implements SmtLibSymbolTable { + private static final String problematicCharactersRegex = ":"; + private static final String problematicCharactersReplacement = "\\$"; + private final BiMap, String> constToSymbol; private final BiMap, String> constToDeclaration; @@ -26,7 +29,7 @@ public boolean definesConst(final ConstDecl constDecl) { @Override public boolean definesSymbol(final String symbol) { - return constToSymbol.inverse().containsKey(symbol); + return constToSymbol.inverse().containsKey(symbol.replaceAll(problematicCharactersRegex, problematicCharactersReplacement)); } @Override @@ -53,7 +56,7 @@ public void put(final ConstDecl constDecl, final String symbol, final String checkNotNull(symbol); checkNotNull(declaration); checkState(!constToSymbol.containsKey(constDecl), "Constant not found."); - constToSymbol.put(constDecl, symbol); - constToDeclaration.put(constDecl, declaration); + constToSymbol.put(constDecl, symbol.replaceAll(problematicCharactersRegex, problematicCharactersReplacement)); + constToDeclaration.put(constDecl, declaration.replaceAll(problematicCharactersRegex, problematicCharactersReplacement)); } } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java index 519efbca57..2b61c42d94 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java @@ -141,6 +141,7 @@ public GenericSmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { put("-", exprMinusOperator()); put("*", exprMultiaryOperator(MulExpr::create2)); put("div", exprBinaryOperator(DivExpr::create2)); + put("/", exprBinaryOperator(DivExpr::create2)); put("mod", exprBinaryOperator(ModExpr::create2)); put("rem", exprBinaryOperator(RemExpr::create2)); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java index 4326acfa46..abe3029e5a 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java @@ -129,7 +129,7 @@ protected void uninstallSolver(Path installDir, String version) { } @Override protected String[] getDefaultSolverArgs(String version) throws SmtLibSolverInstallerException { - return new String[] { }; + return new String[] { "-theory.bv.eager=false" }; } @Override diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpSolver.java index ec74b25e0e..b5f5187ee4 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibItpSolver.java @@ -10,18 +10,18 @@ import hu.bme.mit.theta.solver.ItpMarkerTree; import hu.bme.mit.theta.solver.ItpPattern; import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; +import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; import hu.bme.mit.theta.solver.smtlib.solver.SmtLibItpSolver; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibInterpolant; import hu.bme.mit.theta.solver.smtlib.solver.interpolation.SmtLibItpPattern; import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; -import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; -import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; -import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; -import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; -import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.ParserRuleContext; @@ -39,7 +39,6 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.False; public final class Z3SmtLibItpSolver extends SmtLibItpSolver { private boolean topMostContainsAssertions = false; @@ -64,6 +63,8 @@ public Z3SmtLibItpMarker createMarker() { return marker; } + + @Override public void add(ItpMarker marker, Expr assertion) { if(topMostContainsAssertions) { @@ -89,14 +90,29 @@ public SolverStatus check() { topMostContainsAssertions = true; for(final var marker : markers.toCollection()) { - final var term = String.format("(and %s)", String.join(" ", marker.getTerms().stream().map(Tuple2::get2).collect(Collectors.toUnmodifiableList()))); + final var terms = marker.getTerms(); + if(terms.size() == 0) { + issueGeneralCommand(String.format("(assert (! true :named %s))", marker.getMarkerName())); + } + else { + final var term = String.format("(and %s)", String.join(" ", marker.getTerms().stream().map(Tuple2::get2).collect(Collectors.toUnmodifiableList()))); - issueGeneralCommand(String.format("(assert (! %s :named %s))", term, marker.getMarkerName())); + issueGeneralCommand(String.format("(assert (! %s :named %s))", term, marker.getMarkerName())); + } } return super.check(); } + @Override + public void push() { + if(topMostContainsAssertions) { + issueGeneralCommand("(pop 1)"); // Topmost frame contains marker assertions + topMostContainsAssertions = false; + } + super.push(); // Topmost frame contains marker assertions + } + @Override public void pop(int n) { if(topMostContainsAssertions) { @@ -119,11 +135,11 @@ public Interpolant getInterpolant(final ItpPattern pattern) { final List> itpList = new LinkedList<>(); solverBinary.issueCommand(String.format("(get-interpolant %s)", term)); - for(var i = 0; i < markerCount - 1; i++) { + for(var i = 0; i < markerCount; i++) { final var res = parseItpResponse(solverBinary.readResponse()); itpList.add(termTransformer.toExpr(res, BoolExprs.Bool(), new SmtLibModel(Collections.emptyMap()))); } - itpList.add(False()); + // itpList.add(False()); final Map> itpMap = new HashMap<>(); buildItpMapFormList(z3ItpPattern.getRoot(), itpList, itpMap); @@ -136,7 +152,6 @@ private String patternToTerm(final ItpMarkerTree markerTree) final Z3SmtLibItpMarker marker = markerTree.getMarker(); opTerms.add(marker.getMarkerName()); - //opTerms.addAll(marker.getTerms().stream().map(Tuple2::get2).collect(Collectors.toUnmodifiableList())); for (final var child : markerTree.getChildren()) { final var childTerm = patternToTerm(child); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java index d1d0d7b48d..65897370f7 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java @@ -147,7 +147,7 @@ public void pop(final int n) { } assertions.pop(n); declarationStack.pop(n); - issueGeneralCommand("(pop 1)"); + issueGeneralCommand(String.format("(pop %d)", n)); clearState(); } From 303956b26590f8970f4db83b8757379640ecee34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 30 Mar 2021 22:50:39 +0200 Subject: [PATCH 84/99] Remove boolector unsat core support, as there is none --- .../smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java index 60cdb93007..6150264263 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverFactory.java @@ -1,6 +1,7 @@ package hu.bme.mit.theta.solver.smtlib.impl.boolector; import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.smtlib.impl.generic.GenericSmtLibSolverFactory; import java.nio.file.Path; @@ -14,6 +15,11 @@ public static BoolectorSmtLibSolverFactory create(Path solverPath, String[] args return new BoolectorSmtLibSolverFactory(solverPath, args); } + @Override + public UCSolver createUCSolver() { + throw new UnsupportedOperationException("Boolector does not support unsat cores"); + } + @Override public ItpSolver createItpSolver() { throw new UnsupportedOperationException("Boolector does not support interpolation"); From 80623f40265645a5912fda39cf965d9ba407d8d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 23 Sep 2021 19:37:54 +0200 Subject: [PATCH 85/99] Make solver AutoCloseable --- .../bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java | 5 +++++ .../hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java | 6 +++++- .../solver/smtlib/solver/binary/SmtLibSolverBinary.java | 2 +- .../main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java | 5 +++++ .../src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java | 5 +++++ .../src/main/java/hu/bme/mit/theta/solver/SolverBase.java | 2 +- .../main/java/hu/bme/mit/theta/solver/impl/NullSolver.java | 5 +++++ 7 files changed, 27 insertions(+), 3 deletions(-) diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java index 65897370f7..c691f0d6d1 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibItpSolver.java @@ -201,6 +201,11 @@ public Collection> getAssertions() { return assertions.toCollection(); } + @Override + public void close() throws Exception { + solverBinary.close(); + } + protected void clearState() { status = null; model = null; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java index a8374c5fe5..534f298e04 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java @@ -241,6 +241,11 @@ public Collection> getAssertions() { return assertions.toCollection(); } + @Override + public void close() throws Exception { + solverBinary.close(); + } + private void init() { issueGeneralCommand("(set-option :print-success true)"); issueGeneralCommand("(set-option :produce-models true)"); @@ -278,5 +283,4 @@ protected final GeneralResponse parseResponse(final String response) { throw new SmtLibSolverException("Could not parse solver output: " + response, e); } } - } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/binary/SmtLibSolverBinary.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/binary/SmtLibSolverBinary.java index 141a5b6252..61091d5ac8 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/binary/SmtLibSolverBinary.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/binary/SmtLibSolverBinary.java @@ -1,6 +1,6 @@ package hu.bme.mit.theta.solver.smtlib.solver.binary; -public interface SmtLibSolverBinary { +public interface SmtLibSolverBinary extends AutoCloseable { void issueCommand(String command); String readResponse(); } diff --git a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java index 96ca76ee79..3cfc31e3e2 100644 --- a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java +++ b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java @@ -193,4 +193,9 @@ public Collection> getAssertions() { return solver.getAssertions(); } + @Override + public void close() { + z3Context.close(); + solver.close(); + } } diff --git a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java index 5edbd4064d..c45e35b271 100644 --- a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java +++ b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java @@ -226,6 +226,11 @@ private void clearState() { unsatCore = null; } + @Override + public void close() { + z3Context.close(); + } + //// private final class Z3Model extends Valuation { diff --git a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java index cb6af94eb4..0d3326be68 100644 --- a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java +++ b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverBase.java @@ -6,7 +6,7 @@ import java.util.Collection; -public interface SolverBase { +public interface SolverBase extends AutoCloseable { /** diff --git a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java index d5b7d45055..2b52d5eead 100644 --- a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java +++ b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/impl/NullSolver.java @@ -76,4 +76,9 @@ public Collection> getAssertions() { throw new UnsupportedOperationException(); } + @Override + public void close() throws Exception { + throw new UnsupportedOperationException(); + } + } From b3b3eaa4d46322e37dbb5e07f489e997fb500c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 23 Sep 2021 19:38:28 +0200 Subject: [PATCH 86/99] Fix fp semantics --- subprojects/cfa/cfa/src/main/antlr/CfaDsl.g4 | 6 +- .../bme/mit/theta/cfa/dsl/CfaExpression.java | 13 +++- .../mit/theta/core/type/fptype/FpExprs.java | 59 +++++++++++++++++-- .../mit/theta/core/type/fptype/FpLitExpr.java | 27 --------- .../mit/theta/core/type/fptype/FpMaxExpr.java | 20 +++---- .../mit/theta/core/type/fptype/FpMinExpr.java | 20 +++---- .../mit/theta/core/type/fptype/FpRemExpr.java | 29 ++++----- .../hu/bme/mit/theta/core/utils/FpUtils.java | 14 ++++- .../bme/mit/theta/core/utils/FpTestUtils.java | 16 ++--- 9 files changed, 111 insertions(+), 93 deletions(-) diff --git a/subprojects/cfa/cfa/src/main/antlr/CfaDsl.g4 b/subprojects/cfa/cfa/src/main/antlr/CfaDsl.g4 index 15bfce3af0..29bb06c56a 100644 --- a/subprojects/cfa/cfa/src/main/antlr/CfaDsl.g4 +++ b/subprojects/cfa/cfa/src/main/antlr/CfaDsl.g4 @@ -541,15 +541,15 @@ FP_IS_NAN ; FPMAX - : 'fpmax' FP_ROUNDINGMODE? + : 'fpmax' ; FPMIN - : 'fpmin' FP_ROUNDINGMODE? + : 'fpmin' ; FPREM - : 'fprem' FP_ROUNDINGMODE? + : 'fprem' ; FPROUNDTOINT diff --git a/subprojects/cfa/cfa/src/main/java/hu/bme/mit/theta/cfa/dsl/CfaExpression.java b/subprojects/cfa/cfa/src/main/java/hu/bme/mit/theta/cfa/dsl/CfaExpression.java index 6ffe416e3c..e7e53b4c5f 100644 --- a/subprojects/cfa/cfa/src/main/java/hu/bme/mit/theta/cfa/dsl/CfaExpression.java +++ b/subprojects/cfa/cfa/src/main/java/hu/bme/mit/theta/cfa/dsl/CfaExpression.java @@ -128,6 +128,7 @@ import static hu.bme.mit.theta.core.utils.ExprUtils.simplify; import static hu.bme.mit.theta.core.utils.TypeUtils.cast; import static hu.bme.mit.theta.core.utils.TypeUtils.castBv; +import static hu.bme.mit.theta.core.utils.TypeUtils.castFp; import static java.util.stream.Collectors.toList; final class CfaExpression { @@ -392,9 +393,9 @@ public Expr visitFpFuncExpr(FpFuncExprContext ctx){ switch (ctx.oper.getType()) { case FPMAX: - return Max(getRoundingMode(ctx.oper.getText()), leftOp, rightOp); + return Max(leftOp, rightOp); case FPMIN: - return Min(getRoundingMode(ctx.oper.getText()), leftOp, rightOp); + return Min(leftOp, rightOp); default: throw new ParseException(ctx, "Unknown operator"); } @@ -538,6 +539,12 @@ private Expr createAdditiveSubExpr(final Expr leftOp, final Expr rightO case BV_SUB: return createBvSubExpr(castBv(leftOp), castBv(rightOp)); + case FPADD: + return FpExprs.Add(getRoundingMode(oper.getText()), List.of(castFp(leftOp), castFp(rightOp))); + + case FPSUB: + return FpExprs.Sub(getRoundingMode(oper.getText()), castFp(leftOp), castFp(rightOp)); + default: throw new ParseException(ctx, "Unknown operator '" + oper.getText() + "'"); } @@ -646,7 +653,7 @@ private Expr createMultiplicativeSubExpr(final Expr leftOp, final Expr return createBvSRemExpr(castBv(leftOp), castBv(rightOp)); case FPREM: - return FpExprs.Rem(getRoundingMode(oper.getText()), (Expr) leftOp, (Expr) rightOp); + return FpExprs.Rem((Expr) leftOp, (Expr) rightOp); case FPMUL: return FpExprs.Mul(getRoundingMode(oper.getText()), List.of((Expr) leftOp, (Expr) rightOp)); diff --git a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpExprs.java b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpExprs.java index 421054d600..591369e05f 100644 --- a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpExprs.java +++ b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpExprs.java @@ -4,6 +4,8 @@ import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; import hu.bme.mit.theta.core.type.bvtype.BvType; +import java.util.Arrays; + public final class FpExprs { private FpExprs() { } @@ -16,6 +18,51 @@ public static FpLitExpr Fp(boolean hidden, BvLitExpr exponent, BvLitExpr signifi return FpLitExpr.of(hidden, exponent, significand); } + public static FpLitExpr NaN(final FpType fpType) { + final var exponent = new boolean[fpType.getExponent()]; + Arrays.fill(exponent, true); + final var significand = new boolean[fpType.getSignificand() - 1]; + Arrays.fill(significand, true); + + return Fp(false, BvLitExpr.of(exponent), BvLitExpr.of(significand)); + } + + public static FpLitExpr PositiveInfinity(final FpType fpType) { + final var exponent = new boolean[fpType.getExponent()]; + Arrays.fill(exponent, true); + final var significand = new boolean[fpType.getSignificand() - 1]; + Arrays.fill(significand, false); + + return Fp(false, BvLitExpr.of(exponent), BvLitExpr.of(significand)); + } + + public static FpLitExpr NegativeInfinity(final FpType fpType) { + final var exponent = new boolean[fpType.getExponent()]; + Arrays.fill(exponent, true); + final var significand = new boolean[fpType.getSignificand() - 1]; + Arrays.fill(significand, false); + + return Fp(true, BvLitExpr.of(exponent), BvLitExpr.of(significand)); + } + + public static FpLitExpr PositiveZero(final FpType fpType) { + final var exponent = new boolean[fpType.getExponent()]; + Arrays.fill(exponent, false); + final var significand = new boolean[fpType.getSignificand() - 1]; + Arrays.fill(significand, false); + + return Fp(false, BvLitExpr.of(exponent), BvLitExpr.of(significand)); + } + + public static FpLitExpr NegativeZero(final FpType fpType) { + final var exponent = new boolean[fpType.getExponent()]; + Arrays.fill(exponent, false); + final var significand = new boolean[fpType.getSignificand() - 1]; + Arrays.fill(significand, false); + + return Fp(true, BvLitExpr.of(exponent), BvLitExpr.of(significand)); + } + public static FpAddExpr Add(final FpRoundingMode roundingMode, final Iterable> ops) { return FpAddExpr.of(roundingMode, ops); } @@ -40,8 +87,8 @@ public static FpDivExpr Div(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { - return FpRemExpr.of(roundingMode, leftOp, rightOp); + public static FpRemExpr Rem(final Expr leftOp, final Expr rightOp) { + return FpRemExpr.of(leftOp, rightOp); } public static FpAbsExpr Abs(final Expr op) { @@ -88,12 +135,12 @@ public static FpSqrtExpr Sqrt(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { - return FpMaxExpr.of(roundingMode, leftOp, rightOp); + public static FpMaxExpr Max(final Expr leftOp, final Expr rightOp) { + return FpMaxExpr.of(leftOp, rightOp); } - public static FpMinExpr Min(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { - return FpMinExpr.of(roundingMode, leftOp, rightOp); + public static FpMinExpr Min(final Expr leftOp, final Expr rightOp) { + return FpMinExpr.of(leftOp, rightOp); } public static FpToBvExpr ToBv(final FpRoundingMode roundingMode, final Expr op, final int size, final boolean sgn) { diff --git a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpLitExpr.java b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpLitExpr.java index f3886937d4..922cdd5d37 100644 --- a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpLitExpr.java +++ b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpLitExpr.java @@ -35,33 +35,6 @@ public static FpLitExpr of(final boolean hidden, final BvLitExpr exponent, final return new FpLitExpr(hidden, exponent, significand); } - public static FpLitExpr NaN(final FpType fpType) { - final var exponent = new boolean[fpType.getExponent()]; - Arrays.fill(exponent, true); - final var significand = new boolean[fpType.getSignificand() - 1]; - Arrays.fill(significand, true); - - return new FpLitExpr(false, BvLitExpr.of(exponent), BvLitExpr.of(significand)); - } - - public static FpLitExpr PositiveInfinity(final FpType fpType) { - final var exponent = new boolean[fpType.getExponent()]; - Arrays.fill(exponent, true); - final var significand = new boolean[fpType.getSignificand() - 1]; - Arrays.fill(significand, false); - - return new FpLitExpr(false, BvLitExpr.of(exponent), BvLitExpr.of(significand)); - } - - public static FpLitExpr NegativeInfinity(final FpType fpType) { - final var exponent = new boolean[fpType.getExponent()]; - Arrays.fill(exponent, true); - final var significand = new boolean[fpType.getSignificand() - 1]; - Arrays.fill(significand, false); - - return new FpLitExpr(true, BvLitExpr.of(exponent), BvLitExpr.of(significand)); - } - public boolean getHidden() { return hidden; } diff --git a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpMaxExpr.java b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpMaxExpr.java index 7bc37d3af4..c16d77b84a 100644 --- a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpMaxExpr.java +++ b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpMaxExpr.java @@ -14,24 +14,20 @@ public class FpMaxExpr extends BinaryExpr { private static final int HASH_SEED = 6668; private static final String OPERATOR_LABEL = "fpmax"; - private final FpRoundingMode roundingMode; - - private FpMaxExpr(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { + private FpMaxExpr(final Expr leftOp, final Expr rightOp) { super(leftOp, rightOp); checkAllTypesEqual(leftOp, rightOp); - checkNotNull(roundingMode); - this.roundingMode = roundingMode; } - public static FpMaxExpr of(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { - return new FpMaxExpr(roundingMode, leftOp, rightOp); + public static FpMaxExpr of(final Expr leftOp, final Expr rightOp) { + return new FpMaxExpr(leftOp, rightOp); } - public static FpMaxExpr create(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { + public static FpMaxExpr create(final Expr leftOp, final Expr rightOp) { checkNotNull(leftOp, rightOp); final Expr newLeftOp = castFp(leftOp); final Expr newRightOp = castFp(rightOp); - return FpMaxExpr.of(roundingMode, newLeftOp, newRightOp); + return FpMaxExpr.of(newLeftOp, newRightOp); } @Override @@ -39,7 +35,7 @@ public BinaryExpr with(Expr leftOp, Expr rightOp if (leftOp == getLeftOp() && rightOp == getRightOp()) { return this; } else { - return FpMaxExpr.of(roundingMode, leftOp, rightOp); + return FpMaxExpr.of(leftOp, rightOp); } } @@ -74,7 +70,7 @@ public boolean equals(final Object obj) { return true; } else if (obj instanceof FpMaxExpr) { final FpMaxExpr that = (FpMaxExpr) obj; - return this.getLeftOp().equals(that.getLeftOp()) && this.getRightOp().equals(that.getRightOp()) && roundingMode == that.roundingMode; + return this.getLeftOp().equals(that.getLeftOp()) && this.getRightOp().equals(that.getRightOp()); } else { return false; } @@ -83,7 +79,7 @@ public boolean equals(final Object obj) { public LitExpr eval(Valuation val) { final FpLitExpr leftOpVal = (FpLitExpr) getLeftOp().eval(val); final FpLitExpr rightOpVal = (FpLitExpr) getRightOp().eval(val); - if (FpUtils.fpLitExprToBigFloat(roundingMode, leftOpVal).greaterThan(FpUtils.fpLitExprToBigFloat(roundingMode, rightOpVal))) { + if (FpUtils.fpLitExprToBigFloat(null, leftOpVal).greaterThan(FpUtils.fpLitExprToBigFloat(null, rightOpVal))) { return leftOpVal; } else { return rightOpVal; diff --git a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpMinExpr.java b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpMinExpr.java index f5010af3eb..8be8693110 100644 --- a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpMinExpr.java +++ b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpMinExpr.java @@ -14,24 +14,20 @@ public class FpMinExpr extends BinaryExpr { private static final int HASH_SEED = 6667; private static final String OPERATOR_LABEL = "fpmin"; - private final FpRoundingMode roundingMode; - - private FpMinExpr(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { + private FpMinExpr(final Expr leftOp, final Expr rightOp) { super(leftOp, rightOp); checkAllTypesEqual(leftOp, rightOp); - checkNotNull(roundingMode); - this.roundingMode = roundingMode; } - public static FpMinExpr of(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { - return new FpMinExpr(roundingMode, leftOp, rightOp); + public static FpMinExpr of(final Expr leftOp, final Expr rightOp) { + return new FpMinExpr(leftOp, rightOp); } - public static FpMinExpr create(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { + public static FpMinExpr create(final Expr leftOp, final Expr rightOp) { checkNotNull(leftOp, rightOp); final Expr newLeftOp = castFp(leftOp); final Expr newRightOp = castFp(rightOp); - return FpMinExpr.of(roundingMode, newLeftOp, newRightOp); + return FpMinExpr.of(newLeftOp, newRightOp); } @Override @@ -39,7 +35,7 @@ public BinaryExpr with(Expr leftOp, Expr rightOp if (leftOp == getLeftOp() && rightOp == getRightOp()) { return this; } else { - return FpMinExpr.of(roundingMode, leftOp, rightOp); + return FpMinExpr.of(leftOp, rightOp); } } @@ -74,7 +70,7 @@ public boolean equals(final Object obj) { return true; } else if (obj instanceof FpMinExpr) { final FpMinExpr that = (FpMinExpr) obj; - return this.getLeftOp().equals(that.getLeftOp()) && this.getRightOp().equals(that.getRightOp()) && roundingMode == that.roundingMode; + return this.getLeftOp().equals(that.getLeftOp()) && this.getRightOp().equals(that.getRightOp()); } else { return false; } @@ -83,7 +79,7 @@ public boolean equals(final Object obj) { public LitExpr eval(Valuation val) { final FpLitExpr leftOpVal = (FpLitExpr) getLeftOp().eval(val); final FpLitExpr rightOpVal = (FpLitExpr) getRightOp().eval(val); - if (FpUtils.fpLitExprToBigFloat(roundingMode, leftOpVal).lessThan(FpUtils.fpLitExprToBigFloat(roundingMode, rightOpVal))) { + if (FpUtils.fpLitExprToBigFloat(null, leftOpVal).lessThan(FpUtils.fpLitExprToBigFloat(null, rightOpVal))) { return leftOpVal; } else { return rightOpVal; diff --git a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpRemExpr.java b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpRemExpr.java index 9699a7cd9a..7762aa874b 100644 --- a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpRemExpr.java +++ b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpRemExpr.java @@ -21,7 +21,6 @@ import hu.bme.mit.theta.core.utils.FpUtils; import org.kframework.mpfr.BigFloat; -import static com.google.common.base.Preconditions.checkNotNull; import static hu.bme.mit.theta.core.utils.TypeUtils.castFp; import static hu.bme.mit.theta.core.utils.TypeUtils.checkAllTypesEqual; @@ -31,27 +30,19 @@ public final class FpRemExpr extends BinaryExpr { private static final String OPERATOR_LABEL = "fprem"; - private final FpRoundingMode roundingMode; - - private FpRemExpr(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { + private FpRemExpr(final Expr leftOp, final Expr rightOp) { super(leftOp, rightOp); checkAllTypesEqual(leftOp, rightOp); - checkNotNull(roundingMode); - this.roundingMode = roundingMode; } - public static FpRemExpr of(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { - return new FpRemExpr(roundingMode, leftOp, rightOp); + public static FpRemExpr of(final Expr leftOp, final Expr rightOp) { + return new FpRemExpr(leftOp, rightOp); } - public static FpRemExpr create(final FpRoundingMode roundingMode, final Expr leftOp, final Expr rightOp) { + public static FpRemExpr create(final Expr leftOp, final Expr rightOp) { final Expr newLeftOp = castFp(leftOp); final Expr newRightOp = castFp(rightOp); - return FpRemExpr.of(roundingMode, newLeftOp, newRightOp); - } - - public FpRoundingMode getRoundingMode() { - return roundingMode; + return FpRemExpr.of(newLeftOp, newRightOp); } @Override @@ -63,9 +54,9 @@ public FpType getType() { public FpLitExpr eval(final Valuation val) { final FpLitExpr leftOpVal = (FpLitExpr) getLeftOp().eval(val); final FpLitExpr rightOpVal = (FpLitExpr) getRightOp().eval(val); - BigFloat leftFloat = FpUtils.fpLitExprToBigFloat(roundingMode, leftOpVal); - BigFloat rightFloat = FpUtils.fpLitExprToBigFloat(roundingMode, rightOpVal); - BigFloat remainder = leftFloat.remainder(rightFloat, FpUtils.getMathContext(this.getType(), roundingMode)); + BigFloat leftFloat = FpUtils.fpLitExprToBigFloat(null, leftOpVal); + BigFloat rightFloat = FpUtils.fpLitExprToBigFloat(null, rightOpVal); + BigFloat remainder = leftFloat.remainder(rightFloat, FpUtils.getMathContext(this.getType(), null)); return FpUtils.bigFloatToFpLitExpr(remainder, this.getType()); } @@ -77,7 +68,7 @@ public FpRemExpr with(final Expr leftOp, final Expr rightOp) { if (leftOp == getLeftOp() && rightOp == getRightOp()) { return this; } else { - return FpRemExpr.of(roundingMode, leftOp, rightOp); + return FpRemExpr.of(leftOp, rightOp); } } @@ -97,7 +88,7 @@ public boolean equals(final Object obj) { return true; } else if (obj instanceof FpRemExpr) { final FpRemExpr that = (FpRemExpr) obj; - return this.getLeftOp().equals(that.getLeftOp()) && this.getRightOp().equals(that.getRightOp()) && roundingMode == that.roundingMode; + return this.getLeftOp().equals(that.getLeftOp()) && this.getRightOp().equals(that.getRightOp()); } else { return false; } diff --git a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/FpUtils.java b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/FpUtils.java index f45b5a01e1..666cf09f69 100644 --- a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/FpUtils.java +++ b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/utils/FpUtils.java @@ -9,6 +9,10 @@ import java.math.BigInteger; import java.math.RoundingMode; +import static hu.bme.mit.theta.core.type.fptype.FpExprs.NaN; +import static hu.bme.mit.theta.core.type.fptype.FpExprs.NegativeInfinity; +import static hu.bme.mit.theta.core.type.fptype.FpExprs.PositiveInfinity; + public final class FpUtils { private FpUtils() { } @@ -36,11 +40,11 @@ public static BigFloat fpLitExprToBigFloat(final FpRoundingMode roundingMode, fi public static FpLitExpr bigFloatToFpLitExpr(final BigFloat bigFloat, final FpType type) { if (bigFloat.isNaN()) { - return FpLitExpr.NaN(type); + return NaN(type); } else if (bigFloat.isInfinite() && bigFloat.greaterThan(BigFloat.zero(type.getSignificand()))) { - return FpLitExpr.PositiveInfinity(type); + return PositiveInfinity(type); } else if (bigFloat.isInfinite() && bigFloat.lessThan(BigFloat.zero(type.getSignificand()))) { - return FpLitExpr.NegativeInfinity(type); + return NegativeInfinity(type); } else { final var minExponent = -(1L << (type.getExponent() - 1)) + 2; final var maxExponent = (1L << (type.getExponent() - 1)) - 1; @@ -58,6 +62,10 @@ public static FpLitExpr bigFloatToFpLitExpr(final BigFloat bigFloat, final FpTyp } public static RoundingMode getMathContextRoundingMode(final FpRoundingMode roundingMode) { + if(roundingMode == null) { + return RoundingMode.UNNECESSARY; + } + switch (roundingMode) { case RNE: return RoundingMode.HALF_EVEN; diff --git a/subprojects/common/core/src/testFixtures/java/hu/bme/mit/theta/core/utils/FpTestUtils.java b/subprojects/common/core/src/testFixtures/java/hu/bme/mit/theta/core/utils/FpTestUtils.java index a8cf72172c..783b844dc5 100644 --- a/subprojects/common/core/src/testFixtures/java/hu/bme/mit/theta/core/utils/FpTestUtils.java +++ b/subprojects/common/core/src/testFixtures/java/hu/bme/mit/theta/core/utils/FpTestUtils.java @@ -114,14 +114,14 @@ private static Collection BasicOperations() { {FpLtExpr.class, Bool(true), Lt(Fp16("7.14"), Fp16("7.15"))}, {FpLtExpr.class, Bool(false), Lt(Fp16("7.14"), Fp16("7.14"))}, {FpLtExpr.class, Bool(false), Lt(Fp16("-7.14"), Fp16("-7.15"))}, - {FpMaxExpr.class, Fp16("2.1"), Max(RNE, Fp16("-2.1"), Fp16("2.1"))}, - {FpMaxExpr.class, Fp16("2.1"), Max(RNE, Fp16("1.9"), Fp16("2.1"))}, - {FpMinExpr.class, Fp16("-2.1"), Min(RNE, Fp16("-2.1"), Fp16("2.1"))}, - {FpMinExpr.class, Fp16("1.9"), Min(RNE, Fp16("1.9"), Fp16("2.1"))}, - {FpRemExpr.class, Fp16("0.1"), Rem(RNE, Fp16("4.3"), Fp16("2.1"))}, - {FpRemExpr.class, Fp16("-0.1"), Rem(RNE, Fp16("-4.3"), Fp16("2.1"))}, - {FpRemExpr.class, Fp16("0.1"), Rem(RNE, Fp16("4.3"), Fp16("-2.1"))}, - {FpRemExpr.class, Fp16("-0.1"), Rem(RNE, Fp16("-4.3"), Fp16("-2.1"))}, + {FpMaxExpr.class, Fp16("2.1"), Max(Fp16("-2.1"), Fp16("2.1"))}, + {FpMaxExpr.class, Fp16("2.1"), Max(Fp16("1.9"), Fp16("2.1"))}, + {FpMinExpr.class, Fp16("-2.1"), Min(Fp16("-2.1"), Fp16("2.1"))}, + {FpMinExpr.class, Fp16("1.9"), Min(Fp16("1.9"), Fp16("2.1"))}, + {FpRemExpr.class, Fp16("0.1"), Rem(Fp16("4.3"), Fp16("2.1"))}, + {FpRemExpr.class, Fp16("-0.1"), Rem(Fp16("-4.3"), Fp16("2.1"))}, + {FpRemExpr.class, Fp16("0.1"), Rem(Fp16("4.3"), Fp16("-2.1"))}, + {FpRemExpr.class, Fp16("-0.1"), Rem(Fp16("-4.3"), Fp16("-2.1"))}, {FpRoundToIntegralExpr.class, Fp16("2.0"), RoundToIntegral(RNE, Fp16("2.49"))}, {FpRoundToIntegralExpr.class, Fp16("-10.0"), RoundToIntegral(RNE, Fp16("-10.49"))}, {FpSqrtExpr.class, Fp16("2.1"), Sqrt(RNE, Fp16("4.41"))}, From 8c5cf11b8618598f1e8721f33d7ec32c7f2f0b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 23 Sep 2021 19:39:15 +0200 Subject: [PATCH 87/99] Add floating point support to smtlib-solver --- .../generic/GenericSmtLibExprTransformer.java | 247 +++++++++++++++++- .../generic/GenericSmtLibSolverBinary.java | 5 + .../generic/GenericSmtLibTermTransformer.java | 128 ++++++++- .../generic/GenericSmtLibTypeTransformer.java | 6 + 4 files changed, 371 insertions(+), 15 deletions(-) diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibExprTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibExprTransformer.java index 43b5fdbf75..cf2d868045 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibExprTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibExprTransformer.java @@ -15,6 +15,7 @@ import hu.bme.mit.theta.core.type.anytype.IteExpr; import hu.bme.mit.theta.core.type.anytype.RefExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayEqExpr; +import hu.bme.mit.theta.core.type.arraytype.ArrayInitExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayLitExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayNeqExpr; import hu.bme.mit.theta.core.type.arraytype.ArrayReadExpr; @@ -63,6 +64,30 @@ import hu.bme.mit.theta.core.type.bvtype.BvURemExpr; import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; import hu.bme.mit.theta.core.type.bvtype.BvZExtExpr; +import hu.bme.mit.theta.core.type.fptype.FpAbsExpr; +import hu.bme.mit.theta.core.type.fptype.FpAddExpr; +import hu.bme.mit.theta.core.type.fptype.FpDivExpr; +import hu.bme.mit.theta.core.type.fptype.FpEqExpr; +import hu.bme.mit.theta.core.type.fptype.FpFromBvExpr; +import hu.bme.mit.theta.core.type.fptype.FpGeqExpr; +import hu.bme.mit.theta.core.type.fptype.FpGtExpr; +import hu.bme.mit.theta.core.type.fptype.FpIsNanExpr; +import hu.bme.mit.theta.core.type.fptype.FpLeqExpr; +import hu.bme.mit.theta.core.type.fptype.FpLitExpr; +import hu.bme.mit.theta.core.type.fptype.FpLtExpr; +import hu.bme.mit.theta.core.type.fptype.FpMaxExpr; +import hu.bme.mit.theta.core.type.fptype.FpMinExpr; +import hu.bme.mit.theta.core.type.fptype.FpMulExpr; +import hu.bme.mit.theta.core.type.fptype.FpNegExpr; +import hu.bme.mit.theta.core.type.fptype.FpNeqExpr; +import hu.bme.mit.theta.core.type.fptype.FpPosExpr; +import hu.bme.mit.theta.core.type.fptype.FpRemExpr; +import hu.bme.mit.theta.core.type.fptype.FpRoundToIntegralExpr; +import hu.bme.mit.theta.core.type.fptype.FpRoundingMode; +import hu.bme.mit.theta.core.type.fptype.FpSqrtExpr; +import hu.bme.mit.theta.core.type.fptype.FpSubExpr; +import hu.bme.mit.theta.core.type.fptype.FpToBvExpr; +import hu.bme.mit.theta.core.type.fptype.FpToFpExpr; import hu.bme.mit.theta.core.type.functype.FuncAppExpr; import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.type.inttype.IntAddExpr; @@ -99,7 +124,6 @@ import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; import java.math.BigInteger; -import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutionException; @@ -279,6 +303,54 @@ public GenericSmtLibExprTransformer(final SmtLibTransformationManager transforme .addCase(BvSLeqExpr.class, this::transformBvSLeq) .addCase(BvSLtExpr.class, this::transformBvSLt) + + // Floating points + + .addCase(FpLitExpr.class, this::transformFpLit) + + .addCase(FpAddExpr.class, this::transformFpAdd) + + .addCase(FpSubExpr.class, this::transformFpSub) + + .addCase(FpPosExpr.class, this::transformFpPos) + + .addCase(FpNegExpr.class, this::transformFpNeg) + + .addCase(FpMulExpr.class, this::transformFpMul) + + .addCase(FpDivExpr.class, this::transformFpDiv) + + .addCase(FpEqExpr.class, this::transformFpEq) + + .addCase(FpGeqExpr.class, this::transformFpGeq) + + .addCase(FpLeqExpr.class, this::transformFpLeq) + + .addCase(FpGtExpr.class, this::transformFpGt) + + .addCase(FpLtExpr.class, this::transformFpLt) + + .addCase(FpNeqExpr.class, this::transformFpNeq) + + .addCase(FpAbsExpr.class, this::transformFpAbs) + + .addCase(FpRoundToIntegralExpr.class, this::transformFpRoundToIntegral) + + .addCase(FpMaxExpr.class, this::transformFpMax) + + .addCase(FpMinExpr.class, this::transformFpMin) + + .addCase(FpSqrtExpr.class, this::transformFpSqrt) + + .addCase(FpRemExpr.class, this::transformFpRem) + + .addCase(FpIsNanExpr.class, this::transformFpIsNaN) + + .addCase(FpFromBvExpr.class, this::transformFpFromBv) + + .addCase(FpToBvExpr.class, this::transformFpToBv) + + .addCase(FpToFpExpr.class, this::transformFpToFp) // Functions @@ -296,6 +368,8 @@ public GenericSmtLibExprTransformer(final SmtLibTransformationManager transforme .addCase(ArrayLitExpr.class, this::transformArrayLit) + .addCase(ArrayInitExpr.class, this::transformArrayInit) + .build(); } @@ -517,7 +591,7 @@ protected String transformRatLt(final RatLtExpr expr) { protected String transformIntLit(final IntLitExpr expr) { if(expr.getValue().compareTo(BigInteger.ZERO) < 0) { - return String.format("(- %s)", expr.getValue().abs().toString()); + return String.format("(- %s)", expr.getValue().abs()); } else { return expr.getValue().toString(); @@ -613,15 +687,13 @@ protected String transformIntToRat(final IntToRatExpr expr) { */ protected String transformBvLit(final BvLitExpr expr) { - final String value = Arrays.toString(expr.getValue()) - .replace("true", "1") - .replace("false", "0") - .replace("[", "") - .replace("]", "") - .replace(",", "") - .replace(" ", ""); + final StringBuilder sb = new StringBuilder(expr.getType().getSize() + 1); - return String.format("#b%s", value); + for(boolean value : expr.getValue()) { + sb.append(value ? "1" : "0"); + } + + return String.format("#b%s", sb); } protected String transformBvConcat(final BvConcatExpr expr) { @@ -636,7 +708,7 @@ protected String transformBvExtract(final BvExtractExpr expr) { final var until = expr.getUntil().getValue().subtract(BigInteger.ONE); final var from = expr.getFrom().getValue(); - return String.format("((_ extract %s %s) %s)", until.toString(), from.toString(), toTerm(expr.getBitvec())); + return String.format("((_ extract %s %s) %s)", until, from, toTerm(expr.getBitvec())); } protected String transformBvZExt(final BvZExtExpr expr) { @@ -831,6 +903,151 @@ protected String transformBvSLt(final BvSLtExpr expr) { return String.format("(bvslt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); } + /* + * Floating points + */ + + protected String transformFpLit(final FpLitExpr expr) { + return String.format("(fp #b%s #b%s #b%s)", + expr.getHidden() ? "1" : "0", + transformBvLit(expr.getExponent()).substring(2), + transformBvLit(expr.getSignificand()).substring(2) + ); + } + + protected String transformFpAdd(final FpAddExpr expr) { + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return String.format("(_ +zero %d %d)", expr.getType().getExponent(), expr.getType().getSignificand()); + } + else { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(fp.add %s %s)", transformFpRoundingMode(expr.getRoundingMode()), String.join(" ", opTerms)); + } + } + + protected String transformFpSub(final FpSubExpr expr) { + return String.format("(fp.sub %s %s %s)", transformFpRoundingMode(expr.getRoundingMode()), toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformFpPos(final FpPosExpr expr) { + return toTerm(expr.getOp()); + } + + protected String transformFpNeg(final FpNegExpr expr) { + return String.format("(fp.neg %s)", toTerm(expr.getOp())); + } + + protected String transformFpMul(final FpMulExpr expr) { + if(expr.getArity() == 1) { + return toTerm(expr.getOps().get(0)); + } + else if(expr.getArity() == 0) { + return String.format("(fp #b0 #b0%s #b%s)", "1".repeat(expr.getType().getExponent()-1), "0".repeat(expr.getType().getSignificand())); + } + else { + final String[] opTerms = expr.getOps().stream() + .map(this::toTerm) + .toArray(String[]::new); + + return String.format("(fp.mul %s %s)", transformFpRoundingMode(expr.getRoundingMode()), String.join(" ", opTerms)); + } + } + + protected String transformFpDiv(final FpDivExpr expr) { + return String.format("(fp.div %s %s %s)", transformFpRoundingMode(expr.getRoundingMode()), toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformFpEq(final FpEqExpr expr) { + return String.format("(fp.eq %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformFpNeq(final FpNeqExpr expr) { + return String.format("(not (fp.eq %s %s))", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformFpGeq(final FpGeqExpr expr) { + return String.format("(fp.geq %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformFpGt(final FpGtExpr expr) { + return String.format("(fp.gt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformFpLeq(final FpLeqExpr expr) { + return String.format("(fp.leq %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformFpLt(final FpLtExpr expr) { + return String.format("(fp.lt %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformFpAbs(final FpAbsExpr expr) { + return String.format("(fp.abs %s)", toTerm(expr.getOp())); + } + + protected String transformFpRoundToIntegral(final FpRoundToIntegralExpr expr) { + return String.format("(fp.roundToIntegral %s %s)", transformFpRoundingMode(expr.getRoundingMode()), toTerm(expr.getOp())); + } + + protected String transformFpMin(final FpMinExpr expr) { + return String.format("(fp.min %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformFpMax(final FpMaxExpr expr) { + return String.format("(fp.max %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformFpSqrt(final FpSqrtExpr expr) { + return String.format("(fp.sqrt %s %s)", transformFpRoundingMode(expr.getRoundingMode()), toTerm(expr.getOp())); + } + + protected String transformFpRem(final FpRemExpr expr) { + return String.format("(fp.rem %s %s)", toTerm(expr.getLeftOp()), toTerm(expr.getRightOp())); + } + + protected String transformFpIsNaN(final FpIsNanExpr expr) { + return String.format("(fp.isNaN %s)", toTerm(expr.getOp())); + } + + protected String transformFpFromBv(final FpFromBvExpr expr) { + if(expr.isSigned()) { + return String.format("((_ to_fp %d %d) %s %s)", expr.getType().getExponent(), expr.getType().getSignificand(), transformFpRoundingMode(expr.getRoundingMode()), toTerm(expr.getOp())); + } + else { + return String.format("((_ to_fp_unsigned %d %d) %s %s)", expr.getType().getExponent(), expr.getType().getSignificand(), transformFpRoundingMode(expr.getRoundingMode()), toTerm(expr.getOp())); + } + } + + protected String transformFpToBv(final FpToBvExpr expr) { + if(expr.getSgn()) { + return String.format("((_ fp.to_sbv %d) %s %s) ", expr.getType().getSize(), transformFpRoundingMode(expr.getRoundingMode()), toTerm(expr.getOp())); + } + else { + return String.format("((_ fp.to_ubv %d) %s %s) ", expr.getType().getSize(), transformFpRoundingMode(expr.getRoundingMode()), toTerm(expr.getOp())); + } + } + + protected String transformFpToFp(final FpToFpExpr expr) { + return String.format("((_ to_fp %d %d) %s %s)", expr.getType().getExponent(), expr.getType().getSignificand(), transformFpRoundingMode(expr.getRoundingMode()), toTerm(expr.getOp())); + } + + private String transformFpRoundingMode(FpRoundingMode roundingMode) { + switch (roundingMode) { + case RNE: return "RNE"; + case RNA: return "RNA"; + case RTP: return "RTP"; + case RTN: return "RTN"; + case RTZ: return "RTZ"; + default: throw new UnsupportedOperationException(); + } + } + /* * Functions */ @@ -895,4 +1112,12 @@ protected String transformArrayLit(final ArrayLitExpr expr) { } return running; } + + protected String transformArrayInit(final ArrayInitExpr expr) { + String running = String.format("((as const %s) %s)", transformer.toSort(expr.getType()), toTerm(expr.getElseElem())); + for (Tuple2, ? extends Expr> elem : expr.getElements()) { + running = String.format("(store %s %s %s)", running, toTerm(elem.get1()), toTerm(elem.get2())); + } + return running; + } } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverBinary.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverBinary.java index 8ff838ce1b..0a8db6cee2 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverBinary.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverBinary.java @@ -63,6 +63,11 @@ public String readResponse() { return sb.toString().trim(); } + @Override + public void close() { + solverProcess.destroyForcibly(); + } + private static final class ReadProcessor { private enum ReadStatus { INIT, LINE, PARENTHESES, STRING, COMMENT, READY diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java index 2b61c42d94..a397343dd6 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java @@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableList; import hu.bme.mit.theta.common.QuadFunction; import hu.bme.mit.theta.common.TernaryOperator; +import hu.bme.mit.theta.common.TriFunction; import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.core.decl.Decl; import hu.bme.mit.theta.core.decl.ParamDecl; @@ -64,19 +65,38 @@ import hu.bme.mit.theta.core.type.bvtype.BvURemExpr; import hu.bme.mit.theta.core.type.bvtype.BvXorExpr; import hu.bme.mit.theta.core.type.bvtype.BvZExtExpr; +import hu.bme.mit.theta.core.type.fptype.FpAbsExpr; +import hu.bme.mit.theta.core.type.fptype.FpAddExpr; +import hu.bme.mit.theta.core.type.fptype.FpDivExpr; +import hu.bme.mit.theta.core.type.fptype.FpEqExpr; +import hu.bme.mit.theta.core.type.fptype.FpExprs; +import hu.bme.mit.theta.core.type.fptype.FpGeqExpr; +import hu.bme.mit.theta.core.type.fptype.FpGtExpr; +import hu.bme.mit.theta.core.type.fptype.FpIsNanExpr; +import hu.bme.mit.theta.core.type.fptype.FpLeqExpr; +import hu.bme.mit.theta.core.type.fptype.FpLtExpr; +import hu.bme.mit.theta.core.type.fptype.FpMaxExpr; +import hu.bme.mit.theta.core.type.fptype.FpMinExpr; +import hu.bme.mit.theta.core.type.fptype.FpMulExpr; +import hu.bme.mit.theta.core.type.fptype.FpNegExpr; +import hu.bme.mit.theta.core.type.fptype.FpRemExpr; +import hu.bme.mit.theta.core.type.fptype.FpRoundToIntegralExpr; +import hu.bme.mit.theta.core.type.fptype.FpRoundingMode; +import hu.bme.mit.theta.core.type.fptype.FpSqrtExpr; +import hu.bme.mit.theta.core.type.fptype.FpSubExpr; import hu.bme.mit.theta.core.type.functype.FuncExprs; import hu.bme.mit.theta.core.type.functype.FuncLitExpr; import hu.bme.mit.theta.core.type.functype.FuncType; import hu.bme.mit.theta.core.type.inttype.IntToRatExpr; import hu.bme.mit.theta.core.utils.BvUtils; import hu.bme.mit.theta.core.utils.ExprUtils; -import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; -import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; -import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; -import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.solver.SmtLibSolverException; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; +import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; @@ -188,6 +208,27 @@ public GenericSmtLibTermTransformer(final SmtLibSymbolTable symbolTable) { put("bvuge", exprBinaryOperator(BvUGeqExpr::create)); put("bvsge", exprBinaryOperator(BvSGeqExpr::create)); + // Floating point + + put("fp", exprFpLit()); + put("fp.add", exprFpMultiaryOperator(FpAddExpr::create)); + put("fp.sub", exprFpBinaryOperator(FpSubExpr::create)); + put("fp.neg", exprUnaryOperator(FpNegExpr::create)); + put("fp.mul", exprFpMultiaryOperator(FpMulExpr::create)); + put("fp.div", exprFpBinaryOperator(FpDivExpr::create)); + put("fp.eq", exprBinaryOperator(FpEqExpr::create)); + put("fp.geq", exprBinaryOperator(FpGeqExpr::create)); + put("fp.gt", exprBinaryOperator(FpGtExpr::create)); + put("fp.leq", exprBinaryOperator(FpLeqExpr::create)); + put("fp.lt", exprBinaryOperator(FpLtExpr::create)); + put("fp.abs", exprUnaryOperator(FpAbsExpr::create)); + put("fp.roundToIntegral", exprFpUnaryOperator(FpRoundToIntegralExpr::create)); + put("fp.min", exprBinaryOperator(FpMinExpr::create)); + put("fp.max", exprBinaryOperator(FpMaxExpr::create)); + put("fp.sqrt", exprFpUnaryOperator(FpSqrtExpr::create)); + put("fp.rem", exprBinaryOperator(FpRemExpr::create)); + put("fp.isNaN", exprUnaryOperator(FpIsNanExpr::create)); + // Array put("select", exprArrayReadOperator()); put("store", exprArrayWriteOperator()); @@ -496,6 +537,26 @@ else if(ctx.symbol().getText().startsWith("bv")) { final var bvSize = Integer.parseInt(ctx.index().get(0).getText()); return BvUtils.bigIntegerToNeutralBvLitExpr(new BigInteger(value), bvSize); } + else if(ctx.symbol().getText().equals("+oo")) { + final var eb = Integer.parseInt(ctx.index().get(0).getText()); + final var sb = Integer.parseInt(ctx.index().get(1).getText()); + return FpExprs.PositiveInfinity(FpExprs.FpType(eb, sb)); + } + else if(ctx.symbol().getText().equals("-oo")) { + final var eb = Integer.parseInt(ctx.index().get(0).getText()); + final var sb = Integer.parseInt(ctx.index().get(1).getText()); + return FpExprs.NegativeInfinity(FpExprs.FpType(eb, sb)); + } + else if(ctx.symbol().getText().equals("+zero")) { + final var eb = Integer.parseInt(ctx.index().get(0).getText()); + final var sb = Integer.parseInt(ctx.index().get(1).getText()); + return FpExprs.PositiveZero(FpExprs.FpType(eb, sb)); + } + else if(ctx.symbol().getText().equals("-zero")) { + final var eb = Integer.parseInt(ctx.index().get(0).getText()); + final var sb = Integer.parseInt(ctx.index().get(1).getText()); + return FpExprs.NegativeZero(FpExprs.FpType(eb, sb)); + } else { return transformSymbol(ctx.symbol(), model, vars); } @@ -731,6 +792,65 @@ private OperatorCreatorFunction exprMultiaryOperator(final Function }; } + private OperatorCreatorFunction exprFpLit() { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 3, "Three operators expected"); + + final var hidden = (BvLitExpr) transformTerm(ops.get(1), model, vars); + final var exponent = (BvLitExpr) transformTerm(ops.get(1), model, vars); + final var significand = (BvLitExpr) transformTerm(ops.get(2), model, vars); + + return FpExprs.Fp(hidden.getValue()[0], exponent, significand); + }; + } + + private OperatorCreatorFunction exprFpUnaryOperator(final BiFunction, Expr> function) { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 2, "Unary floating point operator expected"); + + final var roundingMode = fpOperatorRoundingMode(ops.get(0)); + final var op = transformTerm(ops.get(1), model, vars); + return function.apply(roundingMode, op); + }; + } + + private OperatorCreatorFunction exprFpBinaryOperator(final TriFunction, Expr, Expr> function) { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() == 3, "Binary floating point operator expected"); + + final var roundingMode = fpOperatorRoundingMode(ops.get(0)); + final var op1 = transformTerm(ops.get(1), model, vars); + final var op2 = transformTerm(ops.get(2), model, vars); + return function.apply(roundingMode, op1, op2); + }; + } + + private OperatorCreatorFunction exprFpMultiaryOperator(final BiFunction>, Expr> function) { + return (params, ops, model, vars) -> { + checkArgument(params.size() == 0, "No parameters expected"); + checkArgument(ops.size() >= 1); + + return function.apply( + fpOperatorRoundingMode(ops.get(0)), + ops.stream().skip(1).map(op -> transformTerm(op, model, vars)).collect(Collectors.toUnmodifiableList()) + ); + }; + } + + private FpRoundingMode fpOperatorRoundingMode(final TermContext term) { + switch(term.getText()) { + case "RNE": return FpRoundingMode.RNE; + case "RNA": return FpRoundingMode.RNA; + case "RTP": return FpRoundingMode.RTP; + case "RTN": return FpRoundingMode.RTN; + case "RTZ": return FpRoundingMode.RTZ; + default: throw new UnsupportedOperationException(); + } + } + private interface OperatorCreatorFunction extends QuadFunction< List, // Parameters List, // Operands diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTypeTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTypeTransformer.java index 613876454e..eeb94773c4 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTypeTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTypeTransformer.java @@ -7,6 +7,7 @@ import hu.bme.mit.theta.core.type.arraytype.ArrayType; import hu.bme.mit.theta.core.type.booltype.BoolType; import hu.bme.mit.theta.core.type.bvtype.BvType; +import hu.bme.mit.theta.core.type.fptype.FpType; import hu.bme.mit.theta.core.type.inttype.IntType; import hu.bme.mit.theta.core.type.rattype.RatType; import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; @@ -33,6 +34,7 @@ public GenericSmtLibTypeTransformer(final SmtLibTransformationManager transforme .addCase(IntType.class, this::intType) .addCase(RatType.class, this::ratType) .addCase(BvType.class, this::bvType) + .addCase(FpType.class, this::fpType) .addCase(ArrayType.class, this::arrayType) .build(); } @@ -62,6 +64,10 @@ protected String bvType(final BvType type) { return String.format("(_ BitVec %d)", type.getSize()); } + protected String fpType(final FpType type) { + return String.format("(_ FloatingPoint %d %d)", type.getExponent(), type.getSignificand()); + } + protected String arrayType(final ArrayType type) { return String.format("(Array %s %s)", toSort(type.getIndexType()), toSort(type.getElemType())); } From 251c9bbd654774f103c44447a60a5c57a922d96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 23 Sep 2021 19:40:16 +0200 Subject: [PATCH 88/99] Adjust default MathSAT options to support floating points --- .../smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java index abe3029e5a..f316a3a2e9 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java @@ -129,7 +129,7 @@ protected void uninstallSolver(Path installDir, String version) { } @Override protected String[] getDefaultSolverArgs(String version) throws SmtLibSolverInstallerException { - return new String[] { "-theory.bv.eager=false" }; + return new String[] { "-theory.bv.eager=false", "-theory.fp.mode=2" }; } @Override From 5d251fa0266bc8340df069354cc1a7e5a3390ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Thu, 23 Sep 2021 19:40:35 +0200 Subject: [PATCH 89/99] Add floating point tests --- .../bme/mit/theta/cfa/analysis/CfaTest.java | 15 ++- .../src/test/resources/counter_fp_true.cfa | 17 +++ .../cfa-analysis/src/test/resources/fp1.cfa | 21 ++++ .../cfa-analysis/src/test/resources/fp2.cfa | 21 ++++ .../solver/smtlib/SmtLibSolverFPTest.java | 113 ++++++++++++++++++ 5 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 subprojects/cfa/cfa-analysis/src/test/resources/counter_fp_true.cfa create mode 100644 subprojects/cfa/cfa-analysis/src/test/resources/fp1.cfa create mode 100644 subprojects/cfa/cfa-analysis/src/test/resources/fp2.cfa create mode 100644 subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java diff --git a/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java b/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java index 25935c9a41..2ae883244d 100644 --- a/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java +++ b/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java @@ -25,6 +25,9 @@ import hu.bme.mit.theta.cfa.analysis.config.CfaConfig; import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder; import hu.bme.mit.theta.cfa.dsl.CfaDslManager; +import hu.bme.mit.theta.common.logging.NullLogger; +import hu.bme.mit.theta.solver.smtlib.SmtLibSolverManager; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import hu.bme.mit.theta.solver.z3.Z3SolverFactory; import org.junit.Assert; import org.junit.Test; @@ -33,6 +36,8 @@ import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.Collection; @@ -116,6 +121,12 @@ public static Collection data() { { "src/test/resources/counter_bv_false.cfa", PRED_CART, UCB, false, 13 }, + { "src/test/resources/fp1.cfa", PRED_CART, NWT_IT_WP, false, 5 }, + + { "src/test/resources/fp2.cfa", PRED_CART, NWT_IT_WP, false, 5 }, + + { "src/test/resources/counter_fp_true.cfa", EXPL, SEQ_ITP, true, 0 }, + { "src/test/resources/ifelse.cfa", PRED_CART, SEQ_ITP, false, 3 }, { "src/test/resources/ifelse.cfa", PRED_BOOL, BW_BIN_ITP, false, 3 }, @@ -128,7 +139,7 @@ public static Collection data() { } @Test - public void test() throws IOException { + public void test() throws IOException, SmtLibSolverInstallerException { CFA cfa = CfaDslManager.createCfa(new FileInputStream(filePath)); CfaConfig config = new CfaConfigBuilder(domain, refinement, Z3SolverFactory.getInstance()).build(cfa, cfa.getErrorLoc().get()); @@ -137,7 +148,7 @@ public void test() throws IOException { if (result.isUnsafe()) { Trace, CfaAction> trace = CfaTraceConcretizer.concretize( (Trace, CfaAction>) result.asUnsafe().getTrace(), - Z3SolverFactory.getInstance()); + Z3SolverFactory.getInstance()); Assert.assertEquals(cexLength, trace.length()); } } diff --git a/subprojects/cfa/cfa-analysis/src/test/resources/counter_fp_true.cfa b/subprojects/cfa/cfa-analysis/src/test/resources/counter_fp_true.cfa new file mode 100644 index 0000000000..bb8b90ba84 --- /dev/null +++ b/subprojects/cfa/cfa-analysis/src/test/resources/counter_fp_true.cfa @@ -0,0 +1,17 @@ +main process cfa { + var x : fp[8:24] + + init loc L0 + loc L1 + loc L2 + loc L3 + final loc END + error loc ERR + + L0 -> L1 { x := 8'd0.23'd0 } + L1 -> L2 { assume x < 8'b10000001.23'b01000000000000000000000 } + L1 -> L3 { assume not (x < 8'b10000001.23'b01000000000000000000000) } + L2 -> L1 { x := (x fpadd[RNE] 8'b01111111.23'd0) } + L3 -> END { assume x >= 8'b10000001.23'b01000000000000000000000 } + L3 -> ERR { assume not (x >= 8'b10000001.23'b01000000000000000000000) } +} \ No newline at end of file diff --git a/subprojects/cfa/cfa-analysis/src/test/resources/fp1.cfa b/subprojects/cfa/cfa-analysis/src/test/resources/fp1.cfa new file mode 100644 index 0000000000..ee192546d0 --- /dev/null +++ b/subprojects/cfa/cfa-analysis/src/test/resources/fp1.cfa @@ -0,0 +1,21 @@ +main process cfa { + var f2 : fp[5:11] + var f3 : fp[11:53] + var f4 : fp[11:53] + var b1 : bv[4] + + init loc L1 + loc L2 + loc L3 + loc L4 + loc L5 + final loc END + error loc ERR + + L1 -> L2 { f2 := 5'b10010.10'd0 } + L2 -> L3 { f3 := fptofp[11:53][RNE] f2 } + L3 -> L4 { b1 := 4'd8 } + L4 -> L5 { f4 := fpfrombv[11:53][u][RNE] b1 } + L5 -> END { assume f3 = f4 } + L5 -> ERR { assume not (f3 = f4) } +} \ No newline at end of file diff --git a/subprojects/cfa/cfa-analysis/src/test/resources/fp2.cfa b/subprojects/cfa/cfa-analysis/src/test/resources/fp2.cfa new file mode 100644 index 0000000000..27a6d8b8b7 --- /dev/null +++ b/subprojects/cfa/cfa-analysis/src/test/resources/fp2.cfa @@ -0,0 +1,21 @@ +main process cfa { + var f2 : fp[2:3] + var f3 : fp[2:3] + var f4 : fp[2:3] + var f5 : fp[2:3] + + init loc L1 + loc L2 + loc L3 + loc L4 + loc L5 + final loc END + error loc ERR + + L1 -> L2 { f2 := 2'b01.2'b00 } + L2 -> L3 { f3 := 2'b10.2'b11 } + L3 -> L4 { f4 := f2 fpdiv[RTP] f3 } + L4 -> L5 { f5 := f2 / f3 } + L5 -> END { assume (f4 = f5) } + L5 -> ERR { assume not (f4 = f5) } +} \ No newline at end of file diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java new file mode 100644 index 0000000000..12082ecdae --- /dev/null +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java @@ -0,0 +1,113 @@ +package hu.bme.mit.theta.solver.smtlib; + +import hu.bme.mit.theta.common.logging.NullLogger; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.abstracttype.EqExpr; +import hu.bme.mit.theta.core.type.fptype.FpLeqExpr; +import hu.bme.mit.theta.core.type.fptype.FpLitExpr; +import hu.bme.mit.theta.core.type.fptype.FpType; +import hu.bme.mit.theta.core.utils.BvTestUtils; +import hu.bme.mit.theta.core.utils.FpTestUtils; +import hu.bme.mit.theta.core.utils.FpUtils; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.kframework.mpfr.BigFloat; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collection; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static hu.bme.mit.theta.core.type.fptype.FpExprs.Abs; +import static hu.bme.mit.theta.core.type.fptype.FpExprs.IsNan; +import static hu.bme.mit.theta.core.type.fptype.FpExprs.Leq; +import static hu.bme.mit.theta.core.type.fptype.FpExprs.Sub; +import static hu.bme.mit.theta.core.type.fptype.FpRoundingMode.RNE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class SmtLibSolverFPTest { + private static SmtLibSolverManager solverManager; + + @Parameterized.Parameter(0) + public Class exprType; + + @Parameterized.Parameter(1) + public Expr expected; + + @Parameterized.Parameter(2) + public Expr actual; + + @BeforeClass + public static void init() throws SmtLibSolverInstallerException, IOException { + Path home = Files.createTempDirectory("theta-solver"); + + solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); + solverManager.install("z3", "latest", "latest", null, false); + } + + @AfterClass + public static void destroy() throws SmtLibSolverInstallerException { + solverManager.uninstall("z3", "latest"); + } + + @Parameters(name = "expr: {0}, expected: {1}, actual: {2}") + public static Collection operations() { + return FpTestUtils.GetOperations().collect(Collectors.toUnmodifiableList()); + } + + @Test + public void testOperationEquals() throws SmtLibSolverInstallerException { + // Sanity check + assertNotNull(exprType); + assertNotNull(expected); + assertNotNull(actual); + + // Type checks + assertTrue( + "The type of actual is " + actual.getClass().getName() + " instead of " + exprType.getName(), + exprType.isInstance(actual) + ); + assertEquals( + "The type of expected (" + expected.getType() + ") must match the type of actual (" + actual.getType() + ")", + expected.getType(), + actual.getType() + ); + + // Equality check + final Solver solver = solverManager.getSolverFactory("z3", "latest").createSolver(); + solver.push(); + + if (expected instanceof FpLitExpr && actual.getType() instanceof FpType) { + if (((FpLitExpr) expected).isNaN()) { + //noinspection unchecked + solver.add(IsNan((Expr) actual)); + } else if (((FpLitExpr) expected).isNegativeInfinity()) { + solver.add(EqExpr.create2(expected, actual)); + } else if (((FpLitExpr) expected).isPositiveInfinity()) { + solver.add(EqExpr.create2(expected, actual)); + } else { + //noinspection unchecked + FpLeqExpr leq = Leq(Abs(Sub(RNE, (FpLitExpr) expected, (Expr) actual)), + FpUtils.bigFloatToFpLitExpr(new BigFloat("1e-2", FpUtils.getMathContext((FpType) actual.getType(), RNE)), (FpType) actual.getType())); + solver.add(leq); + } + } else { + solver.add(EqExpr.create2(expected, actual)); + } + + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + } +} From 90a5b510b7df74079438d2349d97814cec7e90c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Tue, 28 Sep 2021 14:28:04 +0200 Subject: [PATCH 90/99] Fix solver test issues --- .../solver/solver-smtlib/build.gradle.kts | 1 + .../generic/GenericSmtLibTermTransformer.java | 2 +- .../solver/smtlib/SmtLibSolverFPTest.java | 3 -- .../bme/mit/theta/solver/z3/Z3ItpSolver.java | 48 ++++++++++--------- .../mit/theta/solver/z3/Z3SolverFPTest.java | 0 .../bme/mit/theta/solver/z3/Z3SolverTest.java | 1 + 6 files changed, 28 insertions(+), 27 deletions(-) rename subprojects/{common => solver}/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverFPTest.java (100%) diff --git a/subprojects/solver/solver-smtlib/build.gradle.kts b/subprojects/solver/solver-smtlib/build.gradle.kts index 92ad3fa008..ea9f63f693 100644 --- a/subprojects/solver/solver-smtlib/build.gradle.kts +++ b/subprojects/solver/solver-smtlib/build.gradle.kts @@ -8,4 +8,5 @@ dependencies { compile(project(":theta-core")) compile(project(":theta-solver")) compile("org.apache.commons:commons-compress:1.20") + testImplementation(testFixtures(project(":theta-core"))) } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java index a397343dd6..3cb7e5c0c3 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibTermTransformer.java @@ -324,7 +324,7 @@ public LitExpr> toArrayLitExpr return null; } else if(arrayLitExpr instanceof IteExpr) { - final var entryExprsBuilder = new ImmutableList.Builder, Expr>>(); + final var entryExprsBuilder = new ImmutableList.Builder, ? extends Expr>>(); var iteExpr = (IteExpr) arrayLitExpr; while (true) { entryExprsBuilder.add(Tuple2.of((Expr) iteExpr.getCond().getOps().get(1), iteExpr.getThen())); diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java index 12082ecdae..91ef5687ad 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java @@ -6,7 +6,6 @@ import hu.bme.mit.theta.core.type.fptype.FpLeqExpr; import hu.bme.mit.theta.core.type.fptype.FpLitExpr; import hu.bme.mit.theta.core.type.fptype.FpType; -import hu.bme.mit.theta.core.utils.BvTestUtils; import hu.bme.mit.theta.core.utils.FpTestUtils; import hu.bme.mit.theta.core.utils.FpUtils; import hu.bme.mit.theta.solver.Solver; @@ -20,11 +19,9 @@ import org.kframework.mpfr.BigFloat; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.util.Collection; import java.util.stream.Collectors; -import java.util.stream.Stream; import static hu.bme.mit.theta.core.type.fptype.FpExprs.Abs; import static hu.bme.mit.theta.core.type.fptype.FpExprs.IsNan; diff --git a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java index 3cfc31e3e2..bb03052c47 100644 --- a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java +++ b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java @@ -15,29 +15,29 @@ */ package hu.bme.mit.theta.solver.z3; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -import java.util.Collection; import hu.bme.mit.theta.common.container.Containers; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - import hu.bme.mit.theta.core.model.Valuation; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.booltype.BoolType; import hu.bme.mit.theta.solver.Interpolant; import hu.bme.mit.theta.solver.ItpMarker; +import hu.bme.mit.theta.solver.ItpMarkerTree; import hu.bme.mit.theta.solver.ItpPattern; import hu.bme.mit.theta.solver.ItpSolver; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.Stack; -import hu.bme.mit.theta.solver.impl.ItpPatternImpl; import hu.bme.mit.theta.solver.impl.StackImpl; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + final class Z3ItpSolver implements ItpSolver, Solver { private final Z3TransformationManager transformationManager; @@ -64,13 +64,13 @@ public Z3ItpSolver(final Z3SymbolTable symbolTable, final Z3TransformationManage } @Override - public ItpPattern createPattern(final ItpMarker marker) { - checkNotNull(marker); - return new ItpPatternImpl(marker); + public ItpPattern createTreePattern(final ItpMarkerTree root) { + checkNotNull(root); + return Z3ItpPattern.of(root); } @Override - public ItpMarker createMarker() { + public Z3ItpMarker createMarker() { final Z3ItpMarker marker = new Z3ItpMarker(); markers.add(marker); return marker; @@ -90,9 +90,11 @@ public void add(final ItpMarker marker, final Expr assertion) { @Override public Interpolant getInterpolant(final ItpPattern pattern) { checkState(solver.getStatus() == SolverStatus.UNSAT, "Cannot get interpolant if status is not UNSAT."); + checkArgument(pattern instanceof Z3ItpPattern); + final Z3ItpPattern z3ItpPattern = (Z3ItpPattern) pattern; final com.microsoft.z3.Expr proof = z3Solver.getProof(); - final com.microsoft.z3.Expr term = patternToTerm(pattern); + final com.microsoft.z3.Expr term = patternToTerm(z3ItpPattern.getRoot()); final com.microsoft.z3.Params params = z3Context.mkParams(); final com.microsoft.z3.BoolExpr[] itpArray = z3Context.GetInterpolant(proof, term, params); @@ -104,31 +106,31 @@ public Interpolant getInterpolant(final ItpPattern pattern) { } final Map> itpMap = Containers.createMap(); - buildItpMapFormList(pattern, itpList, itpMap); + buildItpMapFormList(z3ItpPattern.getRoot(), itpList, itpMap); return new Z3Interpolant(itpMap); } - private com.microsoft.z3.BoolExpr patternToTerm(final ItpPattern pattern) { + private com.microsoft.z3.BoolExpr patternToTerm(final ItpMarkerTree markerTree) { final Collection opTerms = new LinkedList<>(); - final Z3ItpMarker marker = (Z3ItpMarker) pattern.getMarker(); + final Z3ItpMarker marker = (Z3ItpMarker) markerTree.getMarker(); opTerms.addAll(marker.getTerms()); - for (final ItpPattern child : pattern.getChildren()) { + for (final ItpMarkerTree child : markerTree.getChildren()) { final com.microsoft.z3.BoolExpr childTerm = patternToTerm(child); opTerms.add(childTerm); } final com.microsoft.z3.BoolExpr andTerm = z3Context - .mkAnd(opTerms.toArray(new com.microsoft.z3.BoolExpr[opTerms.size()])); + .mkAnd(opTerms.toArray(new com.microsoft.z3.BoolExpr[opTerms.size()])); final com.microsoft.z3.BoolExpr term = z3Context.MkInterpolant(andTerm); return term; } - private void buildItpMapFormList(final ItpPattern pattern, final List> itpList, + private void buildItpMapFormList(final ItpMarkerTree pattern, final List> itpList, final Map> itpMap) { - for (final ItpPattern child : pattern.getChildren()) { + for (final ItpMarkerTree child : pattern.getChildren()) { buildItpMapFormList(child, itpList, itpMap); } final ItpMarker marker = pattern.getMarker(); @@ -198,4 +200,4 @@ public void close() { z3Context.close(); solver.close(); } -} +} \ No newline at end of file diff --git a/subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverFPTest.java b/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverFPTest.java similarity index 100% rename from subprojects/common/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverFPTest.java rename to subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverFPTest.java diff --git a/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java b/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java index 6088e4ba22..f77876b373 100644 --- a/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java +++ b/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java @@ -37,6 +37,7 @@ import hu.bme.mit.theta.core.utils.BvUtils; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverStatus; +import hu.bme.mit.theta.solver.UCSolver; import org.junit.Before; import org.junit.Test; From 640ad2481f47b43cd80b39c3af6931d79932a58b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 27 Sep 2021 16:20:39 +0200 Subject: [PATCH 91/99] Add SolverManager --- .../java/hu/bme/mit/theta/cfa/cli/CfaCli.java | 35 +++++++------- .../theta/solver/smtlib/cli/SmtLibCli.java | 10 +--- .../solver/smtlib/SmtLibSolverManager.java | 47 ++++++++++++++++++- .../mit/theta/solver/z3/Z3SolverManager.java | 26 ++++++++++ .../bme/mit/theta/solver/SolverManager.java | 26 ++++++++++ 5 files changed, 116 insertions(+), 28 deletions(-) create mode 100644 subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverManager.java create mode 100644 subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverManager.java diff --git a/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java b/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java index cd3c64978e..4cf3bbf14d 100644 --- a/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java +++ b/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java @@ -52,6 +52,7 @@ import hu.bme.mit.theta.cfa.analysis.utils.CfaVisualizer; import hu.bme.mit.theta.cfa.dsl.CfaDslManager; import hu.bme.mit.theta.common.CliUtils; +import hu.bme.mit.theta.common.OsHelper; import hu.bme.mit.theta.common.logging.ConsoleLogger; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.common.logging.Logger.Level; @@ -61,8 +62,10 @@ import hu.bme.mit.theta.common.visualization.Graph; import hu.bme.mit.theta.common.visualization.writer.GraphvizWriter; import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.SolverManager; import hu.bme.mit.theta.solver.smtlib.SmtLibSolverManager; import hu.bme.mit.theta.solver.z3.Z3SolverFactory; +import hu.bme.mit.theta.solver.z3.Z3SolverManager; import static com.google.common.base.Preconditions.checkNotNull; @@ -96,7 +99,7 @@ public class CfaCli { String refinementSolver; @Parameter(names = "--home", description = "The path of the solver registry") - String home = Path.of(System.getProperty("user.home"), ".theta").toAbsolutePath().toString(); + String home = SmtLibSolverManager.HOME.toAbsolutePath().toString(); @Parameter(names = "--model", description = "Path of the input CFA model", required = true) String model; @@ -177,8 +180,12 @@ private void run() { } try { - final var homePath = Path.of(home); - final var smtLibSolverManager = SmtLibSolverManager.create(homePath, logger); + SolverManager.registerSolverManager(Z3SolverManager.getInstance()); + if(OsHelper.getOs().equals(OsHelper.OperatingSystem.LINUX)) { + final var homePath = Path.of(home); + final var smtLibSolverManager = SmtLibSolverManager.create(homePath, logger); + SolverManager.registerSolverManager(smtLibSolverManager); + } final Stopwatch sw = Stopwatch.createStarted(); final CFA cfa = loadModel(); @@ -210,30 +217,20 @@ private void run() { checkNotNull(errLoc, "Error location must be specified in CFA or as argument"); final SolverFactory abstractionSolverFactory; - if(abstractionSolver != null && !abstractionSolver.equals("Z3")) { - final var s = abstractionSolver.split("\\."); - abstractionSolverFactory = smtLibSolverManager.getSolverFactory(s[0], s[1]); - } - else if(!solver.equals("Z3")) { - final var s = solver.split("\\."); - abstractionSolverFactory = smtLibSolverManager.getSolverFactory(s[0], s[1]); + if(abstractionSolver != null) { + abstractionSolverFactory = SolverManager.resolveSolverFactory(abstractionSolver); } else { - abstractionSolverFactory = Z3SolverFactory.getInstance(); + abstractionSolverFactory = SolverManager.resolveSolverFactory(solver); } final SolverFactory refinementSolverFactory; - if(refinementSolver != null && !refinementSolver.equals("Z3")) { - final var s = refinementSolver.split("\\."); - refinementSolverFactory = smtLibSolverManager.getSolverFactory(s[0], s[1]); - } - else if(!solver.equals("Z3")) { - final var s = solver.split("\\."); - refinementSolverFactory = smtLibSolverManager.getSolverFactory(s[0], s[1]); + if(refinementSolver != null) { + refinementSolverFactory = SolverManager.resolveSolverFactory(refinementSolver); } else { - refinementSolverFactory = Z3SolverFactory.getInstance(); + refinementSolverFactory = SolverManager.resolveSolverFactory(solver); } final CfaConfig configuration = buildConfiguration(cfa, errLoc, abstractionSolverFactory, refinementSolverFactory); diff --git a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java index 4888685296..e16c3ff738 100644 --- a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java +++ b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java @@ -26,7 +26,7 @@ public class SmtLibCli { static class MainParams { @Parameter(names = "--home", description = "The path of the solver registry") - String home = Path.of(System.getProperty("user.home"), ".theta").toAbsolutePath().toString(); + String home = SmtLibSolverManager.HOME.toAbsolutePath().toString(); @Parameter(names = "--loglevel", description = "Detailedness of logging") Logger.Level logLevel = Logger.Level.MAINSTEP; @@ -293,13 +293,7 @@ else if(Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop } private static Tuple2 decodeVersionString(final String version) { - final var versionArr = version.split(":"); - - if(versionArr.length != 2) { - throw new IllegalArgumentException("Invalid version string: " + version); - } - - return Tuple2.of(versionArr[0], versionArr[1]); + return Tuple2.of(SmtLibSolverManager.getSolverName(version), SmtLibSolverManager.getSolverVersion(version)); } private Path createIfNotExists(final Path path) throws IOException { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java index 5e3d8b6b72..c244fe7195 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java @@ -4,6 +4,7 @@ import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.SolverManager; import hu.bme.mit.theta.solver.smtlib.impl.boolector.BoolectorSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.impl.princess.PrincessSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.impl.smtinterpol.SMTInterpolSmtLibSolverInstaller; @@ -29,7 +30,9 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -public final class SmtLibSolverManager { +public final class SmtLibSolverManager extends SolverManager { + public static final Path HOME = Path.of(System.getProperty("user.home"), ".theta"); + private static final Map> installerDeclarations = new HashMap<>(); private static Tuple2> genericInstallerDeclaration; @@ -53,6 +56,36 @@ public static void registerGenericInsta registerGenericInstaller("generic", GenericSmtLibSolverInstaller.class); } + public static String getSolverName(final String name) { + final var solverName = decodeSolverName(name, 0); + if(solverName != null) { + return solverName; + } + else { + throw new IllegalArgumentException("Invalid version string: " + name); + } + } + + public static String getSolverVersion(final String name) { + final var solverVersion = decodeSolverName(name, 1); + if(solverVersion != null) { + return solverVersion; + } + else { + throw new IllegalArgumentException("Invalid version string: " + name); + } + } + + private static String decodeSolverName(final String name, final int part) { + final var versionArr = name.split(":"); + + if(versionArr.length != 2) { + return null; + } + + return versionArr[part]; + } + private final Path home; private final Logger logger; @@ -98,6 +131,12 @@ public String getGenericInstallerName() { return genericInstaller.get1(); } + @Override + public boolean managesSolver(final String name) { + final var solverName = decodeSolverName(name, 0); + return solverName != null && installers.containsKey(solverName); + } + public void install(final String solver, final String version, final String name, final Path solverPath, final boolean installUnsupported) throws SmtLibSolverInstallerException { checkArgument(!solver.equals(genericInstaller.get1())); @@ -169,6 +208,12 @@ public Path getArgsFile(final String solver, final String version) throws SmtLib return installers.get(solver).getArgsFile(home.resolve(solver), getVersionString(solver, version, true)); } + @Override + public SolverFactory getSolverFactory(final String name) throws SmtLibSolverInstallerException { + checkArgument(managesSolver(name)); + return getSolverFactory(getSolverName(name), getSolverVersion(name)); + } + public SolverFactory getSolverFactory(final String solver, final String version) throws SmtLibSolverInstallerException { if(!installers.containsKey(solver)) { throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); diff --git a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverManager.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverManager.java new file mode 100644 index 0000000000..1eeb1b444c --- /dev/null +++ b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverManager.java @@ -0,0 +1,26 @@ +package hu.bme.mit.theta.solver.z3; + +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.SolverManager; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class Z3SolverManager extends SolverManager { + private static final Z3SolverManager INSTANCE = new Z3SolverManager(); + public static Z3SolverManager getInstance() { + return INSTANCE; + } + + private static final String NAME = "Z3"; + + @Override + public boolean managesSolver(final String name) { + return NAME.equals(name); + } + + @Override + public SolverFactory getSolverFactory(final String name) { + checkArgument(NAME.equals(name)); + return Z3SolverFactory.getInstance(); + } +} diff --git a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverManager.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverManager.java new file mode 100644 index 0000000000..a9931af725 --- /dev/null +++ b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverManager.java @@ -0,0 +1,26 @@ +package hu.bme.mit.theta.solver; + +import java.util.ArrayList; +import java.util.Collection; + +public abstract class SolverManager { + private static final Collection solverManagers = new ArrayList<>(); + + public static void registerSolverManager(final SolverManager solverManager) { + solverManagers.add(solverManager); + } + + public static SolverFactory resolveSolverFactory(final String name) throws Exception { + for(final SolverManager solverManager : solverManagers) { + if(solverManager.managesSolver(name)) { + return solverManager.getSolverFactory(name); + } + } + + throw new UnsupportedOperationException("Solver " + name + " not supported"); + } + + public abstract boolean managesSolver(final String name); + public abstract SolverFactory getSolverFactory(final String name) throws Exception; + +} From fdaf24a2fc24fe10d7c2a7296a338f3a246fa9a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 27 Sep 2021 17:00:14 +0200 Subject: [PATCH 92/99] Speed up tests --- .../java/hu/bme/mit/theta/cfa/analysis/CfaTest.java | 4 ++-- .../mit/theta/solver/smtlib/SmtLibItpSolverTest.java | 12 ++++++++---- .../mit/theta/solver/smtlib/SmtLibSolverBVTest.java | 10 +++++++--- .../mit/theta/solver/smtlib/SmtLibSolverFPTest.java | 10 +++++++--- .../mit/theta/solver/smtlib/SmtLibSolverTest.java | 12 ++++++++---- .../java/hu/bme/mit/theta/solver/SolverStub.java | 2 ++ 6 files changed, 34 insertions(+), 16 deletions(-) diff --git a/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java b/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java index 2ae883244d..5e282dcca2 100644 --- a/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java +++ b/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java @@ -121,11 +121,11 @@ public static Collection data() { { "src/test/resources/counter_bv_false.cfa", PRED_CART, UCB, false, 13 }, - { "src/test/resources/fp1.cfa", PRED_CART, NWT_IT_WP, false, 5 }, + { "src/test/resources/fp1.cfa", PRED_CART, NWT_IT_WP, true, 0 }, { "src/test/resources/fp2.cfa", PRED_CART, NWT_IT_WP, false, 5 }, - { "src/test/resources/counter_fp_true.cfa", EXPL, SEQ_ITP, true, 0 }, + { "src/test/resources/counter_fp_true.cfa", EXPL, NWT_IT_WP, true, 0 }, { "src/test/resources/ifelse.cfa", PRED_CART, SEQ_ITP, false, 3 }, diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java index 50b4cf54d2..02b1f41533 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java @@ -59,22 +59,26 @@ import static hu.bme.mit.theta.solver.ItpMarkerTree.Tree; public final class SmtLibItpSolverTest { + private static boolean solverInstalled = false; private static SmtLibSolverManager solverManager; private static SolverFactory solverFactory; @BeforeClass public static void init() throws SmtLibSolverInstallerException, IOException { - Path home = Files.createTempDirectory("theta-solver"); + Path home = SmtLibSolverManager.HOME; solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); - solverManager.install("z3", "4.5.0", "4.5.0", null, false); + try { + solverManager.install("z3", "4.5.0", "4.5.0", null, false); + solverInstalled = true; + } catch(SmtLibSolverInstallerException e) {} - solverFactory = solverManager.getSolverFactory("z3", "latest"); + solverFactory = solverManager.getSolverFactory("z3", "4.5.0"); } @AfterClass public static void destroy() throws SmtLibSolverInstallerException { - solverManager.uninstall("z3", "latest"); + if(solverInstalled) solverManager.uninstall("z3", "4.5.0"); } ItpSolver solver; diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java index b670039ca2..891b40fb61 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java @@ -27,6 +27,7 @@ @RunWith(Parameterized.class) public class SmtLibSolverBVTest { + private static boolean solverInstalled = false; private static SmtLibSolverManager solverManager; @Parameterized.Parameter(0) @@ -40,15 +41,18 @@ public class SmtLibSolverBVTest { @BeforeClass public static void init() throws SmtLibSolverInstallerException, IOException { - Path home = Files.createTempDirectory("theta-solver"); + Path home = SmtLibSolverManager.HOME; solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); - solverManager.install("z3", "latest", "latest", null, false); + try { + solverManager.install("z3", "latest", "latest", null, false); + solverInstalled = true; + } catch(SmtLibSolverInstallerException e) {} } @AfterClass public static void destroy() throws SmtLibSolverInstallerException { - solverManager.uninstall("z3", "latest"); + if(solverInstalled) solverManager.uninstall("z3", "latest"); } @Parameters(name = "expr: {0}, expected: {1}, actual: {2}") diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java index 91ef5687ad..c1afced30d 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java @@ -35,6 +35,7 @@ @RunWith(Parameterized.class) public class SmtLibSolverFPTest { + private static boolean solverInstalled = false; private static SmtLibSolverManager solverManager; @Parameterized.Parameter(0) @@ -48,15 +49,18 @@ public class SmtLibSolverFPTest { @BeforeClass public static void init() throws SmtLibSolverInstallerException, IOException { - Path home = Files.createTempDirectory("theta-solver"); + Path home = SmtLibSolverManager.HOME; solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); - solverManager.install("z3", "latest", "latest", null, false); + try { + solverManager.install("z3", "4.5.0", "4.5.0", null, false); + solverInstalled = true; + } catch(SmtLibSolverInstallerException e) {} } @AfterClass public static void destroy() throws SmtLibSolverInstallerException { - solverManager.uninstall("z3", "latest"); + if(solverInstalled) solverManager.uninstall("z3", "4.5.0"); } @Parameters(name = "expr: {0}, expected: {1}, actual: {2}") diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index 800922a1d5..d15461d558 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -53,22 +53,26 @@ import static org.junit.Assert.assertTrue; public final class SmtLibSolverTest { + private static boolean solverInstalled = false; private static SmtLibSolverManager solverManager; private static SolverFactory solverFactory; @BeforeClass public static void init() throws SmtLibSolverInstallerException, IOException { - Path home = Files.createTempDirectory("theta-solver"); + Path home = SmtLibSolverManager.HOME; solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); - solverManager.install("z3", "latest", "latest", null, false); + try { + solverManager.install("z3", "4.5.0", "4.5.0", null, false); + solverInstalled = true; + } catch(SmtLibSolverInstallerException e) {} - solverFactory = solverManager.getSolverFactory("z3", "latest"); + solverFactory = solverManager.getSolverFactory("z3", "4.5.0"); } @AfterClass public static void destroy() throws SmtLibSolverInstallerException { - solverManager.uninstall("z3", "latest"); + if(solverInstalled) solverManager.uninstall("z3", "4.5.0"); } @Test diff --git a/subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java b/subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java index 78b76d2eee..e913522d01 100644 --- a/subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java +++ b/subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java @@ -67,4 +67,6 @@ public Collection> getAssertions() { return null; } + @Override + public void close() {} } From d0cd4e4cab61f0aee3fa3bb5c3eaa6d310eccd42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 27 Sep 2021 19:04:40 +0200 Subject: [PATCH 93/99] Make SolverManager AutoCloseable --- .../bme/mit/theta/cfa/analysis/CfaTest.java | 137 +++++++++++------- .../java/hu/bme/mit/theta/cfa/cli/CfaCli.java | 2 +- .../solver/smtlib/SmtLibSolverManager.java | 52 ++++++- .../solver/smtlib/SmtLibSolverBVTest.java | 18 ++- .../solver/smtlib/SmtLibSolverFPTest.java | 43 +++--- .../bme/mit/theta/solver/z3/Z3ItpSolver.java | 1 - .../mit/theta/solver/z3/Z3SolverManager.java | 64 +++++++- .../bme/mit/theta/solver/SolverFactory.java | 1 + .../bme/mit/theta/solver/SolverManager.java | 15 +- 9 files changed, 241 insertions(+), 92 deletions(-) diff --git a/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java b/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java index 5e282dcca2..96bc0e767a 100644 --- a/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java +++ b/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/CfaTest.java @@ -25,24 +25,29 @@ import hu.bme.mit.theta.cfa.analysis.config.CfaConfig; import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder; import hu.bme.mit.theta.cfa.dsl.CfaDslManager; +import hu.bme.mit.theta.common.OsHelper; import hu.bme.mit.theta.common.logging.NullLogger; +import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.SolverManager; import hu.bme.mit.theta.solver.smtlib.SmtLibSolverManager; -import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; -import hu.bme.mit.theta.solver.z3.Z3SolverFactory; +import hu.bme.mit.theta.solver.z3.Z3SolverManager; import org.junit.Assert; +import org.junit.Assume; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.Arrays; import java.util.Collection; -import static hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Domain.*; -import static hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Refinement.*; +import static hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Domain.EXPL; +import static hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Domain.PRED_BOOL; +import static hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Domain.PRED_CART; +import static hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Refinement.BW_BIN_ITP; +import static hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Refinement.NWT_IT_WP; +import static hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Refinement.SEQ_ITP; +import static hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Refinement.UCB; @RunWith(value = Parameterized.class) public class CfaTest { @@ -61,95 +66,121 @@ public class CfaTest { @Parameterized.Parameter(value = 4) public int cexLength; - @Parameterized.Parameters(name = "{index}: {0}, {1}, {2}, {3}, {4}") + @Parameterized.Parameter(value = 5) + public String solver; + + @Parameterized.Parameters(name = "{index}: {0}, {1}, {2}, {3}, {4}, {5}") public static Collection data() { return Arrays.asList(new Object[][] { - { "src/test/resources/arithmetic-bool00.cfa", PRED_CART, SEQ_ITP, false, 15 }, + { "src/test/resources/arithmetic-bool00.cfa", PRED_CART, SEQ_ITP, false, 15, "Z3" }, + + { "src/test/resources/arithmetic-bool00.cfa", PRED_BOOL, BW_BIN_ITP, false, 15, "Z3" }, + + { "src/test/resources/arithmetic-bool00.cfa", EXPL, SEQ_ITP, false, 15, "Z3" }, - { "src/test/resources/arithmetic-bool00.cfa", PRED_BOOL, BW_BIN_ITP, false, 15 }, + { "src/test/resources/arithmetic-bool01.cfa", PRED_CART, SEQ_ITP, false, 15, "Z3" }, - { "src/test/resources/arithmetic-bool00.cfa", EXPL, SEQ_ITP, false, 15 }, + { "src/test/resources/arithmetic-bool01.cfa", PRED_BOOL, BW_BIN_ITP, false, 15, "Z3" }, - { "src/test/resources/arithmetic-bool01.cfa", PRED_CART, SEQ_ITP, false, 15 }, + { "src/test/resources/arithmetic-bool01.cfa", EXPL, SEQ_ITP, false, 15, "Z3" }, - { "src/test/resources/arithmetic-bool01.cfa", PRED_BOOL, BW_BIN_ITP, false, 15 }, + { "src/test/resources/arithmetic-bool10.cfa", PRED_BOOL, SEQ_ITP, false, 15, "Z3" }, - { "src/test/resources/arithmetic-bool01.cfa", EXPL, SEQ_ITP, false, 15 }, + { "src/test/resources/arithmetic-bool10.cfa", PRED_CART, BW_BIN_ITP, false, 15, "Z3" }, - { "src/test/resources/arithmetic-bool10.cfa", PRED_BOOL, SEQ_ITP, false, 15 }, + { "src/test/resources/arithmetic-bool10.cfa", EXPL, SEQ_ITP, false, 15, "Z3" }, - { "src/test/resources/arithmetic-bool10.cfa", PRED_CART, BW_BIN_ITP, false, 15 }, + { "src/test/resources/arithmetic-bool11.cfa", PRED_CART, SEQ_ITP, false, 15, "Z3" }, - { "src/test/resources/arithmetic-bool10.cfa", EXPL, SEQ_ITP, false, 15 }, + { "src/test/resources/arithmetic-bool11.cfa", PRED_BOOL, BW_BIN_ITP, false, 15, "Z3" }, - { "src/test/resources/arithmetic-bool11.cfa", PRED_CART, SEQ_ITP, false, 15 }, + { "src/test/resources/arithmetic-bool11.cfa", EXPL, SEQ_ITP, false, 15, "Z3" }, - { "src/test/resources/arithmetic-bool11.cfa", PRED_BOOL, BW_BIN_ITP, false, 15 }, + { "src/test/resources/arithmetic-int.cfa", PRED_CART, SEQ_ITP, false, 13, "Z3" }, - { "src/test/resources/arithmetic-bool11.cfa", EXPL, SEQ_ITP, false, 15 }, + { "src/test/resources/arithmetic-int.cfa", PRED_BOOL, BW_BIN_ITP, false, 13, "Z3" }, - { "src/test/resources/arithmetic-int.cfa", PRED_CART, SEQ_ITP, false, 13 }, + { "src/test/resources/arithmetic-int.cfa", EXPL, SEQ_ITP, false, 13, "Z3" }, - { "src/test/resources/arithmetic-int.cfa", PRED_BOOL, BW_BIN_ITP, false, 13 }, + { "src/test/resources/arithmetic-mod.cfa", PRED_CART, SEQ_ITP, true, 0, "Z3" }, - { "src/test/resources/arithmetic-int.cfa", EXPL, SEQ_ITP, false, 13 }, + { "src/test/resources/arithmetic-mod.cfa", EXPL, BW_BIN_ITP, true, 0, "Z3" }, - { "src/test/resources/arithmetic-mod.cfa", PRED_CART, SEQ_ITP, true, 0 }, + { "src/test/resources/arrays.cfa", PRED_CART, SEQ_ITP, false, 8, "Z3" }, - { "src/test/resources/arithmetic-mod.cfa", EXPL, BW_BIN_ITP, true, 0 }, + { "src/test/resources/arrays.cfa", PRED_BOOL, BW_BIN_ITP, false, 8, "Z3" }, - { "src/test/resources/arrays.cfa", PRED_CART, SEQ_ITP, false, 8 }, + { "src/test/resources/arrayinit.cfa", PRED_CART, BW_BIN_ITP, false, 3, "Z3" }, - { "src/test/resources/arrays.cfa", PRED_BOOL, BW_BIN_ITP, false, 8 }, + { "src/test/resources/arrays.cfa", EXPL, SEQ_ITP, false, 8, "Z3" }, - { "src/test/resources/arrayinit.cfa", PRED_CART, BW_BIN_ITP, false, 3 }, + { "src/test/resources/counter5_true.cfa", PRED_BOOL, SEQ_ITP, true, 0, "Z3" }, - { "src/test/resources/arrays.cfa", EXPL, SEQ_ITP, false, 8 }, + { "src/test/resources/counter5_true.cfa", PRED_CART, BW_BIN_ITP, true, 0, "Z3" }, - { "src/test/resources/counter5_true.cfa", PRED_BOOL, SEQ_ITP, true, 0 }, + { "src/test/resources/counter5_true.cfa", EXPL, SEQ_ITP, true, 0, "Z3" }, - { "src/test/resources/counter5_true.cfa", PRED_CART, BW_BIN_ITP, true, 0 }, + { "src/test/resources/counter_bv_true.cfa", EXPL, NWT_IT_WP, true, 0, "Z3" }, - { "src/test/resources/counter5_true.cfa", EXPL, SEQ_ITP, true, 0 }, + { "src/test/resources/counter_bv_false.cfa", EXPL, NWT_IT_WP, false, 13, "Z3" }, - { "src/test/resources/counter_bv_true.cfa", EXPL, NWT_IT_WP, true, 0 }, + { "src/test/resources/counter_bv_true.cfa", PRED_CART, NWT_IT_WP, true, 0, "Z3" }, - { "src/test/resources/counter_bv_false.cfa", EXPL, NWT_IT_WP, false, 13 }, + { "src/test/resources/counter_bv_false.cfa", PRED_CART, UCB, false, 13, "Z3" }, - { "src/test/resources/counter_bv_true.cfa", PRED_CART, NWT_IT_WP, true, 0 }, + { "src/test/resources/counter_bv_true.cfa", EXPL, SEQ_ITP, true, 0, "mathsat:latest" }, - { "src/test/resources/counter_bv_false.cfa", PRED_CART, UCB, false, 13 }, + { "src/test/resources/counter_bv_false.cfa", EXPL, SEQ_ITP, false, 13, "mathsat:latest" }, - { "src/test/resources/fp1.cfa", PRED_CART, NWT_IT_WP, true, 0 }, + { "src/test/resources/fp1.cfa", PRED_CART, NWT_IT_WP, true, 0, "Z3" }, - { "src/test/resources/fp2.cfa", PRED_CART, NWT_IT_WP, false, 5 }, + { "src/test/resources/fp2.cfa", PRED_CART, NWT_IT_WP, false, 5, "Z3" }, - { "src/test/resources/counter_fp_true.cfa", EXPL, NWT_IT_WP, true, 0 }, + { "src/test/resources/counter_fp_true.cfa", EXPL, NWT_IT_WP, true, 0, "Z3" }, - { "src/test/resources/ifelse.cfa", PRED_CART, SEQ_ITP, false, 3 }, + { "src/test/resources/ifelse.cfa", PRED_CART, SEQ_ITP, false, 3, "Z3" }, - { "src/test/resources/ifelse.cfa", PRED_BOOL, BW_BIN_ITP, false, 3 }, + { "src/test/resources/ifelse.cfa", PRED_BOOL, BW_BIN_ITP, false, 3, "Z3" }, - { "src/test/resources/ifelse.cfa", EXPL, SEQ_ITP, false, 3 }, + { "src/test/resources/ifelse.cfa", EXPL, SEQ_ITP, false, 3, "Z3" }, - { "src/test/resources/locking.cfa", PRED_CART, SEQ_ITP, true, 0 }, + { "src/test/resources/locking.cfa", PRED_CART, SEQ_ITP, true, 0, "Z3" }, }); } @Test - public void test() throws IOException, SmtLibSolverInstallerException { - CFA cfa = CfaDslManager.createCfa(new FileInputStream(filePath)); - CfaConfig config - = new CfaConfigBuilder(domain, refinement, Z3SolverFactory.getInstance()).build(cfa, cfa.getErrorLoc().get()); - SafetyResult result = config.check(); - Assert.assertEquals(isSafe, result.isSafe()); - if (result.isUnsafe()) { - Trace, CfaAction> trace = CfaTraceConcretizer.concretize( + public void test() throws Exception { + SolverManager.registerSolverManager(Z3SolverManager.create()); + if(OsHelper.getOs().equals(OsHelper.OperatingSystem.LINUX)) { + SolverManager.registerSolverManager(SmtLibSolverManager.create(SmtLibSolverManager.HOME, NullLogger.getInstance())); + } + + final SolverFactory solverFactory; + try { + solverFactory = SolverManager.resolveSolverFactory(solver); + } + catch (Exception e) { + Assume.assumeNoException(e); + return; + } + + try { + CFA cfa = CfaDslManager.createCfa(new FileInputStream(filePath)); + CfaConfig config + = new CfaConfigBuilder(domain, refinement, solverFactory).build(cfa, cfa.getErrorLoc().get()); + SafetyResult result = config.check(); + Assert.assertEquals(isSafe, result.isSafe()); + if (result.isUnsafe()) { + Trace, CfaAction> trace = CfaTraceConcretizer.concretize( (Trace, CfaAction>) result.asUnsafe().getTrace(), - Z3SolverFactory.getInstance()); - Assert.assertEquals(cexLength, trace.length()); + solverFactory); + Assert.assertEquals(cexLength, trace.length()); + } + } + finally { + SolverManager.closeAll(); } } diff --git a/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java b/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java index 4cf3bbf14d..7d30c2eeaa 100644 --- a/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java +++ b/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java @@ -180,7 +180,7 @@ private void run() { } try { - SolverManager.registerSolverManager(Z3SolverManager.getInstance()); + SolverManager.registerSolverManager(Z3SolverManager.create()); if(OsHelper.getOs().equals(OsHelper.OperatingSystem.LINUX)) { final var homePath = Path.of(home); final var smtLibSolverManager = SmtLibSolverManager.create(homePath, logger); diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java index c244fe7195..3095b25ad9 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverManager.java @@ -3,8 +3,12 @@ import com.google.common.collect.ImmutableList; import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverBase; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.SolverManager; +import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.smtlib.impl.boolector.BoolectorSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.impl.princess.PrincessSmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.impl.smtinterpol.SMTInterpolSmtLibSolverInstaller; @@ -21,8 +25,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -92,6 +98,9 @@ private static String decodeSolverName(final String name, final int part) { private final Map installers; private final Tuple2 genericInstaller; + private boolean closed = false; + private final Set instantiatedSolvers; + private SmtLibSolverManager(final Path home, final Logger logger) { this.logger = logger; checkNotNull(home); @@ -120,6 +129,7 @@ private SmtLibSolverManager(final Path home, final Logger logger) { throw new RuntimeException(e); } + this.instantiatedSolvers = new HashSet<>(); } public static SmtLibSolverManager create(final Path home, final Logger logger) throws IOException { @@ -219,7 +229,7 @@ public SolverFactory getSolverFactory(final String solver, final String version) throw new SmtLibSolverInstallerException(String.format("Unknown solver: %s", solver)); } - return installers.get(solver).getSolverFactory(home.resolve(solver), getVersionString(solver, version, true)); + return new ManagedFactory(installers.get(solver).getSolverFactory(home.resolve(solver), getVersionString(solver, version, true))); } public List getSupportedSolvers() { @@ -284,4 +294,44 @@ private static Path createIfNotExists(final Path path) throws IOException { } return path; } + + @Override + public void close() throws Exception { + for(final var solver : instantiatedSolvers) { + solver.close(); + } + closed = true; + } + + private final class ManagedFactory implements SolverFactory { + private final SolverFactory solverFactory; + + private ManagedFactory(final SolverFactory solverFactory) { + this.solverFactory = solverFactory; + } + + @Override + public Solver createSolver() { + checkState(!closed, "Solver manager was closed"); + final var solver = solverFactory.createSolver(); + instantiatedSolvers.add(solver); + return solver; + } + + @Override + public UCSolver createUCSolver() { + checkState(!closed, "Solver manager was closed"); + final var solver = solverFactory.createUCSolver(); + instantiatedSolvers.add(solver); + return solver; + } + + @Override + public ItpSolver createItpSolver() { + checkState(!closed, "Solver manager was closed"); + final var solver = solverFactory.createItpSolver(); + instantiatedSolvers.add(solver); + return solver; + } + } } diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java index 891b40fb61..cc4d044a8d 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java @@ -27,6 +27,7 @@ @RunWith(Parameterized.class) public class SmtLibSolverBVTest { + private static final String SOLVER = "princess"; private static boolean solverInstalled = false; private static SmtLibSolverManager solverManager; @@ -45,14 +46,14 @@ public static void init() throws SmtLibSolverInstallerException, IOException { solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); try { - solverManager.install("z3", "latest", "latest", null, false); + solverManager.install(SOLVER, "latest", "latest", null, false); solverInstalled = true; } catch(SmtLibSolverInstallerException e) {} } @AfterClass public static void destroy() throws SmtLibSolverInstallerException { - if(solverInstalled) solverManager.uninstall("z3", "latest"); + if(solverInstalled) solverManager.uninstall(SOLVER, "latest"); } @Parameters(name = "expr: {0}, expected: {1}, actual: {2}") @@ -67,7 +68,7 @@ public static Collection operations() { } @Test - public void testOperationEquals() throws SmtLibSolverInstallerException { + public void testOperationEquals() throws Exception { // Sanity check assertNotNull(exprType); assertNotNull(expected); @@ -85,12 +86,13 @@ public void testOperationEquals() throws SmtLibSolverInstallerException { ); // Equality check - final Solver solver = solverManager.getSolverFactory("z3", "latest").createSolver(); - solver.push(); + try(final Solver solver = solverManager.getSolverFactory(SOLVER, "latest").createSolver()) { + solver.push(); - solver.add(EqExpr.create2(expected, actual)); + solver.add(EqExpr.create2(expected, actual)); - SolverStatus status = solver.check(); - assertTrue(status.isSat()); + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + } } } diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java index c1afced30d..4215e0dd8e 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java @@ -69,7 +69,7 @@ public static Collection operations() { } @Test - public void testOperationEquals() throws SmtLibSolverInstallerException { + public void testOperationEquals() throws Exception { // Sanity check assertNotNull(exprType); assertNotNull(expected); @@ -87,28 +87,29 @@ public void testOperationEquals() throws SmtLibSolverInstallerException { ); // Equality check - final Solver solver = solverManager.getSolverFactory("z3", "latest").createSolver(); - solver.push(); - - if (expected instanceof FpLitExpr && actual.getType() instanceof FpType) { - if (((FpLitExpr) expected).isNaN()) { - //noinspection unchecked - solver.add(IsNan((Expr) actual)); - } else if (((FpLitExpr) expected).isNegativeInfinity()) { - solver.add(EqExpr.create2(expected, actual)); - } else if (((FpLitExpr) expected).isPositiveInfinity()) { - solver.add(EqExpr.create2(expected, actual)); + try(final Solver solver = solverManager.getSolverFactory("z3", "latest").createSolver()) { + solver.push(); + + if (expected instanceof FpLitExpr && actual.getType() instanceof FpType) { + if (((FpLitExpr) expected).isNaN()) { + //noinspection unchecked + solver.add(IsNan((Expr) actual)); + } else if (((FpLitExpr) expected).isNegativeInfinity()) { + solver.add(EqExpr.create2(expected, actual)); + } else if (((FpLitExpr) expected).isPositiveInfinity()) { + solver.add(EqExpr.create2(expected, actual)); + } else { + //noinspection unchecked + FpLeqExpr leq = Leq(Abs(Sub(RNE, (FpLitExpr) expected, (Expr) actual)), + FpUtils.bigFloatToFpLitExpr(new BigFloat("1e-2", FpUtils.getMathContext((FpType) actual.getType(), RNE)), (FpType) actual.getType())); + solver.add(leq); + } } else { - //noinspection unchecked - FpLeqExpr leq = Leq(Abs(Sub(RNE, (FpLitExpr) expected, (Expr) actual)), - FpUtils.bigFloatToFpLitExpr(new BigFloat("1e-2", FpUtils.getMathContext((FpType) actual.getType(), RNE)), (FpType) actual.getType())); - solver.add(leq); + solver.add(EqExpr.create2(expected, actual)); } - } else { - solver.add(EqExpr.create2(expected, actual)); - } - SolverStatus status = solver.check(); - assertTrue(status.isSat()); + SolverStatus status = solver.check(); + assertTrue(status.isSat()); + } } } diff --git a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java index bb03052c47..ee2f798be3 100644 --- a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java +++ b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3ItpSolver.java @@ -197,7 +197,6 @@ public Collection> getAssertions() { @Override public void close() { - z3Context.close(); solver.close(); } } \ No newline at end of file diff --git a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverManager.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverManager.java index 1eeb1b444c..d891156fda 100644 --- a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverManager.java +++ b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3SolverManager.java @@ -1,18 +1,30 @@ package hu.bme.mit.theta.solver.z3; +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; +import hu.bme.mit.theta.solver.SolverBase; import hu.bme.mit.theta.solver.SolverFactory; import hu.bme.mit.theta.solver.SolverManager; +import hu.bme.mit.theta.solver.UCSolver; + +import java.util.HashSet; +import java.util.Set; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; public final class Z3SolverManager extends SolverManager { - private static final Z3SolverManager INSTANCE = new Z3SolverManager(); - public static Z3SolverManager getInstance() { - return INSTANCE; - } - private static final String NAME = "Z3"; + private boolean closed = false; + private final Set instantiatedSolvers = new HashSet<>(); + + private Z3SolverManager() {} + + public static Z3SolverManager create() { + return new Z3SolverManager(); + } + @Override public boolean managesSolver(final String name) { return NAME.equals(name); @@ -21,6 +33,46 @@ public boolean managesSolver(final String name) { @Override public SolverFactory getSolverFactory(final String name) { checkArgument(NAME.equals(name)); - return Z3SolverFactory.getInstance(); + return new ManagedFactory(Z3SolverFactory.getInstance()); + } + + @Override + public synchronized void close() throws Exception { + for(final var solver : instantiatedSolvers) { + solver.close(); + } + closed = true; + } + + private final class ManagedFactory implements SolverFactory { + private final SolverFactory solverFactory; + + private ManagedFactory(final SolverFactory solverFactory) { + this.solverFactory = solverFactory; + } + + @Override + public Solver createSolver() { + checkState(!closed, "Solver manager was closed"); + final var solver = solverFactory.createSolver(); + instantiatedSolvers.add(solver); + return solver; + } + + @Override + public UCSolver createUCSolver() { + checkState(!closed, "Solver manager was closed"); + final var solver = solverFactory.createUCSolver(); + instantiatedSolvers.add(solver); + return solver; + } + + @Override + public ItpSolver createItpSolver() { + checkState(!closed, "Solver manager was closed"); + final var solver = solverFactory.createItpSolver(); + instantiatedSolvers.add(solver); + return solver; + } } } diff --git a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java index e8bac9f596..62e0bd62da 100644 --- a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java +++ b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverFactory.java @@ -17,6 +17,7 @@ /** * Interface for solver factories that can instantiate solvers. + * Stores a configuration of a solver, and creates instances with that configuration. */ public interface SolverFactory { diff --git a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverManager.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverManager.java index a9931af725..34a5db8996 100644 --- a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverManager.java +++ b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/SolverManager.java @@ -3,7 +3,10 @@ import java.util.ArrayList; import java.util.Collection; -public abstract class SolverManager { +/** + * Owns the lifecycle of the Solvers created by the SolverFactory instances returned by resolveSolverFactory + */ +public abstract class SolverManager implements AutoCloseable { private static final Collection solverManagers = new ArrayList<>(); public static void registerSolverManager(final SolverManager solverManager) { @@ -20,6 +23,16 @@ public static SolverFactory resolveSolverFactory(final String name) throws Excep throw new UnsupportedOperationException("Solver " + name + " not supported"); } + /** + * Closes all SolverManager instances registered + */ + public static void closeAll() throws Exception { + for(final var solverManager : solverManagers) { + solverManager.close(); + } + solverManagers.clear(); + } + public abstract boolean managesSolver(final String name); public abstract SolverFactory getSolverFactory(final String name) throws Exception; From b2f476719b1514c54acbb22a1d29da86738b72ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 27 Sep 2021 19:28:12 +0200 Subject: [PATCH 94/99] Update SMT-LIB docs --- subprojects/solver/solver-smtlib-cli/README.md | 15 +++++++++++---- subprojects/solver/solver-smtlib/README.md | 13 +++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/subprojects/solver/solver-smtlib-cli/README.md b/subprojects/solver/solver-smtlib-cli/README.md index a0a2683e1f..ba39e549fd 100644 --- a/subprojects/solver/solver-smtlib-cli/README.md +++ b/subprojects/solver/solver-smtlib-cli/README.md @@ -28,13 +28,15 @@ The tool supports the following commands and their arguments: * `install :`: Installs a solver with the given name and version to the current solver registry. The __ identifies the driver (a.k.a. the type) of the solver, while the __ identifies the version of the solver to install. (See the list of supported solvers and their versions with `list-supported`) * `--name`: Install the solver version under this custom name (:), instead of the default (:) + * `--solver-path`: The path of the solver to install. The solver will not be downloaded, instead the binary on this path will be used. Caveat emptor: the version must be specified correctly, there is no automatic detection. * `--tempt-murphy`: Enables the installation of unsupported solver versions. If you enable this, you can expect things to break, as these solvers were not tested with Theta at all! * `install-generic`: Installs an SMT-LIB compatible solver with the generic driver. For more information see the [Generic driver](#Generic-driver) section. * `--solver-path` **[required]**: Denotes the path to the binary of the solver. * `--solver-args`: The command line arguments to pass to the generic solver. * `--name` **[required]**: Install the solver under this custom name (generic:) * `uninstall :`: Uninstalls a solver with the given name and version from the current solver registry. (See the list of installed solvers and their versions with `list-installed`) -* `reinstall :`: Reinstalls a solver with the given name and version in the current solver registry. (See the list of installed solvers and their versions with `list-installed`.) **Note**: This command is not available for solvers installed with the generic driver. +* `rename :`: Renames one installed solver version. (See the list of installed solvers and their versions with `list-installed`) + * `--name` **[required]**: Rename the solver version to this custom name (:). * `get-info :`: Gets the stored information about the solver with the given name and version in the current solver registry. (See the list of installed solvers and their versions with `list-installed`) * `edit-args :`: Edits the command line arguments of the solver with the given name and version. The command opens a txt file that stores the command line arguments to edit with the default editor, or prints the path of the file to edit if the default editor is not applicable (e.g. CLI). (See the list of installed solvers and their versions with `list-installed`) * `--print`: If given, the path of the file to edit will be printed instead of opening. @@ -66,8 +68,13 @@ For more information see the default configurations of the supported solvers. Currently, the following solvers are supported. +* Boolector +* CVC4 +* MathSAT5: Supported with interpolation +* Princess: Supported with interpolation +* SMTInterpol: Supported with interpolation +* Yices2: *Partial, error-prone support* * Z3 * `4.4.0` - `4.6.0`: Supported with interpolation. - * `4.7.1` - `4.8.9`: Supported without interpolation. Interpolation was removed in `4.7.0`. -* CVC4 - * `1.0` - `1.8`: Supported. \ No newline at end of file + * `4.7.1` - : Supported without interpolation. Interpolation was removed in `4.7.0`. +* Generic: Any other solver that can communicate with SMT-LIBv2 standard. See section Generic driver for more details. \ No newline at end of file diff --git a/subprojects/solver/solver-smtlib/README.md b/subprojects/solver/solver-smtlib/README.md index 2aadbdd189..674f5b6278 100644 --- a/subprojects/solver/solver-smtlib/README.md +++ b/subprojects/solver/solver-smtlib/README.md @@ -38,9 +38,9 @@ In general, to have an SMT-LIB supporting solver, components implementing the fo The SMT-LIB grammar that the component supports is defined using ANTLR. The ANTLR grammar can be found in the source folder (`SMTLIBv2.g4`). -The components above are integrated into a working solver implementation with Theta's solver interface by the followin classes: +The components above are integrated into a working solver implementation with Theta's solver interface by the following classes: - `SmtLibSolver`: Provides a solver implementing Theta's `Solver` and `UCSolver` interface supporting basic satisfiability checks, model querying and unsat core querying. -- `BaseSmtLibItpSolver`: Provides a solver implementinf Theta`s `ItpSolver` interface supporting interpolating solvers. **Note**: As interpolation is not part of the SMT-LIB standard, this class is abstract. Each solver supporting interpolation has to extend this class and configure it properly. +- `BaseSmtLibItpSolver`: Provides a solver implementing Theta's `ItpSolver` interface supporting interpolating solvers. **Note**: As interpolation is not part of the SMT-LIB standard, this class is abstract. Each solver supporting interpolation has to extend this class and configure it properly. ### Generic interface implementation @@ -50,5 +50,10 @@ The interfaces above have a default, generic implementation that works with solv Right now, the solver-smtlib subproject supports the following solvers. Each package contains the specialization of the interfaces above that communicate with the said solver: -- **Z3** (`hu.bme.mit.theta.solver.smtlib.impl.z3`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors, functions), and supports interpolation as well (binary, sequential and tree interpolation) up to version 4.7. -- **CVC4** (`hu.bme.mit.theta.solver.smtlib.impl.cvc4`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). \ No newline at end of file +- **Boolector** (`hu.bme.mit.theta.solver.smtlib.impl.boolector`): The solver specializes in bitvector and array theories, but lacks support for others. It cannot interpolate or produce unsat cores, so it can only be used for abstraction. +- **CVC4** (`hu.bme.mit.theta.solver.smtlib.impl.cvc4`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). +- **Mathsat5** (`hu.bme.mit.theta.solver.smtlib.impl.mathsat`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors, floating points). It also supports interpolation (binary, sequential and tree interpolation) with many of them. +- **Princess** (`hu.bme.mit.theta.solver.smtlib.impl.princess`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). It also supports interpolation (binary, sequential and tree interpolation) with many of them. +- **SMTInterpol** (`hu.bme.mit.theta.solver.smtlib.impl.smtinterpol`): The solver specializes in integer and rational theories. It also supports interpolation (binary, sequential and tree interpolation) with them. +- **Yices2** (`hu.bme.mit.theta.solver.smtlib.impl.yices2`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). +- **Z3** (`hu.bme.mit.theta.solver.smtlib.impl.z3`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors, functions), and supports interpolation as well (binary, sequential and tree interpolation) up to version 4.7. \ No newline at end of file From 033bfae3246c670ed4b26f4fdf14942f42baf174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 27 Sep 2021 20:22:42 +0200 Subject: [PATCH 95/99] Add new solver versions --- .../BoolectorSmtLibSolverInstaller.java | 21 +++++++++++++------ .../mathsat/MathSATSmtLibSolverInstaller.java | 2 +- .../PrincessSmtLibSolverInstaller.java | 2 +- .../SMTInterpolSmtLibSolverInstaller.java | 3 ++- .../impl/z3/Z3SmtLibSolverInstaller.java | 18 ++++++++++++++-- .../solver/smtlib/SmtLibSolverBVTest.java | 2 +- 6 files changed, 36 insertions(+), 12 deletions(-) diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java index cfc80e4808..90b3c47d7e 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java @@ -6,6 +6,7 @@ import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import hu.bme.mit.theta.solver.smtlib.utils.Compress; +import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import java.io.IOException; import java.net.URI; @@ -63,11 +64,19 @@ protected void uninstallSolver(final Path installDir, final String version) { } @Override protected String[] getDefaultSolverArgs(String version) { - return new String[] { - "--smt2", - "--smt2-model", - "-i" - }; + if(SemVer.of(version).compareTo(SemVer.of("3.2.2")) >= 0) { + return new String[]{ + "--smt2", + "-i" + }; + } + else { + return new String[]{ + "--smt2", + "--smt2-model", + "-i" + }; + } } @Override @@ -78,7 +87,7 @@ public SolverFactory getSolverFactory(final Path installDir, final String versio @Override public List getSupportedVersions() { - return Arrays.asList("3.2.1", "3.2.0", "3.1.0", "3.0.0"); + return Arrays.asList("3.2.2", "3.2.1", "3.2.0", "3.1.0", "3.0.0"); } private String getSolverBinaryName() { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java index f316a3a2e9..6a250f2969 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java @@ -141,7 +141,7 @@ public SolverFactory getSolverFactory(final Path installDir, final String versio @Override public List getSupportedVersions() { return Arrays.asList( - "5.6.5", "5.6.4", "5.6.3", "5.6.2", "5.6.1", "5.6.0", + "5.6.6", "5.6.5", "5.6.4", "5.6.3", "5.6.2", "5.6.1", "5.6.0", "5.5.4", "5.5.3", "5.5.2", "5.5.1", "5.5.0", "5.4.1", "5.4.0", "5.3.14", "5.3.13", "5.3.12", "5.3.11", "5.3.10", "5.3.9", "5.3.8", "5.3.7", "5.3.6", "5.3.5", "5.3.4", "5.3.3", "5.3.2", "5.3.1", diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java index db3e76de23..ac9b561052 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java @@ -76,7 +76,7 @@ public SolverFactory getSolverFactory(final Path installDir, final String versio @Override public List getSupportedVersions() { return Arrays.asList( - "2021-03-10", "2020-03-12", "2019-10-02", "2019-07-24", + "2021-05-10", "2021-03-10", "2020-03-12", "2019-10-02", "2019-07-24", "2018-10-26", "2018-05-25", "2018-01-27", "2017-12-06", "2017-07-17" ); } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java index 894926db84..4250025ce8 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java @@ -66,12 +66,13 @@ public SolverFactory getSolverFactory(final Path installDir, final String versio @Override public List getSupportedVersions() { - return Arrays.asList("2.5-663", "2.5-479", "2.5-7"); + return Arrays.asList("2.5-916", "2.5-663", "2.5-479", "2.5-7"); } private URL getDownloadUrl(final String version) throws SmtLibSolverInstallerException, MalformedURLException { final String fileName; switch (version) { + case "2.5-916": fileName = "2.5-916-ga5843d8b"; break; case "2.5-663": fileName = "2.5-663-gf15aa217"; break; case "2.5-479": fileName = "2.5-479-ga49e50b1"; break; case "2.5-7": fileName = "2.5-7-g64ec65d"; break; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java index 6efaec73df..369c017c15 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java @@ -30,6 +30,20 @@ public Z3SmtLibSolverInstaller(final Logger logger) { super(logger); versions = new ArrayList<>(); + versions.add(SemVer.VersionDecoder.create(SemVer.of("4.8.12")) + .addString(LINUX, X64, "x64-glibc-2.31") + .addString(WINDOWS, X64, "x64-win") + .addString(WINDOWS, X86, "x86-win") + .addString(MAC, X64, "x64-osx-10.15.7") + .build() + ); + versions.add(SemVer.VersionDecoder.create(SemVer.of("4.8.10")) + .addString(LINUX, X64, "x64-ubuntu-18.04") + .addString(WINDOWS, X64, "x64-win") + .addString(WINDOWS, X86, "x86-win") + .addString(MAC, X64, "x64-osx-10.15.7") + .build() + ); versions.add(SemVer.VersionDecoder.create(SemVer.of("4.8.5")) .addString(LINUX, X64, "x64-ubuntu-16.04") .addString(WINDOWS, X64, "x64-win") @@ -134,8 +148,8 @@ public SolverFactory getSolverFactory(final Path installDir, final String versio @Override public List getSupportedVersions() { return Arrays.asList( - "4.8.9", "4.8.8", "4.8.7", "4.8.6", "4.8.5", "4.8.4", "4.8.3", "4.8.2", "4.8.1", - "4.7.1", "4.6.0", "4.5.0", "4.4.1", "4.4.0", "4.3.2" + "4.8.12", "4.8.11", "3.8.10", "4.8.9", "4.8.8", "4.8.7", "4.8.6", "4.8.5", "4.8.4", "4.8.3", + "4.8.2", "4.8.1", "4.7.1", "4.6.0", "4.5.0", "4.4.1", "4.4.0", "4.3.2" ); } diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java index cc4d044a8d..7f14c697b5 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java @@ -27,7 +27,7 @@ @RunWith(Parameterized.class) public class SmtLibSolverBVTest { - private static final String SOLVER = "princess"; + private static final String SOLVER = "z3"; private static boolean solverInstalled = false; private static SmtLibSolverManager solverManager; From ee0cc56a2c9bdb40c2fd6be363261d525d6ae6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 27 Sep 2021 20:38:52 +0200 Subject: [PATCH 96/99] Skip SMT-LIB tests on Windows --- .../solver/smtlib/SmtLibItpSolverTest.java | 25 ++++++++++------ .../solver/smtlib/SmtLibSolverBVTest.java | 26 +++++++++++------ .../solver/smtlib/SmtLibSolverFPTest.java | 21 +++++++++----- .../theta/solver/smtlib/SmtLibSolverTest.java | 29 +++++++++++++------ 4 files changed, 67 insertions(+), 34 deletions(-) diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java index 02b1f41533..a60f6ee235 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java @@ -16,6 +16,7 @@ package hu.bme.mit.theta.solver.smtlib; import com.google.common.collect.ImmutableList; +import hu.bme.mit.theta.common.OsHelper; import hu.bme.mit.theta.common.logging.NullLogger; import hu.bme.mit.theta.core.decl.ConstDecl; import hu.bme.mit.theta.core.decl.ParamDecl; @@ -33,6 +34,7 @@ import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Assume; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -65,15 +67,18 @@ public final class SmtLibItpSolverTest { @BeforeClass public static void init() throws SmtLibSolverInstallerException, IOException { - Path home = SmtLibSolverManager.HOME; - - solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); - try { - solverManager.install("z3", "4.5.0", "4.5.0", null, false); - solverInstalled = true; - } catch(SmtLibSolverInstallerException e) {} - - solverFactory = solverManager.getSolverFactory("z3", "4.5.0"); + if(OsHelper.getOs().equals(OsHelper.OperatingSystem.LINUX)) { + Path home = SmtLibSolverManager.HOME; + + solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); + try { + solverManager.install("z3", "4.5.0", "4.5.0", null, false); + solverInstalled = true; + } catch (SmtLibSolverInstallerException e) { + } + + solverFactory = solverManager.getSolverFactory("z3", "4.5.0"); + } } @AfterClass @@ -93,6 +98,8 @@ public static void destroy() throws SmtLibSolverInstallerException { @Before public void initialize() { + Assume.assumeTrue(OsHelper.getOs().equals(OsHelper.OperatingSystem.LINUX)); + solver = solverFactory.createItpSolver(); final ConstDecl ad = Const("a", Int()); diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java index 7f14c697b5..c7653c794f 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java @@ -1,5 +1,6 @@ package hu.bme.mit.theta.solver.smtlib; +import hu.bme.mit.theta.common.OsHelper; import hu.bme.mit.theta.common.logging.NullLogger; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.abstracttype.EqExpr; @@ -8,6 +9,7 @@ import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import org.junit.AfterClass; +import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -28,6 +30,7 @@ @RunWith(Parameterized.class) public class SmtLibSolverBVTest { private static final String SOLVER = "z3"; + private static final String VERSION = "4.5.0"; private static boolean solverInstalled = false; private static SmtLibSolverManager solverManager; @@ -42,18 +45,21 @@ public class SmtLibSolverBVTest { @BeforeClass public static void init() throws SmtLibSolverInstallerException, IOException { - Path home = SmtLibSolverManager.HOME; - - solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); - try { - solverManager.install(SOLVER, "latest", "latest", null, false); - solverInstalled = true; - } catch(SmtLibSolverInstallerException e) {} + if(OsHelper.getOs().equals(OsHelper.OperatingSystem.LINUX)) { + Path home = SmtLibSolverManager.HOME; + + solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); + try { + solverManager.install(SOLVER, VERSION, VERSION, null, false); + solverInstalled = true; + } catch (SmtLibSolverInstallerException e) { + } + } } @AfterClass public static void destroy() throws SmtLibSolverInstallerException { - if(solverInstalled) solverManager.uninstall(SOLVER, "latest"); + if(solverInstalled) solverManager.uninstall(SOLVER, VERSION); } @Parameters(name = "expr: {0}, expected: {1}, actual: {2}") @@ -69,6 +75,8 @@ public static Collection operations() { @Test public void testOperationEquals() throws Exception { + Assume.assumeTrue(OsHelper.getOs().equals(OsHelper.OperatingSystem.LINUX)); + // Sanity check assertNotNull(exprType); assertNotNull(expected); @@ -86,7 +94,7 @@ public void testOperationEquals() throws Exception { ); // Equality check - try(final Solver solver = solverManager.getSolverFactory(SOLVER, "latest").createSolver()) { + try(final Solver solver = solverManager.getSolverFactory(SOLVER, VERSION).createSolver()) { solver.push(); solver.add(EqExpr.create2(expected, actual)); diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java index 4215e0dd8e..f6879af48c 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverFPTest.java @@ -1,5 +1,6 @@ package hu.bme.mit.theta.solver.smtlib; +import hu.bme.mit.theta.common.OsHelper; import hu.bme.mit.theta.common.logging.NullLogger; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.abstracttype.EqExpr; @@ -12,6 +13,7 @@ import hu.bme.mit.theta.solver.SolverStatus; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import org.junit.AfterClass; +import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -49,13 +51,16 @@ public class SmtLibSolverFPTest { @BeforeClass public static void init() throws SmtLibSolverInstallerException, IOException { - Path home = SmtLibSolverManager.HOME; - - solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); - try { - solverManager.install("z3", "4.5.0", "4.5.0", null, false); - solverInstalled = true; - } catch(SmtLibSolverInstallerException e) {} + if(OsHelper.getOs().equals(OsHelper.OperatingSystem.LINUX)) { + Path home = SmtLibSolverManager.HOME; + + solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); + try { + solverManager.install("z3", "4.5.0", "4.5.0", null, false); + solverInstalled = true; + } catch (SmtLibSolverInstallerException e) { + } + } } @AfterClass @@ -70,6 +75,8 @@ public static Collection operations() { @Test public void testOperationEquals() throws Exception { + Assume.assumeTrue(OsHelper.getOs().equals(OsHelper.OperatingSystem.LINUX)); + // Sanity check assertNotNull(exprType); assertNotNull(expected); diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index d15461d558..fdb641e162 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -1,5 +1,6 @@ package hu.bme.mit.theta.solver.smtlib; +import hu.bme.mit.theta.common.OsHelper; import hu.bme.mit.theta.common.logging.NullLogger; import hu.bme.mit.theta.core.decl.ConstDecl; import hu.bme.mit.theta.core.decl.ParamDecl; @@ -27,6 +28,8 @@ import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibModel; import org.junit.AfterClass; +import org.junit.Assume; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -59,15 +62,18 @@ public final class SmtLibSolverTest { @BeforeClass public static void init() throws SmtLibSolverInstallerException, IOException { - Path home = SmtLibSolverManager.HOME; - - solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); - try { - solverManager.install("z3", "4.5.0", "4.5.0", null, false); - solverInstalled = true; - } catch(SmtLibSolverInstallerException e) {} - - solverFactory = solverManager.getSolverFactory("z3", "4.5.0"); + if(OsHelper.getOs().equals(OsHelper.OperatingSystem.LINUX)) { + Path home = SmtLibSolverManager.HOME; + + solverManager = SmtLibSolverManager.create(home, NullLogger.getInstance()); + try { + solverManager.install("z3", "4.5.0", "4.5.0", null, false); + solverInstalled = true; + } catch (SmtLibSolverInstallerException e) { + } + + solverFactory = solverManager.getSolverFactory("z3", "4.5.0"); + } } @AfterClass @@ -75,6 +81,11 @@ public static void destroy() throws SmtLibSolverInstallerException { if(solverInstalled) solverManager.uninstall("z3", "4.5.0"); } + @Before + public void before() { + Assume.assumeTrue(OsHelper.getOs().equals(OsHelper.OperatingSystem.LINUX)); + } + @Test public void test() { final var symbolTable = new GenericSmtLibSymbolTable(); From e284443516a0cce04886a096b26d78806876a404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Mon, 27 Sep 2021 21:15:17 +0200 Subject: [PATCH 97/99] Update docs --- README.md | 30 +++++++++---------- doc/CEGAR-algorithms.md | 9 ++++++ .../solver/solver-smtlib-cli/README.md | 2 ++ subprojects/solver/solver-smtlib/README.md | 2 ++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 366b0bec62..0e9ed7e108 100644 --- a/README.md +++ b/README.md @@ -35,32 +35,32 @@ Currently, the following tools are available (follow the links for more informat Theta can be divided into the following four layers. * **Formalisms**: The core elements of Theta are the formalisms, which represent models of real life systems (e.g., software, hardware, protocols). -Formalisms are usually low level, mathematical representations based on first order logic expressions and graph like structures. -Formalisms can also support higher level languages that can be mapped to that particular formalism by a language front-end (consisting of a specific parser and possibly reductions for simplification of the model). -The common features of the different formalisms reside in the [`core`](subprojects/common/core) project (e.g., expressions and statements) and each formalism has its own project. -Currently, the following formalisms are supported: (extended) symbolic transition systems ([`sts`](subprojects/sts/sts) / [`xsts`](subprojects/xsts/xsts)), control-flow automata ([`cfa`](subprojects/cfa/cfa)) and timed automata ([`xta`](subprojects/xta/xta)). + Formalisms are usually low level, mathematical representations based on first order logic expressions and graph like structures. + Formalisms can also support higher level languages that can be mapped to that particular formalism by a language front-end (consisting of a specific parser and possibly reductions for simplification of the model). + The common features of the different formalisms reside in the [`core`](subprojects/common/core) project (e.g., expressions and statements) and each formalism has its own project. + Currently, the following formalisms are supported: (extended) symbolic transition systems ([`sts`](subprojects/sts/sts) / [`xsts`](subprojects/xsts/xsts)), control-flow automata ([`cfa`](subprojects/cfa/cfa)) and timed automata ([`xta`](subprojects/xta/xta)). * **Analysis back-end**: The analysis back-end provides the verification algorithms that can formally prove whether a model meets certain requirements. -There is an interpreter for each formalism, providing a common interface towards the algorithms (e.g., calculating initial states and successors). -This ensures that most components of the algorithms work for all formalisms (as long as they provide the interpreter). -The verification algorithms are mostly based on abstraction. -The analysis back-end defines various abstract domains (e.g., predicates, explicit values, zones), strategies for performing abstraction and refinement (e.g., interpolation), and algorithms built from these components. -The common components reside in the [`analysis`](subprojects/common/analysis) project (e.g., CEGAR loop) and the formalism-specific modules (e.g., the interpreters) are implemented in separate analysis projects (with suffix `-analysis`) for each formalism. + There is an interpreter for each formalism, providing a common interface towards the algorithms (e.g., calculating initial states and successors). + This ensures that most components of the algorithms work for all formalisms (as long as they provide the interpreter). + The verification algorithms are mostly based on abstraction. + The analysis back-end defines various abstract domains (e.g., predicates, explicit values, zones), strategies for performing abstraction and refinement (e.g., interpolation), and algorithms built from these components. + The common components reside in the [`analysis`](subprojects/common/analysis) project (e.g., CEGAR loop) and the formalism-specific modules (e.g., the interpreters) are implemented in separate analysis projects (with suffix `-analysis`) for each formalism. * **SMT solver interface and SMT solvers**: Many components of the algorithms rely on satisfiability modulo theories (SMT) solvers. -The framework provides a general SMT solver interface in the project [`solver`](subprojects/common/solver) that supports incremental solving, unsat cores, and the generation of binary and sequence interpolants. -Currently, the interface is implemented by the [Z3](https://github.com/Z3Prover/z3) SMT solver in the project [`solver-z3`](subprojects/common/solver-z3), but it can easily be extended with new solvers. + The framework provides a general SMT solver interface in the project [`solver`](subprojects/common/solver) that supports incremental solving, unsat cores, and the generation of binary and sequence interpolants. + Currently, the interface is implemented by the [Z3](https://github.com/Z3Prover/z3) SMT solver in the project [`solver-z3`](subprojects/common/solver-z3), but it can easily be extended with new solvers. * **Tools**: Tools are command line applications that can be compiled into a runnable jar file. -Tools usually read some input and then instantiate and run the algorithms. -Tools are implemented in separate projects, currently with the `-cli` suffix. + Tools usually read some input and then instantiate and run the algorithms. + Tools are implemented in separate projects, currently with the `-cli` suffix. The table below shows the architecture and the projects. Each project contains a README.md in its root directory describing its purpose in more detail. | | Common | CFA | STS | XTA | XSTS | |--|--|--|--|--|--| -| **Tools** | | [`cfa-cli`](subprojects/cfa/cfa-cli) | [`sts-cli`](subprojects/sts/sts-cli) | [`xta-cli`](subprojects/xta/xta-cli) | [`xsts-cli`](subprojects/xsts/xsts-cli) | +| **Tools** | [`solver-smtlib-cli`](subprojects/solver/solver-smtlib-cli) | [`cfa-cli`](subprojects/cfa/cfa-cli) | [`sts-cli`](subprojects/sts/sts-cli) | [`xta-cli`](subprojects/xta/xta-cli) | [`xsts-cli`](subprojects/xsts/xsts-cli) | | **Analyses** | [`analysis`](subprojects/common/analysis) | [`cfa-analysis`](subprojects/cfa/cfa-analysis) | [`sts-analysis`](subprojects/sts/sts-analysis) | [`xta-analysis`](subprojects/xta/xta-analysis) | [`xsts-analysis`](subprojects/xsts/xsts-analysis) | | **Formalisms** | [`core`](subprojects/common/core), [`common`](subprojects/common/common) | [`cfa`](subprojects/cfa/cfa) | [`sts`](subprojects/sts/sts) | [`xta`](subprojects/xta/xta) | [`xsts`](subprojects/xsts/xsts) | -| **SMT solvers** | [`solver`](subprojects/common/solver), [`solver-z3`](subprojects/common/solver-z3) | +| **SMT solvers** | [`solver`](subprojects/solver/solver), [`solver-z3`](subprojects/solver/solver-z3), [`solver-smtlib`](subprojects/solver/solver-smtlib) | ## Extend Theta diff --git a/doc/CEGAR-algorithms.md b/doc/CEGAR-algorithms.md index 3adb2d5e04..478946b09d 100644 --- a/doc/CEGAR-algorithms.md +++ b/doc/CEGAR-algorithms.md @@ -141,3 +141,12 @@ The pruning strategy controls which portion of the abstract state space is disca * `LAZY`: The ARG is only pruned back to the first point where refinement was applied. (See [Lazy abstraction](https://dl.acm.org/doi/10.1145/565816.503279).) It is recommended to first try `LAZY` and fall back to `FULL` if there is no refinement progress (seemingly infinite iterations with the same counterexample). + +### `--solver`, `--abstraction-solver`, `--refinement-solver` + +Available for CFA. The SMT-solver to use during verification. The `--abstraction-solver` specifies the solver to use during the abstraction phase, while `--refinement-solver` specifies the solver to use during the refinement phase. The option `--solver` sets both the abstraction and the refinement solver to be the same. Possible values: + +* `Z3`: The native integration of Microsoft's Z3 solver. (See subproject [solver-z3](../subprojects/solver/solver-z3) for more details.) +* `:`: An installed SMT-LIB solver. (See subprojects [solver-smtlib](../subprojects/solver/solver-smtlib) and [solver-smtlib-cli](../subprojects/solver/solver-smtlib-cli) for more details.) + +It is recommended to stick with the default `Z3` option at first, and only use the SMT-LIB based solvers, if some required features are not supported by `Z3` (e.g. interpolating with bitvectors, floating points). \ No newline at end of file diff --git a/subprojects/solver/solver-smtlib-cli/README.md b/subprojects/solver/solver-smtlib-cli/README.md index ba39e549fd..5fd20c29bc 100644 --- a/subprojects/solver/solver-smtlib-cli/README.md +++ b/subprojects/solver/solver-smtlib-cli/README.md @@ -1,5 +1,7 @@ ## Overview +**This project is in alpha state. Expect breaking changes in the near future!** + The `solver-smtlib-cli` project is an executable (command line) tool for managing the SMT-LIB compatible solvers. For more information about the SMT-LIB compatibility in Theta, take a look at the [`solver-smtlib`](../solver-smtlib/README.md) project. diff --git a/subprojects/solver/solver-smtlib/README.md b/subprojects/solver/solver-smtlib/README.md index 674f5b6278..87ea774f89 100644 --- a/subprojects/solver/solver-smtlib/README.md +++ b/subprojects/solver/solver-smtlib/README.md @@ -1,5 +1,7 @@ ## Overview +**This project is in alpha state. Expect breaking changes in the near future!** + This project wraps a generic solver that supports the SMT-LIB2 interface into our common interfaces for solvers (located in the [solver](..) project). ### Related projects From 27da6a1dc33b803a04b67c6e256d5d71f85806f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 29 Sep 2021 10:55:37 +0200 Subject: [PATCH 98/99] Fix codacy warnings --- .../refinement/ExprTraceNewtonChecker.java | 1 - .../hu/bme/mit/theta/common/OsHelper.java | 4 +- .../mit/theta/core/type/fptype/FpLitExpr.java | 2 - .../solver/solver-smtlib-cli/README.md | 8 +- .../theta/solver/smtlib/cli/SmtLibCli.java | 301 ++++++++++-------- subprojects/solver/solver-smtlib/README.md | 40 +-- .../BoolectorSmtLibSolverInstaller.java | 4 +- .../impl/cvc4/CVC4SmtLibSolverInstaller.java | 10 +- .../generic/GenericSmtLibSolverBinary.java | 1 + .../generic/GenericSmtLibSolverInstaller.java | 2 - .../mathsat/MathSATSmtLibSolverInstaller.java | 12 +- .../PrincessSmtLibSolverInstaller.java | 14 +- .../SMTInterpolSmtLibSolverInstaller.java | 11 +- .../impl/z3/Z3SmtLibSolverInstaller.java | 12 +- .../solver/smtlib/solver/SmtLibSolver.java | 5 +- .../installer/SmtLibSolverInstaller.java | 2 - .../theta/solver/smtlib/utils/Compress.java | 2 + .../solver/smtlib/SmtLibItpSolverTest.java | 1 - .../solver/smtlib/SmtLibSolverBVTest.java | 1 - .../theta/solver/smtlib/SmtLibSolverTest.java | 32 +- .../hu/bme/mit/theta/solver/z3/Z3Solver.java | 9 +- .../bme/mit/theta/solver/z3/Z3SolverTest.java | 13 +- .../hu/bme/mit/theta/solver/ItpPattern.java | 1 - .../hu/bme/mit/theta/solver/ItpSolver.java | 10 +- .../java/hu/bme/mit/theta/solver/Solver.java | 3 - .../mit/theta/solver/utils/WithPushPop.java | 5 +- .../hu/bme/mit/theta/solver/SolverStub.java | 6 +- 27 files changed, 267 insertions(+), 245 deletions(-) diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java index 5321992d04..6f31cceae3 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/ExprTraceNewtonChecker.java @@ -34,7 +34,6 @@ import hu.bme.mit.theta.core.utils.StmtUtils; import hu.bme.mit.theta.core.utils.VarIndexing; import hu.bme.mit.theta.core.utils.WpState; -import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.UCSolver; import hu.bme.mit.theta.solver.utils.WithPushPop; diff --git a/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/OsHelper.java b/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/OsHelper.java index 5fb7a52489..062b089a1b 100644 --- a/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/OsHelper.java +++ b/subprojects/common/common/src/main/java/hu/bme/mit/theta/common/OsHelper.java @@ -49,9 +49,9 @@ public enum Architecture { public static Architecture getArch() { final String arch = StandardSystemProperty.OS_ARCH.value(); - if (arch.toLowerCase().equals("x86")) { + if (arch.equalsIgnoreCase("x86")) { return Architecture.X86; - } else if (arch.toLowerCase().equals("amd64")) { + } else if (arch.equalsIgnoreCase("amd64")) { return Architecture.X64; } else { throw new UnsupportedOperationException("Architecture \"" + arch + "\" not supported."); diff --git a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpLitExpr.java b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpLitExpr.java index 922cdd5d37..716a52d9c6 100644 --- a/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpLitExpr.java +++ b/subprojects/common/core/src/main/java/hu/bme/mit/theta/core/type/fptype/FpLitExpr.java @@ -7,8 +7,6 @@ import hu.bme.mit.theta.core.type.booltype.BoolLitExpr; import hu.bme.mit.theta.core.type.bvtype.BvLitExpr; -import java.util.Arrays; - import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static hu.bme.mit.theta.core.utils.FpUtils.bigFloatToFpLitExpr; diff --git a/subprojects/solver/solver-smtlib-cli/README.md b/subprojects/solver/solver-smtlib-cli/README.md index 5fd20c29bc..7754883937 100644 --- a/subprojects/solver/solver-smtlib-cli/README.md +++ b/subprojects/solver/solver-smtlib-cli/README.md @@ -33,12 +33,12 @@ The tool supports the following commands and their arguments: * `--solver-path`: The path of the solver to install. The solver will not be downloaded, instead the binary on this path will be used. Caveat emptor: the version must be specified correctly, there is no automatic detection. * `--tempt-murphy`: Enables the installation of unsupported solver versions. If you enable this, you can expect things to break, as these solvers were not tested with Theta at all! * `install-generic`: Installs an SMT-LIB compatible solver with the generic driver. For more information see the [Generic driver](#Generic-driver) section. - * `--solver-path` **[required]**: Denotes the path to the binary of the solver. + * `--solver-path` **(required)**: Denotes the path to the binary of the solver. * `--solver-args`: The command line arguments to pass to the generic solver. - * `--name` **[required]**: Install the solver under this custom name (generic:) + * `--name` **(required)**: Install the solver under this custom name (generic:) * `uninstall :`: Uninstalls a solver with the given name and version from the current solver registry. (See the list of installed solvers and their versions with `list-installed`) * `rename :`: Renames one installed solver version. (See the list of installed solvers and their versions with `list-installed`) - * `--name` **[required]**: Rename the solver version to this custom name (:). + * `--name` **(required)**: Rename the solver version to this custom name (:). * `get-info :`: Gets the stored information about the solver with the given name and version in the current solver registry. (See the list of installed solvers and their versions with `list-installed`) * `edit-args :`: Edits the command line arguments of the solver with the given name and version. The command opens a txt file that stores the command line arguments to edit with the default editor, or prints the path of the file to edit if the default editor is not applicable (e.g. CLI). (See the list of installed solvers and their versions with `list-installed`) * `--print`: If given, the path of the file to edit will be printed instead of opening. @@ -75,7 +75,7 @@ Currently, the following solvers are supported. * MathSAT5: Supported with interpolation * Princess: Supported with interpolation * SMTInterpol: Supported with interpolation -* Yices2: *Partial, error-prone support* +* Yices2: _Partial, error-prone support_ * Z3 * `4.4.0` - `4.6.0`: Supported with interpolation. * `4.7.1` - : Supported without interpolation. Interpolation was removed in `4.7.0`. diff --git a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java index e16c3ff738..ba65077f26 100644 --- a/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java +++ b/subprojects/solver/solver-smtlib-cli/src/main/java/hu/bme/mit/theta/solver/smtlib/cli/SmtLibCli.java @@ -17,6 +17,7 @@ import java.io.StringWriter; import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; public class SmtLibCli { private static final String JAR_NAME = "theta-solver-smtlib-cli.jar"; @@ -38,8 +39,13 @@ static class MainParams { private boolean help = false; } + interface Command { + String getCommand(); + void handle(SmtLibSolverManager smtLibSolverManager, Logger logger) throws SmtLibSolverInstallerException; + } + @Parameters(commandDescription = "Installs the solver") - static class InstallCommand { + static class InstallCommand implements Command { static final String COMMAND = "install"; @Parameter(description = "The solver to install (:)", validateWith = SolverNameAndVersionValidator.class, required = true) @@ -53,10 +59,32 @@ static class InstallCommand { @Parameter(names = "--tempt-murphy", description = "Allows the installation of unsupported solver version") boolean temptMurphy = false; + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public void handle(final SmtLibSolverManager smtLibSolverManager, final Logger logger) throws SmtLibSolverInstallerException{ + final var solver = decodeVersionString(this.solver); + + if(solver.get1().equals(smtLibSolverManager.getGenericInstallerName())) { + logger.write(Logger.Level.RESULT, "To install a generic solver, use the \"%s\" command", InstallGenericCommand.COMMAND); + return; + } + + if(name != null) { + smtLibSolverManager.install(solver.get1(), solver.get2(), name, solverPath != null ? Path.of(solverPath) : null, temptMurphy); + } + else { + smtLibSolverManager.install(solver.get1(), solver.get2(), solver.get2(), solverPath != null ? Path.of(solverPath) : null, temptMurphy); + } + } } @Parameters(commandDescription = "Installs a generic solver") - static class InstallGenericCommand { + static class InstallGenericCommand implements Command { static final String COMMAND = "install-generic"; @Parameter(names = "--solver-path", description = "The path of the generic solver to install", required = true) @@ -67,18 +95,43 @@ static class InstallGenericCommand { @Parameter(names = "--name", description = "Install the solver version under this custom name (:), instead of the default (:)", required = true) String name; + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public void handle(final SmtLibSolverManager smtLibSolverManager, final Logger logger) throws SmtLibSolverInstallerException { + smtLibSolverManager.installGeneric( + name, + Path.of(solverPath), + (solverArgs == null ? "" : solverArgs).split(" ") + ); + } } @Parameters(commandDescription = "Uninstalls the solver") - static class UninstallCommand { + static class UninstallCommand implements Command { static final String COMMAND = "uninstall"; @Parameter(description = "The solver to uninstall (:)", validateWith = SolverNameAndVersionValidator.class, required = true) String solver; + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public void handle(SmtLibSolverManager smtLibSolverManager, Logger logger) throws SmtLibSolverInstallerException { + final var solver = decodeVersionString(this.solver); + smtLibSolverManager.uninstall(solver.get1(), solver.get2()); + } } @Parameters(commandDescription = "Renames one installed solver version") - static class RenameCommand { + static class RenameCommand implements Command { static final String COMMAND = "rename"; @Parameter(description = "The solver to reinstall (:)", validateWith = SolverNameAndVersionValidator.class, required = true) @@ -86,18 +139,41 @@ static class RenameCommand { @Parameter(names = "--name", description = "Rename the solver version to this custom name (:).", required = true) String name; + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public void handle(SmtLibSolverManager smtLibSolverManager, Logger logger) throws SmtLibSolverInstallerException { + final var solver = decodeVersionString(this.solver); + smtLibSolverManager.rename(solver.get1(), solver.get2(), name); + } } @Parameters(commandDescription = "Prints info about the solver") - static class GetInfoCommand { + static class GetInfoCommand implements Command { static final String COMMAND = "get-info"; @Parameter(description = "The solver to print info about (:)", validateWith = SolverNameAndVersionValidator.class, required = true) String solver; + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public void handle(SmtLibSolverManager smtLibSolverManager, Logger logger) throws SmtLibSolverInstallerException { + final var solver = decodeVersionString(this.solver); + final var info = smtLibSolverManager.getInfo(solver.get1(), solver.get2()); + logger.write(Logger.Level.RESULT, "%s\n", info); + } } @Parameters(commandDescription = "Edits the runtime arguments passed to the solver") - static class EditArgsCommand { + static class EditArgsCommand implements Command { static final String COMMAND = "edit-args"; @Parameter(description = "The solver, whose runtime arguments are to be edited (:)", validateWith = SolverNameAndVersionValidator.class, required = true) @@ -105,22 +181,94 @@ static class EditArgsCommand { @Parameter(names = "--print", description = "Print the path instead of opening it for editing") boolean print = false; + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public void handle(SmtLibSolverManager smtLibSolverManager, Logger logger) throws SmtLibSolverInstallerException { + final var solver = decodeVersionString(this.solver); + final var argsFilePath = smtLibSolverManager.getArgsFile(solver.get1(), solver.get2()); + + if(print) { + logger.write(Logger.Level.RESULT, String.format("%s\n", argsFilePath.toAbsolutePath())); + } + else if(Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.EDIT)) { + try { + Desktop.getDesktop().edit(argsFilePath.toFile()); + } catch (IOException e) { + throw new SmtLibSolverInstallerException(e); + } + } + else { + logger.write(Logger.Level.MAINSTEP, "Open the following text file in your favourite editor, and edit the content:\n"); + logger.write(Logger.Level.RESULT, String.format("%s\n", argsFilePath.toAbsolutePath())); + } + } } @Parameters(commandDescription = "Lists installed solvers and their versions") - static class ListInstalledCommand { + static class ListInstalledCommand implements Command { static final String COMMAND = "list-installed"; @Parameter(description = "The solver, whose installed versions are to be listed ()", validateWith = SolverNameValidator.class) String solver; + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public void handle(SmtLibSolverManager smtLibSolverManager, Logger logger) throws SmtLibSolverInstallerException { + if(solver != null) { + logger.write(Logger.Level.MAINSTEP, "The currently installed versions of solver %s are: \n", solver); + smtLibSolverManager.getInstalledVersions(solver).forEach(version -> { + logger.write(Logger.Level.RESULT, "\t%s:%s\n", solver, version); + }); + } + else { + logger.write(Logger.Level.MAINSTEP, "The currently installed solvers are: \n"); + smtLibSolverManager.getInstalledVersions().forEach(solver -> { + solver.get2().forEach(version -> { + logger.write(Logger.Level.RESULT, "\t%s:%s\n", solver.get1(), version); + }); + }); + } + } } @Parameters(commandDescription = "Lists supported solvers and their versions") - static class ListSupportedCommand { + static class ListSupportedCommand implements Command { static final String COMMAND = "list-supported"; @Parameter(description = "The solver, whose supported versions are to be listed ()", validateWith = SolverNameValidator.class) String solver; + + @Override + public String getCommand() { + return COMMAND; + } + + @Override + public void handle(SmtLibSolverManager smtLibSolverManager, Logger logger) throws SmtLibSolverInstallerException { + if(solver != null) { + logger.write(Logger.Level.MAINSTEP, "The currently supported versions of solver %s are: \n", solver); + smtLibSolverManager.getSupportedVersions(solver).forEach(version -> { + logger.write(Logger.Level.RESULT, "\t%s:%s\n", solver, version); + }); + } + else { + logger.write(Logger.Level.MAINSTEP, "The currently supported solvers are: \n"); + smtLibSolverManager.getSupportedVersions().forEach(solver -> { + solver.get2().forEach(version -> { + logger.write(Logger.Level.RESULT, "\t%s:%s\n", solver.get1(), version); + }); + }); + } + } } public SmtLibCli(final String[] args) { @@ -134,27 +282,20 @@ public static void main(final String[] args) { private void run() { final var mainParams = new MainParams(); - final var installCommand = new InstallCommand(); - final var installGenericCommand = new InstallGenericCommand(); - final var uninstallCommand = new UninstallCommand(); - final var renameCommand = new RenameCommand(); - final var getInfoCommand = new GetInfoCommand(); - final var editArgsCommand = new EditArgsCommand(); - final var listInstalledCommand = new ListInstalledCommand(); - final var listSupportedCommand = new ListSupportedCommand(); - - final var jc = JCommander.newBuilder() - .addObject(mainParams) - .addCommand(InstallCommand.COMMAND, installCommand) - .addCommand(InstallGenericCommand.COMMAND, installGenericCommand) - .addCommand(UninstallCommand.COMMAND, uninstallCommand) - .addCommand(RenameCommand.COMMAND, renameCommand) - .addCommand(GetInfoCommand.COMMAND, getInfoCommand) - .addCommand(EditArgsCommand.COMMAND, editArgsCommand) - .addCommand(ListInstalledCommand.COMMAND, listInstalledCommand) - .addCommand(ListSupportedCommand.COMMAND, listSupportedCommand) - .programName(JAR_NAME) - .build(); + List commands = List.of( + new InstallCommand(), + new InstallGenericCommand(), + new UninstallCommand(), + new RenameCommand(), + new GetInfoCommand(), + new EditArgsCommand(), + new ListInstalledCommand(), + new ListSupportedCommand() + ); + + final var jcBuilder = JCommander.newBuilder().addObject(mainParams); + commands.forEach(command -> jcBuilder.addCommand(command.getCommand(), command)); + final var jc = jcBuilder.programName(JAR_NAME).build(); try { jc.parse(args); @@ -181,105 +322,15 @@ private void run() { return; } - switch(jc.getParsedCommand()) { - case InstallCommand.COMMAND: { - final var solver = decodeVersionString(installCommand.solver); - - if(solver.get1().equals(smtLibSolverManager.getGenericInstallerName())) { - logger.write(Logger.Level.RESULT, "To install a generic solver, use the \"%s\" command", InstallGenericCommand.COMMAND); - return; - } - - if(installCommand.name != null) { - smtLibSolverManager.install(solver.get1(), solver.get2(), installCommand.name, installCommand.solverPath != null ? Path.of(installCommand.solverPath) : null, installCommand.temptMurphy); - } - else { - smtLibSolverManager.install(solver.get1(), solver.get2(), solver.get2(), installCommand.solverPath != null ? Path.of(installCommand.solverPath) : null, installCommand.temptMurphy); - } - - return; - } - case InstallGenericCommand.COMMAND: { - smtLibSolverManager.installGeneric( - installGenericCommand.name, - Path.of(installGenericCommand.solverPath), - (installGenericCommand.solverArgs == null ? "" : installGenericCommand.solverArgs).split(" ") - ); - return; - } - case UninstallCommand.COMMAND: { - final var solver = decodeVersionString(uninstallCommand.solver); - smtLibSolverManager.uninstall(solver.get1(), solver.get2()); - return; - } - case RenameCommand.COMMAND: { - final var solver = decodeVersionString(renameCommand.solver); - smtLibSolverManager.rename(solver.get1(), solver.get2(), renameCommand.name); - return; - } - case GetInfoCommand.COMMAND: { - final var solver = decodeVersionString(getInfoCommand.solver); - final var info = smtLibSolverManager.getInfo(solver.get1(), solver.get2()); - logger.write(Logger.Level.RESULT, "%s\n", info); - return; - } - case EditArgsCommand.COMMAND: { - final var solver = decodeVersionString(editArgsCommand.solver); - final var argsFilePath = smtLibSolverManager.getArgsFile(solver.get1(), solver.get2()); - - if(editArgsCommand.print) { - logger.write(Logger.Level.RESULT, String.format("%s\n", argsFilePath.toAbsolutePath().toString())); - } - else if(Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.EDIT)) { - Desktop.getDesktop().edit(argsFilePath.toFile()); - } - else { - logger.write(Logger.Level.MAINSTEP, "Open the following text file in your favourite editor, and edit the content:\n"); - logger.write(Logger.Level.RESULT, String.format("%s\n", argsFilePath.toAbsolutePath().toString())); - } - - return; - } - case ListInstalledCommand.COMMAND: { - if(listInstalledCommand.solver != null) { - logger.write(Logger.Level.MAINSTEP, "The currently installed versions of solver %s are: \n", listInstalledCommand.solver); - smtLibSolverManager.getInstalledVersions(listInstalledCommand.solver).forEach(version -> { - logger.write(Logger.Level.RESULT, "\t%s:%s\n", listInstalledCommand.solver, version); - }); - } - else { - logger.write(Logger.Level.MAINSTEP, "The currently installed solvers are: \n"); - smtLibSolverManager.getInstalledVersions().forEach(solver -> { - solver.get2().forEach(version -> { - logger.write(Logger.Level.RESULT, "\t%s:%s\n", solver.get1(), version); - }); - }); - } - return; - } - case ListSupportedCommand.COMMAND: { - if(listSupportedCommand.solver != null) { - logger.write(Logger.Level.MAINSTEP, "The currently supported versions of solver %s are: \n", listSupportedCommand.solver); - smtLibSolverManager.getSupportedVersions(listSupportedCommand.solver).forEach(version -> { - logger.write(Logger.Level.RESULT, "\t%s:%s\n", listSupportedCommand.solver, version); - }); - } - else { - logger.write(Logger.Level.MAINSTEP, "The currently supported solvers are: \n"); - smtLibSolverManager.getSupportedVersions().forEach(solver -> { - solver.get2().forEach(version -> { - logger.write(Logger.Level.RESULT, "\t%s:%s\n", solver.get1(), version); - }); - }); - } - return; - } - default: { - logger.write(Logger.Level.RESULT, "Unknown command\n"); - jc.usage(); + final var parsedCommand = jc.getParsedCommand(); + for(final var command : commands) { + if(command.getCommand().equals(parsedCommand)) { + command.handle(smtLibSolverManager, logger); return; } } + logger.write(Logger.Level.RESULT, "Unknown command\n"); + jc.usage(); } catch (SmtLibSolverInstallerException e) { logger.write(Logger.Level.RESULT, "%s\n", e.getMessage()); diff --git a/subprojects/solver/solver-smtlib/README.md b/subprojects/solver/solver-smtlib/README.md index 87ea774f89..dbde95da63 100644 --- a/subprojects/solver/solver-smtlib/README.md +++ b/subprojects/solver/solver-smtlib/README.md @@ -15,9 +15,9 @@ The [SMT-LIB2 standard](http://smtlib.cs.uiowa.edu/) is an international initiat However, there are some limitation to this standard, both in terms of its content and its practical application by the solvers that support it: -- There are no standard way of denoting an array literal in SMT-LIB. Each solver that support the said theory used to come up with a solution of their own in this matter. This lead to the creation of the `as-array` (Z3), and the `as const` (CVC4, MathSAT) constructs. Nowadays, solvers tend to support the `as const` construct (event the newer versions of Z3). -- There are no standard way of denoting interpolation. Solvers that support interpolation (Z3, SMTInterpol, MathSAT) have their own extension added to SMT-LIB to support this feature. -- The support for the standard tends to be loose in some solvers. For example, MathSAT expects a numeric argument to `push` and `pop`, does not default to 1, like the standard. Moreover, MathSAT uses a custom output language when outputting models, that is not part of the standard. +* There are no standard way of denoting an array literal in SMT-LIB. Each solver that support the said theory used to come up with a solution of their own in this matter. This lead to the creation of the `as-array` (Z3), and the `as const` (CVC4, MathSAT) constructs. Nowadays, solvers tend to support the `as const` construct (event the newer versions of Z3). +* There are no standard way of denoting interpolation. Solvers that support interpolation (Z3, SMTInterpol, MathSAT) have their own extension added to SMT-LIB to support this feature. +* The support for the standard tends to be loose in some solvers. For example, MathSAT expects a numeric argument to `push` and `pop`, does not default to 1, like the standard. Moreover, MathSAT uses a custom output language when outputting models, that is not part of the standard. This list is unfortunately far from being complete, so one has to be careful when integrating a new solver with SMT-LIB support. @@ -29,20 +29,20 @@ The issues of compatibility described in the earlier section warranted to be con In general, to have an SMT-LIB supporting solver, components implementing the following interfaces has to be developed: -- `SmtLibTransformationManager`: Transforms anything in Theta to their SMT-LIB counterpart. It uses further components for this feature: - - `SmtLibTypeTransformer`: Transforms a Theta type to and SMT-LIB type. - - `SmtLibDeclTransformer`: Transforms a Theta declaration to an SMT-LIB declaration. - - `SmtLibExprTransformer`: Transforms a Theta expression to an SMT-LIB expression. - - `SmtLibSymbolTable`: Caches the Theta declarations and their SMT-LIB counterpart. -- `SmtLibTermTransformer`: Transforms an SMT-LIB expression to a Theta expression. It provides methods that ensure type-safety. -- `SmtLibSolverBinary`: Provides an interface to communicate with the binary of the solver. -- `SmtLibSolverInstaller`: An interface to support installation scripts and solver management. +* `SmtLibTransformationManager`: Transforms anything in Theta to their SMT-LIB counterpart. It uses further components for this feature: + * `SmtLibTypeTransformer`: Transforms a Theta type to and SMT-LIB type. + * `SmtLibDeclTransformer`: Transforms a Theta declaration to an SMT-LIB declaration. + * `SmtLibExprTransformer`: Transforms a Theta expression to an SMT-LIB expression. + * `SmtLibSymbolTable`: Caches the Theta declarations and their SMT-LIB counterpart. +* `SmtLibTermTransformer`: Transforms an SMT-LIB expression to a Theta expression. It provides methods that ensure type-safety. +* `SmtLibSolverBinary`: Provides an interface to communicate with the binary of the solver. +* `SmtLibSolverInstaller`: An interface to support installation scripts and solver management. The SMT-LIB grammar that the component supports is defined using ANTLR. The ANTLR grammar can be found in the source folder (`SMTLIBv2.g4`). The components above are integrated into a working solver implementation with Theta's solver interface by the following classes: -- `SmtLibSolver`: Provides a solver implementing Theta's `Solver` and `UCSolver` interface supporting basic satisfiability checks, model querying and unsat core querying. -- `BaseSmtLibItpSolver`: Provides a solver implementing Theta's `ItpSolver` interface supporting interpolating solvers. **Note**: As interpolation is not part of the SMT-LIB standard, this class is abstract. Each solver supporting interpolation has to extend this class and configure it properly. +* `SmtLibSolver`: Provides a solver implementing Theta's `Solver` and `UCSolver` interface supporting basic satisfiability checks, model querying and unsat core querying. +* `BaseSmtLibItpSolver`: Provides a solver implementing Theta's `ItpSolver` interface supporting interpolating solvers. **Note**: As interpolation is not part of the SMT-LIB standard, this class is abstract. Each solver supporting interpolation has to extend this class and configure it properly. ### Generic interface implementation @@ -52,10 +52,10 @@ The interfaces above have a default, generic implementation that works with solv Right now, the solver-smtlib subproject supports the following solvers. Each package contains the specialization of the interfaces above that communicate with the said solver: -- **Boolector** (`hu.bme.mit.theta.solver.smtlib.impl.boolector`): The solver specializes in bitvector and array theories, but lacks support for others. It cannot interpolate or produce unsat cores, so it can only be used for abstraction. -- **CVC4** (`hu.bme.mit.theta.solver.smtlib.impl.cvc4`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). -- **Mathsat5** (`hu.bme.mit.theta.solver.smtlib.impl.mathsat`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors, floating points). It also supports interpolation (binary, sequential and tree interpolation) with many of them. -- **Princess** (`hu.bme.mit.theta.solver.smtlib.impl.princess`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). It also supports interpolation (binary, sequential and tree interpolation) with many of them. -- **SMTInterpol** (`hu.bme.mit.theta.solver.smtlib.impl.smtinterpol`): The solver specializes in integer and rational theories. It also supports interpolation (binary, sequential and tree interpolation) with them. -- **Yices2** (`hu.bme.mit.theta.solver.smtlib.impl.yices2`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). -- **Z3** (`hu.bme.mit.theta.solver.smtlib.impl.z3`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors, functions), and supports interpolation as well (binary, sequential and tree interpolation) up to version 4.7. \ No newline at end of file +* **Boolector** (`hu.bme.mit.theta.solver.smtlib.impl.boolector`): The solver specializes in bitvector and array theories, but lacks support for others. It cannot interpolate or produce unsat cores, so it can only be used for abstraction. +* **CVC4** (`hu.bme.mit.theta.solver.smtlib.impl.cvc4`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). +* **Mathsat5** (`hu.bme.mit.theta.solver.smtlib.impl.mathsat`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors, floating points). It also supports interpolation (binary, sequential and tree interpolation) with many of them. +* **Princess** (`hu.bme.mit.theta.solver.smtlib.impl.princess`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). It also supports interpolation (binary, sequential and tree interpolation) with many of them. +* **SMTInterpol** (`hu.bme.mit.theta.solver.smtlib.impl.smtinterpol`): The solver specializes in integer and rational theories. It also supports interpolation (binary, sequential and tree interpolation) with them. +* **Yices2** (`hu.bme.mit.theta.solver.smtlib.impl.yices2`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors). +* **Z3** (`hu.bme.mit.theta.solver.smtlib.impl.z3`): The solver supports basic satisfiability problems for numerous theories (integers, rationals, quantifiers, arrays, bitvectors, functions), and supports interpolation as well (binary, sequential and tree interpolation) up to version 4.7. \ No newline at end of file diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java index 90b3c47d7e..a033be0c45 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/boolector/BoolectorSmtLibSolverInstaller.java @@ -60,7 +60,9 @@ protected void installSolver(final Path installDir, final String version) throws } @Override - protected void uninstallSolver(final Path installDir, final String version) { } + protected void uninstallSolver(final Path installDir, final String version) { + // Default uninstall is suitable + } @Override protected String[] getDefaultSolverArgs(String version) { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java index 05654c9731..789c0821e4 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/cvc4/CVC4SmtLibSolverInstaller.java @@ -1,11 +1,11 @@ package hu.bme.mit.theta.solver.smtlib.impl.cvc4; import hu.bme.mit.theta.common.OsHelper; -import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; -import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import java.io.FileOutputStream; import java.io.IOException; @@ -17,8 +17,6 @@ import java.util.Arrays; import java.util.List; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; @@ -53,7 +51,9 @@ protected void installSolver(final Path installDir, final String version) throws } @Override - protected void uninstallSolver(final Path installDir, final String version) { } + protected void uninstallSolver(final Path installDir, final String version) { + // Default uninstall is suitable + } @Override protected String[] getDefaultSolverArgs(String version) { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverBinary.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverBinary.java index 0a8db6cee2..30bf700ec7 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverBinary.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverBinary.java @@ -122,6 +122,7 @@ public void step(final StringBuilder sb, final char c) { } break; case READY: + default: throw new AssertionError(); } } diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java index f4124852cd..1ccc548242 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/generic/GenericSmtLibSolverInstaller.java @@ -12,8 +12,6 @@ import java.util.Collections; import java.util.List; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; public final class GenericSmtLibSolverInstaller extends SmtLibSolverInstaller.Default { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java index 6a250f2969..88298c3d1b 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/mathsat/MathSATSmtLibSolverInstaller.java @@ -1,12 +1,12 @@ package hu.bme.mit.theta.solver.smtlib.impl.mathsat; import hu.bme.mit.theta.common.OsHelper; -import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; -import hu.bme.mit.theta.solver.smtlib.utils.Compress; -import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.utils.Compress; +import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import java.io.IOException; import java.net.URI; @@ -15,8 +15,6 @@ import java.util.Arrays; import java.util.List; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; import static hu.bme.mit.theta.common.OsHelper.Architecture.X86; import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; @@ -125,7 +123,9 @@ protected void installSolver(Path installDir, String version) throws SmtLibSolve } @Override - protected void uninstallSolver(Path installDir, String version) { } + protected void uninstallSolver(Path installDir, String version) { + // Default uninstall is suitable + } @Override protected String[] getDefaultSolverArgs(String version) throws SmtLibSolverInstallerException { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java index ac9b561052..b6c0dad3a7 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/princess/PrincessSmtLibSolverInstaller.java @@ -3,26 +3,16 @@ import hu.bme.mit.theta.common.OsHelper; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.smtlib.impl.cvc4.CVC4SmtLibSolverFactory; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; import hu.bme.mit.theta.solver.smtlib.utils.Compress; -import hu.bme.mit.theta.solver.smtlib.utils.SemVer; -import java.io.FileOutputStream; import java.io.IOException; -import java.net.MalformedURLException; import java.net.URI; -import java.net.URL; -import java.nio.channels.Channels; import java.nio.file.Path; import java.util.Arrays; import java.util.List; -import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; -import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; -import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; - public class PrincessSmtLibSolverInstaller extends SmtLibSolverInstaller.Default { public PrincessSmtLibSolverInstaller(final Logger logger) { @@ -56,7 +46,9 @@ protected void installSolver(final Path installDir, final String version) throws } @Override - protected void uninstallSolver(final Path installDir, final String version) { } + protected void uninstallSolver(final Path installDir, final String version) { + // Default uninstall is suitable + } @Override protected String[] getDefaultSolverArgs(String version) { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java index 4250025ce8..57ce9c5867 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/smtinterpol/SMTInterpolSmtLibSolverInstaller.java @@ -1,12 +1,9 @@ package hu.bme.mit.theta.solver.smtlib.impl.smtinterpol; -import hu.bme.mit.theta.common.OsHelper; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; -import hu.bme.mit.theta.solver.smtlib.impl.cvc4.CVC4SmtLibSolverFactory; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; -import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import java.io.FileOutputStream; import java.io.IOException; @@ -18,10 +15,6 @@ import java.util.Arrays; import java.util.List; -import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; -import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; -import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.WINDOWS; - public class SMTInterpolSmtLibSolverInstaller extends SmtLibSolverInstaller.Default { public SMTInterpolSmtLibSolverInstaller(final Logger logger) { @@ -51,7 +44,9 @@ protected void installSolver(final Path installDir, final String version) throws } @Override - protected void uninstallSolver(final Path installDir, final String version) { } + protected void uninstallSolver(final Path installDir, final String version) { + // Default uninstall is suitable + } @Override protected String[] getDefaultSolverArgs(String version) { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java index 369c017c15..b69d66af09 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/impl/z3/Z3SmtLibSolverInstaller.java @@ -1,12 +1,12 @@ package hu.bme.mit.theta.solver.smtlib.impl.z3; import hu.bme.mit.theta.common.OsHelper; -import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; -import hu.bme.mit.theta.solver.smtlib.utils.Compress; -import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverFactory; +import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstaller; import hu.bme.mit.theta.solver.smtlib.solver.installer.SmtLibSolverInstallerException; +import hu.bme.mit.theta.solver.smtlib.utils.Compress; +import hu.bme.mit.theta.solver.smtlib.utils.SemVer; import java.io.IOException; import java.net.URI; @@ -15,8 +15,6 @@ import java.util.Arrays; import java.util.List; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; import static hu.bme.mit.theta.common.OsHelper.Architecture.X64; import static hu.bme.mit.theta.common.OsHelper.Architecture.X86; import static hu.bme.mit.theta.common.OsHelper.OperatingSystem.LINUX; @@ -132,7 +130,9 @@ protected void installSolver(final Path installDir, final String version) throws } @Override - protected void uninstallSolver(Path installDir, String version) { } + protected void uninstallSolver(Path installDir, String version) { + // Default uninstall is suitable + } @Override protected String[] getDefaultSolverArgs(String version) { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java index 534f298e04..f01184a717 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/SmtLibSolver.java @@ -13,13 +13,13 @@ import hu.bme.mit.theta.solver.impl.StackImpl; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Lexer; import hu.bme.mit.theta.solver.smtlib.dsl.gen.SMTLIBv2Parser; +import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; +import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibValuation; import hu.bme.mit.theta.solver.smtlib.solver.parser.CheckSatResponse; import hu.bme.mit.theta.solver.smtlib.solver.parser.GeneralResponse; import hu.bme.mit.theta.solver.smtlib.solver.parser.GetModelResponse; import hu.bme.mit.theta.solver.smtlib.solver.parser.GetUnsatCoreResponse; import hu.bme.mit.theta.solver.smtlib.solver.parser.ThrowExceptionErrorListener; -import hu.bme.mit.theta.solver.smtlib.solver.binary.SmtLibSolverBinary; -import hu.bme.mit.theta.solver.smtlib.solver.model.SmtLibValuation; import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibSymbolTable; import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTermTransformer; import hu.bme.mit.theta.solver.smtlib.solver.transformer.SmtLibTransformationManager; @@ -32,7 +32,6 @@ import java.util.LinkedList; import java.util.Map; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; public class SmtLibSolver implements UCSolver, Solver { diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java index 5648b9963d..b662892029 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/solver/installer/SmtLibSolverInstaller.java @@ -6,10 +6,8 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.nio.file.CopyOption; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Collections; import java.util.List; diff --git a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/Compress.java b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/Compress.java index 0de0b7d885..6dbff73c27 100644 --- a/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/Compress.java +++ b/subprojects/solver/solver-smtlib/src/main/java/hu/bme/mit/theta/solver/smtlib/utils/Compress.java @@ -27,6 +27,8 @@ public static void extract(final InputStream inputStream, final Path extractDir, case TARGZ: extract(new TarArchiveInputStream(new GzipCompressorInputStream(new BufferedInputStream(inputStream))), extractDir); break; + default: + throw new AssertionError(); } } diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java index a60f6ee235..f8351c3899 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibItpSolverTest.java @@ -40,7 +40,6 @@ import org.junit.Test; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import static hu.bme.mit.theta.core.decl.Decls.Const; diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java index c7653c794f..c1b3125947 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverBVTest.java @@ -16,7 +16,6 @@ import org.junit.runners.Parameterized; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.util.Collection; import java.util.stream.Collectors; diff --git a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java index fdb641e162..ecac1d4e4e 100644 --- a/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java +++ b/subprojects/solver/solver-smtlib/src/test/java/hu/bme/mit/theta/solver/smtlib/SmtLibSolverTest.java @@ -34,7 +34,6 @@ import org.junit.Test; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Map; @@ -46,11 +45,9 @@ import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Read; import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Write; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; import static hu.bme.mit.theta.core.type.bvtype.BvExprs.Bv; import static hu.bme.mit.theta.core.type.functype.FuncExprs.App; import static hu.bme.mit.theta.core.type.functype.FuncExprs.Func; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -100,7 +97,7 @@ public void test() { ); assertNotNull(expr); assertTrue(expr instanceof ForallExpr); - assertEquals(Array(x.getType(), Int()), ((ForallExpr) expr).getParamDecls().get(0).getType()); + assertEquals(Array(x.getType(), IntExprs.Int()), ((ForallExpr) expr).getParamDecls().get(0).getType()); } @Test @@ -108,11 +105,11 @@ public void testSimple() { final Solver solver = solverFactory.createSolver(); // Create two integer constants x and y - final ConstDecl cx = Const("x", Int()); - final ConstDecl cy = Const("y", Int()); + final ConstDecl cx = Const("x", IntExprs.Int()); + final ConstDecl cy = Const("y", IntExprs.Int()); // Add x == y + 1 to the solver - solver.add(IntExprs.Eq(cx.getRef(), IntExprs.Add(cy.getRef(), Int(1)))); + solver.add(IntExprs.Eq(cx.getRef(), IntExprs.Add(cy.getRef(), IntExprs.Int(1)))); // Check, the expression should be satisfiable SolverStatus status = solver.check(); @@ -131,7 +128,7 @@ public void testTrack() { final UCSolver solver = solverFactory.createUCSolver(); final ConstDecl ca = Const("a", BoolExprs.Bool()); - final Expr expr = BoolExprs.And(ca.getRef(), True()); + final Expr expr = BoolExprs.And(ca.getRef(), BoolExprs.True()); solver.push(); solver.track(expr); @@ -198,13 +195,13 @@ public void testModel() { public void testFunc() { // Arrange final Solver solver = solverFactory.createSolver(); - final ConstDecl> ca = Const("a", Func(Int(), Int())); + final ConstDecl> ca = Const("a", Func(IntExprs.Int(), IntExprs.Int())); final Expr> a = ca.getRef(); - final ParamDecl px = Param("x", Int()); + final ParamDecl px = Param("x", IntExprs.Int()); final Expr x = px.getRef(); - solver.add(BoolExprs.Forall(of(px), BoolExprs.Imply(IntExprs.Leq(x, Int(0)), IntExprs.Eq(App(a, x), Int(0))))); - solver.add(BoolExprs.Forall(of(px), BoolExprs.Imply(IntExprs.Geq(x, Int(1)), IntExprs.Eq(App(a, x), Int(1))))); + solver.add(BoolExprs.Forall(of(px), BoolExprs.Imply(IntExprs.Leq(x, IntExprs.Int(0)), IntExprs.Eq(App(a, x), IntExprs.Int(0))))); + solver.add(BoolExprs.Forall(of(px), BoolExprs.Imply(IntExprs.Geq(x, IntExprs.Int(1)), IntExprs.Eq(App(a, x), IntExprs.Int(1))))); // Act final SolverStatus status = solver.check(); @@ -221,10 +218,10 @@ public void testFunc() { public void testArray() { final Solver solver = solverFactory.createSolver(); - final ConstDecl> arr = Const("arr", Array(Int(), Int())); + final ConstDecl> arr = Const("arr", Array(IntExprs.Int(), IntExprs.Int())); - solver.add(ArrayExprs.Eq(Write(arr.getRef(), Int(0), Int(1)), arr.getRef())); - solver.add(ArrayExprs.Eq(Write(arr.getRef(), Int(1), Int(2)), arr.getRef())); + solver.add(ArrayExprs.Eq(Write(arr.getRef(), IntExprs.Int(0), IntExprs.Int(1)), arr.getRef())); + solver.add(ArrayExprs.Eq(Write(arr.getRef(), IntExprs.Int(1), IntExprs.Int(2)), arr.getRef())); // Check, the expression should be satisfiable SolverStatus status = solver.check(); @@ -236,8 +233,8 @@ public void testArray() { assertTrue(val instanceof ArrayLitExpr); var valLit = (ArrayLitExpr)val; assertTrue(2 <= valLit.getElements().size()); - assertEquals(Int(1), Read(valLit, Int(0)).eval(ImmutableValuation.empty())); - assertEquals(Int(2), Read(valLit, Int(1)).eval(ImmutableValuation.empty())); + assertEquals(IntExprs.Int(1), Read(valLit, IntExprs.Int(0)).eval(ImmutableValuation.empty())); + assertEquals(IntExprs.Int(2), Read(valLit, IntExprs.Int(1)).eval(ImmutableValuation.empty())); } @Test @@ -264,7 +261,6 @@ public void testBV2() { final Solver solver = solverFactory.createSolver(); final ConstDecl cx = Const("x", BvExprs.BvType(4)); - final ConstDecl cy = Const("y", BvExprs.BvType(4)); final ConstDecl cz = Const("z", BvExprs.BvType(4)); solver.push(); diff --git a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java index c45e35b271..37dea628cd 100644 --- a/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java +++ b/subprojects/solver/solver-z3/src/main/java/hu/bme/mit/theta/solver/z3/Z3Solver.java @@ -283,7 +283,7 @@ private LitExpr extractLiteral(final ConstDecl extractArrayLiteral(final FuncDecl funcDecl) { return (LitExpr) expr; } - private LitExpr extractBvConstLiteral(final FuncDecl funcDecl, final BvType type) { + private LitExpr extractBvConstLiteral(final FuncDecl funcDecl) { final com.microsoft.z3.Expr term = z3Model.getConstInterp(funcDecl); if (term == null) { return null; @@ -331,11 +331,12 @@ private Collection> constDeclsOf(final com.microsoft.z3.Model z3Mod if (symbolTable.definesSymbol(symbol)) { final ConstDecl constDecl = symbolTable.getConst(symbol); builder.add(constDecl); - } else { + } + /* else { if (!assumptions.containsKey(symbol.getName().toString())) { // Quantifier? } - } + } */ } return builder.build(); } diff --git a/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java b/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java index f77876b373..a5d650d667 100644 --- a/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java +++ b/subprojects/solver/solver-z3/src/test/java/hu/bme/mit/theta/solver/z3/Z3SolverTest.java @@ -80,7 +80,7 @@ public void testSimple() { final ConstDecl cy = Const("y", Int()); // Add x == y + 1 to the solver - solver.add(IntExprs.Eq(cx.getRef(), IntExprs.Add(cy.getRef(), Int(1)))); + solver.add(Eq(cx.getRef(), Add(cy.getRef(), Int(1)))); // Check, the expression should be satisfiable SolverStatus status = solver.check(); @@ -122,8 +122,8 @@ public void testFunc() { final ParamDecl px = Param("x", Int()); final Expr x = px.getRef(); - solver.add(BoolExprs.Forall(of(px), BoolExprs.Imply(IntExprs.Leq(x, Int(0)), IntExprs.Eq(App(a, x), Int(0))))); - solver.add(BoolExprs.Forall(of(px), BoolExprs.Imply(IntExprs.Geq(x, Int(1)), IntExprs.Eq(App(a, x), Int(1))))); + solver.add(BoolExprs.Forall(of(px), BoolExprs.Imply(IntExprs.Leq(x, Int(0)), Eq(App(a, x), Int(0))))); + solver.add(BoolExprs.Forall(of(px), BoolExprs.Imply(IntExprs.Geq(x, Int(1)), Eq(App(a, x), Int(1))))); // Act final SolverStatus status = solver.check(); @@ -193,7 +193,7 @@ public void testReset() { final ConstDecl cx = Const("x", Int()); final ConstDecl cy = Const("y", Int()); - IntEqExpr eqExpr = IntExprs.Eq(cx.getRef(), IntExprs.Add(cy.getRef(), Int(1))); + IntEqExpr eqExpr = Eq(cx.getRef(), Add(cy.getRef(), Int(1))); solver.add(eqExpr); SolverStatus status = solver.check(); assertTrue(status.isSat()); @@ -455,9 +455,4 @@ public void testBV12() { solver.pop(); } - - private static BvLitExpr uint16ToBvLitExpr(int value) { - return BvUtils.bigIntegerToUnsignedBvLitExpr(BigInteger.valueOf(value), 16); - } - } diff --git a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java index cdc7029ae4..044c03a645 100644 --- a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java +++ b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpPattern.java @@ -15,7 +15,6 @@ */ package hu.bme.mit.theta.solver; -import java.util.Collection; import java.util.List; /** diff --git a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java index 1309f6281d..21abc34101 100644 --- a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java +++ b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/ItpSolver.java @@ -15,17 +15,15 @@ */ package hu.bme.mit.theta.solver; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; +import hu.bme.mit.theta.core.type.Expr; +import hu.bme.mit.theta.core.type.booltype.BoolType; import java.util.Arrays; import java.util.Collection; import java.util.List; -import com.google.common.collect.Lists; - -import hu.bme.mit.theta.core.type.Expr; -import hu.bme.mit.theta.core.type.booltype.BoolType; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; /** * An extension of the {@link Solver} interface, which also supports interpolation. diff --git a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java index 8ea8851771..bfc9496ca6 100644 --- a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java +++ b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/Solver.java @@ -15,9 +15,6 @@ */ package hu.bme.mit.theta.solver; -import java.util.Collection; - -import hu.bme.mit.theta.core.model.Valuation; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.booltype.BoolType; diff --git a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java index 20eab0dc40..88d4371038 100644 --- a/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java +++ b/subprojects/solver/solver/src/main/java/hu/bme/mit/theta/solver/utils/WithPushPop.java @@ -15,11 +15,10 @@ */ package hu.bme.mit.theta.solver.utils; -import java.io.Closeable; - -import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverBase; +import java.io.Closeable; + /** * A helper class for automatic push and pop for solvers using the * try-with-resources statement. diff --git a/subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java b/subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java index e913522d01..6b1979dba3 100644 --- a/subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java +++ b/subprojects/solver/solver/src/test/java/hu/bme/mit/theta/solver/SolverStub.java @@ -31,6 +31,7 @@ public SolverStub() { @Override public void add(final Expr assertion) { + // Stub } @Override @@ -50,6 +51,7 @@ public void pop(final int n) { @Override public void reset() { + // Stub } @Override @@ -68,5 +70,7 @@ public Collection> getAssertions() { } @Override - public void close() {} + public void close() { + // Nothing to close + } } From 980e20da1afa006b5abcb7ff4d37e3f8292ae1a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Dobos-Kov=C3=A1cs?= Date: Wed, 29 Sep 2021 10:56:26 +0200 Subject: [PATCH 99/99] Bump version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3dc1baea67..282a38fe25 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ buildscript { allprojects { group = "hu.bme.mit.inf.theta" - version = "2.23.0" + version = "3.0.0" apply(from = rootDir.resolve("gradle/shared-with-buildSrc/mirrors.gradle.kts")) }