From 0e4656f98b369707e34edd64b0188a28a21677c4 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Thu, 14 Aug 2025 13:12:08 +0200 Subject: [PATCH 01/89] Trace: Add API tracing --- .../java_smt/SolverContextFactory.java | 9 + .../trace/TraceArrayFormulaManager.java | 92 ++++++++ .../trace/TraceBitvectorFormulaManager.java | 194 +++++++++++++++++ .../trace/TraceBooleanFormulaManager.java | 188 ++++++++++++++++ .../delegate/trace/TraceFormulaManager.java | 203 ++++++++++++++++++ .../trace/TraceIntegerFormulaManager.java | 198 +++++++++++++++++ .../java_smt/delegate/trace/TraceLogger.java | 105 +++++++++ .../trace/TraceProverEnvironment.java | 92 ++++++++ .../delegate/trace/TraceSolverContext.java | 69 ++++++ .../delegate/trace/TraceUFManager.java | 78 +++++++ .../java_smt/delegate/trace/package-info.java | 15 ++ 11 files changed, 1243 insertions(+) create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/package-info.java diff --git a/src/org/sosy_lab/java_smt/SolverContextFactory.java b/src/org/sosy_lab/java_smt/SolverContextFactory.java index 34c547ae28..b5aa969e8c 100644 --- a/src/org/sosy_lab/java_smt/SolverContextFactory.java +++ b/src/org/sosy_lab/java_smt/SolverContextFactory.java @@ -30,6 +30,7 @@ import org.sosy_lab.java_smt.delegate.logging.LoggingSolverContext; import org.sosy_lab.java_smt.delegate.statistics.StatisticsSolverContext; import org.sosy_lab.java_smt.delegate.synchronize.SynchronizedSolverContext; +import org.sosy_lab.java_smt.delegate.trace.TraceSolverContext; import org.sosy_lab.java_smt.solvers.bitwuzla.BitwuzlaSolverContext; import org.sosy_lab.java_smt.solvers.boolector.BoolectorSolverContext; import org.sosy_lab.java_smt.solvers.cvc4.CVC4SolverContext; @@ -95,6 +96,11 @@ public enum Solvers { @Option(secure = true, description = "Apply additional checks to catch common user errors.") private boolean useDebugMode = false; + @Option( + secure = true, + description = "Enable API tracing to record all calls to the JavaSMT library") + private boolean trace = false; + @Option( secure = true, description = "Counts all operations and interactions towards the SMT solver.") @@ -230,6 +236,9 @@ public SolverContext generateContext(Solvers solverToCreate) if (useDebugMode) { context = new DebuggingSolverContext(solverToCreate, config, context); } + if (trace) { + context = new TraceSolverContext(context); + } if (collectStatistics) { // statistics need to be the most outer wrapping layer. context = new StatisticsSolverContext(context); diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java new file mode 100644 index 0000000000..24ee2c74b4 --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java @@ -0,0 +1,92 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import org.sosy_lab.java_smt.api.ArrayFormula; +import org.sosy_lab.java_smt.api.ArrayFormulaManager; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.FormulaType; + +public class TraceArrayFormulaManager implements ArrayFormulaManager { + private final ArrayFormulaManager delegate; + private final TraceLogger logger; + + TraceArrayFormulaManager(ArrayFormulaManager pDelegate, TraceLogger pLogger) { + delegate = pDelegate; + logger = pLogger; + } + + @Override + public TE select( + ArrayFormula pArray, TI pIndex) { + return logger.logDef( + "mgr.getArrayFormulaManager()", + String.format("select(%s, %s)", logger.toVariable(pArray), logger.toVariable(pIndex)), + () -> delegate.select(pArray, pIndex)); + } + + @Override + public ArrayFormula store( + ArrayFormula pArray, TI pIndex, TE pValue) { + return logger.logDef( + "mgr.getArrayFormulaManager()", + String.format( + "store(%s, %s, %s)", + logger.toVariable(pArray), logger.toVariable(pIndex), logger.toVariable(pValue)), + () -> delegate.store(pArray, pIndex, pValue)); + } + + @Override + public < + TI extends Formula, + TE extends Formula, + FTI extends FormulaType, + FTE extends FormulaType> + ArrayFormula makeArray(String pName, FTI pIndexType, FTE pElementType) { + return logger.logDef( + "mgr.getArrayFormulaManager()", + String.format( + "makeArray(\"%s\", %s, %s)", + pName, logger.printFormulaType(pIndexType), logger.printFormulaType(pElementType)), + () -> delegate.makeArray(pName, pIndexType, pElementType)); + } + + @Override + public < + TI extends Formula, + TE extends Formula, + FTI extends FormulaType, + FTE extends FormulaType> + ArrayFormula makeArray(FTI pIndexType, FTE pElementType, TE defaultElement) { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula equivalence( + ArrayFormula pArray1, ArrayFormula pArray2) { + return logger.logDef( + "mgr.getArrayFormulaManager", + String.format( + "equivalence(%s, %s)", logger.toVariable(pArray1), logger.toVariable(pArray2)), + () -> delegate.equivalence(pArray1, pArray2)); + } + + @Override + public FormulaType getIndexType(ArrayFormula pArray) { + return delegate.getIndexType(pArray); + } + + @Override + public FormulaType getElementType(ArrayFormula pArray) { + return delegate.getElementType(pArray); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java new file mode 100644 index 0000000000..db5c044a2f --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java @@ -0,0 +1,194 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import java.math.BigInteger; +import java.util.List; +import org.sosy_lab.java_smt.api.BitvectorFormula; +import org.sosy_lab.java_smt.api.BitvectorFormulaManager; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.FormulaType.BitvectorType; +import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; + +public class TraceBitvectorFormulaManager implements BitvectorFormulaManager { + + @Override + public BitvectorFormula makeBitvector(int length, long pI) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula makeBitvector(int length, BigInteger pI) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula makeBitvector(int length, IntegerFormula pI) { + throw new UnsupportedOperationException(); + } + + @Override + public IntegerFormula toIntegerFormula(BitvectorFormula pI, boolean signed) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula makeVariable(int length, String pVar) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula makeVariable(BitvectorType type, String pVar) { + throw new UnsupportedOperationException(); + } + + @Override + public int getLength(BitvectorFormula number) { + return 0; + } + + @Override + public BitvectorFormula negate(BitvectorFormula number) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula add(BitvectorFormula number1, BitvectorFormula number2) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula subtract(BitvectorFormula number1, BitvectorFormula number2) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula divide( + BitvectorFormula dividend, BitvectorFormula divisor, boolean signed) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula smodulo(BitvectorFormula dividend, BitvectorFormula divisor) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula remainder( + BitvectorFormula dividend, BitvectorFormula divisor, boolean signed) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula multiply(BitvectorFormula number1, BitvectorFormula number2) { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula equal(BitvectorFormula number1, BitvectorFormula number2) { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula greaterThan( + BitvectorFormula number1, BitvectorFormula number2, boolean signed) { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula greaterOrEquals( + BitvectorFormula number1, BitvectorFormula number2, boolean signed) { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula lessThan( + BitvectorFormula number1, BitvectorFormula number2, boolean signed) { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula lessOrEquals( + BitvectorFormula number1, BitvectorFormula number2, boolean signed) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula not(BitvectorFormula bits) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula and(BitvectorFormula bits1, BitvectorFormula bits2) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula or(BitvectorFormula bits1, BitvectorFormula bits2) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula xor(BitvectorFormula bits1, BitvectorFormula bits2) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula shiftRight( + BitvectorFormula number, BitvectorFormula toShift, boolean signed) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula shiftLeft(BitvectorFormula number, BitvectorFormula toShift) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula rotateLeft(BitvectorFormula number, int toRotate) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula rotateLeft(BitvectorFormula number, BitvectorFormula toRotate) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula rotateRight(BitvectorFormula number, int toRotate) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula rotateRight(BitvectorFormula number, BitvectorFormula toRotate) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula concat(BitvectorFormula prefix, BitvectorFormula suffix) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula extract(BitvectorFormula number, int msb, int lsb) { + throw new UnsupportedOperationException(); + } + + @Override + public BitvectorFormula extend(BitvectorFormula number, int extensionBits, boolean signed) { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula distinct(List pBits) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java new file mode 100644 index 0000000000..78ae819fe0 --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java @@ -0,0 +1,188 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collector; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.BooleanFormulaManager; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.visitors.BooleanFormulaTransformationVisitor; +import org.sosy_lab.java_smt.api.visitors.BooleanFormulaVisitor; +import org.sosy_lab.java_smt.api.visitors.TraversalProcess; + +public class TraceBooleanFormulaManager implements BooleanFormulaManager { + private final BooleanFormulaManager delegate; + private final TraceLogger logger; + + TraceBooleanFormulaManager(BooleanFormulaManager pDelegate, TraceLogger pLogger) { + delegate = pDelegate; + logger = pLogger; + } + + @Override + public BooleanFormula makeTrue() { + return logger.logDef("mgr.getBooleanFormulaManager()", "makeTrue()", delegate::makeTrue); + } + + @Override + public BooleanFormula makeFalse() { + return logger.logDef("mgr.getBooleanFormulaManager()", "makeFalse()", delegate::makeFalse); + } + + @Override + public BooleanFormula makeVariable(String pVar) { + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format("makeVariable(\"%s\")", pVar), + () -> delegate.makeVariable(pVar)); + } + + @Override + public BooleanFormula equivalence(BooleanFormula formula1, BooleanFormula formula2) { + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format( + "equivalence(%s, %s)", logger.toVariable(formula1), logger.toVariable(formula2)), + () -> delegate.equivalence(formula1, formula2)); + } + + @Override + public BooleanFormula implication(BooleanFormula formula1, BooleanFormula formula2) { + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format( + "implication(%s, %s)", logger.toVariable(formula1), logger.toVariable(formula2)), + () -> delegate.implication(formula1, formula2)); + } + + @Override + public boolean isTrue(BooleanFormula formula) { + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format("isTrue(%s)", logger.toVariable(formula)), + () -> delegate.isTrue(formula)); + } + + @Override + public boolean isFalse(BooleanFormula formula) { + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format("isFalse(%s)", logger.toVariable(formula)), + () -> delegate.isFalse(formula)); + } + + @Override + public T ifThenElse(BooleanFormula cond, T f1, T f2) { + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format( + "ifThenElse(%s, %s, %s)", + logger.toVariable(cond), logger.toVariable(f1), logger.toVariable(f2)), + () -> delegate.ifThenElse(cond, f1, f2)); + } + + @Override + public BooleanFormula not(BooleanFormula formula) { + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format("not(%s)", logger.toVariable(formula)), + () -> delegate.not(formula)); + } + + @Override + public BooleanFormula and(BooleanFormula formula1, BooleanFormula formula2) { + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format("and(%s, %s)", logger.toVariable(formula1), logger.toVariable(formula2)), + () -> delegate.and(formula1, formula2)); + } + + @Override + public BooleanFormula and(Collection bits) { + BooleanFormula f = makeTrue(); + for (BooleanFormula bf : bits) { + f = and(bf, f); + } + return f; + } + + @Override + public BooleanFormula and(BooleanFormula... bits) { + return and(Arrays.asList(bits)); + } + + @Override + public Collector toConjunction() { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula or(BooleanFormula formula1, BooleanFormula formula2) { + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format("or(%s, %s)", logger.toVariable(formula1), logger.toVariable(formula2)), + () -> delegate.or(formula1, formula2)); + } + + @Override + public BooleanFormula or(Collection bits) { + BooleanFormula f = makeFalse(); + for (BooleanFormula bf : bits) { + f = or(bf, f); + } + return f; + } + + @Override + public BooleanFormula or(BooleanFormula... bits) { + return or(Arrays.asList(bits)); + } + + @Override + public Collector toDisjunction() { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula xor(BooleanFormula bits1, BooleanFormula bits2) { + throw new UnsupportedOperationException(); + } + + @Override + public R visit(BooleanFormula pFormula, BooleanFormulaVisitor visitor) { + throw new UnsupportedOperationException(); + } + + @Override + public void visitRecursively( + BooleanFormula f, BooleanFormulaVisitor rFormulaVisitor) { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula transformRecursively( + BooleanFormula f, BooleanFormulaTransformationVisitor pVisitor) { + throw new UnsupportedOperationException(); + } + + @Override + public Set toConjunctionArgs(BooleanFormula f, boolean flatten) { + throw new UnsupportedOperationException(); + } + + @Override + public Set toDisjunctionArgs(BooleanFormula f, boolean flatten) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java new file mode 100644 index 0000000000..96a31cf520 --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -0,0 +1,203 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.List; +import java.util.Map; +import org.sosy_lab.common.Appender; +import org.sosy_lab.java_smt.api.ArrayFormulaManager; +import org.sosy_lab.java_smt.api.BitvectorFormulaManager; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.BooleanFormulaManager; +import org.sosy_lab.java_smt.api.EnumerationFormulaManager; +import org.sosy_lab.java_smt.api.FloatingPointFormulaManager; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.FormulaManager; +import org.sosy_lab.java_smt.api.FormulaType; +import org.sosy_lab.java_smt.api.FunctionDeclaration; +import org.sosy_lab.java_smt.api.IntegerFormulaManager; +import org.sosy_lab.java_smt.api.QuantifiedFormulaManager; +import org.sosy_lab.java_smt.api.RationalFormulaManager; +import org.sosy_lab.java_smt.api.SLFormulaManager; +import org.sosy_lab.java_smt.api.SolverException; +import org.sosy_lab.java_smt.api.StringFormulaManager; +import org.sosy_lab.java_smt.api.Tactic; +import org.sosy_lab.java_smt.api.UFManager; +import org.sosy_lab.java_smt.api.visitors.FormulaTransformationVisitor; +import org.sosy_lab.java_smt.api.visitors.FormulaVisitor; +import org.sosy_lab.java_smt.api.visitors.TraversalProcess; + +public class TraceFormulaManager implements FormulaManager { + private final FormulaManager delegate; + private final TraceLogger logger; + + TraceFormulaManager(FormulaManager pDelegate, TraceLogger pLogger) { + delegate = pDelegate; + logger = pLogger; + } + + @Override + public IntegerFormulaManager getIntegerFormulaManager() { + return new TraceIntegerFormulaManager(delegate.getIntegerFormulaManager(), logger); + } + + @Override + public RationalFormulaManager getRationalFormulaManager() { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormulaManager getBooleanFormulaManager() { + return new TraceBooleanFormulaManager(delegate.getBooleanFormulaManager(), logger); + } + + @Override + public ArrayFormulaManager getArrayFormulaManager() { + return new TraceArrayFormulaManager(delegate.getArrayFormulaManager(), logger); + } + + @Override + public BitvectorFormulaManager getBitvectorFormulaManager() { + throw new UnsupportedOperationException(); + } + + @Override + public FloatingPointFormulaManager getFloatingPointFormulaManager() { + throw new UnsupportedOperationException(); + } + + @Override + public UFManager getUFManager() { + return new TraceUFManager(delegate.getUFManager(), logger); + } + + @Override + public SLFormulaManager getSLFormulaManager() { + throw new UnsupportedOperationException(); + } + + @Override + public QuantifiedFormulaManager getQuantifiedFormulaManager() { + throw new UnsupportedOperationException(); + } + + @Override + public StringFormulaManager getStringFormulaManager() { + throw new UnsupportedOperationException(); + } + + @Override + public EnumerationFormulaManager getEnumerationFormulaManager() { + throw new UnsupportedOperationException(); + } + + @Override + public T makeVariable(FormulaType formulaType, String name) { + return logger.logDef( + "mgr", + String.format("makeVariable(%s, \"%s\")", logger.printFormulaType(formulaType), name), + () -> delegate.makeVariable(formulaType, name)); + } + + @Override + public T makeApplication( + FunctionDeclaration declaration, List args) { + throw new UnsupportedOperationException(); + } + + @Override + public T makeApplication( + FunctionDeclaration declaration, Formula... args) { + return makeApplication(declaration, ImmutableList.copyOf(args)); + } + + @Override + public FormulaType getFormulaType(T formula) { + // FIXME Add proper tracing + return delegate.getFormulaType(formula); + } + + @Override + public BooleanFormula parse(String s) throws IllegalArgumentException { + throw new UnsupportedOperationException(); + } + + @Override + public Appender dumpFormula(BooleanFormula pT) { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula applyTactic(BooleanFormula input, Tactic tactic) + throws InterruptedException, SolverException { + throw new UnsupportedOperationException(); + } + + @Override + public T simplify(T input) throws InterruptedException { + throw new UnsupportedOperationException(); + } + + @Override + public R visit(Formula f, FormulaVisitor rFormulaVisitor) { + throw new UnsupportedOperationException(); + } + + @Override + public void visitRecursively(Formula f, FormulaVisitor rFormulaVisitor) { + throw new UnsupportedOperationException(); + } + + @Override + public T transformRecursively( + T f, FormulaTransformationVisitor pFormulaVisitor) { + throw new UnsupportedOperationException(); + } + + @Override + public ImmutableMap extractVariables(Formula f) { + // FIXME Add proper tracing + return delegate.extractVariables(f); + } + + @Override + public ImmutableMap extractVariablesAndUFs(Formula f) { + throw new UnsupportedOperationException(); + } + + @Override + public T substitute( + T f, Map fromToMapping) { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula translateFrom(BooleanFormula formula, FormulaManager otherManager) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isValidName(String variableName) { + throw new UnsupportedOperationException(); + } + + @Override + public String escape(String variableName) { + throw new UnsupportedOperationException(); + } + + @Override + public String unescape(String variableName) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java new file mode 100644 index 0000000000..338132499b --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java @@ -0,0 +1,198 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.List; +import org.sosy_lab.common.rationals.Rational; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.IntegerFormulaManager; +import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; + +public class TraceIntegerFormulaManager implements IntegerFormulaManager { + private final IntegerFormulaManager delegate; + private final TraceLogger logger; + + TraceIntegerFormulaManager(IntegerFormulaManager pDelegate, TraceLogger pLogger) { + delegate = pDelegate; + logger = pLogger; + } + + @Override + public BooleanFormula modularCongruence( + IntegerFormula number1, IntegerFormula number2, BigInteger n) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "modularCongruence(%s, %s, new BigInteger(\"%s\"))", + logger.toVariable(number1), logger.toVariable(number2), n), + () -> delegate.modularCongruence(number1, number2, n)); + } + + @Override + public BooleanFormula modularCongruence(IntegerFormula number1, IntegerFormula number2, long n) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "modularCongruence(%s, %s, %s)", + logger.toVariable(number1), logger.toVariable(number2), n), + () -> delegate.modularCongruence(number1, number2, n)); + } + + @Override + public IntegerFormula modulo(IntegerFormula numerator, IntegerFormula denominator) { + throw new UnsupportedOperationException(); + } + + @Override + public IntegerFormula makeNumber(long number) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("makeNumber(%s)", number), + () -> delegate.makeNumber(number)); + } + + @Override + public IntegerFormula makeNumber(BigInteger number) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("makeNumber(new BigInteger(\"%s\"))", number), + () -> delegate.makeNumber(number)); + } + + @Override + public IntegerFormula makeNumber(double number) { + throw new UnsupportedOperationException(); + } + + @Override + public IntegerFormula makeNumber(BigDecimal number) { + throw new UnsupportedOperationException(); + } + + @Override + public IntegerFormula makeNumber(String pI) { + throw new UnsupportedOperationException(); + } + + @Override + public IntegerFormula makeNumber(Rational pRational) { + throw new UnsupportedOperationException(); + } + + @Override + public IntegerFormula makeVariable(String pVar) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("makeVariable(\"%s\")", pVar), + () -> delegate.makeVariable(pVar)); + } + + @Override + public IntegerFormula negate(IntegerFormula number) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("negate(%s)", logger.toVariable(number)), + () -> delegate.negate(number)); + } + + @Override + public IntegerFormula add(IntegerFormula number1, IntegerFormula number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("add(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.add(number1, number2)); + } + + @Override + public IntegerFormula sum(List operands) { + throw new UnsupportedOperationException(); + } + + @Override + public IntegerFormula subtract(IntegerFormula number1, IntegerFormula number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("subtract(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.subtract(number1, number2)); + } + + @Override + public IntegerFormula divide(IntegerFormula numerator, IntegerFormula denominator) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "divide(%s, %s)", logger.toVariable(numerator), logger.toVariable(denominator)), + () -> delegate.divide(numerator, denominator)); + } + + @Override + public IntegerFormula multiply(IntegerFormula number1, IntegerFormula number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("multiply(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.multiply(number1, number2)); + } + + @Override + public BooleanFormula equal(IntegerFormula number1, IntegerFormula number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("equal(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.equal(number1, number2)); + } + + @Override + public BooleanFormula distinct(List pNumbers) { + throw new UnsupportedOperationException(); + } + + @Override + public BooleanFormula greaterThan(IntegerFormula number1, IntegerFormula number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "greaterThan(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.greaterThan(number1, number2)); + } + + @Override + public BooleanFormula greaterOrEquals(IntegerFormula number1, IntegerFormula number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "greaterOrEquals(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.greaterOrEquals(number1, number2)); + } + + @Override + public BooleanFormula lessThan(IntegerFormula number1, IntegerFormula number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("lessThan(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.lessThan(number1, number2)); + } + + @Override + public BooleanFormula lessOrEquals(IntegerFormula number1, IntegerFormula number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "lessOrEquals(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.lessOrEquals(number1, number2)); + } + + @Override + public IntegerFormula floor(IntegerFormula formula) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java new file mode 100644 index 0000000000..c8d28776f8 --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -0,0 +1,105 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import com.google.common.base.Joiner; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.FormulaType; + +public class TraceLogger { + private long id = 0; + + private final Map valueMap = new HashMap<>(); + private final List trace = new ArrayList<>(); + + /** Returns a fresh variable */ + private String newVariable() { + return "var" + id++; + } + + /** + * Bind an object to a variable + * + *

Use {@link #toVariable(Object)} to get the variable name for a tracked object + */ + private void mapVariable(String pVar, Object f) { + valueMap.putIfAbsent(f, pVar); + } + + /** + * Returns the variable name of a tracked object + * + *

Use {@link #mapVariable(String, Object)} to bind an object to a variable + */ + public String toVariable(Object f) { + return valueMap.get(f); + } + + /** Add a definition to the log */ + private void appendDef(String pVar, String pExpr) { + trace.add(String.format("var %s = %s;", pVar, pExpr)); + } + + /** Add a statement to the log */ + private void appendStmt(String pStmt) { + trace.add(String.format("%s;", pStmt)); + } + + /** Log an API call with return value */ + public TE logDef(String prefix, String method, Callable closure) { + String var = newVariable(); + appendDef(var, prefix + "." + method); + try { + TE f = closure.call(); + mapVariable(var, f); + return f; + + } catch (Exception pE) { + throw new RuntimeException(pE); + } + } + + /** Just like {@link Runnable}, but allows checked exceptions */ + public interface CheckedRunnable { + void run() throws Exception; + } + + /** Log an API call without return value */ + public void logStmt(String prefix, String method, CheckedRunnable closure) { + appendStmt(prefix + "." + method); + try { + closure.run(); + } catch (Exception pE) { + throw new RuntimeException(pE); + } + } + + /** + * Takes a {@link org.sosy_lab.java_smt.api.FormulaType} and returns a Java expression to + * construct this type + */ + public String printFormulaType(FormulaType pType) { + if (pType.isIntegerType()) { + return "FormulaType.IntegerType"; + } + // FIXME Handle other cases + throw new IllegalArgumentException("Unsupported formula type: " + pType); + } + + public String getLog() { + return Joiner.on('\n').join(trace); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java new file mode 100644 index 0000000000..ed8240ce0f --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java @@ -0,0 +1,92 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.Model; +import org.sosy_lab.java_smt.api.ProverEnvironment; +import org.sosy_lab.java_smt.api.SolverException; + +public class TraceProverEnvironment implements ProverEnvironment { + private final ProverEnvironment delegate; + private final TraceLogger logger; + + TraceProverEnvironment(ProverEnvironment pDelegate, TraceLogger pLogger) { + delegate = pDelegate; + logger = pLogger; + } + + @Override + public void pop() { + logger.logStmt(logger.toVariable(this), "pop()", delegate::pop); + } + + @Override + public @Nullable Void addConstraint(BooleanFormula constraint) throws InterruptedException { + return logger.logDef( + logger.toVariable(this), + String.format("addConstraint(%s)", logger.toVariable(constraint)), + () -> delegate.addConstraint(constraint)); + } + + @Override + public void push() throws InterruptedException { + logger.logStmt(logger.toVariable(this), "push()", delegate::push); + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isUnsat() throws SolverException, InterruptedException { + return logger.logDef(logger.toVariable(this), "isUnsat()", delegate::isUnsat); + } + + @Override + public boolean isUnsatWithAssumptions(Collection assumptions) + throws SolverException, InterruptedException { + throw new UnsupportedOperationException(); + } + + @Override + public Model getModel() throws SolverException { + // FIXME Add tracing for the model + return logger.logDef(logger.toVariable(this), "getModel()", delegate::getModel); + } + + @Override + public List getUnsatCore() { + throw new UnsupportedOperationException(); + } + + @Override + public Optional> unsatCoreOverAssumptions( + Collection assumptions) throws SolverException, InterruptedException { + throw new UnsupportedOperationException(); + } + + @Override + public void close() { + logger.logStmt(logger.toVariable(this), "close()", delegate::close); + } + + @Override + public R allSat(AllSatCallback callback, List important) + throws InterruptedException, SolverException { + throw new UnsupportedOperationException(); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java new file mode 100644 index 0000000000..984f508287 --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -0,0 +1,69 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + + +import org.sosy_lab.java_smt.SolverContextFactory.Solvers; +import org.sosy_lab.java_smt.api.FormulaManager; +import org.sosy_lab.java_smt.api.InterpolatingProverEnvironment; +import org.sosy_lab.java_smt.api.OptimizationProverEnvironment; +import org.sosy_lab.java_smt.api.ProverEnvironment; +import org.sosy_lab.java_smt.api.SolverContext; + +public class TraceSolverContext implements SolverContext { + private final SolverContext delegate; + private final TraceLogger logger; + + public TraceSolverContext(SolverContext pDelegate) { + + delegate = pDelegate; + logger = new TraceLogger(); + } + + @Override + public FormulaManager getFormulaManager() { + return new TraceFormulaManager(delegate.getFormulaManager(), logger); + } + + @SuppressWarnings("resource") + @Override + public ProverEnvironment newProverEnvironment(ProverOptions... options) { + return new TraceProverEnvironment(delegate.newProverEnvironment(options), logger); + } + + @SuppressWarnings("resource") + @Override + public InterpolatingProverEnvironment newProverEnvironmentWithInterpolation( + ProverOptions... options) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("resource") + @Override + public OptimizationProverEnvironment newOptimizationProverEnvironment(ProverOptions... options) { + throw new UnsupportedOperationException(); + } + + @Override + public String getVersion() { + return delegate.getVersion(); + } + + @Override + public Solvers getSolverName() { + return delegate.getSolverName(); + } + + @Override + public void close() { + delegate.close(); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java new file mode 100644 index 0000000000..835ab82103 --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java @@ -0,0 +1,78 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; +import java.util.Arrays; +import java.util.List; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.FormulaType; +import org.sosy_lab.java_smt.api.FunctionDeclaration; +import org.sosy_lab.java_smt.api.UFManager; + +public class TraceUFManager implements UFManager { + private final UFManager delegate; + private final TraceLogger logger; + + TraceUFManager(UFManager pDelegate, TraceLogger pLogger) { + delegate = pDelegate; + logger = pLogger; + } + + @Override + public FunctionDeclaration declareUF( + String name, FormulaType returnType, List> args) { + return logger.logDef( + "mgr.getUFManager()", + String.format( + "declareUF(\"%s\", %s, ImmutableList.of(%s))", + name, + logger.printFormulaType(returnType), + Joiner.on(", ").join(FluentIterable.from(args).transform(logger::printFormulaType))), + () -> delegate.declareUF(name, returnType, args)); + } + + @Override + public FunctionDeclaration declareUF( + String name, FormulaType returnType, FormulaType... args) { + return declareUF(name, returnType, Arrays.asList(args)); + } + + @Override + public T callUF( + FunctionDeclaration funcType, List args) { + return logger.logDef( + "mgr.getUFManager()", + String.format( + "callUF(%s, ImmutableList.of(%s))", + logger.toVariable(funcType), + Joiner.on(", ").join(FluentIterable.from(args).transform(logger::toVariable))), + () -> delegate.callUF(funcType, args)); + } + + @Override + public T callUF(FunctionDeclaration funcType, Formula... args) { + return callUF(funcType, Arrays.asList(args)); + } + + @Override + public T declareAndCallUF( + String name, FormulaType pReturnType, List pArgs) { + throw new UnsupportedOperationException(); + } + + @Override + public T declareAndCallUF( + String name, FormulaType pReturnType, Formula... pArgs) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/package-info.java b/src/org/sosy_lab/java_smt/delegate/trace/package-info.java new file mode 100644 index 0000000000..1b69a33f5b --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/package-info.java @@ -0,0 +1,15 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +@com.google.errorprone.annotations.CheckReturnValue +@javax.annotation.ParametersAreNonnullByDefault +@org.sosy_lab.common.annotations.FieldsAreNonnullByDefault +@org.sosy_lab.common.annotations.ReturnValuesAreNonnullByDefault +package org.sosy_lab.java_smt.delegate.trace; From f7ef298d26c4e1acf01beefc8ff564849c0a26ab Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Thu, 14 Aug 2025 13:46:29 +0200 Subject: [PATCH 02/89] Trace: Apply error-prone patch --- src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java index 835ab82103..a01af0a494 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java @@ -37,7 +37,7 @@ public FunctionDeclaration declareUF( "declareUF(\"%s\", %s, ImmutableList.of(%s))", name, logger.printFormulaType(returnType), - Joiner.on(", ").join(FluentIterable.from(args).transform(logger::printFormulaType))), + FluentIterable.from(args).transform(logger::printFormulaType).join(Joiner.on(", "))), () -> delegate.declareUF(name, returnType, args)); } @@ -55,7 +55,7 @@ public T callUF( String.format( "callUF(%s, ImmutableList.of(%s))", logger.toVariable(funcType), - Joiner.on(", ").join(FluentIterable.from(args).transform(logger::toVariable))), + FluentIterable.from(args).transform(logger::toVariable).join(Joiner.on(", "))), () -> delegate.callUF(funcType, args)); } From 9acb1d78c8b7409f7dd40d98724062403dfb1aae Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Thu, 14 Aug 2025 13:59:09 +0200 Subject: [PATCH 03/89] Trace: Fix checkstyle issues --- .../trace/TraceArrayFormulaManager.java | 1 + .../java_smt/delegate/trace/TraceLogger.java | 30 +++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java index 24ee2c74b4..951f671900 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java @@ -16,6 +16,7 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.FormulaType; +@SuppressWarnings("MethodTypeParameterName") public class TraceArrayFormulaManager implements ArrayFormulaManager { private final ArrayFormulaManager delegate; private final TraceLogger logger; diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index c8d28776f8..c80a0c2e42 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -25,13 +25,13 @@ public class TraceLogger { private final Map valueMap = new HashMap<>(); private final List trace = new ArrayList<>(); - /** Returns a fresh variable */ + /** Returns a fresh variable. */ private String newVariable() { return "var" + id++; } /** - * Bind an object to a variable + * Bind an object to a variable. * *

Use {@link #toVariable(Object)} to get the variable name for a tracked object */ @@ -40,7 +40,7 @@ private void mapVariable(String pVar, Object f) { } /** - * Returns the variable name of a tracked object + * Returns the variable name of a tracked object. * *

Use {@link #mapVariable(String, Object)} to bind an object to a variable */ @@ -48,48 +48,48 @@ public String toVariable(Object f) { return valueMap.get(f); } - /** Add a definition to the log */ + /** Add a definition to the log. */ private void appendDef(String pVar, String pExpr) { trace.add(String.format("var %s = %s;", pVar, pExpr)); } - /** Add a statement to the log */ + /** Add a statement to the log. */ private void appendStmt(String pStmt) { trace.add(String.format("%s;", pStmt)); } - /** Log an API call with return value */ - public TE logDef(String prefix, String method, Callable closure) { + /** Log an API call with return value. */ + public R logDef(String prefix, String method, Callable closure) { String var = newVariable(); appendDef(var, prefix + "." + method); try { - TE f = closure.call(); + R f = closure.call(); mapVariable(var, f); return f; - } catch (Exception pE) { - throw new RuntimeException(pE); + } catch (Exception e) { + throw new RuntimeException(e); } } - /** Just like {@link Runnable}, but allows checked exceptions */ + /** Just like {@link Runnable}, but allows checked exceptions. */ public interface CheckedRunnable { void run() throws Exception; } - /** Log an API call without return value */ + /** Log an API call without return value. */ public void logStmt(String prefix, String method, CheckedRunnable closure) { appendStmt(prefix + "." + method); try { closure.run(); - } catch (Exception pE) { - throw new RuntimeException(pE); + } catch (Exception e) { + throw new RuntimeException(e); } } /** * Takes a {@link org.sosy_lab.java_smt.api.FormulaType} and returns a Java expression to - * construct this type + * construct this type. */ public String printFormulaType(FormulaType pType) { if (pType.isIntegerType()) { From 63f28641321737ee83aef671b103200a42152cc6 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Thu, 14 Aug 2025 14:42:42 +0200 Subject: [PATCH 04/89] Trace: Log prover creation --- .../java_smt/delegate/trace/TraceSolverContext.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index 984f508287..0f686d7799 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -10,7 +10,8 @@ package org.sosy_lab.java_smt.delegate.trace; - +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; import org.sosy_lab.java_smt.SolverContextFactory.Solvers; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.InterpolatingProverEnvironment; @@ -36,7 +37,12 @@ public FormulaManager getFormulaManager() { @SuppressWarnings("resource") @Override public ProverEnvironment newProverEnvironment(ProverOptions... options) { - return new TraceProverEnvironment(delegate.newProverEnvironment(options), logger); + return logger.logDef( + "context", + String.format( + "newProverEnvironment(%s)", + Joiner.on(", ").join(FluentIterable.from(options).transform(Enum::toString))), + () -> new TraceProverEnvironment(delegate.newProverEnvironment(options), logger)); } @SuppressWarnings("resource") @@ -64,6 +70,6 @@ public Solvers getSolverName() { @Override public void close() { - delegate.close(); + logger.logStmt("context", "close()", delegate::close); } } From 0b0e604091219e4fbbedd72cba1c54cd8b99ef66 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Fri, 15 Aug 2025 11:24:28 +0200 Subject: [PATCH 05/89] Trace: Write trace directly to a file --- .../java_smt/delegate/trace/TraceLogger.java | 37 ++++++++++++------- .../delegate/trace/TraceSolverContext.java | 6 ++- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index c80a0c2e42..f484a8eaeb 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -10,10 +10,12 @@ package org.sosy_lab.java_smt.delegate.trace; -import com.google.common.base.Joiner; -import java.util.ArrayList; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import org.sosy_lab.java_smt.api.Formula; @@ -23,7 +25,16 @@ public class TraceLogger { private long id = 0; private final Map valueMap = new HashMap<>(); - private final List trace = new ArrayList<>(); + private final BufferedWriter output; + + TraceLogger(String pFile) { + // FIXME Check if the file already exists + try { + output = Files.newBufferedWriter(Paths.get(pFile), Charset.defaultCharset()); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } /** Returns a fresh variable. */ private String newVariable() { @@ -49,20 +60,22 @@ public String toVariable(Object f) { } /** Add a definition to the log. */ - private void appendDef(String pVar, String pExpr) { - trace.add(String.format("var %s = %s;", pVar, pExpr)); + private void appendDef(String pVar, String pExpr) throws IOException { + output.append(String.format("var %s = %s;%n", pVar, pExpr)); + output.flush(); } /** Add a statement to the log. */ - private void appendStmt(String pStmt) { - trace.add(String.format("%s;", pStmt)); + private void appendStmt(String pStmt) throws IOException { + output.append(String.format("%s;%n", pStmt)); + output.flush(); } /** Log an API call with return value. */ public R logDef(String prefix, String method, Callable closure) { String var = newVariable(); - appendDef(var, prefix + "." + method); try { + appendDef(var, prefix + "." + method); R f = closure.call(); mapVariable(var, f); return f; @@ -79,8 +92,8 @@ public interface CheckedRunnable { /** Log an API call without return value. */ public void logStmt(String prefix, String method, CheckedRunnable closure) { - appendStmt(prefix + "." + method); try { + appendStmt(prefix + "." + method); closure.run(); } catch (Exception e) { throw new RuntimeException(e); @@ -98,8 +111,4 @@ public String printFormulaType(FormulaType pType) { // FIXME Handle other cases throw new IllegalArgumentException("Unsupported formula type: " + pType); } - - public String getLog() { - return Joiner.on('\n').join(trace); - } } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index 0f686d7799..75fddc4f09 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -24,9 +24,11 @@ public class TraceSolverContext implements SolverContext { private final TraceLogger logger; public TraceSolverContext(SolverContext pDelegate) { - delegate = pDelegate; - logger = new TraceLogger(); + // FIXME Move the files to the output folder? + logger = + new TraceLogger( + "trace" + Integer.toUnsignedString(System.identityHashCode(this)) + ".java"); } @Override From 4080a59b438c87ef058bedc7211ea44268bdf0eb Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Fri, 15 Aug 2025 12:50:03 +0200 Subject: [PATCH 06/89] Trace: Fix prefix in ArrayFormulaManager.equivalence --- .../java_smt/delegate/trace/TraceArrayFormulaManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java index 951f671900..d641eea34f 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java @@ -75,7 +75,7 @@ ArrayFormula makeArray(FTI pIndexType, FTE pElementType, TE defaultEleme public BooleanFormula equivalence( ArrayFormula pArray1, ArrayFormula pArray2) { return logger.logDef( - "mgr.getArrayFormulaManager", + "mgr.getArrayFormulaManager()", String.format( "equivalence(%s, %s)", logger.toVariable(pArray1), logger.toVariable(pArray2)), () -> delegate.equivalence(pArray1, pArray2)); From 40d81d2ef95227a85548e58d11ac53721d59e79b Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Fri, 15 Aug 2025 13:07:08 +0200 Subject: [PATCH 07/89] Trace: Use full path when printing ProverOptions in the trace --- .../sosy_lab/java_smt/delegate/trace/TraceSolverContext.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index 75fddc4f09..41f9c3038d 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -43,7 +43,10 @@ public ProverEnvironment newProverEnvironment(ProverOptions... options) { "context", String.format( "newProverEnvironment(%s)", - Joiner.on(", ").join(FluentIterable.from(options).transform(Enum::toString))), + Joiner.on(", ") + .join( + FluentIterable.from(options) + .transform(v -> "SolverContext" + ".ProverOptions." + v.name()))), () -> new TraceProverEnvironment(delegate.newProverEnvironment(options), logger)); } From 84c71434a90b76049f82348ce8724ba16b9cfd74 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Fri, 15 Aug 2025 13:07:40 +0200 Subject: [PATCH 08/89] Trace: Log creation of the solver context --- .../java_smt/SolverContextFactory.java | 2 +- .../java_smt/delegate/trace/TraceLogger.java | 4 +- .../delegate/trace/TraceSolverContext.java | 41 ++++++++++++++++++- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/SolverContextFactory.java b/src/org/sosy_lab/java_smt/SolverContextFactory.java index b5aa969e8c..8d9cc34dfb 100644 --- a/src/org/sosy_lab/java_smt/SolverContextFactory.java +++ b/src/org/sosy_lab/java_smt/SolverContextFactory.java @@ -237,7 +237,7 @@ public SolverContext generateContext(Solvers solverToCreate) context = new DebuggingSolverContext(solverToCreate, config, context); } if (trace) { - context = new TraceSolverContext(context); + context = new TraceSolverContext(context, config); } if (collectStatistics) { // statistics need to be the most outer wrapping layer. diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index f484a8eaeb..f4fd504975 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -60,13 +60,13 @@ public String toVariable(Object f) { } /** Add a definition to the log. */ - private void appendDef(String pVar, String pExpr) throws IOException { + public void appendDef(String pVar, String pExpr) throws IOException { output.append(String.format("var %s = %s;%n", pVar, pExpr)); output.flush(); } /** Add a statement to the log. */ - private void appendStmt(String pStmt) throws IOException { + public void appendStmt(String pStmt) throws IOException { output.append(String.format("%s;%n", pStmt)); output.flush(); } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index 41f9c3038d..80c06bca35 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -11,7 +11,13 @@ package org.sosy_lab.java_smt.delegate.trace; import com.google.common.base.Joiner; +import com.google.common.base.Splitter; import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.util.List; +import java.util.Map.Entry; +import org.sosy_lab.common.configuration.Configuration; import org.sosy_lab.java_smt.SolverContextFactory.Solvers; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.InterpolatingProverEnvironment; @@ -23,12 +29,45 @@ public class TraceSolverContext implements SolverContext { private final SolverContext delegate; private final TraceLogger logger; - public TraceSolverContext(SolverContext pDelegate) { + public TraceSolverContext(SolverContext pDelegate, Configuration config) { delegate = pDelegate; // FIXME Move the files to the output folder? logger = new TraceLogger( "trace" + Integer.toUnsignedString(System.identityHashCode(this)) + ".java"); + + // Get relevant options from the configuration + String props = config.asPropertiesString(); + ImmutableMap.Builder options = ImmutableMap.builder(); + for (String s : props.lines().toArray(String[]::new)) { + List parts = Splitter.on(" = ").splitToList(s); + ; + if (parts.get(0).startsWith("solver") && !parts.get(0).equals("solver.trace")) { + options.put(parts.get(0), parts.get(1)); + } + } + + // Write code for creating a solver context to the trace log + try { + logger.appendDef( + "config", + "Configuration.builder()." + + Joiner.on(".") + .join( + FluentIterable.from(options.build().entrySet()) + .transform( + (Entry e) -> + String.format( + "setOption(\"%s\", \"%s\")", e.getKey(), e.getValue()))) + + ".build()"); + logger.appendDef("logger", "LogManager.createNullLogManager()"); + logger.appendDef("notifier", "ShutdownNotifier.createDummy()"); + logger.appendDef( + "context", "SolverContextFactory.createSolverContext(config, logger, notifier)"); + logger.appendDef("mgr", "context.getFormulaManager()"); + } catch (IOException e) { + throw new RuntimeException(e); + } } @Override From 28575ebb9212fc1d504ad8d2bb93a1a26d32fb4b Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Fri, 15 Aug 2025 13:36:01 +0200 Subject: [PATCH 09/89] Trace: Log access to the model --- .../java_smt/delegate/trace/TraceModel.java | 120 ++++++++++++++++++ .../trace/TraceProverEnvironment.java | 4 +- 2 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java new file mode 100644 index 0000000000..6b6cc1e123 --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java @@ -0,0 +1,120 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import com.google.common.collect.ImmutableList; +import java.math.BigInteger; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.sosy_lab.common.rationals.Rational; +import org.sosy_lab.java_smt.api.BitvectorFormula; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.EnumerationFormula; +import org.sosy_lab.java_smt.api.FloatingPointFormula; +import org.sosy_lab.java_smt.api.FloatingPointNumber; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.Model; +import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; +import org.sosy_lab.java_smt.api.NumeralFormula.RationalFormula; +import org.sosy_lab.java_smt.api.StringFormula; + +public class TraceModel implements Model { + private final Model delegate; + private final TraceLogger logger; + + TraceModel(Model pDelegate, TraceLogger pLogger) { + delegate = pDelegate; + logger = pLogger; + } + + @Override + public ImmutableList asList() { + // FIXME We need to introduce local variables for all terms in the model so that they can be + // referenced later + return logger.logDef(logger.toVariable(this), "asList()", delegate::asList); + } + + @Override + public @Nullable T eval(T formula) { + return logger.logDef( + logger.toVariable(this), + String.format("eval(%s)", logger.toVariable(formula)), + () -> delegate.eval(formula)); + } + + @Override + public @Nullable Object evaluate(Formula formula) { + return logger.logDef( + logger.toVariable(this), + String.format("evaluate(%s)", logger.toVariable(formula)), + () -> delegate.evaluate(formula)); + } + + @Override + public @Nullable BigInteger evaluate(IntegerFormula formula) { + return logger.logDef( + logger.toVariable(this), + String.format("evaluate(%s)", logger.toVariable(formula)), + () -> delegate.evaluate(formula)); + } + + @Override + public @Nullable Rational evaluate(RationalFormula formula) { + return logger.logDef( + logger.toVariable(this), + String.format("evaluate(%s)", logger.toVariable(formula)), + () -> delegate.evaluate(formula)); + } + + @Override + public @Nullable Boolean evaluate(BooleanFormula formula) { + return logger.logDef( + logger.toVariable(this), + String.format("evaluate(%s)", logger.toVariable(formula)), + () -> delegate.evaluate(formula)); + } + + @Override + public @Nullable BigInteger evaluate(BitvectorFormula formula) { + return logger.logDef( + logger.toVariable(this), + String.format("evaluate(%s)", logger.toVariable(formula)), + () -> delegate.evaluate(formula)); + } + + @Override + public @Nullable String evaluate(StringFormula formula) { + return logger.logDef( + logger.toVariable(this), + String.format("evaluate(%s)", logger.toVariable(formula)), + () -> delegate.evaluate(formula)); + } + + @Override + public @Nullable String evaluate(EnumerationFormula formula) { + return logger.logDef( + logger.toVariable(this), + String.format("evaluate(%s)", logger.toVariable(formula)), + () -> delegate.evaluate(formula)); + } + + @Override + public @Nullable FloatingPointNumber evaluate(FloatingPointFormula formula) { + return logger.logDef( + logger.toVariable(this), + String.format("evaluate(%s)", logger.toVariable(formula)), + () -> delegate.evaluate(formula)); + } + + @Override + public void close() { + logger.logStmt(logger.toVariable(this), "close()", delegate::close); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java index ed8240ce0f..64ac1d39f4 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java @@ -64,8 +64,8 @@ public boolean isUnsatWithAssumptions(Collection assumptions) @Override public Model getModel() throws SolverException { - // FIXME Add tracing for the model - return logger.logDef(logger.toVariable(this), "getModel()", delegate::getModel); + return logger.logDef( + logger.toVariable(this), "getModel()", () -> new TraceModel(delegate.getModel(), logger)); } @Override From e7dfc700f747390e014bc2a2a50499206085e9e0 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Fri, 15 Aug 2025 13:50:54 +0200 Subject: [PATCH 10/89] Trace: Apply error-prone patch --- .../java_smt/delegate/trace/TraceLogger.java | 4 ++-- .../delegate/trace/TraceSolverContext.java | 19 ++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index f4fd504975..bfbe53da3e 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -14,7 +14,7 @@ import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; @@ -30,7 +30,7 @@ public class TraceLogger { TraceLogger(String pFile) { // FIXME Check if the file already exists try { - output = Files.newBufferedWriter(Paths.get(pFile), Charset.defaultCharset()); + output = Files.newBufferedWriter(Path.of(pFile), Charset.defaultCharset()); } catch (IOException e) { throw new IllegalArgumentException(e); } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index 80c06bca35..f3ae08abd4 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -52,13 +52,11 @@ public TraceSolverContext(SolverContext pDelegate, Configuration config) { logger.appendDef( "config", "Configuration.builder()." - + Joiner.on(".") - .join( - FluentIterable.from(options.build().entrySet()) - .transform( - (Entry e) -> - String.format( - "setOption(\"%s\", \"%s\")", e.getKey(), e.getValue()))) + + FluentIterable.from(options.build().entrySet()) + .transform( + (Entry e) -> + String.format("setOption(\"%s\", \"%s\")", e.getKey(), e.getValue())) + .join(Joiner.on(".")) + ".build()"); logger.appendDef("logger", "LogManager.createNullLogManager()"); logger.appendDef("notifier", "ShutdownNotifier.createDummy()"); @@ -82,10 +80,9 @@ public ProverEnvironment newProverEnvironment(ProverOptions... options) { "context", String.format( "newProverEnvironment(%s)", - Joiner.on(", ") - .join( - FluentIterable.from(options) - .transform(v -> "SolverContext" + ".ProverOptions." + v.name()))), + FluentIterable.from(options) + .transform(v -> "SolverContext" + ".ProverOptions." + v.name()) + .join(Joiner.on(", "))), () -> new TraceProverEnvironment(delegate.newProverEnvironment(options), logger)); } From 010fb1e3741655958a0a9d82a50bf907fc7c7831 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Fri, 15 Aug 2025 13:52:26 +0200 Subject: [PATCH 11/89] Trace: Remove ; --- src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index f3ae08abd4..fa5b5a7122 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -41,7 +41,6 @@ public TraceSolverContext(SolverContext pDelegate, Configuration config) { ImmutableMap.Builder options = ImmutableMap.builder(); for (String s : props.lines().toArray(String[]::new)) { List parts = Splitter.on(" = ").splitToList(s); - ; if (parts.get(0).startsWith("solver") && !parts.get(0).equals("solver.trace")) { options.put(parts.get(0), parts.get(1)); } From 8ac6c0cf9fc9291b2c613fc213e5b08c365c6895 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Fri, 15 Aug 2025 13:58:17 +0200 Subject: [PATCH 12/89] Trace: Add "resource" annotation for TraceModel.getModel --- .../sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java index 64ac1d39f4..ab5abb2992 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java @@ -62,6 +62,7 @@ public boolean isUnsatWithAssumptions(Collection assumptions) throw new UnsupportedOperationException(); } + @SuppressWarnings("resource") @Override public Model getModel() throws SolverException { return logger.logDef( From d2958ed154cf6008186e2494e56e131a6ebf10b8 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Fri, 15 Aug 2025 14:04:36 +0200 Subject: [PATCH 13/89] Trace: Add a superclass TraceBasicProverEnvironment for TraceProverEnvironment (and later TraceInterpolatingProverEnvironment) --- .../trace/TraceBasicProverEnvironment.java | 93 +++++++++++++++++++ .../trace/TraceProverEnvironment.java | 82 +--------------- 2 files changed, 98 insertions(+), 77 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java new file mode 100644 index 0000000000..dfcb804b96 --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java @@ -0,0 +1,93 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.sosy_lab.java_smt.api.BasicProverEnvironment; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.Model; +import org.sosy_lab.java_smt.api.SolverException; + +public class TraceBasicProverEnvironment implements BasicProverEnvironment { + private final BasicProverEnvironment delegate; + private final TraceLogger logger; + + TraceBasicProverEnvironment(BasicProverEnvironment pDelegate, TraceLogger pLogger) { + delegate = pDelegate; + logger = pLogger; + } + + @Override + public void pop() { + logger.logStmt(logger.toVariable(this), "pop()", delegate::pop); + } + + @Override + public @Nullable T addConstraint(BooleanFormula constraint) throws InterruptedException { + return logger.logDef( + logger.toVariable(this), + String.format("addConstraint(%s)", logger.toVariable(constraint)), + () -> delegate.addConstraint(constraint)); + } + + @Override + public void push() throws InterruptedException { + logger.logStmt(logger.toVariable(this), "push()", delegate::push); + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isUnsat() throws SolverException, InterruptedException { + return logger.logDef(logger.toVariable(this), "isUnsat()", delegate::isUnsat); + } + + @Override + public boolean isUnsatWithAssumptions(Collection assumptions) + throws SolverException, InterruptedException { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("resource") + @Override + public Model getModel() throws SolverException { + return logger.logDef( + logger.toVariable(this), "getModel()", () -> new TraceModel(delegate.getModel(), logger)); + } + + @Override + public List getUnsatCore() { + throw new UnsupportedOperationException(); + } + + @Override + public Optional> unsatCoreOverAssumptions( + Collection assumptions) throws SolverException, InterruptedException { + throw new UnsupportedOperationException(); + } + + @Override + public void close() { + logger.logStmt(logger.toVariable(this), "close()", delegate::close); + } + + @Override + public R allSat(AllSatCallback callback, List important) + throws InterruptedException, SolverException { + throw new UnsupportedOperationException(); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java index ab5abb2992..d8c1e79ef6 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java @@ -10,84 +10,12 @@ package org.sosy_lab.java_smt.delegate.trace; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.sosy_lab.java_smt.api.BooleanFormula; -import org.sosy_lab.java_smt.api.Model; +import org.sosy_lab.java_smt.api.BasicProverEnvironment; import org.sosy_lab.java_smt.api.ProverEnvironment; -import org.sosy_lab.java_smt.api.SolverException; -public class TraceProverEnvironment implements ProverEnvironment { - private final ProverEnvironment delegate; - private final TraceLogger logger; - - TraceProverEnvironment(ProverEnvironment pDelegate, TraceLogger pLogger) { - delegate = pDelegate; - logger = pLogger; - } - - @Override - public void pop() { - logger.logStmt(logger.toVariable(this), "pop()", delegate::pop); - } - - @Override - public @Nullable Void addConstraint(BooleanFormula constraint) throws InterruptedException { - return logger.logDef( - logger.toVariable(this), - String.format("addConstraint(%s)", logger.toVariable(constraint)), - () -> delegate.addConstraint(constraint)); - } - - @Override - public void push() throws InterruptedException { - logger.logStmt(logger.toVariable(this), "push()", delegate::push); - } - - @Override - public int size() { - return delegate.size(); - } - - @Override - public boolean isUnsat() throws SolverException, InterruptedException { - return logger.logDef(logger.toVariable(this), "isUnsat()", delegate::isUnsat); - } - - @Override - public boolean isUnsatWithAssumptions(Collection assumptions) - throws SolverException, InterruptedException { - throw new UnsupportedOperationException(); - } - - @SuppressWarnings("resource") - @Override - public Model getModel() throws SolverException { - return logger.logDef( - logger.toVariable(this), "getModel()", () -> new TraceModel(delegate.getModel(), logger)); - } - - @Override - public List getUnsatCore() { - throw new UnsupportedOperationException(); - } - - @Override - public Optional> unsatCoreOverAssumptions( - Collection assumptions) throws SolverException, InterruptedException { - throw new UnsupportedOperationException(); - } - - @Override - public void close() { - logger.logStmt(logger.toVariable(this), "close()", delegate::close); - } - - @Override - public R allSat(AllSatCallback callback, List important) - throws InterruptedException, SolverException { - throw new UnsupportedOperationException(); +public class TraceProverEnvironment extends TraceBasicProverEnvironment + implements ProverEnvironment { + TraceProverEnvironment(BasicProverEnvironment pDelegate, TraceLogger pLogger) { + super(pDelegate, pLogger); } } From fb252cdddd6f307f37727101476a7802323fd6c7 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Fri, 15 Aug 2025 14:26:30 +0200 Subject: [PATCH 14/89] Trace: Apply error-prone patch --- .../sosy_lab/java_smt/delegate/trace/TraceSolverContext.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index fa5b5a7122..38bac71956 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -51,7 +51,7 @@ public TraceSolverContext(SolverContext pDelegate, Configuration config) { logger.appendDef( "config", "Configuration.builder()." - + FluentIterable.from(options.build().entrySet()) + + FluentIterable.from(options.buildOrThrow().entrySet()) .transform( (Entry e) -> String.format("setOption(\"%s\", \"%s\")", e.getKey(), e.getValue())) From fef163534d0793a39cd424bdbc5a30b14ad1b05e Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Tue, 19 Aug 2025 12:46:23 +0200 Subject: [PATCH 15/89] Trace: Add bitvector support --- .../trace/TraceBitvectorFormulaManager.java | 189 +++++++++++++++--- .../delegate/trace/TraceFormulaManager.java | 2 +- .../java_smt/delegate/trace/TraceLogger.java | 5 + 3 files changed, 162 insertions(+), 34 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java index db5c044a2f..a247ec978b 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java @@ -10,6 +10,8 @@ package org.sosy_lab.java_smt.delegate.trace; +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; import java.math.BigInteger; import java.util.List; import org.sosy_lab.java_smt.api.BitvectorFormula; @@ -19,176 +21,297 @@ import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; public class TraceBitvectorFormulaManager implements BitvectorFormulaManager { + private final BitvectorFormulaManager delegate; + private final TraceLogger logger; + + TraceBitvectorFormulaManager(BitvectorFormulaManager pDelegate, TraceLogger pLogger) { + delegate = pDelegate; + logger = pLogger; + } @Override public BitvectorFormula makeBitvector(int length, long pI) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("makeBitvector(%s, %s)", length, pI), + () -> delegate.makeBitvector(length, pI)); } @Override public BitvectorFormula makeBitvector(int length, BigInteger pI) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("makeBitvector(%s, new BigInteger(\"%s\"))", length, pI), + () -> delegate.makeBitvector(length, pI)); } @Override public BitvectorFormula makeBitvector(int length, IntegerFormula pI) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("makeBitvector(%s, %s)", length, logger.toVariable(pI)), + () -> delegate.makeBitvector(length, pI)); } @Override public IntegerFormula toIntegerFormula(BitvectorFormula pI, boolean signed) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("toIntegerFormula(%s, %s)", logger.toVariable(pI), signed), + () -> delegate.toIntegerFormula(pI, signed)); } @Override public BitvectorFormula makeVariable(int length, String pVar) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("makeVariable(%s, \"%s\")", length, pVar), + () -> delegate.makeVariable(length, pVar)); } @Override public BitvectorFormula makeVariable(BitvectorType type, String pVar) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("makeVariable(%s, \"%s\")", logger.printFormulaType(type), pVar), + () -> delegate.makeVariable(type, pVar)); } @Override public int getLength(BitvectorFormula number) { - return 0; + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("getLength(%s)", logger.toVariable(number)), + () -> delegate.getLength(number)); } @Override public BitvectorFormula negate(BitvectorFormula number) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("negate(%s)", logger.toVariable(number)), + () -> delegate.negate(number)); } @Override public BitvectorFormula add(BitvectorFormula number1, BitvectorFormula number2) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("add(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.add(number1, number2)); } @Override public BitvectorFormula subtract(BitvectorFormula number1, BitvectorFormula number2) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("subtract(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.subtract(number1, number2)); } @Override public BitvectorFormula divide( BitvectorFormula dividend, BitvectorFormula divisor, boolean signed) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format( + "divide(%s, %s, %s)", logger.toVariable(dividend), logger.toVariable(divisor), signed), + () -> delegate.divide(dividend, divisor, signed)); } @Override public BitvectorFormula smodulo(BitvectorFormula dividend, BitvectorFormula divisor) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("smodulo(%s, %s)", logger.toVariable(dividend), logger.toVariable(dividend)), + () -> delegate.smodulo(dividend, divisor)); } @Override public BitvectorFormula remainder( BitvectorFormula dividend, BitvectorFormula divisor, boolean signed) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format( + "remainder(%s, %s, %s)", + logger.toVariable(dividend), logger.toVariable(divisor), signed), + () -> delegate.remainder(dividend, divisor, signed)); } @Override public BitvectorFormula multiply(BitvectorFormula number1, BitvectorFormula number2) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("multiply(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.multiply(number1, number2)); } @Override public BooleanFormula equal(BitvectorFormula number1, BitvectorFormula number2) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("equal(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.equal(number1, number2)); } @Override public BooleanFormula greaterThan( BitvectorFormula number1, BitvectorFormula number2, boolean signed) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format( + "greaterThan(%s, %s, %s)", + logger.toVariable(number1), logger.toVariable(number2), signed), + () -> delegate.greaterThan(number1, number2, signed)); } @Override public BooleanFormula greaterOrEquals( BitvectorFormula number1, BitvectorFormula number2, boolean signed) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format( + "greaterOrEquals(%s, %s, %s)", + logger.toVariable(number1), logger.toVariable(number2), signed), + () -> delegate.greaterOrEquals(number1, number2, signed)); } @Override public BooleanFormula lessThan( BitvectorFormula number1, BitvectorFormula number2, boolean signed) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format( + "lessThan(%s, %s, %s)", logger.toVariable(number1), logger.toVariable(number2), signed), + () -> delegate.lessThan(number1, number2, signed)); } @Override public BooleanFormula lessOrEquals( BitvectorFormula number1, BitvectorFormula number2, boolean signed) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format( + "lessOrEquals(%s, %s, %s)", + logger.toVariable(number1), logger.toVariable(number2), signed), + () -> delegate.lessOrEquals(number1, number2, signed)); } @Override public BitvectorFormula not(BitvectorFormula bits) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("not(%s)", logger.toVariable(bits)), + () -> delegate.not(bits)); } @Override public BitvectorFormula and(BitvectorFormula bits1, BitvectorFormula bits2) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("and(%s, %s)", logger.toVariable(bits1), logger.toVariable(bits2)), + () -> delegate.and(bits1, bits2)); } @Override public BitvectorFormula or(BitvectorFormula bits1, BitvectorFormula bits2) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("or(%s, %s)", logger.toVariable(bits1), logger.toVariable(bits2)), + () -> delegate.or(bits1, bits2)); } @Override public BitvectorFormula xor(BitvectorFormula bits1, BitvectorFormula bits2) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("xor(%s, %s)", logger.toVariable(bits1), logger.toVariable(bits2)), + () -> delegate.xor(bits1, bits2)); } @Override public BitvectorFormula shiftRight( BitvectorFormula number, BitvectorFormula toShift, boolean signed) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format( + "shiftRight(%s, %s, %s)", + logger.toVariable(number), logger.toVariable(toShift), signed), + () -> delegate.shiftRight(number, toShift, signed)); } @Override public BitvectorFormula shiftLeft(BitvectorFormula number, BitvectorFormula toShift) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("shiftLeft(%s, %s)", logger.toVariable(number), logger.toVariable(toShift)), + () -> delegate.shiftLeft(number, toShift)); } @Override public BitvectorFormula rotateLeft(BitvectorFormula number, int toRotate) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("rotateLeft(%s, %s)", logger.toVariable(number), toRotate), + () -> delegate.rotateLeft(number, toRotate)); } @Override public BitvectorFormula rotateLeft(BitvectorFormula number, BitvectorFormula toRotate) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("rotateLeft(%s, %s)", logger.toVariable(number), logger.toVariable(toRotate)), + () -> delegate.rotateLeft(number, toRotate)); } @Override public BitvectorFormula rotateRight(BitvectorFormula number, int toRotate) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("rotateRight(%s, %s)", logger.toVariable(number), toRotate), + () -> delegate.rotateRight(number, toRotate)); } @Override public BitvectorFormula rotateRight(BitvectorFormula number, BitvectorFormula toRotate) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format( + "rotateRight(%s, %s)", logger.toVariable(number), logger.toVariable(toRotate)), + () -> delegate.rotateRight(number, toRotate)); } @Override public BitvectorFormula concat(BitvectorFormula prefix, BitvectorFormula suffix) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("concat(%s, %s)", logger.toVariable(prefix), logger.toVariable(prefix)), + () -> delegate.concat(prefix, suffix)); } @Override public BitvectorFormula extract(BitvectorFormula number, int msb, int lsb) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("extract(%s, %s, %s)", logger.toVariable(number), msb, lsb), + () -> delegate.extract(number, msb, lsb)); } @Override public BitvectorFormula extend(BitvectorFormula number, int extensionBits, boolean signed) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("extend(%s, %s, %s)", logger.toVariable(number), extensionBits, signed), + () -> delegate.extend(number, extensionBits, signed)); } @Override public BooleanFormula distinct(List pBits) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format( + "distinct(ImmutableList.of(%s))", + FluentIterable.from(pBits).transform(logger::toVariable).join(Joiner.on(", "))), + () -> delegate.distinct(pBits)); } } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 96a31cf520..63789f8a7c 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -68,7 +68,7 @@ public ArrayFormulaManager getArrayFormulaManager() { @Override public BitvectorFormulaManager getBitvectorFormulaManager() { - throw new UnsupportedOperationException(); + return new TraceBitvectorFormulaManager(delegate.getBitvectorFormulaManager(), logger); } @Override diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index bfbe53da3e..74178540ed 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -20,6 +20,7 @@ import java.util.concurrent.Callable; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.FormulaType; +import org.sosy_lab.java_smt.api.FormulaType.BitvectorType; public class TraceLogger { private long id = 0; @@ -108,6 +109,10 @@ public String printFormulaType(FormulaType pType) { if (pType.isIntegerType()) { return "FormulaType.IntegerType"; } + if (pType.isBitvectorType()) { + BitvectorType bvType = (BitvectorType) pType; + return String.format("FormulaType.getBitvectorTypeWithSize(%s)", bvType.getSize()); + } // FIXME Handle other cases throw new IllegalArgumentException("Unsupported formula type: " + pType); } From cb7a7d27fc13094dd287765da07c9bf72fd3284b Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Tue, 19 Aug 2025 14:03:08 +0200 Subject: [PATCH 16/89] Trace: Add floating point support --- .../TraceFloatingPointFormulaManager.java | 451 ++++++++++++++++++ .../delegate/trace/TraceFormulaManager.java | 2 +- .../java_smt/delegate/trace/TraceLogger.java | 7 + 3 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java new file mode 100644 index 0000000000..4d4746caff --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java @@ -0,0 +1,451 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import java.math.BigDecimal; +import java.math.BigInteger; +import org.sosy_lab.common.rationals.Rational; +import org.sosy_lab.java_smt.api.BitvectorFormula; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.FloatingPointFormula; +import org.sosy_lab.java_smt.api.FloatingPointFormulaManager; +import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign; +import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; +import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.FormulaType; +import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType; + +public class TraceFloatingPointFormulaManager implements FloatingPointFormulaManager { + private final FloatingPointFormulaManager delegate; + private final TraceLogger logger; + + public TraceFloatingPointFormulaManager( + FloatingPointFormulaManager pDelegate, TraceLogger pLogger) { + delegate = pDelegate; + logger = pLogger; + } + + @Override + public FloatingPointFormula makeNumber(double n, FloatingPointType type) { + return makeNumber(n, type, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + } + + private String printRoundingMode(FloatingPointRoundingMode pRoundingMode) { + return "FloatingPointRoundingMode." + pRoundingMode.name(); + } + + @Override + public FloatingPointFormula makeNumber( + double n, FloatingPointType type, FloatingPointRoundingMode pFloatingPointRoundingMode) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "makeNumber(%s, %s, %s)", + n, logger.printFormulaType(type), printRoundingMode(pFloatingPointRoundingMode)), + () -> delegate.makeNumber(n, type, pFloatingPointRoundingMode)); + } + + @Override + public FloatingPointFormula makeNumber(BigDecimal n, FloatingPointType type) { + return makeNumber(n, type, FloatingPointRoundingMode.NEAREST_TIES_AWAY); + } + + @Override + public FloatingPointFormula makeNumber( + BigDecimal n, FloatingPointType type, FloatingPointRoundingMode pFloatingPointRoundingMode) { + throw new UnsupportedOperationException(); + } + + @Override + public FloatingPointFormula makeNumber(String n, FloatingPointType type) { + return makeNumber(n, type, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + } + + @Override + public FloatingPointFormula makeNumber( + String n, FloatingPointType type, FloatingPointRoundingMode pFloatingPointRoundingMode) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "makeNumber(\"%s\", %s, %s)", + n, logger.printFormulaType(type), printRoundingMode(pFloatingPointRoundingMode)), + () -> delegate.makeNumber(n, type, pFloatingPointRoundingMode)); + } + + @Override + public FloatingPointFormula makeNumber(Rational n, FloatingPointType type) { + throw new UnsupportedOperationException(); + } + + @Override + public FloatingPointFormula makeNumber( + Rational n, FloatingPointType type, FloatingPointRoundingMode pFloatingPointRoundingMode) { + throw new UnsupportedOperationException(); + } + + private String printSign(Sign pSign) { + return "FloatingPointNumber.Sign." + pSign.name(); + } + + @Override + public FloatingPointFormula makeNumber( + BigInteger exponent, BigInteger mantissa, Sign sign, FloatingPointType type) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "makeNumber(new BigInteger(\"%s\"), new BigInteger(\"%s\"), %s, %s)", + exponent, mantissa, printSign(sign), logger.printFormulaType(type)), + () -> delegate.makeNumber(exponent, mantissa, sign, type)); + } + + @Override + public FloatingPointFormula makeVariable(String pVar, FloatingPointType type) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("makeVariable(\"%s\", %s)", pVar, logger.printFormulaType(type)), + () -> delegate.makeVariable(pVar, type)); + } + + @Override + public FloatingPointFormula makePlusInfinity(FloatingPointType type) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("makePlusInfinity(%s)", logger.printFormulaType(type)), + () -> delegate.makePlusInfinity(type)); + } + + @Override + public FloatingPointFormula makeMinusInfinity(FloatingPointType type) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("makeMinusInfinity(%s)", logger.printFormulaType(type)), + () -> delegate.makeMinusInfinity(type)); + } + + @Override + public FloatingPointFormula makeNaN(FloatingPointType type) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("makeNaN(%s)", logger.printFormulaType(type)), + () -> delegate.makeNaN(type)); + } + + @Override + public T castTo( + FloatingPointFormula source, boolean signed, FormulaType targetType) { + return castTo(source, signed, targetType, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + } + + @Override + public T castTo( + FloatingPointFormula source, + boolean signed, + FormulaType targetType, + FloatingPointRoundingMode pFloatingPointRoundingMode) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "castTo(%s, %s, %s, %s)", + logger.toVariable(source), + signed, + logger.printFormulaType(targetType), + printRoundingMode(pFloatingPointRoundingMode)), + () -> delegate.castTo(source, signed, targetType, pFloatingPointRoundingMode)); + } + + @Override + public FloatingPointFormula castFrom( + Formula source, boolean signed, FloatingPointType targetType) { + return castFrom(source, signed, targetType, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + } + + @Override + public FloatingPointFormula castFrom( + Formula source, + boolean signed, + FloatingPointType targetType, + FloatingPointRoundingMode pFloatingPointRoundingMode) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "castFrom(%s, %s, %s, %s)", + logger.toVariable(source), + signed, + logger.printFormulaType(targetType), + printRoundingMode(pFloatingPointRoundingMode)), + () -> delegate.castFrom(source, signed, targetType, pFloatingPointRoundingMode)); + } + + @Override + public FloatingPointFormula fromIeeeBitvector( + BitvectorFormula number, FloatingPointType pTargetType) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "fromIeeeBitvector(%s, %s)", + logger.toVariable(number), logger.printFormulaType(pTargetType)), + () -> delegate.fromIeeeBitvector(number, pTargetType)); + } + + @Override + public BitvectorFormula toIeeeBitvector(FloatingPointFormula number) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("toIeeeBitvector(%s)", logger.toVariable(number)), + () -> delegate.toIeeeBitvector(number)); + } + + @Override + public FloatingPointFormula round( + FloatingPointFormula formula, FloatingPointRoundingMode roundingMode) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("round(%s, %s)", logger.toVariable(formula), printRoundingMode(roundingMode)), + () -> delegate.round(formula, roundingMode)); + } + + @Override + public FloatingPointFormula negate(FloatingPointFormula number) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("negate(%s)", logger.toVariable(number)), + () -> delegate.negate(number)); + } + + @Override + public FloatingPointFormula abs(FloatingPointFormula number) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("abs(%s)", logger.toVariable(number)), + () -> delegate.abs(number)); + } + + @Override + public FloatingPointFormula max(FloatingPointFormula number1, FloatingPointFormula number2) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("max(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.max(number1, number2)); + } + + @Override + public FloatingPointFormula min(FloatingPointFormula number1, FloatingPointFormula number2) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("min(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.min(number1, number2)); + } + + @Override + public FloatingPointFormula sqrt(FloatingPointFormula number) { + return sqrt(number, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + } + + @Override + public FloatingPointFormula sqrt( + FloatingPointFormula number, FloatingPointRoundingMode roundingMode) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("sqrt(%s, %s)", logger.toVariable(number), printRoundingMode(roundingMode)), + () -> delegate.sqrt(number, roundingMode)); + } + + @Override + public FloatingPointFormula add(FloatingPointFormula number1, FloatingPointFormula number2) { + return add(number1, number2, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + } + + @Override + public FloatingPointFormula add( + FloatingPointFormula number1, + FloatingPointFormula number2, + FloatingPointRoundingMode pFloatingPointRoundingMode) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "add(%s, %s, %s)", + logger.toVariable(number1), + logger.toVariable(number2), + printRoundingMode(pFloatingPointRoundingMode)), + () -> delegate.add(number1, number2, pFloatingPointRoundingMode)); + } + + @Override + public FloatingPointFormula subtract(FloatingPointFormula number1, FloatingPointFormula number2) { + return subtract(number1, number2, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + } + + @Override + public FloatingPointFormula subtract( + FloatingPointFormula number1, + FloatingPointFormula number2, + FloatingPointRoundingMode pFloatingPointRoundingMode) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "subtract(%s, %s, %s)", + logger.toVariable(number1), + logger.toVariable(number2), + printRoundingMode(pFloatingPointRoundingMode)), + () -> delegate.subtract(number1, number2, pFloatingPointRoundingMode)); + } + + @Override + public FloatingPointFormula divide(FloatingPointFormula number1, FloatingPointFormula number2) { + return divide(number1, number2, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + } + + @Override + public FloatingPointFormula divide( + FloatingPointFormula number1, + FloatingPointFormula number2, + FloatingPointRoundingMode pFloatingPointRoundingMode) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "divide(%s, %s, %s)", + logger.toVariable(number1), + logger.toVariable(number2), + printRoundingMode(pFloatingPointRoundingMode)), + () -> delegate.divide(number1, number2, pFloatingPointRoundingMode)); + } + + @Override + public FloatingPointFormula multiply(FloatingPointFormula number1, FloatingPointFormula number2) { + return multiply(number1, number2, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + } + + @Override + public FloatingPointFormula multiply( + FloatingPointFormula number1, + FloatingPointFormula number2, + FloatingPointRoundingMode pFloatingPointRoundingMode) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "multiply(%s, %s, %s)", + logger.toVariable(number1), + logger.toVariable(number2), + printRoundingMode(pFloatingPointRoundingMode)), + () -> delegate.multiply(number1, number2, pFloatingPointRoundingMode)); + } + + @Override + public FloatingPointFormula remainder( + FloatingPointFormula dividend, FloatingPointFormula divisor) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("remainder(%s, %s)", logger.toVariable(dividend), logger.toVariable(divisor)), + () -> delegate.remainder(dividend, divisor)); + } + + @Override + public BooleanFormula assignment(FloatingPointFormula number1, FloatingPointFormula number2) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("assignment(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.assignment(number1, number2)); + } + + @Override + public BooleanFormula equalWithFPSemantics( + FloatingPointFormula number1, FloatingPointFormula number2) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "equalWithFPSemantics(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.equalWithFPSemantics(number1, number2)); + } + + @Override + public BooleanFormula greaterThan(FloatingPointFormula number1, FloatingPointFormula number2) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "greaterThan(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.greaterThan(number1, number2)); + } + + @Override + public BooleanFormula greaterOrEquals( + FloatingPointFormula number1, FloatingPointFormula number2) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "greaterOrEquals(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.greaterOrEquals(number1, number2)); + } + + @Override + public BooleanFormula lessThan(FloatingPointFormula number1, FloatingPointFormula number2) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("lessThan(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.lessThan(number1, number2)); + } + + @Override + public BooleanFormula lessOrEquals(FloatingPointFormula number1, FloatingPointFormula number2) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "lessOrEquals(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.lessOrEquals(number1, number2)); + } + + @Override + public BooleanFormula isNaN(FloatingPointFormula number) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("isNaN(%s)", logger.toVariable(number)), + () -> delegate.isNaN(number)); + } + + @Override + public BooleanFormula isInfinity(FloatingPointFormula number) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("isInfinity(%s)", logger.toVariable(number)), + () -> delegate.isInfinity(number)); + } + + @Override + public BooleanFormula isZero(FloatingPointFormula number) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("isZero(%s)", logger.toVariable(number)), + () -> delegate.isZero(number)); + } + + @Override + public BooleanFormula isNormal(FloatingPointFormula number) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("isNormal(%s)", logger.toVariable(number)), + () -> delegate.isNormal(number)); + } + + @Override + public BooleanFormula isSubnormal(FloatingPointFormula number) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("isSubnormal(%s)", logger.toVariable(number)), + () -> delegate.isSubnormal(number)); + } + + @Override + public BooleanFormula isNegative(FloatingPointFormula number) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("isNegative(%s)", logger.toVariable(number)), + () -> delegate.isNegative(number)); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 63789f8a7c..c01e252624 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -73,7 +73,7 @@ public BitvectorFormulaManager getBitvectorFormulaManager() { @Override public FloatingPointFormulaManager getFloatingPointFormulaManager() { - throw new UnsupportedOperationException(); + return new TraceFloatingPointFormulaManager(delegate.getFloatingPointFormulaManager(), logger); } @Override diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index 74178540ed..5748383bd5 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -21,6 +21,7 @@ import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.FormulaType; import org.sosy_lab.java_smt.api.FormulaType.BitvectorType; +import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType; public class TraceLogger { private long id = 0; @@ -113,6 +114,12 @@ public String printFormulaType(FormulaType pType) { BitvectorType bvType = (BitvectorType) pType; return String.format("FormulaType.getBitvectorTypeWithSize(%s)", bvType.getSize()); } + if (pType.isFloatingPointType()) { + FloatingPointType fpType = (FloatingPointType) pType; + return String.format( + "FormulaType.getFloatingPointType(%s, %s)", + fpType.getExponentSize(), fpType.getMantissaSize()); + } // FIXME Handle other cases throw new IllegalArgumentException("Unsupported formula type: " + pType); } From 7c432fc1cf5b1119a6abfad7501f8dfa1a07534f Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Tue, 19 Aug 2025 14:53:37 +0200 Subject: [PATCH 17/89] Trace: Specify the solver backend in the trace when creating a new context --- src/org/sosy_lab/java_smt/SolverContextFactory.java | 2 +- .../java_smt/delegate/trace/TraceSolverContext.java | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/SolverContextFactory.java b/src/org/sosy_lab/java_smt/SolverContextFactory.java index 8d9cc34dfb..cda52a0f09 100644 --- a/src/org/sosy_lab/java_smt/SolverContextFactory.java +++ b/src/org/sosy_lab/java_smt/SolverContextFactory.java @@ -237,7 +237,7 @@ public SolverContext generateContext(Solvers solverToCreate) context = new DebuggingSolverContext(solverToCreate, config, context); } if (trace) { - context = new TraceSolverContext(context, config); + context = new TraceSolverContext(solverToCreate, config, context); } if (collectStatistics) { // statistics need to be the most outer wrapping layer. diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index 38bac71956..5cc71a17b9 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -29,7 +29,7 @@ public class TraceSolverContext implements SolverContext { private final SolverContext delegate; private final TraceLogger logger; - public TraceSolverContext(SolverContext pDelegate, Configuration config) { + public TraceSolverContext(Solvers pSolver, Configuration config, SolverContext pDelegate) { delegate = pDelegate; // FIXME Move the files to the output folder? logger = @@ -41,7 +41,9 @@ public TraceSolverContext(SolverContext pDelegate, Configuration config) { ImmutableMap.Builder options = ImmutableMap.builder(); for (String s : props.lines().toArray(String[]::new)) { List parts = Splitter.on(" = ").splitToList(s); - if (parts.get(0).startsWith("solver") && !parts.get(0).equals("solver.trace")) { + if (parts.get(0).startsWith("solver") + && !parts.get(0).equals("solver.trace") + && !parts.get(0).equals("solver.solver")) { options.put(parts.get(0), parts.get(1)); } } @@ -60,7 +62,11 @@ public TraceSolverContext(SolverContext pDelegate, Configuration config) { logger.appendDef("logger", "LogManager.createNullLogManager()"); logger.appendDef("notifier", "ShutdownNotifier.createDummy()"); logger.appendDef( - "context", "SolverContextFactory.createSolverContext(config, logger, notifier)"); + "context", + "SolverContextFactory.createSolverContext(config, logger, notifier, " + + "SolverContextFactory.Solvers." + + pSolver.name() + + ")"); logger.appendDef("mgr", "context.getFormulaManager()"); } catch (IOException e) { throw new RuntimeException(e); From c676391690e785a075df90978e0f72cc42d0a314 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Tue, 19 Aug 2025 15:12:53 +0200 Subject: [PATCH 18/89] Trace: Add a note --- .../sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index c01e252624..97f7596ec6 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -183,6 +183,7 @@ public T substitute( @Override public BooleanFormula translateFrom(BooleanFormula formula, FormulaManager otherManager) { + // TODO Write API calls from all contexts into one file to allow us to support this method throw new UnsupportedOperationException(); } From 299c901ab12f455c0407cccbc866e4b55803d212 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Wed, 20 Aug 2025 11:49:48 +0200 Subject: [PATCH 19/89] Trace: Add printing support for ArrayFormulaTypes --- src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index 5748383bd5..e3e149e406 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -20,6 +20,7 @@ import java.util.concurrent.Callable; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.FormulaType; +import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType; import org.sosy_lab.java_smt.api.FormulaType.BitvectorType; import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType; @@ -110,6 +111,12 @@ public String printFormulaType(FormulaType pType) { if (pType.isIntegerType()) { return "FormulaType.IntegerType"; } + if (pType.isArrayType()) { + ArrayFormulaType arrayType = (ArrayFormulaType) pType; + return String.format( + "FormulaType.getArrayType(%s, %s)", + printFormulaType(arrayType.getIndexType()), printFormulaType(arrayType.getElementType())); + } if (pType.isBitvectorType()) { BitvectorType bvType = (BitvectorType) pType; return String.format("FormulaType.getBitvectorTypeWithSize(%s)", bvType.getSize()); From d2292192b5354beb2ae0b2e6dd716090cedb86ce Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Wed, 20 Aug 2025 16:32:50 +0200 Subject: [PATCH 20/89] Trace: Catch I/O exceptions directly in the logger --- .../java_smt/delegate/trace/TraceLogger.java | 20 ++++++--- .../delegate/trace/TraceSolverContext.java | 41 ++++++++----------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index e3e149e406..d3618c480f 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -63,15 +63,23 @@ public String toVariable(Object f) { } /** Add a definition to the log. */ - public void appendDef(String pVar, String pExpr) throws IOException { - output.append(String.format("var %s = %s;%n", pVar, pExpr)); - output.flush(); + public void appendDef(String pVar, String pExpr) { + try { + output.append(String.format("var %s = %s;%n", pVar, pExpr)); + output.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } } /** Add a statement to the log. */ - public void appendStmt(String pStmt) throws IOException { - output.append(String.format("%s;%n", pStmt)); - output.flush(); + public void appendStmt(String pStmt) { + try { + output.append(String.format("%s;%n", pStmt)); + output.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } } /** Log an API call with return value. */ diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index 5cc71a17b9..ffbd4a7e8e 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -14,7 +14,6 @@ import com.google.common.base.Splitter; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableMap; -import java.io.IOException; import java.util.List; import java.util.Map.Entry; import org.sosy_lab.common.configuration.Configuration; @@ -49,28 +48,24 @@ public TraceSolverContext(Solvers pSolver, Configuration config, SolverContext p } // Write code for creating a solver context to the trace log - try { - logger.appendDef( - "config", - "Configuration.builder()." - + FluentIterable.from(options.buildOrThrow().entrySet()) - .transform( - (Entry e) -> - String.format("setOption(\"%s\", \"%s\")", e.getKey(), e.getValue())) - .join(Joiner.on(".")) - + ".build()"); - logger.appendDef("logger", "LogManager.createNullLogManager()"); - logger.appendDef("notifier", "ShutdownNotifier.createDummy()"); - logger.appendDef( - "context", - "SolverContextFactory.createSolverContext(config, logger, notifier, " - + "SolverContextFactory.Solvers." - + pSolver.name() - + ")"); - logger.appendDef("mgr", "context.getFormulaManager()"); - } catch (IOException e) { - throw new RuntimeException(e); - } + logger.appendDef( + "config", + "Configuration.builder()." + + FluentIterable.from(options.buildOrThrow().entrySet()) + .transform( + (Entry e) -> + String.format("setOption(\"%s\", \"%s\")", e.getKey(), e.getValue())) + .join(Joiner.on(".")) + + ".build()"); + logger.appendDef("logger", "LogManager.createNullLogManager()"); + logger.appendDef("notifier", "ShutdownNotifier.createDummy()"); + logger.appendDef( + "context", + "SolverContextFactory.createSolverContext(config, logger, notifier, " + + "SolverContextFactory.Solvers." + + pSolver.name() + + ")"); + logger.appendDef("mgr", "context.getFormulaManager()"); } @Override From a187568373176f16e7f3aff9966b7b4ca908a776 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Wed, 20 Aug 2025 16:33:53 +0200 Subject: [PATCH 21/89] Trace: Add support for visitors --- .../delegate/trace/TraceFormulaManager.java | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 97f7596ec6..43f1a66de8 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -27,6 +27,7 @@ import org.sosy_lab.java_smt.api.FunctionDeclaration; import org.sosy_lab.java_smt.api.IntegerFormulaManager; import org.sosy_lab.java_smt.api.QuantifiedFormulaManager; +import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier; import org.sosy_lab.java_smt.api.RationalFormulaManager; import org.sosy_lab.java_smt.api.SLFormulaManager; import org.sosy_lab.java_smt.api.SolverException; @@ -148,14 +149,65 @@ public T simplify(T input) throws InterruptedException { throw new UnsupportedOperationException(); } + private class TraceVisitor implements FormulaVisitor { + private final FormulaVisitor delegateVisitor; + + private TraceVisitor(FormulaVisitor pDelegate) { + delegateVisitor = pDelegate; + } + + @Override + public T visitFreeVariable(Formula f, String name) { + return delegateVisitor.visitFreeVariable(f, name); + } + + @Override + public T visitConstant(Formula f, Object value) { + return delegateVisitor.visitConstant(f, value); + } + + @SuppressWarnings("unused") + @Override + public T visitFunction( + Formula f, List args, FunctionDeclaration functionDeclaration) { + for (int i = 0; i <= args.size(); i++) { + var value = i == 0 ? functionDeclaration : args.get(i - 1); + var unused = + logger.logDef( + "mgr", + String.format("visit(%s, new ExtractingVisitor(%s))", logger.toVariable(f), i), + () -> value); + } + return delegateVisitor.visitFunction(f, args, functionDeclaration); + } + + @SuppressWarnings("unused") + @Override + public T visitQuantifier( + BooleanFormula f, + Quantifier quantifier, + List boundVariables, + BooleanFormula body) { + for (int i = 0; i <= boundVariables.size(); i++) { + var value = i == boundVariables.size() ? body : boundVariables.get(i - 1); + var unused = + logger.logDef( + "mgr", + String.format("visit(%s, new ExtractingVisitor(%s))", logger.toVariable(f), i), + () -> value); + } + return delegateVisitor.visitQuantifier(f, quantifier, boundVariables, body); + } + } + @Override public R visit(Formula f, FormulaVisitor rFormulaVisitor) { - throw new UnsupportedOperationException(); + return delegate.visit(f, new TraceVisitor<>(rFormulaVisitor)); } @Override public void visitRecursively(Formula f, FormulaVisitor rFormulaVisitor) { - throw new UnsupportedOperationException(); + delegate.visitRecursively(f, new TraceVisitor<>(rFormulaVisitor)); } @Override From 0590364fa2fc1f6b86c7b668521597a31831699b Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Wed, 20 Aug 2025 16:36:40 +0200 Subject: [PATCH 22/89] Trace: Allow parsing and printing --- .../java_smt/delegate/trace/TraceFormulaManager.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 43f1a66de8..5465a39564 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -130,12 +130,15 @@ public FormulaType getFormulaType(T formula) { @Override public BooleanFormula parse(String s) throws IllegalArgumentException { - throw new UnsupportedOperationException(); + return logger.logDef("mgr", String.format("parse(\"%s\")", s), () -> delegate.parse(s)); } @Override public Appender dumpFormula(BooleanFormula pT) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr", + String.format("dumpFormula(%s)", logger.toVariable(pT)), + () -> delegate.dumpFormula(pT)); } @Override From b0dd829a459abf18f18430e7c219671f1ba978bf Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Thu, 21 Aug 2025 12:32:17 +0200 Subject: [PATCH 23/89] Trace: Fix checkstyle issue --- .../sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 5465a39564..9649aa4cd2 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -152,7 +152,7 @@ public T simplify(T input) throws InterruptedException { throw new UnsupportedOperationException(); } - private class TraceVisitor implements FormulaVisitor { + private final class TraceVisitor implements FormulaVisitor { private final FormulaVisitor delegateVisitor; private TraceVisitor(FormulaVisitor pDelegate) { From 2ed82e59cebeb831a7bada01003855cc08d8eff1 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Thu, 21 Aug 2025 12:33:01 +0200 Subject: [PATCH 24/89] Trace: Throw an exception when trying to get the variable for an object that is not tracked --- src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index d3618c480f..08553bd8b4 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -59,7 +59,11 @@ private void mapVariable(String pVar, Object f) { *

Use {@link #mapVariable(String, Object)} to bind an object to a variable */ public String toVariable(Object f) { - return valueMap.get(f); + String r = valueMap.get(f); + if (r == null) { + throw new IllegalArgumentException("Object not tracked"); + } + return r; } /** Add a definition to the log. */ From 3ce7e7b93aaa57d30b5469cc21aeb6abf35f103b Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Thu, 21 Aug 2025 12:37:11 +0200 Subject: [PATCH 25/89] Trace: Make TraceLogger package-private --- src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index 08553bd8b4..696db63dac 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -24,7 +24,7 @@ import org.sosy_lab.java_smt.api.FormulaType.BitvectorType; import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType; -public class TraceLogger { +class TraceLogger { private long id = 0; private final Map valueMap = new HashMap<>(); From 2d35c3d18ef95ed762ae585f1f7089c61e3bcfd2 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Thu, 21 Aug 2025 13:40:29 +0200 Subject: [PATCH 26/89] Trace: Add support for printing more formula types --- src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index 696db63dac..120990a0ba 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -120,9 +120,15 @@ public void logStmt(String prefix, String method, CheckedRunnable closure) { * construct this type. */ public String printFormulaType(FormulaType pType) { + if (pType.isBooleanType()) { + return "FormulaType.BooleanType"; + } if (pType.isIntegerType()) { return "FormulaType.IntegerType"; } + if (pType.isRationalType()) { + return "FormulaType.RationalType"; + } if (pType.isArrayType()) { ArrayFormulaType arrayType = (ArrayFormulaType) pType; return String.format( From b273c253d0b45fb392e2e5ed00271002374b2e8d Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Thu, 21 Aug 2025 21:32:41 +0200 Subject: [PATCH 27/89] Trace: Apply refaster patch --- src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index 120990a0ba..c60317ca6d 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -10,6 +10,7 @@ package org.sosy_lab.java_smt.delegate.trace; +import com.google.common.base.Preconditions; import java.io.BufferedWriter; import java.io.IOException; import java.nio.charset.Charset; @@ -60,9 +61,7 @@ private void mapVariable(String pVar, Object f) { */ public String toVariable(Object f) { String r = valueMap.get(f); - if (r == null) { - throw new IllegalArgumentException("Object not tracked"); - } + Preconditions.checkArgument(r != null, "Object not tracked"); return r; } From c7c15bfe5413a485a172d8a29d715b689ed5e966 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sat, 23 Aug 2025 15:44:18 +0200 Subject: [PATCH 28/89] Trace: Remove duplicate "." when creating a trace for the configuration builder --- .../java_smt/delegate/trace/TraceSolverContext.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index ffbd4a7e8e..858ac04ee7 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -50,12 +50,12 @@ public TraceSolverContext(Solvers pSolver, Configuration config, SolverContext p // Write code for creating a solver context to the trace log logger.appendDef( "config", - "Configuration.builder()." + "Configuration.builder()" + FluentIterable.from(options.buildOrThrow().entrySet()) .transform( (Entry e) -> - String.format("setOption(\"%s\", \"%s\")", e.getKey(), e.getValue())) - .join(Joiner.on(".")) + String.format(".setOption(\"%s\", \"%s\")", e.getKey(), e.getValue())) + .join(Joiner.on("")) + ".build()"); logger.appendDef("logger", "LogManager.createNullLogManager()"); logger.appendDef("notifier", "ShutdownNotifier.createDummy()"); From 01cb338674005e64703f34c4e83f0ae797c5eb3b Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 16:01:50 +0200 Subject: [PATCH 29/89] Trace: Refactor code and rebuild all terms that are returned by the solver Rebuilding the terms makes sure that we don't encounter any unknown subformulas in the visitors --- .../trace/TraceBasicProverEnvironment.java | 6 +- .../trace/TraceBitvectorFormulaManager.java | 2 +- .../trace/TraceBooleanFormulaManager.java | 4 +- .../delegate/trace/TraceFormulaManager.java | 624 ++++++++++++++++-- .../java_smt/delegate/trace/TraceLogger.java | 84 ++- .../java_smt/delegate/trace/TraceModel.java | 18 +- .../delegate/trace/TraceSolverContext.java | 9 +- .../delegate/trace/TraceUFManager.java | 32 +- 8 files changed, 671 insertions(+), 108 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java index dfcb804b96..fe202cc466 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java @@ -35,7 +35,7 @@ public void pop() { @Override public @Nullable T addConstraint(BooleanFormula constraint) throws InterruptedException { - return logger.logDef( + return logger.logDefKeep( logger.toVariable(this), String.format("addConstraint(%s)", logger.toVariable(constraint)), () -> delegate.addConstraint(constraint)); @@ -53,7 +53,7 @@ public int size() { @Override public boolean isUnsat() throws SolverException, InterruptedException { - return logger.logDef(logger.toVariable(this), "isUnsat()", delegate::isUnsat); + return logger.logDefKeep(logger.toVariable(this), "isUnsat()", delegate::isUnsat); } @Override @@ -65,7 +65,7 @@ public boolean isUnsatWithAssumptions(Collection assumptions) @SuppressWarnings("resource") @Override public Model getModel() throws SolverException { - return logger.logDef( + return logger.logDefKeep( logger.toVariable(this), "getModel()", () -> new TraceModel(delegate.getModel(), logger)); } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java index a247ec978b..936a12f33c 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java @@ -79,7 +79,7 @@ public BitvectorFormula makeVariable(BitvectorType type, String pVar) { @Override public int getLength(BitvectorFormula number) { - return logger.logDef( + return logger.logDefDiscard( "mgr.getBitvectorFormulaManager()", String.format("getLength(%s)", logger.toVariable(number)), () -> delegate.getLength(number)); diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java index 78ae819fe0..3a8179a0c6 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java @@ -68,7 +68,7 @@ public BooleanFormula implication(BooleanFormula formula1, BooleanFormula formul @Override public boolean isTrue(BooleanFormula formula) { - return logger.logDef( + return logger.logDefDiscard( "mgr.getBooleanFormulaManager()", String.format("isTrue(%s)", logger.toVariable(formula)), () -> delegate.isTrue(formula)); @@ -76,7 +76,7 @@ public boolean isTrue(BooleanFormula formula) { @Override public boolean isFalse(BooleanFormula formula) { - return logger.logDef( + return logger.logDefDiscard( "mgr.getBooleanFormulaManager()", String.format("isFalse(%s)", logger.toVariable(formula)), () -> delegate.isFalse(formula)); diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 9649aa4cd2..bf8152a7aa 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -10,22 +10,33 @@ package org.sosy_lab.java_smt.delegate.trace; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import java.math.BigInteger; import java.util.List; import java.util.Map; import org.sosy_lab.common.Appender; +import org.sosy_lab.java_smt.api.ArrayFormula; import org.sosy_lab.java_smt.api.ArrayFormulaManager; +import org.sosy_lab.java_smt.api.BitvectorFormula; import org.sosy_lab.java_smt.api.BitvectorFormulaManager; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.BooleanFormulaManager; import org.sosy_lab.java_smt.api.EnumerationFormulaManager; +import org.sosy_lab.java_smt.api.FloatingPointFormula; import org.sosy_lab.java_smt.api.FloatingPointFormulaManager; +import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; +import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.FormulaType; +import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType; +import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType; import org.sosy_lab.java_smt.api.FunctionDeclaration; +import org.sosy_lab.java_smt.api.FunctionDeclarationKind; import org.sosy_lab.java_smt.api.IntegerFormulaManager; +import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; import org.sosy_lab.java_smt.api.QuantifiedFormulaManager; import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier; import org.sosy_lab.java_smt.api.RationalFormulaManager; @@ -40,10 +51,13 @@ public class TraceFormulaManager implements FormulaManager { private final FormulaManager delegate; - private final TraceLogger logger; + private TraceLogger logger; - TraceFormulaManager(FormulaManager pDelegate, TraceLogger pLogger) { + TraceFormulaManager(FormulaManager pDelegate) { delegate = pDelegate; + } + + void setLogger(TraceLogger pLogger) { logger = pLogger; } @@ -102,17 +116,544 @@ public EnumerationFormulaManager getEnumerationFormulaManager() { throw new UnsupportedOperationException(); } + private class Rebuilder extends FormulaTransformationVisitor { + protected Rebuilder(FormulaManager fmgr) { + super(fmgr); + } + + @Override + public Formula visitFreeVariable(Formula f, String name) { + if (!logger.isTracked(f)) { + var g = + logger.logDef( + "mgr", + String.format( + "makeVariable(%s, %s)", + logger.printFormulaType(delegate.getFormulaType(f)), name), + () -> delegate.makeVariable(delegate.getFormulaType(f), name)); + Preconditions.checkArgument(g.equals(f)); + } + return f; + } + + @Override + public Formula visitConstant(Formula f, Object value) { + if (!logger.isTracked(f)) { + if (f instanceof BooleanFormula && value instanceof Boolean) { + var g = + logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format("makeBoolean(%s)", value), + () -> delegate.getBooleanFormulaManager().makeBoolean((Boolean) value)); + Preconditions.checkArgument(g.equals(f)); + } else if (f instanceof BitvectorFormula && value instanceof BigInteger) { + var bvSize = delegate.getBitvectorFormulaManager().getLength((BitvectorFormula) f); + var g = + logger.logDef( + "mgr.getBitvectorFormulaManager()", + String.format("makeBitvector(%s, %s)", bvSize, value), + () -> + delegate + .getBitvectorFormulaManager() + .makeBitvector(bvSize, (BigInteger) value)); + Preconditions.checkArgument(g.equals(f)); + } else if (f instanceof IntegerFormula && value instanceof BigInteger) { + var g = + logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("makeNumber(%s)", value), + () -> delegate.getIntegerFormulaManager().makeNumber((BigInteger) value)); + Preconditions.checkArgument(g.equals(f)); + } else { + throw new IllegalArgumentException( + String.format( + "Unsupported value: Formula=%s, Value=%s", + delegate.getFormulaType(f), value.getClass().getName())); + } + } + return f; + } + + @Override + public Formula visitFunction( + Formula f, List args, FunctionDeclaration functionDeclaration) { + if (!logger.isTracked(f)) { + Formula g = makeApplication(functionDeclaration, args); + // FIXME Remove the assertion? Argument order can change, f.ex (and a b) becomes (and b a) + // Preconditions.checkArgument(g.equals(f)); + } + return f; + } + + @Override + public BooleanFormula visitQuantifier( + BooleanFormula f, + Quantifier quantifier, + List boundVariables, + BooleanFormula body) { + throw new UnsupportedOperationException(); + } + } + + public T rebuild(T f) { + return delegate.transformRecursively(f, new TraceFormulaManager.Rebuilder(this)); + } + @Override public T makeVariable(FormulaType formulaType, String name) { - return logger.logDef( - "mgr", - String.format("makeVariable(%s, \"%s\")", logger.printFormulaType(formulaType), name), - () -> delegate.makeVariable(formulaType, name)); + String var = logger.newVariable(); + logger.appendDef( + var, + String.format("mgr.makeVariable(%s, \"%s\")", logger.printFormulaType(formulaType), name)); + T f = delegate.makeVariable(formulaType, name); + if (logger.isTracked(f)) { + logger.undoLast(); + } + return f; } + @SuppressWarnings("unchecked") @Override public T makeApplication( FunctionDeclaration declaration, List args) { + if (declaration.getKind().equals(FunctionDeclarationKind.UF)) { + var uf = + getUFManager() + .declareUF( + declaration.getName(), declaration.getType(), declaration.getArgumentTypes()); + return getUFManager().callUF(uf, args); + } else { + // TODO Check that the number of arguments matches the arity of the operation + // TODO Figure out how to handle rounding mode for floats + switch (declaration.getKind()) { + case AND: + return (T) + getBooleanFormulaManager() + .and((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + case NOT: + return (T) getBooleanFormulaManager().not((BooleanFormula) args.get(0)); + case OR: + return (T) + getBooleanFormulaManager() + .or((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + case IFF: + return (T) + getBooleanFormulaManager() + .equivalence((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + case ITE: + return getBooleanFormulaManager() + .ifThenElse((BooleanFormula) args.get(0), (T) args.get(1), (T) args.get(2)); + case XOR: + return (T) + getBooleanFormulaManager() + .xor((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + case IMPLIES: + return (T) + getBooleanFormulaManager() + .implication((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + case DISTINCT: + // TODO We only have 'distinct' for some theories + break; + case STORE: + return (T) + getArrayFormulaManager().store((ArrayFormula) args.get(0), args.get(1), args.get(2)); + case SELECT: + return (T) getArrayFormulaManager().select((ArrayFormula) args.get(0), args.get(1)); + case CONST: + return (T) + getArrayFormulaManager() + .makeArray((ArrayFormulaType) declaration.getType(), args.get(0)); + case UMINUS: + // FIXME Handle rational formulas + return (T) getIntegerFormulaManager().negate((IntegerFormula) args.get(0)); + case SUB: + return (T) + getIntegerFormulaManager() + .subtract((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + case ADD: + return (T) + getIntegerFormulaManager() + .add((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + case DIV: + return (T) + getIntegerFormulaManager() + .divide((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + case MUL: + return (T) + getIntegerFormulaManager() + .multiply((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + case MODULO: + return (T) + getIntegerFormulaManager() + .modulo((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + case LT: + return (T) + getIntegerFormulaManager() + .lessThan((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + case LTE: + return (T) + getIntegerFormulaManager() + .lessOrEquals((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + case GT: + return (T) + getIntegerFormulaManager() + .greaterThan((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + case GTE: + return (T) + getIntegerFormulaManager() + .greaterOrEquals((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + case EQ: + { + if (declaration.getArgumentTypes().get(0).isBooleanType()) { + return (T) + getBooleanFormulaManager() + .equivalence((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + } else if (declaration.getArgumentTypes().get(1).isIntegerType()) { + return (T) + getIntegerFormulaManager() + .equal((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } else if (declaration.getArgumentTypes().get(1).isBitvectorType()) { + return (T) + getBitvectorFormulaManager() + .equal((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + } else { + throw new UnsupportedOperationException( + String.format( + "EQ not supported for theory " + "%s", + declaration.getArgumentTypes().get(0))); + } + } + /* + case EQ_ZERO: + break; + case GTE_ZERO: + break; + case FLOOR: + break; + case TO_REAL: + break; + */ + case BV_EXTRACT: + { + String[] tokens = declaration.getName().split("_"); + return (T) + getBitvectorFormulaManager() + .extract( + (BitvectorFormula) args.get(0), + Integer.parseInt(tokens[1]), + Integer.parseInt(tokens[2])); + } + case BV_CONCAT: + return (T) + getBitvectorFormulaManager() + .concat((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_SIGN_EXTENSION: + // TODO + break; + case BV_ZERO_EXTENSION: + // TODO + break; + case BV_NOT: + return (T) getBitvectorFormulaManager().not((BitvectorFormula) args.get(0)); + case BV_NEG: + return (T) getBitvectorFormulaManager().negate((BitvectorFormula) args.get(0)); + case BV_OR: + return (T) + getBitvectorFormulaManager() + .or((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_AND: + return (T) + getBitvectorFormulaManager() + .and((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_XOR: + return (T) + getBitvectorFormulaManager() + .xor((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_SUB: + return (T) + getBitvectorFormulaManager() + .subtract((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_ADD: + return (T) + getBitvectorFormulaManager() + .add((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_SDIV: + return (T) + getBitvectorFormulaManager() + .divide((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), true); + case BV_UDIV: + return (T) + getBitvectorFormulaManager() + .divide((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), false); + case BV_SREM: + return (T) + getBitvectorFormulaManager() + .remainder((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), true); + case BV_UREM: + return (T) + getBitvectorFormulaManager() + .remainder((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), false); + case BV_SMOD: + return (T) + getBitvectorFormulaManager() + .smodulo((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_MUL: + return (T) + getBitvectorFormulaManager() + .multiply((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_ULT: + return (T) + getBitvectorFormulaManager() + .lessThan((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), false); + case BV_SLT: + return (T) + getBitvectorFormulaManager() + .lessThan((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), true); + case BV_ULE: + return (T) + getBitvectorFormulaManager() + .lessOrEquals( + (BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), false); + case BV_SLE: + return (T) + getBitvectorFormulaManager() + .lessOrEquals( + (BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), true); + case BV_UGT: + return (T) + getBitvectorFormulaManager() + .greaterThan( + (BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), false); + case BV_SGT: + return (T) + getBitvectorFormulaManager() + .greaterThan( + (BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), true); + case BV_UGE: + return (T) + getBitvectorFormulaManager() + .greaterOrEquals( + (BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), false); + case BV_SGE: + return (T) + getBitvectorFormulaManager() + .greaterOrEquals( + (BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), true); + case BV_EQ: // FIXME Why is this a separate symbol? + return (T) + getBitvectorFormulaManager() + .equal((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_SHL: + return (T) + getBitvectorFormulaManager() + .shiftLeft((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_LSHR: + return (T) + getBitvectorFormulaManager() + .shiftRight( + (BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), false); + case BV_ASHR: + return (T) + getBitvectorFormulaManager() + .shiftRight((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), true); + case BV_ROTATE_LEFT: + return (T) + getBitvectorFormulaManager() + .rotateLeft((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_ROTATE_RIGHT: + return (T) + getBitvectorFormulaManager() + .rotateRight((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + case BV_ROTATE_LEFT_BY_INT: + // TODO + break; + case BV_ROTATE_RIGHT_BY_INT: + // TODO + break; + case BV_UCASTTO_FP: + return (T) + getFloatingPointFormulaManager() + .castFrom(args.get(0), false, (FloatingPointType) declaration.getType()); + case BV_SCASTTO_FP: + return (T) + getFloatingPointFormulaManager() + .castFrom(args.get(0), true, (FloatingPointType) declaration.getType()); + case FP_NEG: + return (T) getFloatingPointFormulaManager().negate((FloatingPointFormula) args.get(0)); + case FP_ABS: + return (T) getFloatingPointFormulaManager().abs((FloatingPointFormula) args.get(0)); + case FP_MAX: + return (T) + getFloatingPointFormulaManager() + .max((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_MIN: + return (T) + getFloatingPointFormulaManager() + .min((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_SQRT: + return (T) getFloatingPointFormulaManager().sqrt((FloatingPointFormula) args.get(0)); + case FP_SUB: + return (T) + getFloatingPointFormulaManager() + .subtract((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_ADD: + return (T) + getFloatingPointFormulaManager() + .add((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_DIV: + return (T) + getFloatingPointFormulaManager() + .divide((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_REM: + return (T) + getFloatingPointFormulaManager() + .remainder( + (FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_MUL: + return (T) + getFloatingPointFormulaManager() + .multiply((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_LT: + return (T) + getFloatingPointFormulaManager() + .lessThan((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_LE: + return (T) + getFloatingPointFormulaManager() + .lessOrEquals( + (FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_GE: + return (T) + getFloatingPointFormulaManager() + .greaterOrEquals( + (FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_GT: + return (T) + getFloatingPointFormulaManager() + .greaterThan( + (FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_EQ: + return (T) + getFloatingPointFormulaManager() + .equalWithFPSemantics( + (FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + case FP_ROUND_EVEN: + break; + case FP_ROUND_AWAY: + break; + case FP_ROUND_POSITIVE: + break; + case FP_ROUND_NEGATIVE: + break; + case FP_ROUND_ZERO: + break; + case FP_ROUND_TO_INTEGRAL: + { + var rm = (FloatingPointRoundingModeFormula) args.get(1); + System.out.println("Rounding Mode: " + rm); + return (T) + getFloatingPointFormulaManager() + .round( + (FloatingPointFormula) args.get(0), + FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + } + case FP_IS_NAN: + return (T) getFloatingPointFormulaManager().isNaN((FloatingPointFormula) args.get(0)); + case FP_IS_INF: + return (T) + getFloatingPointFormulaManager().isInfinity((FloatingPointFormula) args.get(0)); + case FP_IS_ZERO: + return (T) getFloatingPointFormulaManager().isZero((FloatingPointFormula) args.get(0)); + case FP_IS_NEGATIVE: + return (T) + getFloatingPointFormulaManager().isNegative((FloatingPointFormula) args.get(0)); + case FP_IS_SUBNORMAL: + return (T) + getFloatingPointFormulaManager().isSubnormal((FloatingPointFormula) args.get(0)); + case FP_IS_NORMAL: + return (T) getFloatingPointFormulaManager().isNormal((FloatingPointFormula) args.get(0)); + case FP_CASTTO_FP: + return getFloatingPointFormulaManager() + .castTo((FloatingPointFormula) args.get(0), true, declaration.getType()); + case FP_CASTTO_SBV: + return getFloatingPointFormulaManager() + .castTo((FloatingPointFormula) args.get(0), true, declaration.getType()); + case FP_CASTTO_UBV: + return getFloatingPointFormulaManager() + .castTo((FloatingPointFormula) args.get(0), false, declaration.getType()); + case FP_AS_IEEEBV: + return (T) + getFloatingPointFormulaManager().toIeeeBitvector((FloatingPointFormula) args.get(0)); + case FP_FROM_IEEEBV: + return (T) + getFloatingPointFormulaManager() + .fromIeeeBitvector( + (BitvectorFormula) args.get(0), (FloatingPointType) declaration.getType()); + /* + case STR_CONCAT: + break; + case STR_PREFIX: + break; + case STR_SUFFIX: + break; + case STR_CONTAINS: + break; + case STR_SUBSTRING: + break; + case STR_REPLACE: + break; + case STR_REPLACE_ALL: + break; + case STR_CHAR_AT: + break; + case STR_LENGTH: + break; + case STR_INDEX_OF: + break; + case STR_TO_RE: + break; + case STR_IN_RE: + break; + case STR_TO_INT: + break; + case INT_TO_STR: + break; + case STR_FROM_CODE: + break; + case STR_TO_CODE: + break; + case STR_LT: + break; + case STR_LE: + break; + case RE_PLUS: + break; + case RE_STAR: + break; + case RE_OPTIONAL: + break; + case RE_CONCAT: + break; + case RE_UNION: + break; + case RE_RANGE: + break; + case RE_INTERSECT: + break; + case RE_COMPLEMENT: + break; + case RE_DIFFERENCE: + break; + case OTHER: + break; + */ + default: + throw new UnsupportedOperationException( + String.format( + "Operation not supported: %s, (%s)", + declaration.getKind(), declaration.getName())); + } + } throw new UnsupportedOperationException(); } @@ -130,15 +671,18 @@ public FormulaType getFormulaType(T formula) { @Override public BooleanFormula parse(String s) throws IllegalArgumentException { - return logger.logDef("mgr", String.format("parse(\"%s\")", s), () -> delegate.parse(s)); + logger.appendStmt(String.format("mgr.parse(\"%s\")", s)); + BooleanFormula f = delegate.parse(s); + logger.undoLast(); + return rebuild(f); } @Override public Appender dumpFormula(BooleanFormula pT) { - return logger.logDef( - "mgr", - String.format("dumpFormula(%s)", logger.toVariable(pT)), - () -> delegate.dumpFormula(pT)); + logger.appendStmt(String.format("mgr.dumpFormula(%s)", logger.toVariable(pT))); + Appender str = delegate.dumpFormula(pT); + logger.undoLast(); + return str; } @Override @@ -152,76 +696,24 @@ public T simplify(T input) throws InterruptedException { throw new UnsupportedOperationException(); } - private final class TraceVisitor implements FormulaVisitor { - private final FormulaVisitor delegateVisitor; - - private TraceVisitor(FormulaVisitor pDelegate) { - delegateVisitor = pDelegate; - } - - @Override - public T visitFreeVariable(Formula f, String name) { - return delegateVisitor.visitFreeVariable(f, name); - } - - @Override - public T visitConstant(Formula f, Object value) { - return delegateVisitor.visitConstant(f, value); - } - - @SuppressWarnings("unused") - @Override - public T visitFunction( - Formula f, List args, FunctionDeclaration functionDeclaration) { - for (int i = 0; i <= args.size(); i++) { - var value = i == 0 ? functionDeclaration : args.get(i - 1); - var unused = - logger.logDef( - "mgr", - String.format("visit(%s, new ExtractingVisitor(%s))", logger.toVariable(f), i), - () -> value); - } - return delegateVisitor.visitFunction(f, args, functionDeclaration); - } - - @SuppressWarnings("unused") - @Override - public T visitQuantifier( - BooleanFormula f, - Quantifier quantifier, - List boundVariables, - BooleanFormula body) { - for (int i = 0; i <= boundVariables.size(); i++) { - var value = i == boundVariables.size() ? body : boundVariables.get(i - 1); - var unused = - logger.logDef( - "mgr", - String.format("visit(%s, new ExtractingVisitor(%s))", logger.toVariable(f), i), - () -> value); - } - return delegateVisitor.visitQuantifier(f, quantifier, boundVariables, body); - } - } - @Override public R visit(Formula f, FormulaVisitor rFormulaVisitor) { - return delegate.visit(f, new TraceVisitor<>(rFormulaVisitor)); + return delegate.visit(f, rFormulaVisitor); } @Override public void visitRecursively(Formula f, FormulaVisitor rFormulaVisitor) { - delegate.visitRecursively(f, new TraceVisitor<>(rFormulaVisitor)); + delegate.visitRecursively(f, rFormulaVisitor); } @Override public T transformRecursively( T f, FormulaTransformationVisitor pFormulaVisitor) { - throw new UnsupportedOperationException(); + return delegate.transformRecursively(f, pFormulaVisitor); } @Override public ImmutableMap extractVariables(Formula f) { - // FIXME Add proper tracing return delegate.extractVariables(f); } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index c60317ca6d..39d9e85c2d 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -11,11 +11,9 @@ package org.sosy_lab.java_smt.delegate.trace; import com.google.common.base.Preconditions; -import java.io.BufferedWriter; import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; +import java.io.RandomAccessFile; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; @@ -26,22 +24,26 @@ import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType; class TraceLogger { + private final TraceFormulaManager mgr; private long id = 0; private final Map valueMap = new HashMap<>(); - private final BufferedWriter output; + private final RandomAccessFile output; - TraceLogger(String pFile) { + private long backtrackPoint = -1; + + TraceLogger(TraceFormulaManager pMgr, String pFile) { + mgr = pMgr; // FIXME Check if the file already exists try { - output = Files.newBufferedWriter(Path.of(pFile), Charset.defaultCharset()); + output = new RandomAccessFile(pFile, "rw"); } catch (IOException e) { throw new IllegalArgumentException(e); } } /** Returns a fresh variable. */ - private String newVariable() { + public String newVariable() { return "var" + id++; } @@ -50,10 +52,15 @@ private String newVariable() { * *

Use {@link #toVariable(Object)} to get the variable name for a tracked object */ - private void mapVariable(String pVar, Object f) { + public void mapVariable(String pVar, Object f) { valueMap.putIfAbsent(f, pVar); } + /** Returns true if the object is tracked. */ + public boolean isTracked(Object f) { + return valueMap.containsKey(f); + } + /** * Returns the variable name of a tracked object. * @@ -61,15 +68,15 @@ private void mapVariable(String pVar, Object f) { */ public String toVariable(Object f) { String r = valueMap.get(f); - Preconditions.checkArgument(r != null, "Object not tracked"); + Preconditions.checkArgument(r != null, "Object not tracked: %s", f); return r; } /** Add a definition to the log. */ public void appendDef(String pVar, String pExpr) { try { - output.append(String.format("var %s = %s;%n", pVar, pExpr)); - output.flush(); + backtrackPoint = output.length(); + output.write(String.format("var %s = %s;%n", pVar, pExpr).getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { throw new RuntimeException(e); } @@ -78,22 +85,69 @@ public void appendDef(String pVar, String pExpr) { /** Add a statement to the log. */ public void appendStmt(String pStmt) { try { - output.append(String.format("%s;%n", pStmt)); - output.flush(); + backtrackPoint = output.length(); + output.write(String.format("%s;%n", pStmt).getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { throw new RuntimeException(e); } } + public void undoLast() { + Preconditions.checkArgument(backtrackPoint >= 0, "Cannot undo last trace"); + try { + output.setLength(backtrackPoint); + } catch (IOException pE) { + throw new RuntimeException(pE); + } + backtrackPoint = -1; + } + /** Log an API call with return value. */ - public R logDef(String prefix, String method, Callable closure) { + public R logDef(String prefix, String method, Callable closure) { + String var = newVariable(); + try { + appendDef(var, prefix + "." + method); + R f = closure.call(); + if (!isTracked(f)) { + mapVariable(var, f); + return f; + } else { + undoLast(); + return mgr.rebuild(f); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Variant of {@link #logDef(String, String, Callable)} that will always keep the call in the log. + * + *

Use this version if the called function has side effects + */ + public R logDefKeep(String prefix, String method, Callable closure) { String var = newVariable(); try { appendDef(var, prefix + "." + method); R f = closure.call(); mapVariable(var, f); return f; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + /** + * Variant of {@link #logDef(String, String, Callable)} that will always remove the call from the + * log after it returned successfully. + */ + public R logDefDiscard(String prefix, String method, Callable closure) { + String var = newVariable(); + try { + appendDef(var, prefix + "." + method); + R f = closure.call(); + undoLast(); + return f; } catch (Exception e) { throw new RuntimeException(e); } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java index 6b6cc1e123..e884b1a0a3 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java @@ -38,7 +38,7 @@ public class TraceModel implements Model { public ImmutableList asList() { // FIXME We need to introduce local variables for all terms in the model so that they can be // referenced later - return logger.logDef(logger.toVariable(this), "asList()", delegate::asList); + return logger.logDefKeep(logger.toVariable(this), "asList()", delegate::asList); } @Override @@ -51,7 +51,7 @@ public ImmutableList asList() { @Override public @Nullable Object evaluate(Formula formula) { - return logger.logDef( + return logger.logDefKeep( logger.toVariable(this), String.format("evaluate(%s)", logger.toVariable(formula)), () -> delegate.evaluate(formula)); @@ -59,7 +59,7 @@ public ImmutableList asList() { @Override public @Nullable BigInteger evaluate(IntegerFormula formula) { - return logger.logDef( + return logger.logDefKeep( logger.toVariable(this), String.format("evaluate(%s)", logger.toVariable(formula)), () -> delegate.evaluate(formula)); @@ -67,7 +67,7 @@ public ImmutableList asList() { @Override public @Nullable Rational evaluate(RationalFormula formula) { - return logger.logDef( + return logger.logDefKeep( logger.toVariable(this), String.format("evaluate(%s)", logger.toVariable(formula)), () -> delegate.evaluate(formula)); @@ -75,7 +75,7 @@ public ImmutableList asList() { @Override public @Nullable Boolean evaluate(BooleanFormula formula) { - return logger.logDef( + return logger.logDefKeep( logger.toVariable(this), String.format("evaluate(%s)", logger.toVariable(formula)), () -> delegate.evaluate(formula)); @@ -83,7 +83,7 @@ public ImmutableList asList() { @Override public @Nullable BigInteger evaluate(BitvectorFormula formula) { - return logger.logDef( + return logger.logDefKeep( logger.toVariable(this), String.format("evaluate(%s)", logger.toVariable(formula)), () -> delegate.evaluate(formula)); @@ -91,7 +91,7 @@ public ImmutableList asList() { @Override public @Nullable String evaluate(StringFormula formula) { - return logger.logDef( + return logger.logDefKeep( logger.toVariable(this), String.format("evaluate(%s)", logger.toVariable(formula)), () -> delegate.evaluate(formula)); @@ -99,7 +99,7 @@ public ImmutableList asList() { @Override public @Nullable String evaluate(EnumerationFormula formula) { - return logger.logDef( + return logger.logDefKeep( logger.toVariable(this), String.format("evaluate(%s)", logger.toVariable(formula)), () -> delegate.evaluate(formula)); @@ -107,7 +107,7 @@ public ImmutableList asList() { @Override public @Nullable FloatingPointNumber evaluate(FloatingPointFormula formula) { - return logger.logDef( + return logger.logDefKeep( logger.toVariable(this), String.format("evaluate(%s)", logger.toVariable(formula)), () -> delegate.evaluate(formula)); diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index 858ac04ee7..3524b6c0c2 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -27,13 +27,16 @@ public class TraceSolverContext implements SolverContext { private final SolverContext delegate; private final TraceLogger logger; + private final TraceFormulaManager mgr; public TraceSolverContext(Solvers pSolver, Configuration config, SolverContext pDelegate) { delegate = pDelegate; // FIXME Move the files to the output folder? + mgr = new TraceFormulaManager(delegate.getFormulaManager()); logger = new TraceLogger( - "trace" + Integer.toUnsignedString(System.identityHashCode(this)) + ".java"); + mgr, "trace" + Integer.toUnsignedString(System.identityHashCode(this)) + ".java"); + mgr.setLogger(logger); // Get relevant options from the configuration String props = config.asPropertiesString(); @@ -70,13 +73,13 @@ public TraceSolverContext(Solvers pSolver, Configuration config, SolverContext p @Override public FormulaManager getFormulaManager() { - return new TraceFormulaManager(delegate.getFormulaManager(), logger); + return mgr; } @SuppressWarnings("resource") @Override public ProverEnvironment newProverEnvironment(ProverOptions... options) { - return logger.logDef( + return logger.logDefKeep( "context", String.format( "newProverEnvironment(%s)", diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java index a01af0a494..fd76ac16c4 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java @@ -31,14 +31,21 @@ public class TraceUFManager implements UFManager { @Override public FunctionDeclaration declareUF( String name, FormulaType returnType, List> args) { - return logger.logDef( - "mgr.getUFManager()", + String var = logger.newVariable(); + logger.appendDef( + var, String.format( - "declareUF(\"%s\", %s, ImmutableList.of(%s))", + "mgr.getUFManager().declareUF(\"%s\", %s, ImmutableList.of(%s))", name, logger.printFormulaType(returnType), - FluentIterable.from(args).transform(logger::printFormulaType).join(Joiner.on(", "))), - () -> delegate.declareUF(name, returnType, args)); + FluentIterable.from(args).transform(logger::printFormulaType).join(Joiner.on(", ")))); + FunctionDeclaration f = delegate.declareUF(name, returnType, args); + if (logger.isTracked(f)) { + logger.undoLast(); + } else { + logger.mapVariable(var, f); + } + return f; } @Override @@ -50,13 +57,20 @@ public FunctionDeclaration declareUF( @Override public T callUF( FunctionDeclaration funcType, List args) { - return logger.logDef( - "mgr.getUFManager()", + String var = logger.newVariable(); + logger.appendDef( + var, String.format( "callUF(%s, ImmutableList.of(%s))", logger.toVariable(funcType), - FluentIterable.from(args).transform(logger::toVariable).join(Joiner.on(", "))), - () -> delegate.callUF(funcType, args)); + FluentIterable.from(args).transform(logger::toVariable).join(Joiner.on(", ")))); + T f = delegate.callUF(funcType, args); + if (logger.isTracked(f)) { + logger.undoLast(); + } else { + logger.mapVariable(var, f); + } + return f; } @Override From 3df3d88297beeefe61f9ac76c890bd811fe2b0e2 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 16:06:57 +0200 Subject: [PATCH 30/89] Trace: Add support for array constants --- .../delegate/trace/TraceArrayFormulaManager.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java index d641eea34f..666320e1b2 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java @@ -68,7 +68,14 @@ ArrayFormula makeArray(String pName, FTI pIndexType, FTE pElementType) { FTI extends FormulaType, FTE extends FormulaType> ArrayFormula makeArray(FTI pIndexType, FTE pElementType, TE defaultElement) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getArrayFormulaManager()", + String.format( + "makeArray(\"%s\", %s, %s)", + logger.printFormulaType(pIndexType), + logger.printFormulaType(pElementType), + logger.toVariable(defaultElement)), + () -> delegate.makeArray(pIndexType, pElementType, defaultElement)); } @Override From 6ad67ab9a1683cd4e6262cc31f344f7f6ca579ea Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 16:14:26 +0200 Subject: [PATCH 31/89] Trace: Avoid catching runtime exceptions while logging --- src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index 39d9e85c2d..d2db0dcdb3 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -11,6 +11,7 @@ package org.sosy_lab.java_smt.delegate.trace; import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.charset.StandardCharsets; @@ -116,6 +117,7 @@ public R logDef(String prefix, String method, Callable cl return mgr.rebuild(f); } } catch (Exception e) { + Throwables.throwIfUnchecked(e); throw new RuntimeException(e); } } @@ -133,6 +135,7 @@ public R logDefKeep(String prefix, String method, Callable closure) { mapVariable(var, f); return f; } catch (Exception e) { + Throwables.throwIfUnchecked(e); throw new RuntimeException(e); } } @@ -149,6 +152,7 @@ public R logDefDiscard(String prefix, String method, Callable closure) { undoLast(); return f; } catch (Exception e) { + Throwables.throwIfUnchecked(e); throw new RuntimeException(e); } } @@ -164,6 +168,7 @@ public void logStmt(String prefix, String method, CheckedRunnable closure) { appendStmt(prefix + "." + method); closure.run(); } catch (Exception e) { + Throwables.throwIfUnchecked(e); throw new RuntimeException(e); } } From ab245e7980246b456f373ff5f003d7dc179ad8a2 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 16:25:15 +0200 Subject: [PATCH 32/89] Trace: Add support for BooleanFormulaManager.xor --- .../java_smt/delegate/trace/TraceBooleanFormulaManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java index 3a8179a0c6..62734b7ac7 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java @@ -156,7 +156,10 @@ public BooleanFormula or(BooleanFormula... bits) { @Override public BooleanFormula xor(BooleanFormula bits1, BooleanFormula bits2) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format("xor(%s, %s)", logger.toVariable(bits1), logger.toVariable(bits2)), + () -> delegate.xor(bits1, bits2)); } @Override From f5f8f0f1ca11552c8327325cc3fd6f7f107b1725 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 16:25:40 +0200 Subject: [PATCH 33/89] Trace: Add support for BooleanFormulaManager.extractVariablesAndUFs --- .../sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index bf8152a7aa..22bbf3e5a4 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -719,7 +719,7 @@ public ImmutableMap extractVariables(Formula f) { @Override public ImmutableMap extractVariablesAndUFs(Formula f) { - throw new UnsupportedOperationException(); + return delegate.extractVariablesAndUFs(f); } @Override From 018dbb8194deb975a06af05d580ca9dd99fb0c2f Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 16:26:10 +0200 Subject: [PATCH 34/89] Trace: Add support for creating integer constants from Strings --- .../java_smt/delegate/trace/TraceIntegerFormulaManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java index 338132499b..2c32ed34d7 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java @@ -81,7 +81,7 @@ public IntegerFormula makeNumber(BigDecimal number) { @Override public IntegerFormula makeNumber(String pI) { - throw new UnsupportedOperationException(); + return makeNumber(new BigInteger(pI)); } @Override From 01871aca7837d0ad66782e70883c67b6abfae3ef Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 16:49:31 +0200 Subject: [PATCH 35/89] Trace: Add some missing logging for methods in TraceFormulaManager --- .../delegate/trace/TraceFormulaManager.java | 43 ++++++++++++++++--- .../java_smt/delegate/trace/TraceLogger.java | 15 +++++++ 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 22bbf3e5a4..379a5f95a7 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -665,8 +665,10 @@ public T makeApplication( @Override public FormulaType getFormulaType(T formula) { - // FIXME Add proper tracing - return delegate.getFormulaType(formula); + return logger.logDefDiscard( + "mgr", + String.format("getFormulaType(%s)", logger.toVariable(formula)), + () -> delegate.getFormulaType(formula)); } @Override @@ -698,28 +700,55 @@ public T simplify(T input) throws InterruptedException { @Override public R visit(Formula f, FormulaVisitor rFormulaVisitor) { - return delegate.visit(f, rFormulaVisitor); + return logger.logDefDiscard( + "mgr", + String.format( + "visit(%s, new DefaultFormulaVisitor<>() {" + + "protected Formula visitDefault(Formula f) {" + + "return f;" + + "}})", + logger.toVariable(f)), + () -> delegate.visit(f, rFormulaVisitor)); } @Override public void visitRecursively(Formula f, FormulaVisitor rFormulaVisitor) { - delegate.visitRecursively(f, rFormulaVisitor); + logger.logStmtDiscard( + "mgr", + String.format( + "visitRecursively(%s, new DefaultFormulaVisitor<>() {" + + "protected TraversalProcess visitDefault(Formula f) {" + + "return TraversalProcess.CONTINUE;" + + "}})", + logger.toVariable(f)), + () -> delegate.visitRecursively(f, rFormulaVisitor)); } @Override public T transformRecursively( T f, FormulaTransformationVisitor pFormulaVisitor) { - return delegate.transformRecursively(f, pFormulaVisitor); + return logger.logDefDiscard( + "mgr", + String.format( + "transformRecursively(%s, new FormulaTransformationVisitor(%s) {})", + logger.toVariable(f), "mgr"), + () -> delegate.transformRecursively(f, pFormulaVisitor)); } @Override public ImmutableMap extractVariables(Formula f) { - return delegate.extractVariables(f); + return logger.logDefDiscard( + "mgr", + String.format("extractVariables(%s)", logger.toVariable(f)), + () -> delegate.extractVariables(f)); } @Override public ImmutableMap extractVariablesAndUFs(Formula f) { - return delegate.extractVariablesAndUFs(f); + return logger.logDefDiscard( + "mgr", + String.format("extractVariablesAndUFs(%s)", logger.toVariable(f)), + () -> delegate.extractVariablesAndUFs(f)); } @Override diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index d2db0dcdb3..ab7f7e48b0 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -173,6 +173,21 @@ public void logStmt(String prefix, String method, CheckedRunnable closure) { } } + /** + * Variant of {@link #logStmt(String, String, CheckedRunnable)} that will remove the call from the + * log after it returned successfully. + */ + public void logStmtDiscard(String prefix, String method, CheckedRunnable closure) { + try { + appendStmt(prefix + "." + method); + closure.run(); + undoLast(); + } catch (Exception e) { + Throwables.throwIfUnchecked(e); + throw new RuntimeException(e); + } + } + /** * Takes a {@link org.sosy_lab.java_smt.api.FormulaType} and returns a Java expression to * construct this type. From bfc4a760525c6e666abec6ec6d6bac5b2db07d62 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 17:01:33 +0200 Subject: [PATCH 36/89] Trace: Make constructor for TraceFloatingPointFormulaManager package-private --- .../delegate/trace/TraceFloatingPointFormulaManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java index 4d4746caff..1e2cc67695 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java @@ -27,8 +27,7 @@ public class TraceFloatingPointFormulaManager implements FloatingPointFormulaMan private final FloatingPointFormulaManager delegate; private final TraceLogger logger; - public TraceFloatingPointFormulaManager( - FloatingPointFormulaManager pDelegate, TraceLogger pLogger) { + TraceFloatingPointFormulaManager(FloatingPointFormulaManager pDelegate, TraceLogger pLogger) { delegate = pDelegate; logger = pLogger; } From adb0cbc2049337f382df9a95f5a3508faadccd16 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 17:01:58 +0200 Subject: [PATCH 37/89] Trace: Add support for creating FloatingPointFormulas from BigDecimals --- .../delegate/trace/TraceFloatingPointFormulaManager.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java index 1e2cc67695..d2a003a11a 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java @@ -60,7 +60,12 @@ public FloatingPointFormula makeNumber(BigDecimal n, FloatingPointType type) { @Override public FloatingPointFormula makeNumber( BigDecimal n, FloatingPointType type, FloatingPointRoundingMode pFloatingPointRoundingMode) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "makeNumber(new BigDecimal(\"%s\"), %s, %s)", + n, logger.printFormulaType(type), printRoundingMode(pFloatingPointRoundingMode)), + () -> delegate.makeNumber(n, type, pFloatingPointRoundingMode)); } @Override From 73f67971fddc88d379ee2cfc391d894af4f428b9 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 17:02:19 +0200 Subject: [PATCH 38/89] Trace: Fix default rounding mode for BigDecimals --- .../delegate/trace/TraceFloatingPointFormulaManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java index d2a003a11a..8a82039fc1 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java @@ -54,7 +54,7 @@ public FloatingPointFormula makeNumber( @Override public FloatingPointFormula makeNumber(BigDecimal n, FloatingPointType type) { - return makeNumber(n, type, FloatingPointRoundingMode.NEAREST_TIES_AWAY); + return makeNumber(n, type, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); } @Override From 69f637eb16f78170c571227eddfa42b09a8fdbc7 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 17:04:55 +0200 Subject: [PATCH 39/89] Trace: Add support for equality on array formulas --- .../sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 379a5f95a7..5f711bb768 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -316,6 +316,10 @@ public T makeApplication( return (T) getBitvectorFormulaManager() .equal((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + } else if (declaration.getArgumentTypes().get(1).isArrayType()) { + return (T) + getArrayFormulaManager() + .equivalence((ArrayFormula) args.get(0), (ArrayFormula) args.get(1)); } else { throw new UnsupportedOperationException( String.format( From 9208bb362ecb4aa31a613c3af73dbd94e5fd6c7c Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 17:15:33 +0200 Subject: [PATCH 40/89] Trace: Add support for boolean formula visitors --- .../trace/TraceBooleanFormulaManager.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java index 62734b7ac7..6540552a06 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java @@ -164,19 +164,40 @@ public BooleanFormula xor(BooleanFormula bits1, BooleanFormula bits2) { @Override public R visit(BooleanFormula pFormula, BooleanFormulaVisitor visitor) { - throw new UnsupportedOperationException(); + return logger.logDefDiscard( + "mgr", + String.format( + "visit(%s, new DefaultBooleanFormulaVisitor<>() {" + + "protected Formula visitDefault(Formula f) {" + + "return %s;" + + "}})", + logger.toVariable(pFormula), logger.toVariable(pFormula)), + () -> delegate.visit(pFormula, visitor)); } @Override public void visitRecursively( BooleanFormula f, BooleanFormulaVisitor rFormulaVisitor) { - throw new UnsupportedOperationException(); + logger.logStmtDiscard( + "mgr", + String.format( + "visitRecursively(%s, new DefaultBooleanFormulaVisitor<>() {" + + "protected TraversalProcess visitDefault(Formula f) {" + + "return TraversalProcess.CONTINUE;" + + "}})", + logger.toVariable(f)), + () -> delegate.visitRecursively(f, rFormulaVisitor)); } @Override public BooleanFormula transformRecursively( BooleanFormula f, BooleanFormulaTransformationVisitor pVisitor) { - throw new UnsupportedOperationException(); + return logger.logDefDiscard( + "mgr", + String.format( + "transformRecursively(%s, new BooleanFormulaTransformationVisitor(%s) {})", + logger.toVariable(f), "mgr"), + () -> delegate.transformRecursively(f, pVisitor)); } @Override From 9065812048112e53ea50efd6fa7c7b95d634a833 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 17:17:47 +0200 Subject: [PATCH 41/89] Trace: Add FormulaManager.simplify --- .../java_smt/delegate/trace/TraceFormulaManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 5f711bb768..2c461d5bf9 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -699,7 +699,10 @@ public BooleanFormula applyTactic(BooleanFormula input, Tactic tactic) @Override public T simplify(T input) throws InterruptedException { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr", + String.format("simplify(%s)", logger.toVariable(input)), + () -> delegate.simplify(input)); } @Override From 2c2ca359af116ebbdc5a305c05e7f0cede9a55d4 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 17:27:35 +0200 Subject: [PATCH 42/89] Trace: Add UFManager.declareAndCallUF --- .../delegate/trace/TraceFormulaManager.java | 2 +- .../java_smt/delegate/trace/TraceUFManager.java | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 2c461d5bf9..406b0b67ca 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -93,7 +93,7 @@ public FloatingPointFormulaManager getFloatingPointFormulaManager() { @Override public UFManager getUFManager() { - return new TraceUFManager(delegate.getUFManager(), logger); + return new TraceUFManager(delegate.getUFManager(), this, logger); } @Override diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java index fd76ac16c4..b0bd5e0bdf 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java @@ -12,19 +12,24 @@ import com.google.common.base.Joiner; import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableList; import java.util.Arrays; import java.util.List; import org.sosy_lab.java_smt.api.Formula; +import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.FormulaType; import org.sosy_lab.java_smt.api.FunctionDeclaration; import org.sosy_lab.java_smt.api.UFManager; public class TraceUFManager implements UFManager { private final UFManager delegate; + + private final FormulaManager mgr; private final TraceLogger logger; - TraceUFManager(UFManager pDelegate, TraceLogger pLogger) { + TraceUFManager(UFManager pDelegate, FormulaManager pMgr, TraceLogger pLogger) { delegate = pDelegate; + mgr = pMgr; logger = pLogger; } @@ -81,12 +86,16 @@ public T callUF(FunctionDeclaration funcType, Formula... @Override public T declareAndCallUF( String name, FormulaType pReturnType, List pArgs) { - throw new UnsupportedOperationException(); + ImmutableList.Builder> builder = ImmutableList.builder(); + for (Formula f : pArgs) { + builder.add(mgr.getFormulaType(f)); + } + return callUF(declareUF(name, pReturnType, builder.build()), pArgs); } @Override public T declareAndCallUF( String name, FormulaType pReturnType, Formula... pArgs) { - throw new UnsupportedOperationException(); + return declareAndCallUF(name, pReturnType, Arrays.asList(pArgs)); } } From 47e937683a540df52ffa68c0e77b6bbed8f0b5a7 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 17:35:42 +0200 Subject: [PATCH 43/89] Trace: Add modulo, distinct and sum from IntegerFormulaManager --- .../trace/TraceIntegerFormulaManager.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java index 2c32ed34d7..119181dd26 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java @@ -10,6 +10,8 @@ package org.sosy_lab.java_smt.delegate.trace; +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; import java.math.BigDecimal; import java.math.BigInteger; import java.util.List; @@ -50,7 +52,11 @@ public BooleanFormula modularCongruence(IntegerFormula number1, IntegerFormula n @Override public IntegerFormula modulo(IntegerFormula numerator, IntegerFormula denominator) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "modulo(%s, %s)", logger.toVariable(numerator), logger.toVariable(denominator)), + () -> delegate.modulo(numerator, denominator)); } @Override @@ -115,7 +121,12 @@ public IntegerFormula add(IntegerFormula number1, IntegerFormula number2) { @Override public IntegerFormula sum(List operands) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "sum(%s)", + FluentIterable.from(operands).transform(logger::toVariable).join(Joiner.on(", "))), + () -> delegate.sum(operands)); } @Override @@ -153,7 +164,12 @@ public BooleanFormula equal(IntegerFormula number1, IntegerFormula number2) { @Override public BooleanFormula distinct(List pNumbers) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "distinct(%s)", + FluentIterable.from(pNumbers).transform(logger::toVariable).join(Joiner.on(", "))), + () -> delegate.distinct(pNumbers)); } @Override From ac6486dee7c67dfbfd2c462310340194c6200762 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 17:58:47 +0200 Subject: [PATCH 44/89] Trace: Add FormulaManager.substitute --- .../delegate/trace/TraceFormulaManager.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 406b0b67ca..c67ffe12af 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -10,7 +10,9 @@ package org.sosy_lab.java_smt.delegate.trace; +import com.google.common.base.Joiner; import com.google.common.base.Preconditions; +import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.math.BigInteger; @@ -761,7 +763,19 @@ public ImmutableMap extractVariablesAndUFs(Formula f) { @Override public T substitute( T f, Map fromToMapping) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr", + String.format( + "substitute(%s, ImmutableMap.ofEntries(%s))", + logger.toVariable(f), + FluentIterable.from(fromToMapping.entrySet()) + .transform( + entry -> + String.format( + "Map.entry(%s, %s)", + logger.toVariable(entry.getKey()), logger.toVariable(entry.getValue()))) + .join(Joiner.on(", "))), + () -> delegate.substitute(f, fromToMapping)); } @Override From 01cc106fd963222d24dea6be90bdb34238797535 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 18:03:45 +0200 Subject: [PATCH 45/89] Trace: Add ProverEnvironment.isUnsatWithAssumptions --- .../delegate/trace/TraceBasicProverEnvironment.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java index fe202cc466..d046908a3e 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java @@ -10,6 +10,8 @@ package org.sosy_lab.java_smt.delegate.trace; +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -59,7 +61,12 @@ public boolean isUnsat() throws SolverException, InterruptedException { @Override public boolean isUnsatWithAssumptions(Collection assumptions) throws SolverException, InterruptedException { - throw new UnsupportedOperationException(); + return logger.logDefKeep( + logger.toVariable(this), + String.format( + "isUnsatWithAssumptions" + "(ImmutableList.of(%s))", + FluentIterable.from(assumptions).transform(logger::toVariable).join(Joiner.on(", "))), + () -> delegate.isUnsatWithAssumptions(assumptions)); } @SuppressWarnings("resource") From ff2faf23c2a7038d8caf08fd64815a5a502b4760 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 18:10:22 +0200 Subject: [PATCH 46/89] Trace: Add FormulaManager.applyTactic --- .../java_smt/delegate/trace/TraceFormulaManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index c67ffe12af..951d25b8b4 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -696,7 +696,10 @@ public Appender dumpFormula(BooleanFormula pT) { @Override public BooleanFormula applyTactic(BooleanFormula input, Tactic tactic) throws InterruptedException, SolverException { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr", + String.format("applyTactic(%s, %s)", logger.toVariable(input), "Tactic" + tactic.name()), + () -> delegate.applyTactic(input, tactic)); } @Override From cb53d5966d7a368bf1393ae9c084cf01e8ada651 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 18:14:19 +0200 Subject: [PATCH 47/89] Trace: Add isValidName, escape and unescape from FormulaManager --- .../java_smt/delegate/trace/TraceFormulaManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 951d25b8b4..a74a83aa41 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -789,16 +789,16 @@ public BooleanFormula translateFrom(BooleanFormula formula, FormulaManager other @Override public boolean isValidName(String variableName) { - throw new UnsupportedOperationException(); + return delegate.isValidName(variableName); } @Override public String escape(String variableName) { - throw new UnsupportedOperationException(); + return delegate.escape(variableName); } @Override public String unescape(String variableName) { - throw new UnsupportedOperationException(); + return delegate.unescape(variableName); } } From 22d532cf8b2dee0b4ae03b9da58109b574c42edf Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 18:20:46 +0200 Subject: [PATCH 48/89] Trace: Avoid using String.split --- .../java_smt/delegate/trace/TraceFormulaManager.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index a74a83aa41..eabea24175 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -12,6 +12,7 @@ import com.google.common.base.Joiner; import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -341,13 +342,13 @@ public T makeApplication( */ case BV_EXTRACT: { - String[] tokens = declaration.getName().split("_"); + List tokens = Splitter.on('_').splitToList(declaration.getName()); return (T) getBitvectorFormulaManager() .extract( (BitvectorFormula) args.get(0), - Integer.parseInt(tokens[1]), - Integer.parseInt(tokens[2])); + Integer.parseInt(tokens.get(1)), + Integer.parseInt(tokens.get(2))); } case BV_CONCAT: return (T) From f30f6944c35ef548f81a445ff43dd9d57d9dda39 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 18:39:27 +0200 Subject: [PATCH 49/89] Trace: Add toConjunctionArgs and toDisjunctionArgs from BooleanFormulaManager --- .../trace/TraceBooleanFormulaManager.java | 19 ++++++++++++++++--- .../delegate/trace/TraceFormulaManager.java | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java index 6540552a06..336620e767 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java @@ -10,6 +10,7 @@ package org.sosy_lab.java_smt.delegate.trace; +import com.google.common.collect.FluentIterable; import java.util.Arrays; import java.util.Collection; import java.util.Set; @@ -23,10 +24,14 @@ public class TraceBooleanFormulaManager implements BooleanFormulaManager { private final BooleanFormulaManager delegate; + + private final TraceFormulaManager mgr; private final TraceLogger logger; - TraceBooleanFormulaManager(BooleanFormulaManager pDelegate, TraceLogger pLogger) { + TraceBooleanFormulaManager( + BooleanFormulaManager pDelegate, TraceFormulaManager pMgr, TraceLogger pLogger) { delegate = pDelegate; + mgr = pMgr; logger = pLogger; } @@ -202,11 +207,19 @@ public BooleanFormula transformRecursively( @Override public Set toConjunctionArgs(BooleanFormula f, boolean flatten) { - throw new UnsupportedOperationException(); + logger.appendStmt( + String.format("mgr.toConjunctionArgs(%s, %s)", logger.toVariable(f), flatten)); + Set set = delegate.toConjunctionArgs(f, flatten); + logger.undoLast(); + return FluentIterable.from(set).transform(mgr::rebuild).toSet(); } @Override public Set toDisjunctionArgs(BooleanFormula f, boolean flatten) { - throw new UnsupportedOperationException(); + logger.appendStmt( + String.format("mgr.toDisjunctionArgs(%s, %s)", logger.toVariable(f), flatten)); + Set set = delegate.toDisjunctionArgs(f, flatten); + logger.undoLast(); + return FluentIterable.from(set).transform(mgr::rebuild).toSet(); } } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index eabea24175..56a4929728 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -76,7 +76,7 @@ public RationalFormulaManager getRationalFormulaManager() { @Override public BooleanFormulaManager getBooleanFormulaManager() { - return new TraceBooleanFormulaManager(delegate.getBooleanFormulaManager(), logger); + return new TraceBooleanFormulaManager(delegate.getBooleanFormulaManager(), this, logger); } @Override From 0b36ff27af221f4d494baced9eb83c493108f8a8 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 18:39:43 +0200 Subject: [PATCH 50/89] Trace: Add toConjunction and toDisjunction --- .../java_smt/delegate/trace/TraceBooleanFormulaManager.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java index 336620e767..77d62414ef 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java @@ -15,6 +15,7 @@ import java.util.Collection; import java.util.Set; import java.util.stream.Collector; +import java.util.stream.Collectors; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.BooleanFormulaManager; import org.sosy_lab.java_smt.api.Formula; @@ -129,7 +130,7 @@ public BooleanFormula and(BooleanFormula... bits) { @Override public Collector toConjunction() { - throw new UnsupportedOperationException(); + return Collectors.collectingAndThen(Collectors.toList(), this::and); } @Override @@ -156,7 +157,7 @@ public BooleanFormula or(BooleanFormula... bits) { @Override public Collector toDisjunction() { - throw new UnsupportedOperationException(); + return Collectors.collectingAndThen(Collectors.toList(), this::or); } @Override From d57db88d57fac45053f6203c29282947dbb26c93 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 18:56:27 +0200 Subject: [PATCH 51/89] Trace: Extract terms from to model --- .../trace/TraceBasicProverEnvironment.java | 12 +++++++-- .../java_smt/delegate/trace/TraceModel.java | 27 ++++++++++++++++--- .../trace/TraceProverEnvironment.java | 7 +++-- .../delegate/trace/TraceSolverContext.java | 2 +- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java index d046908a3e..5fde85c0e2 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java @@ -23,10 +23,16 @@ public class TraceBasicProverEnvironment implements BasicProverEnvironment { private final BasicProverEnvironment delegate; + + private final TraceFormulaManager mgr; private final TraceLogger logger; - TraceBasicProverEnvironment(BasicProverEnvironment pDelegate, TraceLogger pLogger) { + TraceBasicProverEnvironment( + BasicProverEnvironment pDelegate, + TraceFormulaManager pFormulaManager, + TraceLogger pLogger) { delegate = pDelegate; + mgr = pFormulaManager; logger = pLogger; } @@ -73,7 +79,9 @@ public boolean isUnsatWithAssumptions(Collection assumptions) @Override public Model getModel() throws SolverException { return logger.logDefKeep( - logger.toVariable(this), "getModel()", () -> new TraceModel(delegate.getModel(), logger)); + logger.toVariable(this), + "getModel()", + () -> new TraceModel(delegate.getModel(), mgr, logger)); } @Override diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java index e884b1a0a3..7c188037b4 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java @@ -10,6 +10,7 @@ package org.sosy_lab.java_smt.delegate.trace; +import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import java.math.BigInteger; import org.checkerframework.checker.nullness.qual.Nullable; @@ -27,18 +28,36 @@ public class TraceModel implements Model { private final Model delegate; + + private final TraceFormulaManager mgr; private final TraceLogger logger; - TraceModel(Model pDelegate, TraceLogger pLogger) { + TraceModel(Model pDelegate, TraceFormulaManager pMgr, TraceLogger pLogger) { delegate = pDelegate; + mgr = pMgr; logger = pLogger; } @Override public ImmutableList asList() { - // FIXME We need to introduce local variables for all terms in the model so that they can be - // referenced later - return logger.logDefKeep(logger.toVariable(this), "asList()", delegate::asList); + logger.appendStmt(String.format("%s.asList()", logger.toVariable(this))); + ImmutableList result = delegate.asList(); + logger.undoLast(); + return FluentIterable.from(result) + .transform( + (ValueAssignment assigment) -> { + var key = mgr.rebuild(assigment.getKey()); + var val = mgr.rebuild(assigment.getValueAsFormula()); + var map = mgr.rebuild(assigment.getAssignmentAsFormula()); + return new ValueAssignment( + key, + val, + map, + assigment.getName(), + assigment.getValue(), + assigment.getArgumentsInterpretation()); + }) + .toList(); } @Override diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java index d8c1e79ef6..ec11ef5710 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceProverEnvironment.java @@ -15,7 +15,10 @@ public class TraceProverEnvironment extends TraceBasicProverEnvironment implements ProverEnvironment { - TraceProverEnvironment(BasicProverEnvironment pDelegate, TraceLogger pLogger) { - super(pDelegate, pLogger); + TraceProverEnvironment( + BasicProverEnvironment pDelegate, + TraceFormulaManager pFormulaManager, + TraceLogger pLogger) { + super(pDelegate, pFormulaManager, pLogger); } } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index 3524b6c0c2..0205f5d45d 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -86,7 +86,7 @@ public ProverEnvironment newProverEnvironment(ProverOptions... options) { FluentIterable.from(options) .transform(v -> "SolverContext" + ".ProverOptions." + v.name()) .join(Joiner.on(", "))), - () -> new TraceProverEnvironment(delegate.newProverEnvironment(options), logger)); + () -> new TraceProverEnvironment(delegate.newProverEnvironment(options), mgr, logger)); } @SuppressWarnings("resource") From 49cb3bdd2db4fda3686d32f65142d083babe256c Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 18:57:58 +0200 Subject: [PATCH 52/89] Trace: Always print the term kind if we encounter an unsupported term in the visitor --- .../delegate/trace/TraceFormulaManager.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 56a4929728..2482de7597 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -228,6 +228,7 @@ public T makeApplication( } else { // TODO Check that the number of arguments matches the arity of the operation // TODO Figure out how to handle rounding mode for floats + // FIXME Handle rational formulas switch (declaration.getKind()) { case AND: return (T) @@ -254,9 +255,11 @@ public T makeApplication( return (T) getBooleanFormulaManager() .implication((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + // TODO We only have 'distinct' for some theories + /* case DISTINCT: - // TODO We only have 'distinct' for some theories break; + */ case STORE: return (T) getArrayFormulaManager().store((ArrayFormula) args.get(0), args.get(1), args.get(2)); @@ -267,7 +270,6 @@ public T makeApplication( getArrayFormulaManager() .makeArray((ArrayFormulaType) declaration.getType(), args.get(0)); case UMINUS: - // FIXME Handle rational formulas return (T) getIntegerFormulaManager().negate((IntegerFormula) args.get(0)); case SUB: return (T) @@ -330,6 +332,7 @@ public T makeApplication( declaration.getArgumentTypes().get(0))); } } + // TODO /* case EQ_ZERO: break; @@ -354,12 +357,12 @@ public T makeApplication( return (T) getBitvectorFormulaManager() .concat((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); - case BV_SIGN_EXTENSION: - // TODO + // TODO + /*case BV_SIGN_EXTENSION: break; case BV_ZERO_EXTENSION: - // TODO break; + */ case BV_NOT: return (T) getBitvectorFormulaManager().not((BitvectorFormula) args.get(0)); case BV_NEG: @@ -471,12 +474,13 @@ public T makeApplication( return (T) getBitvectorFormulaManager() .rotateRight((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + // TODO + /* case BV_ROTATE_LEFT_BY_INT: - // TODO break; case BV_ROTATE_RIGHT_BY_INT: - // TODO break; + */ case BV_UCASTTO_FP: return (T) getFloatingPointFormulaManager() @@ -544,6 +548,8 @@ public T makeApplication( getFloatingPointFormulaManager() .equalWithFPSemantics( (FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + // TODO + /* case FP_ROUND_EVEN: break; case FP_ROUND_AWAY: @@ -554,6 +560,7 @@ public T makeApplication( break; case FP_ROUND_ZERO: break; + */ case FP_ROUND_TO_INTEGRAL: { var rm = (FloatingPointRoundingModeFormula) args.get(1); @@ -596,6 +603,7 @@ public T makeApplication( getFloatingPointFormulaManager() .fromIeeeBitvector( (BitvectorFormula) args.get(0), (FloatingPointType) declaration.getType()); + // TODO /* case STR_CONCAT: break; @@ -661,7 +669,6 @@ public T makeApplication( declaration.getKind(), declaration.getName())); } } - throw new UnsupportedOperationException(); } @Override From b2fda6ddc7226684d7cc416d251aa74ebf8bbae9 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 19:10:40 +0200 Subject: [PATCH 53/89] Trace: Store backtracking points for the logger on a stack --- .../java_smt/delegate/trace/TraceLogger.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index ab7f7e48b0..2f2f1a57be 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -17,6 +17,7 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; +import java.util.Stack; import java.util.concurrent.Callable; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.FormulaType; @@ -31,7 +32,7 @@ class TraceLogger { private final Map valueMap = new HashMap<>(); private final RandomAccessFile output; - private long backtrackPoint = -1; + private final Stack lastLines = new Stack<>(); TraceLogger(TraceFormulaManager pMgr, String pFile) { mgr = pMgr; @@ -76,7 +77,7 @@ public String toVariable(Object f) { /** Add a definition to the log. */ public void appendDef(String pVar, String pExpr) { try { - backtrackPoint = output.length(); + lastLines.push(output.length()); output.write(String.format("var %s = %s;%n", pVar, pExpr).getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { throw new RuntimeException(e); @@ -86,7 +87,7 @@ public void appendDef(String pVar, String pExpr) { /** Add a statement to the log. */ public void appendStmt(String pStmt) { try { - backtrackPoint = output.length(); + lastLines.push(output.length()); output.write(String.format("%s;%n", pStmt).getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { throw new RuntimeException(e); @@ -94,13 +95,12 @@ public void appendStmt(String pStmt) { } public void undoLast() { - Preconditions.checkArgument(backtrackPoint >= 0, "Cannot undo last trace"); + Preconditions.checkArgument(!lastLines.isEmpty(), "Cannot undo last trace"); try { - output.setLength(backtrackPoint); + output.setLength(lastLines.pop()); } catch (IOException pE) { throw new RuntimeException(pE); } - backtrackPoint = -1; } /** Log an API call with return value. */ From 3e3540eb573fde16aec826e08ac52575b4f3b5cb Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 19:20:57 +0200 Subject: [PATCH 54/89] Trace: Add support for unsat core --- .../trace/TraceBasicProverEnvironment.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java index 5fde85c0e2..396ca37337 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java @@ -86,13 +86,23 @@ public Model getModel() throws SolverException { @Override public List getUnsatCore() { - throw new UnsupportedOperationException(); + logger.appendStmt(String.format("%s.getUnsatCore()", logger.toVariable(this))); + List core = delegate.getUnsatCore(); + logger.undoLast(); + return FluentIterable.from(core).transform(mgr::rebuild).toList(); } @Override public Optional> unsatCoreOverAssumptions( Collection assumptions) throws SolverException, InterruptedException { - throw new UnsupportedOperationException(); + logger.appendStmt( + String.format( + "%s.getUnsatCoreOverAssumptions(ImmutableList.of(%s))", + logger.toVariable(this), + FluentIterable.from(assumptions).transform(logger::toVariable).join(Joiner.on(", ")))); + Optional> maybeCore = delegate.unsatCoreOverAssumptions(assumptions); + logger.undoLast(); + return maybeCore.map(core -> FluentIterable.from(core).transform(mgr::rebuild).toList()); } @Override From 959abe9e88766abe1fde6091e9f47aaddf87a8ca Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 19:48:01 +0200 Subject: [PATCH 55/89] Trace: Inline logger calls in addConstraint, isUnsat, isUnstaWithAssumptions and getModel to make sure we're not catching Solver/InterruptedExceptions --- .../trace/TraceBasicProverEnvironment.java | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java index 396ca37337..56d104fd50 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java @@ -43,10 +43,14 @@ public void pop() { @Override public @Nullable T addConstraint(BooleanFormula constraint) throws InterruptedException { - return logger.logDefKeep( - logger.toVariable(this), - String.format("addConstraint(%s)", logger.toVariable(constraint)), - () -> delegate.addConstraint(constraint)); + String var = logger.newVariable(); + logger.appendDef( + var, + String.format( + "%s.addConstraint(%s)", logger.toVariable(this), logger.toVariable(constraint))); + T f = delegate.addConstraint(constraint); + logger.mapVariable(var, f); + return f; } @Override @@ -61,27 +65,36 @@ public int size() { @Override public boolean isUnsat() throws SolverException, InterruptedException { - return logger.logDefKeep(logger.toVariable(this), "isUnsat()", delegate::isUnsat); + String var = logger.newVariable(); + logger.appendDef(var, String.format("%s.isUnsat()", logger.toVariable(this))); + boolean unsat = delegate.isUnsat(); + logger.mapVariable(var, unsat); + return unsat; } @Override public boolean isUnsatWithAssumptions(Collection assumptions) throws SolverException, InterruptedException { - return logger.logDefKeep( - logger.toVariable(this), + String var = logger.newVariable(); + logger.appendDef( + var, String.format( - "isUnsatWithAssumptions" + "(ImmutableList.of(%s))", - FluentIterable.from(assumptions).transform(logger::toVariable).join(Joiner.on(", "))), - () -> delegate.isUnsatWithAssumptions(assumptions)); + "%s.isUnsatWithAssumptions(ImmutableList.of(%s))", + logger.toVariable(this), + FluentIterable.from(assumptions).transform(logger::toVariable).join(Joiner.on(", ")))); + boolean unsat = delegate.isUnsatWithAssumptions(assumptions); + logger.mapVariable(var, unsat); + return unsat; } @SuppressWarnings("resource") @Override public Model getModel() throws SolverException { - return logger.logDefKeep( - logger.toVariable(this), - "getModel()", - () -> new TraceModel(delegate.getModel(), mgr, logger)); + String var = logger.newVariable(); + logger.appendDef(var, String.format("%s.getModel()", logger.toVariable(this))); + Model model = new TraceModel(delegate.getModel(), mgr, logger); + logger.mapVariable(var, model); + return model; } @Override From e7fae4efa665d67f7be1202777aea737ea20c1cc Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 22:47:14 +0200 Subject: [PATCH 56/89] Trace: Check operator arity in the visitor --- .../delegate/trace/TraceFormulaManager.java | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 2482de7597..bdeee3292d 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -215,6 +215,115 @@ public T makeVariable(FormulaType formulaType, String nam return f; } + private int getArity(FunctionDeclarationKind pKind) { + switch (pKind) { + case AND: + case OR: + case IFF: + case XOR: + case IMPLIES: + case DISTINCT: + case SUB: + case ADD: + case DIV: + case MUL: + case LT: + case LTE: + case GT: + case GTE: + case EQ: + case BV_CONCAT: + case BV_OR: + case BV_AND: + case BV_XOR: + case BV_SUB: + case BV_ADD: + case BV_MUL: + return -1; + + case FP_ROUND_EVEN: + case FP_ROUND_AWAY: + case FP_ROUND_POSITIVE: + case FP_ROUND_NEGATIVE: + case FP_ROUND_ZERO: + return 0; + + case NOT: + case UMINUS: + case EQ_ZERO: + case GTE_ZERO: + case FLOOR: + case TO_REAL: + case CONST: + case BV_EXTRACT: + case BV_SIGN_EXTENSION: + case BV_ZERO_EXTENSION: + case BV_NOT: + case BV_NEG: + case BV_ROTATE_LEFT_BY_INT: + case BV_ROTATE_RIGHT_BY_INT: + case FP_NEG: + case FP_ABS: + case FP_IS_NAN: + case FP_IS_INF: + case FP_IS_ZERO: + case FP_IS_NEGATIVE: + case FP_IS_SUBNORMAL: + case FP_IS_NORMAL: + case FP_AS_IEEEBV: + case FP_FROM_IEEEBV: + return 1; + + case SELECT: + case MODULO: + case BV_SDIV: + case BV_UDIV: + case BV_SREM: + case BV_UREM: + case BV_SMOD: + case BV_ULT: + case BV_SLT: + case BV_ULE: + case BV_SLE: + case BV_UGT: + case BV_SGT: + case BV_UGE: + case BV_SGE: + case BV_SHL: + case BV_LSHR: + case BV_ASHR: + case BV_ROTATE_LEFT: + case BV_ROTATE_RIGHT: + case BV_UCASTTO_FP: + case BV_SCASTTO_FP: + case FP_MAX: + case FP_MIN: + case FP_SQRT: + case FP_REM: + case FP_LT: + case FP_LE: + case FP_GE: + case FP_GT: + case FP_EQ: + case FP_ROUND_TO_INTEGRAL: + case FP_CASTTO_FP: + case FP_CASTTO_SBV: + case FP_CASTTO_UBV: + return 2; + + case ITE: + case STORE: + case FP_SUB: + case FP_ADD: + case FP_DIV: + case FP_MUL: + return 3; + + default: + throw new IllegalArgumentException(String.format("Unsupported kind: %s", pKind)); + } + } + @SuppressWarnings("unchecked") @Override public T makeApplication( @@ -229,6 +338,15 @@ public T makeApplication( // TODO Check that the number of arguments matches the arity of the operation // TODO Figure out how to handle rounding mode for floats // FIXME Handle rational formulas + Preconditions.checkArgument( + getArity(declaration.getKind()) == -1 + ? args.size() > 1 + : args.size() == getArity(declaration.getKind()), + "Term \"%s\" (%s): expecting %s arguments, but found %s", + declaration.getName(), + declaration.getKind(), + getArity(declaration.getKind()), + args.size()); switch (declaration.getKind()) { case AND: return (T) From feb9e8f064ec36950d402e72ed6e9f153c1f0f48 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 23:07:46 +0200 Subject: [PATCH 57/89] Trace: Add guards for binary operators that should really allow an arbitrary number of arguments --- .../delegate/trace/TraceFormulaManager.java | 186 ++++++++++++------ 1 file changed, 121 insertions(+), 65 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index bdeee3292d..30ce6e1571 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -335,9 +335,9 @@ public T makeApplication( declaration.getName(), declaration.getType(), declaration.getArgumentTypes()); return getUFManager().callUF(uf, args); } else { - // TODO Check that the number of arguments matches the arity of the operation + // TODO Handle operations with a variable number of arguments // TODO Figure out how to handle rounding mode for floats - // FIXME Handle rational formulas + // TODO Handle rational formulas Preconditions.checkArgument( getArity(declaration.getKind()) == -1 ? args.size() > 1 @@ -349,30 +349,36 @@ public T makeApplication( args.size()); switch (declaration.getKind()) { case AND: - return (T) - getBooleanFormulaManager() - .and((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + return (T) getBooleanFormulaManager().and((List) args); case NOT: return (T) getBooleanFormulaManager().not((BooleanFormula) args.get(0)); case OR: - return (T) - getBooleanFormulaManager() - .or((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + return (T) getBooleanFormulaManager().or((List) args); case IFF: - return (T) - getBooleanFormulaManager() - .equivalence((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getBooleanFormulaManager() + .equivalence((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + } case ITE: return getBooleanFormulaManager() .ifThenElse((BooleanFormula) args.get(0), (T) args.get(1), (T) args.get(2)); case XOR: - return (T) - getBooleanFormulaManager() - .xor((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + + return (T) + getBooleanFormulaManager() + .xor((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + } case IMPLIES: - return (T) - getBooleanFormulaManager() - .implication((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getBooleanFormulaManager() + .implication((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); + } // TODO We only have 'distinct' for some theories /* case DISTINCT: @@ -390,43 +396,69 @@ public T makeApplication( case UMINUS: return (T) getIntegerFormulaManager().negate((IntegerFormula) args.get(0)); case SUB: - return (T) - getIntegerFormulaManager() - .subtract((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getIntegerFormulaManager() + .subtract((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } case ADD: - return (T) - getIntegerFormulaManager() - .add((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getIntegerFormulaManager() + .add((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } case DIV: - return (T) - getIntegerFormulaManager() - .divide((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + + return (T) + getIntegerFormulaManager() + .divide((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } case MUL: - return (T) - getIntegerFormulaManager() - .multiply((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getIntegerFormulaManager() + .multiply((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } case MODULO: return (T) getIntegerFormulaManager() .modulo((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); case LT: - return (T) - getIntegerFormulaManager() - .lessThan((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getIntegerFormulaManager() + .lessThan((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } case LTE: - return (T) - getIntegerFormulaManager() - .lessOrEquals((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getIntegerFormulaManager() + .lessOrEquals((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } case GT: - return (T) - getIntegerFormulaManager() - .greaterThan((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getIntegerFormulaManager() + .greaterThan((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } case GTE: - return (T) - getIntegerFormulaManager() - .greaterOrEquals((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getIntegerFormulaManager() + .greaterOrEquals((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } case EQ: { + Preconditions.checkArgument(args.size() == 2); if (declaration.getArgumentTypes().get(0).isBooleanType()) { return (T) getBooleanFormulaManager() @@ -472,9 +504,12 @@ public T makeApplication( Integer.parseInt(tokens.get(2))); } case BV_CONCAT: - return (T) - getBitvectorFormulaManager() - .concat((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getBitvectorFormulaManager() + .concat((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + } // TODO /*case BV_SIGN_EXTENSION: break; @@ -486,25 +521,40 @@ public T makeApplication( case BV_NEG: return (T) getBitvectorFormulaManager().negate((BitvectorFormula) args.get(0)); case BV_OR: - return (T) - getBitvectorFormulaManager() - .or((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getBitvectorFormulaManager() + .or((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + } case BV_AND: - return (T) - getBitvectorFormulaManager() - .and((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getBitvectorFormulaManager() + .and((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + } case BV_XOR: - return (T) - getBitvectorFormulaManager() - .xor((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getBitvectorFormulaManager() + .xor((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + } case BV_SUB: - return (T) - getBitvectorFormulaManager() - .subtract((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getBitvectorFormulaManager() + .subtract((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + } case BV_ADD: - return (T) - getBitvectorFormulaManager() - .add((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getBitvectorFormulaManager() + .add((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + } case BV_SDIV: return (T) getBitvectorFormulaManager() @@ -526,9 +576,12 @@ public T makeApplication( getBitvectorFormulaManager() .smodulo((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); case BV_MUL: - return (T) - getBitvectorFormulaManager() - .multiply((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getBitvectorFormulaManager() + .multiply((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + } case BV_ULT: return (T) getBitvectorFormulaManager() @@ -568,9 +621,12 @@ public T makeApplication( .greaterOrEquals( (BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1), true); case BV_EQ: // FIXME Why is this a separate symbol? - return (T) - getBitvectorFormulaManager() - .equal((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + { + Preconditions.checkArgument(args.size() == 2); + return (T) + getBitvectorFormulaManager() + .equal((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); + } case BV_SHL: return (T) getBitvectorFormulaManager() From 3a56e85583ba327490a24614a2fded0dd31945b8 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 23:12:44 +0200 Subject: [PATCH 58/89] Trace: Add missing "." when printing the names of Tactics to the log --- .../sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 30ce6e1571..76aa2a239f 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -880,7 +880,7 @@ public BooleanFormula applyTactic(BooleanFormula input, Tactic tactic) throws InterruptedException, SolverException { return logger.logDef( "mgr", - String.format("applyTactic(%s, %s)", logger.toVariable(input), "Tactic" + tactic.name()), + String.format("applyTactic(%s, %s)", logger.toVariable(input), "Tactic." + tactic.name()), () -> delegate.applyTactic(input, tactic)); } From f00a5a07ff3141d91e1826a83705d2c447e6b596 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 23:23:14 +0200 Subject: [PATCH 59/89] Trace: Fix a bug in TraceLogger.logDef We need to rebuild the term when it's *not* already tracked --- src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index 2f2f1a57be..3394f16fb7 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -109,11 +109,11 @@ public R logDef(String prefix, String method, Callable cl try { appendDef(var, prefix + "." + method); R f = closure.call(); - if (!isTracked(f)) { - mapVariable(var, f); + if (isTracked(f)) { + undoLast(); return f; } else { - undoLast(); + mapVariable(var, f); return mgr.rebuild(f); } } catch (Exception e) { From da00665c7dd23c292c4689679e8fae7583b9ba54 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 23:29:44 +0200 Subject: [PATCH 60/89] Trace: Improve error messages when checking the arity of an unknown operator --- .../delegate/trace/TraceFormulaManager.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 76aa2a239f..f9af6ac520 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -215,8 +215,8 @@ public T makeVariable(FormulaType formulaType, String nam return f; } - private int getArity(FunctionDeclarationKind pKind) { - switch (pKind) { + private int getArity(FunctionDeclaration pDeclaration) { + switch (pDeclaration.getKind()) { case AND: case OR: case IFF: @@ -320,7 +320,9 @@ private int getArity(FunctionDeclarationKind pKind) { return 3; default: - throw new IllegalArgumentException(String.format("Unsupported kind: %s", pKind)); + throw new IllegalArgumentException( + String.format( + "Unsupported kind: \"%s\" (%s)", pDeclaration.getName(), pDeclaration.getKind())); } } @@ -339,13 +341,11 @@ public T makeApplication( // TODO Figure out how to handle rounding mode for floats // TODO Handle rational formulas Preconditions.checkArgument( - getArity(declaration.getKind()) == -1 - ? args.size() > 1 - : args.size() == getArity(declaration.getKind()), + getArity(declaration) == -1 ? args.size() > 1 : args.size() == getArity(declaration), "Term \"%s\" (%s): expecting %s arguments, but found %s", declaration.getName(), declaration.getKind(), - getArity(declaration.getKind()), + getArity(declaration), args.size()); switch (declaration.getKind()) { case AND: From 7bcef2f0a44aa81b289cbf03181a4c4d929e4f38 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 24 Aug 2025 23:43:31 +0200 Subject: [PATCH 61/89] Trace: Don't rewrite and/or terms with more than 2 arguments --- .../trace/TraceBooleanFormulaManager.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java index 77d62414ef..710e2f577c 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java @@ -10,6 +10,7 @@ package org.sosy_lab.java_smt.delegate.trace; +import com.google.common.base.Joiner; import com.google.common.collect.FluentIterable; import java.util.Arrays; import java.util.Collection; @@ -116,11 +117,12 @@ public BooleanFormula and(BooleanFormula formula1, BooleanFormula formula2) { @Override public BooleanFormula and(Collection bits) { - BooleanFormula f = makeTrue(); - for (BooleanFormula bf : bits) { - f = and(bf, f); - } - return f; + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format( + "and(%s)", + FluentIterable.from(bits).transform(logger::toVariable).join(Joiner.on(", "))), + () -> delegate.and(bits)); } @Override @@ -143,11 +145,12 @@ public BooleanFormula or(BooleanFormula formula1, BooleanFormula formula2) { @Override public BooleanFormula or(Collection bits) { - BooleanFormula f = makeFalse(); - for (BooleanFormula bf : bits) { - f = or(bf, f); - } - return f; + return logger.logDef( + "mgr.getBooleanFormulaManager()", + String.format( + "or(%s)", + FluentIterable.from(bits).transform(logger::toVariable).join(Joiner.on(", "))), + () -> delegate.or(bits)); } @Override From 7169aca8f4aaeb76198990dcc38041fe5cec5130 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Mon, 25 Aug 2025 02:55:43 +0200 Subject: [PATCH 62/89] Trace: Fix a bug in TraceFormulaManager.makeVariable --- .../sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index f9af6ac520..ce29854aad 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -211,6 +211,8 @@ public T makeVariable(FormulaType formulaType, String nam T f = delegate.makeVariable(formulaType, name); if (logger.isTracked(f)) { logger.undoLast(); + } else { + logger.mapVariable(var, f); } return f; } From 10c38f6ab0988cfc26ebec863a439c12c6e10a0f Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Mon, 25 Aug 2025 03:52:44 +0200 Subject: [PATCH 63/89] Trace: Add support for rational formulas --- .../delegate/trace/TraceFormulaManager.java | 105 ++++++++--- .../trace/TraceIntegerFormulaManager.java | 175 +++--------------- .../trace/TraceNumeralFormulaManager.java | 170 +++++++++++++++++ .../trace/TraceRationalFormulaManager.java | 56 ++++++ 4 files changed, 323 insertions(+), 183 deletions(-) create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceRationalFormulaManager.java diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index ce29854aad..1184f7daff 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import org.sosy_lab.common.Appender; +import org.sosy_lab.common.rationals.Rational; import org.sosy_lab.java_smt.api.ArrayFormula; import org.sosy_lab.java_smt.api.ArrayFormulaManager; import org.sosy_lab.java_smt.api.BitvectorFormula; @@ -39,7 +40,9 @@ import org.sosy_lab.java_smt.api.FunctionDeclaration; import org.sosy_lab.java_smt.api.FunctionDeclarationKind; import org.sosy_lab.java_smt.api.IntegerFormulaManager; +import org.sosy_lab.java_smt.api.NumeralFormula; import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; +import org.sosy_lab.java_smt.api.NumeralFormula.RationalFormula; import org.sosy_lab.java_smt.api.QuantifiedFormulaManager; import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier; import org.sosy_lab.java_smt.api.RationalFormulaManager; @@ -71,7 +74,7 @@ public IntegerFormulaManager getIntegerFormulaManager() { @Override public RationalFormulaManager getRationalFormulaManager() { - throw new UnsupportedOperationException(); + return new TraceRationalFormulaManager(delegate.getRationalFormulaManager(), logger); } @Override @@ -167,6 +170,13 @@ public Formula visitConstant(Formula f, Object value) { String.format("makeNumber(%s)", value), () -> delegate.getIntegerFormulaManager().makeNumber((BigInteger) value)); Preconditions.checkArgument(g.equals(f)); + } else if (f instanceof RationalFormula && value instanceof Rational) { + var g = + logger.logDef( + "mgr.getRationalFormulaManager()", + String.format("makeNumber(%s)", value), + () -> delegate.getRationalFormulaManager().makeNumber((Rational) value)); + Preconditions.checkArgument(g.equals(f)); } else { throw new IllegalArgumentException( String.format( @@ -396,35 +406,64 @@ public T makeApplication( getArrayFormulaManager() .makeArray((ArrayFormulaType) declaration.getType(), args.get(0)); case UMINUS: - return (T) getIntegerFormulaManager().negate((IntegerFormula) args.get(0)); + { + if (declaration.getType().isIntegerType()) { + return (T) getIntegerFormulaManager().negate((IntegerFormula) args.get(0)); + } else { + return (T) getRationalFormulaManager().negate((NumeralFormula) args.get(0)); + } + } case SUB: { Preconditions.checkArgument(args.size() == 2); - return (T) - getIntegerFormulaManager() - .subtract((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + if (declaration.getType().isIntegerType()) { + return (T) + getIntegerFormulaManager() + .subtract((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } else { + return (T) + getRationalFormulaManager() + .subtract((NumeralFormula) args.get(0), (NumeralFormula) args.get(1)); + } } case ADD: { Preconditions.checkArgument(args.size() == 2); - return (T) - getIntegerFormulaManager() - .add((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + if (declaration.getType().isIntegerType()) { + return (T) + getIntegerFormulaManager() + .add((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } else { + return (T) + getRationalFormulaManager() + .add((NumeralFormula) args.get(0), (NumeralFormula) args.get(1)); + } } case DIV: { Preconditions.checkArgument(args.size() == 2); - - return (T) - getIntegerFormulaManager() - .divide((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + if (declaration.getType().isIntegerType()) { + return (T) + getIntegerFormulaManager() + .divide((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } else { + return (T) + getRationalFormulaManager() + .divide((NumeralFormula) args.get(0), (NumeralFormula) args.get(1)); + } } case MUL: { Preconditions.checkArgument(args.size() == 2); - return (T) - getIntegerFormulaManager() - .multiply((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + if (declaration.getType().isIntegerType()) { + return (T) + getIntegerFormulaManager() + .multiply((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } else { + return (T) + getRationalFormulaManager() + .multiply((NumeralFormula) args.get(0), (NumeralFormula) args.get(1)); + } } case MODULO: return (T) @@ -434,29 +473,29 @@ public T makeApplication( { Preconditions.checkArgument(args.size() == 2); return (T) - getIntegerFormulaManager() - .lessThan((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + getRationalFormulaManager() + .lessThan((NumeralFormula) args.get(0), (NumeralFormula) args.get(1)); } case LTE: { Preconditions.checkArgument(args.size() == 2); return (T) - getIntegerFormulaManager() - .lessOrEquals((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + getRationalFormulaManager() + .lessOrEquals((NumeralFormula) args.get(0), (NumeralFormula) args.get(1)); } case GT: { Preconditions.checkArgument(args.size() == 2); return (T) - getIntegerFormulaManager() - .greaterThan((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + getRationalFormulaManager() + .greaterThan((NumeralFormula) args.get(0), (NumeralFormula) args.get(1)); } case GTE: { Preconditions.checkArgument(args.size() == 2); return (T) - getIntegerFormulaManager() - .greaterOrEquals((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + getRationalFormulaManager() + .greaterOrEquals((NumeralFormula) args.get(0), (NumeralFormula) args.get(1)); } case EQ: { @@ -465,15 +504,15 @@ public T makeApplication( return (T) getBooleanFormulaManager() .equivalence((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); - } else if (declaration.getArgumentTypes().get(1).isIntegerType()) { + } else if (declaration.getArgumentTypes().get(0).isNumeralType()) { return (T) - getIntegerFormulaManager() - .equal((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); - } else if (declaration.getArgumentTypes().get(1).isBitvectorType()) { + getRationalFormulaManager() + .equal((NumeralFormula) args.get(0), (NumeralFormula) args.get(1)); + } else if (declaration.getArgumentTypes().get(0).isBitvectorType()) { return (T) getBitvectorFormulaManager() .equal((BitvectorFormula) args.get(0), (BitvectorFormula) args.get(1)); - } else if (declaration.getArgumentTypes().get(1).isArrayType()) { + } else if (declaration.getArgumentTypes().get(0).isArrayType()) { return (T) getArrayFormulaManager() .equivalence((ArrayFormula) args.get(0), (ArrayFormula) args.get(1)); @@ -490,11 +529,17 @@ public T makeApplication( break; case GTE_ZERO: break; - case FLOOR: - break; case TO_REAL: break; */ + case FLOOR: + { + if (args.get(0) instanceof IntegerFormula) { + return (T) getIntegerFormulaManager().floor((IntegerFormula) args.get(0)); + } else { + return (T) getRationalFormulaManager().floor((NumeralFormula) args.get(0)); + } + } case BV_EXTRACT: { List tokens = Splitter.on('_').splitToList(declaration.getName()); diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java index 119181dd26..6a413d9238 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java @@ -10,205 +10,74 @@ package org.sosy_lab.java_smt.delegate.trace; -import com.google.common.base.Joiner; -import com.google.common.collect.FluentIterable; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.List; import org.sosy_lab.common.rationals.Rational; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.IntegerFormulaManager; import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; -public class TraceIntegerFormulaManager implements IntegerFormulaManager { +public class TraceIntegerFormulaManager + extends TraceNumeralFormulaManager + implements IntegerFormulaManager { private final IntegerFormulaManager delegate; private final TraceLogger logger; TraceIntegerFormulaManager(IntegerFormulaManager pDelegate, TraceLogger pLogger) { + super(pDelegate, pLogger); delegate = pDelegate; logger = pLogger; } - @Override - public BooleanFormula modularCongruence( - IntegerFormula number1, IntegerFormula number2, BigInteger n) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format( - "modularCongruence(%s, %s, new BigInteger(\"%s\"))", - logger.toVariable(number1), logger.toVariable(number2), n), - () -> delegate.modularCongruence(number1, number2, n)); - } - - @Override - public BooleanFormula modularCongruence(IntegerFormula number1, IntegerFormula number2, long n) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format( - "modularCongruence(%s, %s, %s)", - logger.toVariable(number1), logger.toVariable(number2), n), - () -> delegate.modularCongruence(number1, number2, n)); - } - - @Override - public IntegerFormula modulo(IntegerFormula numerator, IntegerFormula denominator) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format( - "modulo(%s, %s)", logger.toVariable(numerator), logger.toVariable(denominator)), - () -> delegate.modulo(numerator, denominator)); - } - - @Override - public IntegerFormula makeNumber(long number) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format("makeNumber(%s)", number), - () -> delegate.makeNumber(number)); - } - - @Override - public IntegerFormula makeNumber(BigInteger number) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format("makeNumber(new BigInteger(\"%s\"))", number), - () -> delegate.makeNumber(number)); - } - @Override public IntegerFormula makeNumber(double number) { - throw new UnsupportedOperationException(); + return makeNumber(BigDecimal.valueOf(number)); } @Override public IntegerFormula makeNumber(BigDecimal number) { - throw new UnsupportedOperationException(); + return makeNumber(Rational.ofBigDecimal(number)); } @Override public IntegerFormula makeNumber(String pI) { - return makeNumber(new BigInteger(pI)); + return makeNumber(new BigDecimal(pI)); } @Override public IntegerFormula makeNumber(Rational pRational) { - throw new UnsupportedOperationException(); - } - - @Override - public IntegerFormula makeVariable(String pVar) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format("makeVariable(\"%s\")", pVar), - () -> delegate.makeVariable(pVar)); - } - - @Override - public IntegerFormula negate(IntegerFormula number) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format("negate(%s)", logger.toVariable(number)), - () -> delegate.negate(number)); - } - - @Override - public IntegerFormula add(IntegerFormula number1, IntegerFormula number2) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format("add(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), - () -> delegate.add(number1, number2)); - } - - @Override - public IntegerFormula sum(List operands) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format( - "sum(%s)", - FluentIterable.from(operands).transform(logger::toVariable).join(Joiner.on(", "))), - () -> delegate.sum(operands)); - } - - @Override - public IntegerFormula subtract(IntegerFormula number1, IntegerFormula number2) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format("subtract(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), - () -> delegate.subtract(number1, number2)); - } - - @Override - public IntegerFormula divide(IntegerFormula numerator, IntegerFormula denominator) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format( - "divide(%s, %s)", logger.toVariable(numerator), logger.toVariable(denominator)), - () -> delegate.divide(numerator, denominator)); - } - - @Override - public IntegerFormula multiply(IntegerFormula number1, IntegerFormula number2) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format("multiply(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), - () -> delegate.multiply(number1, number2)); - } - - @Override - public BooleanFormula equal(IntegerFormula number1, IntegerFormula number2) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format("equal(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), - () -> delegate.equal(number1, number2)); - } - - @Override - public BooleanFormula distinct(List pNumbers) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format( - "distinct(%s)", - FluentIterable.from(pNumbers).transform(logger::toVariable).join(Joiner.on(", "))), - () -> delegate.distinct(pNumbers)); + var num = makeNumber(pRational.getNum()); + var den = makeNumber(pRational.getDen()); + return divide(num, den); } @Override - public BooleanFormula greaterThan(IntegerFormula number1, IntegerFormula number2) { + public BooleanFormula modularCongruence( + IntegerFormula number1, IntegerFormula number2, BigInteger n) { return logger.logDef( "mgr.getIntegerFormulaManager()", String.format( - "greaterThan(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), - () -> delegate.greaterThan(number1, number2)); + "modularCongruence(%s, %s, new BigInteger(\"%s\"))", + logger.toVariable(number1), logger.toVariable(number2), n), + () -> delegate.modularCongruence(number1, number2, n)); } @Override - public BooleanFormula greaterOrEquals(IntegerFormula number1, IntegerFormula number2) { + public BooleanFormula modularCongruence(IntegerFormula number1, IntegerFormula number2, long n) { return logger.logDef( "mgr.getIntegerFormulaManager()", String.format( - "greaterOrEquals(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), - () -> delegate.greaterOrEquals(number1, number2)); - } - - @Override - public BooleanFormula lessThan(IntegerFormula number1, IntegerFormula number2) { - return logger.logDef( - "mgr.getIntegerFormulaManager()", - String.format("lessThan(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), - () -> delegate.lessThan(number1, number2)); + "modularCongruence(%s, %s, %s)", + logger.toVariable(number1), logger.toVariable(number2), n), + () -> delegate.modularCongruence(number1, number2, n)); } @Override - public BooleanFormula lessOrEquals(IntegerFormula number1, IntegerFormula number2) { + public IntegerFormula modulo(IntegerFormula numerator, IntegerFormula denominator) { return logger.logDef( "mgr.getIntegerFormulaManager()", String.format( - "lessOrEquals(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), - () -> delegate.lessOrEquals(number1, number2)); - } - - @Override - public IntegerFormula floor(IntegerFormula formula) { - throw new UnsupportedOperationException(); + "modulo(%s, %s)", logger.toVariable(numerator), logger.toVariable(denominator)), + () -> delegate.modulo(numerator, denominator)); } } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java new file mode 100644 index 0000000000..8a0503ef71 --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java @@ -0,0 +1,170 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; +import java.math.BigInteger; +import java.util.List; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.NumeralFormula; +import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; +import org.sosy_lab.java_smt.api.NumeralFormulaManager; + +@SuppressWarnings("InterfaceTypeParameterName") +public abstract class TraceNumeralFormulaManager< + ParamFormulaType extends NumeralFormula, ResultFormulaType extends NumeralFormula> + implements NumeralFormulaManager { + private final NumeralFormulaManager delegate; + private final TraceLogger logger; + + TraceNumeralFormulaManager( + NumeralFormulaManager pDelegate, TraceLogger pLogger) { + delegate = pDelegate; + logger = pLogger; + } + + @Override + public ResultFormulaType makeNumber(long number) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("makeNumber(%s)", number), + () -> delegate.makeNumber(number)); + } + + @Override + public ResultFormulaType makeNumber(BigInteger number) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("makeNumber(new BigInteger(\"%s\"))", number), + () -> delegate.makeNumber(number)); + } + + @Override + public ResultFormulaType makeVariable(String pVar) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("makeVariable(\"%s\")", pVar), + () -> delegate.makeVariable(pVar)); + } + + @Override + public ResultFormulaType negate(ParamFormulaType number) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("negate(%s)", logger.toVariable(number)), + () -> delegate.negate(number)); + } + + @Override + public ResultFormulaType add(ParamFormulaType number1, ParamFormulaType number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("add(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.add(number1, number2)); + } + + @Override + public ResultFormulaType sum(List operands) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "sum(%s)", + FluentIterable.from(operands).transform(logger::toVariable).join(Joiner.on(", "))), + () -> delegate.sum(operands)); + } + + @Override + public ResultFormulaType subtract(ParamFormulaType number1, ParamFormulaType number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("subtract(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.subtract(number1, number2)); + } + + @Override + public ResultFormulaType divide(ParamFormulaType numerator, ParamFormulaType denominator) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "divide(%s, %s)", logger.toVariable(numerator), logger.toVariable(denominator)), + () -> delegate.divide(numerator, denominator)); + } + + @Override + public ResultFormulaType multiply(ParamFormulaType number1, ParamFormulaType number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("multiply(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.multiply(number1, number2)); + } + + @Override + public BooleanFormula equal(ParamFormulaType number1, ParamFormulaType number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("equal(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.equal(number1, number2)); + } + + @Override + public BooleanFormula distinct(List pNumbers) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "distinct(%s)", + FluentIterable.from(pNumbers).transform(logger::toVariable).join(Joiner.on(", "))), + () -> delegate.distinct(pNumbers)); + } + + @Override + public BooleanFormula greaterThan(ParamFormulaType number1, ParamFormulaType number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "greaterThan(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.greaterThan(number1, number2)); + } + + @Override + public BooleanFormula greaterOrEquals(ParamFormulaType number1, ParamFormulaType number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "greaterOrEquals(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.greaterOrEquals(number1, number2)); + } + + @Override + public BooleanFormula lessThan(ParamFormulaType number1, ParamFormulaType number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("lessThan(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.lessThan(number1, number2)); + } + + @Override + public BooleanFormula lessOrEquals(ParamFormulaType number1, ParamFormulaType number2) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format( + "lessOrEquals(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.lessOrEquals(number1, number2)); + } + + @Override + public IntegerFormula floor(ParamFormulaType formula) { + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("floor(%s)", logger.toVariable(formula)), + () -> delegate.floor(formula)); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceRationalFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceRationalFormulaManager.java new file mode 100644 index 0000000000..cf03d5f5f2 --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceRationalFormulaManager.java @@ -0,0 +1,56 @@ +/* + * This file is part of JavaSMT, + * an API wrapper for a collection of SMT solvers: + * https://github.com/sosy-lab/java-smt + * + * SPDX-FileCopyrightText: 2025 Dirk Beyer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.sosy_lab.java_smt.delegate.trace; + +import java.math.BigDecimal; +import org.sosy_lab.common.rationals.Rational; +import org.sosy_lab.java_smt.api.NumeralFormula; +import org.sosy_lab.java_smt.api.NumeralFormula.RationalFormula; +import org.sosy_lab.java_smt.api.RationalFormulaManager; + +public class TraceRationalFormulaManager + extends TraceNumeralFormulaManager + implements RationalFormulaManager { + final RationalFormulaManager delegate; + final TraceLogger logger; + + TraceRationalFormulaManager(RationalFormulaManager pDelegate, TraceLogger pLogger) { + super(pDelegate, pLogger); + delegate = pDelegate; + logger = pLogger; + } + + @Override + public RationalFormula makeNumber(double number) { + return logger.logDef( + "mgr.getRationalFormulaManager()", + String.format("makeNumber(%s))", number), + () -> delegate.makeNumber(number)); + } + + @Override + public RationalFormula makeNumber(BigDecimal number) { + return makeNumber(Rational.ofBigDecimal(number)); + } + + @Override + public RationalFormula makeNumber(String pI) { + return makeNumber(new BigDecimal(pI)); + } + + @Override + public RationalFormula makeNumber(Rational pRational) { + return logger.logDef( + "mgr.getRationalFormulaManager()", + String.format("makeNumber(Rational.of(\"%s\"))", pRational), + () -> delegate.makeNumber(pRational)); + } +} From e1dff26a1c5eb8a2ed7d30d8e30060d9912e5de3 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Mon, 25 Aug 2025 04:36:52 +0200 Subject: [PATCH 64/89] Trace: Inline logging in FormulaManager.applyTactic to avoid catching InterruptedExceptions --- .../delegate/trace/TraceFormulaManager.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 1184f7daff..dbbfb75212 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -925,10 +925,19 @@ public Appender dumpFormula(BooleanFormula pT) { @Override public BooleanFormula applyTactic(BooleanFormula input, Tactic tactic) throws InterruptedException, SolverException { - return logger.logDef( - "mgr", - String.format("applyTactic(%s, %s)", logger.toVariable(input), "Tactic." + tactic.name()), - () -> delegate.applyTactic(input, tactic)); + String var = logger.newVariable(); + logger.appendDef( + var, + String.format( + "mgr.applyTactic(%s, %s)", logger.toVariable(input), "Tactic." + tactic.name())); + BooleanFormula f = delegate.applyTactic(input, tactic); + if (logger.isTracked(f)) { + logger.undoLast(); + return f; + } else { + logger.mapVariable(var, f); + return rebuild(f); + } } @Override From f6f477fd05399b6df56e40d084cb06d711ae4891 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Mon, 25 Aug 2025 12:11:05 +0200 Subject: [PATCH 65/89] Trace: Suppress warnings --- .../sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index dbbfb75212..9934c752fc 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -187,6 +187,7 @@ public Formula visitConstant(Formula f, Object value) { return f; } + @SuppressWarnings("unused") @Override public Formula visitFunction( Formula f, List args, FunctionDeclaration functionDeclaration) { @@ -338,7 +339,7 @@ private int getArity(FunctionDeclaration pDeclaration) { } } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "rawtypes"}) @Override public T makeApplication( FunctionDeclaration declaration, List args) { From e79a09e299e3da42c64c7921b4d4fa4cf3dc432a Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Mon, 25 Aug 2025 12:11:25 +0200 Subject: [PATCH 66/89] Trace: Use ArrayDeque instead of Stack --- src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index 3394f16fb7..e5a93123ca 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -15,9 +15,10 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.nio.charset.StandardCharsets; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.HashMap; import java.util.Map; -import java.util.Stack; import java.util.concurrent.Callable; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.FormulaType; @@ -32,7 +33,7 @@ class TraceLogger { private final Map valueMap = new HashMap<>(); private final RandomAccessFile output; - private final Stack lastLines = new Stack<>(); + private final Deque lastLines = new ArrayDeque<>(); TraceLogger(TraceFormulaManager pMgr, String pFile) { mgr = pMgr; From bdf22c0c2fc7cc9de74c10de233dd3f8ee317465 Mon Sep 17 00:00:00 2001 From: Karlheinz Friedberger Date: Thu, 28 Aug 2025 23:44:10 +0200 Subject: [PATCH 67/89] TraceLogger: improve tracefiles with FileOption, and id with UniqueIdGenerator. --- .../java_smt/delegate/trace/TraceLogger.java | 12 ++++-- .../delegate/trace/TraceSolverContext.java | 42 ++++++++++++++++--- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index e5a93123ca..1e6a89e51d 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -12,6 +12,7 @@ import com.google.common.base.Preconditions; import com.google.common.base.Throwables; +import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.charset.StandardCharsets; @@ -20,6 +21,7 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; +import org.sosy_lab.common.UniqueIdGenerator; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.FormulaType; import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType; @@ -28,15 +30,17 @@ class TraceLogger { private final TraceFormulaManager mgr; - private long id = 0; + private UniqueIdGenerator id = new UniqueIdGenerator(); private final Map valueMap = new HashMap<>(); private final RandomAccessFile output; private final Deque lastLines = new ArrayDeque<>(); - TraceLogger(TraceFormulaManager pMgr, String pFile) { + TraceLogger(TraceFormulaManager pMgr, File pFile) { mgr = pMgr; + mgr.setLogger(this); + // FIXME Check if the file already exists try { output = new RandomAccessFile(pFile, "rw"); @@ -47,7 +51,7 @@ class TraceLogger { /** Returns a fresh variable. */ public String newVariable() { - return "var" + id++; + return "var" + id.getFreshId(); } /** @@ -75,7 +79,7 @@ public String toVariable(Object f) { return r; } - /** Add a definition to the log. */ + /** Add a definition of a new object to the log. */ public void appendDef(String pVar, String pExpr) { try { lastLines.push(output.length()); diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index 0205f5d45d..6cbd093e66 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -14,9 +14,18 @@ import com.google.common.base.Splitter; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableMap; +import com.google.common.io.MoreFiles; +import java.io.IOException; +import java.nio.file.Path; import java.util.List; import java.util.Map.Entry; +import org.checkerframework.checker.nullness.qual.Nullable; import org.sosy_lab.common.configuration.Configuration; +import org.sosy_lab.common.configuration.FileOption; +import org.sosy_lab.common.configuration.InvalidConfigurationException; +import org.sosy_lab.common.configuration.Option; +import org.sosy_lab.common.configuration.Options; +import org.sosy_lab.common.io.PathTemplate; import org.sosy_lab.java_smt.SolverContextFactory.Solvers; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.InterpolatingProverEnvironment; @@ -24,20 +33,41 @@ import org.sosy_lab.java_smt.api.ProverEnvironment; import org.sosy_lab.java_smt.api.SolverContext; +@Options public class TraceSolverContext implements SolverContext { private final SolverContext delegate; private final TraceLogger logger; private final TraceFormulaManager mgr; - public TraceSolverContext(Solvers pSolver, Configuration config, SolverContext pDelegate) { + @Option( + secure = true, + name = "solver.tracefile", + description = "Export solver interaction as Java code into a file.") + @FileOption(FileOption.Type.OUTPUT_FILE) + private @Nullable PathTemplate tracefileTemplate = + PathTemplate.ofFormatString("traces/trace_%s.java"); + + public TraceSolverContext(Solvers pSolver, Configuration config, SolverContext pDelegate) + throws InvalidConfigurationException { + config.inject(this); delegate = pDelegate; - // FIXME Move the files to the output folder? mgr = new TraceFormulaManager(delegate.getFormulaManager()); - logger = - new TraceLogger( - mgr, "trace" + Integer.toUnsignedString(System.identityHashCode(this)) + ".java"); - mgr.setLogger(logger); + // initialize the trace logger and create the trace file, + // nanotime is used to avoid collisions, and it is sorted by time. + final Path tracefile = tracefileTemplate.getPath(String.valueOf(System.nanoTime())); + try { + MoreFiles.createParentDirectories(tracefile); + } catch (IOException e) { + throw new InvalidConfigurationException("Could not create directory for trace files", e); + } + logger = new TraceLogger(mgr, tracefile.toFile()); + + this.initializeJavaSMT(config, pSolver); + } + + /** Write the header code for using JavaSMT, e.g., to initialize the context and solver. */ + private void initializeJavaSMT(Configuration config, Solvers pSolver) { // Get relevant options from the configuration String props = config.asPropertiesString(); ImmutableMap.Builder options = ImmutableMap.builder(); From 33a9d03df9521582c8003661225ff8c93c5d7774 Mon Sep 17 00:00:00 2001 From: Karlheinz Friedberger Date: Fri, 29 Aug 2025 00:05:19 +0200 Subject: [PATCH 68/89] fix Checkstyle warnings and improve code style --- src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java | 8 ++++---- .../delegate/trace/TraceNumeralFormulaManager.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index 1e6a89e51d..65ded751bd 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -30,7 +30,7 @@ class TraceLogger { private final TraceFormulaManager mgr; - private UniqueIdGenerator id = new UniqueIdGenerator(); + private final UniqueIdGenerator id = new UniqueIdGenerator(); private final Map valueMap = new HashMap<>(); private final RandomAccessFile output; @@ -41,7 +41,7 @@ class TraceLogger { mgr = pMgr; mgr.setLogger(this); - // FIXME Check if the file already exists + // FIXME Check if the file already exists -> quite unlikely, lets ignore this case. try { output = new RandomAccessFile(pFile, "rw"); } catch (IOException e) { @@ -94,8 +94,8 @@ public void appendStmt(String pStmt) { try { lastLines.push(output.length()); output.write(String.format("%s;%n", pStmt).getBytes(StandardCharsets.UTF_8)); - } catch (IOException e) { - throw new RuntimeException(e); + } catch (IOException pIOException) { + throw new RuntimeException(pIOException); } } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java index 8a0503ef71..d35c83edd4 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java @@ -19,7 +19,7 @@ import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; import org.sosy_lab.java_smt.api.NumeralFormulaManager; -@SuppressWarnings("InterfaceTypeParameterName") +@SuppressWarnings("ClassTypeParameterName") public abstract class TraceNumeralFormulaManager< ParamFormulaType extends NumeralFormula, ResultFormulaType extends NumeralFormula> implements NumeralFormulaManager { From 2db414461809ce5934da92c5194b4695004a7cd4 Mon Sep 17 00:00:00 2001 From: Karlheinz Friedberger Date: Fri, 29 Aug 2025 00:35:51 +0200 Subject: [PATCH 69/89] shorten some code with utility methods. --- .../trace/TraceBasicProverEnvironment.java | 12 ++++------ .../trace/TraceBitvectorFormulaManager.java | 6 +---- .../trace/TraceBooleanFormulaManager.java | 24 +++++-------------- .../delegate/trace/TraceFormulaManager.java | 9 +++++++ .../java_smt/delegate/trace/TraceLogger.java | 7 ++++++ .../trace/TraceNumeralFormulaManager.java | 10 ++------ .../delegate/trace/TraceSolverContext.java | 2 +- .../delegate/trace/TraceUFManager.java | 3 +-- 8 files changed, 31 insertions(+), 42 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java index 56d104fd50..6329e4f65f 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBasicProverEnvironment.java @@ -10,8 +10,6 @@ package org.sosy_lab.java_smt.delegate.trace; -import com.google.common.base.Joiner; -import com.google.common.collect.FluentIterable; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -80,8 +78,7 @@ public boolean isUnsatWithAssumptions(Collection assumptions) var, String.format( "%s.isUnsatWithAssumptions(ImmutableList.of(%s))", - logger.toVariable(this), - FluentIterable.from(assumptions).transform(logger::toVariable).join(Joiner.on(", ")))); + logger.toVariable(this), logger.toVariables(assumptions))); boolean unsat = delegate.isUnsatWithAssumptions(assumptions); logger.mapVariable(var, unsat); return unsat; @@ -102,7 +99,7 @@ public List getUnsatCore() { logger.appendStmt(String.format("%s.getUnsatCore()", logger.toVariable(this))); List core = delegate.getUnsatCore(); logger.undoLast(); - return FluentIterable.from(core).transform(mgr::rebuild).toList(); + return mgr.rebuildAll(core); } @Override @@ -111,11 +108,10 @@ public Optional> unsatCoreOverAssumptions( logger.appendStmt( String.format( "%s.getUnsatCoreOverAssumptions(ImmutableList.of(%s))", - logger.toVariable(this), - FluentIterable.from(assumptions).transform(logger::toVariable).join(Joiner.on(", ")))); + logger.toVariable(this), logger.toVariables(assumptions))); Optional> maybeCore = delegate.unsatCoreOverAssumptions(assumptions); logger.undoLast(); - return maybeCore.map(core -> FluentIterable.from(core).transform(mgr::rebuild).toList()); + return maybeCore.map(mgr::rebuildAll); } @Override diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java index 936a12f33c..3f8ec26677 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java @@ -10,8 +10,6 @@ package org.sosy_lab.java_smt.delegate.trace; -import com.google.common.base.Joiner; -import com.google.common.collect.FluentIterable; import java.math.BigInteger; import java.util.List; import org.sosy_lab.java_smt.api.BitvectorFormula; @@ -309,9 +307,7 @@ public BitvectorFormula extend(BitvectorFormula number, int extensionBits, boole public BooleanFormula distinct(List pBits) { return logger.logDef( "mgr.getBitvectorFormulaManager()", - String.format( - "distinct(ImmutableList.of(%s))", - FluentIterable.from(pBits).transform(logger::toVariable).join(Joiner.on(", "))), + String.format("distinct(ImmutableList.of(%s))", logger.toVariables(pBits)), () -> delegate.distinct(pBits)); } } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java index 710e2f577c..0f5d6ae9a1 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBooleanFormulaManager.java @@ -10,8 +10,6 @@ package org.sosy_lab.java_smt.delegate.trace; -import com.google.common.base.Joiner; -import com.google.common.collect.FluentIterable; import java.util.Arrays; import java.util.Collection; import java.util.Set; @@ -109,19 +107,14 @@ public BooleanFormula not(BooleanFormula formula) { @Override public BooleanFormula and(BooleanFormula formula1, BooleanFormula formula2) { - return logger.logDef( - "mgr.getBooleanFormulaManager()", - String.format("and(%s, %s)", logger.toVariable(formula1), logger.toVariable(formula2)), - () -> delegate.and(formula1, formula2)); + return and(Arrays.asList(formula1, formula2)); } @Override public BooleanFormula and(Collection bits) { return logger.logDef( "mgr.getBooleanFormulaManager()", - String.format( - "and(%s)", - FluentIterable.from(bits).transform(logger::toVariable).join(Joiner.on(", "))), + String.format("and(%s)", logger.toVariables(bits)), () -> delegate.and(bits)); } @@ -137,19 +130,14 @@ public BooleanFormula and(BooleanFormula... bits) { @Override public BooleanFormula or(BooleanFormula formula1, BooleanFormula formula2) { - return logger.logDef( - "mgr.getBooleanFormulaManager()", - String.format("or(%s, %s)", logger.toVariable(formula1), logger.toVariable(formula2)), - () -> delegate.or(formula1, formula2)); + return or(Arrays.asList(formula1, formula2)); } @Override public BooleanFormula or(Collection bits) { return logger.logDef( "mgr.getBooleanFormulaManager()", - String.format( - "or(%s)", - FluentIterable.from(bits).transform(logger::toVariable).join(Joiner.on(", "))), + String.format("or(%s)", logger.toVariables(bits)), () -> delegate.or(bits)); } @@ -215,7 +203,7 @@ public Set toConjunctionArgs(BooleanFormula f, boolean flatten) String.format("mgr.toConjunctionArgs(%s, %s)", logger.toVariable(f), flatten)); Set set = delegate.toConjunctionArgs(f, flatten); logger.undoLast(); - return FluentIterable.from(set).transform(mgr::rebuild).toSet(); + return mgr.rebuildAll(set); } @Override @@ -224,6 +212,6 @@ public Set toDisjunctionArgs(BooleanFormula f, boolean flatten) String.format("mgr.toDisjunctionArgs(%s, %s)", logger.toVariable(f), flatten)); Set set = delegate.toDisjunctionArgs(f, flatten); logger.undoLast(); - return FluentIterable.from(set).transform(mgr::rebuild).toSet(); + return mgr.rebuildAll(set); } } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 9934c752fc..9218b023ef 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -19,6 +19,7 @@ import java.math.BigInteger; import java.util.List; import java.util.Map; +import java.util.Set; import org.sosy_lab.common.Appender; import org.sosy_lab.common.rationals.Rational; import org.sosy_lab.java_smt.api.ArrayFormula; @@ -213,6 +214,14 @@ public T rebuild(T f) { return delegate.transformRecursively(f, new TraceFormulaManager.Rebuilder(this)); } + public List rebuildAll(List formulas) { + return FluentIterable.from(formulas).transform(this::rebuild).toList(); + } + + public Set rebuildAll(Set formulas) { + return FluentIterable.from(formulas).transform(this::rebuild).toSet(); + } + @Override public T makeVariable(FormulaType formulaType, String name) { String var = logger.newVariable(); diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index 65ded751bd..1fdaf64a19 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -10,8 +10,10 @@ package org.sosy_lab.java_smt.delegate.trace; +import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.base.Throwables; +import com.google.common.collect.FluentIterable; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; @@ -79,6 +81,11 @@ public String toVariable(Object f) { return r; } + /** Returns a comma-separated list of variable names for the given objects. */ + public String toVariables(Iterable objects) { + return FluentIterable.from(objects).transform(this::toVariable).join(Joiner.on(", ")); + } + /** Add a definition of a new object to the log. */ public void appendDef(String pVar, String pExpr) { try { diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java index d35c83edd4..a7cb340532 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceNumeralFormulaManager.java @@ -10,8 +10,6 @@ package org.sosy_lab.java_smt.delegate.trace; -import com.google.common.base.Joiner; -import com.google.common.collect.FluentIterable; import java.math.BigInteger; import java.util.List; import org.sosy_lab.java_smt.api.BooleanFormula; @@ -76,9 +74,7 @@ public ResultFormulaType add(ParamFormulaType number1, ParamFormulaType number2) public ResultFormulaType sum(List operands) { return logger.logDef( "mgr.getIntegerFormulaManager()", - String.format( - "sum(%s)", - FluentIterable.from(operands).transform(logger::toVariable).join(Joiner.on(", "))), + String.format("sum(%s)", logger.toVariables(operands)), () -> delegate.sum(operands)); } @@ -119,9 +115,7 @@ public BooleanFormula equal(ParamFormulaType number1, ParamFormulaType number2) public BooleanFormula distinct(List pNumbers) { return logger.logDef( "mgr.getIntegerFormulaManager()", - String.format( - "distinct(%s)", - FluentIterable.from(pNumbers).transform(logger::toVariable).join(Joiner.on(", "))), + String.format("distinct(%s)", logger.toVariables(pNumbers)), () -> delegate.distinct(pNumbers)); } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java index 6cbd093e66..236f6e1e42 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceSolverContext.java @@ -114,7 +114,7 @@ public ProverEnvironment newProverEnvironment(ProverOptions... options) { String.format( "newProverEnvironment(%s)", FluentIterable.from(options) - .transform(v -> "SolverContext" + ".ProverOptions." + v.name()) + .transform(v -> "SolverContext.ProverOptions." + v.name()) .join(Joiner.on(", "))), () -> new TraceProverEnvironment(delegate.newProverEnvironment(options), mgr, logger)); } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java index b0bd5e0bdf..349c30cf5e 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java @@ -67,8 +67,7 @@ public T callUF( var, String.format( "callUF(%s, ImmutableList.of(%s))", - logger.toVariable(funcType), - FluentIterable.from(args).transform(logger::toVariable).join(Joiner.on(", ")))); + logger.toVariable(funcType), logger.toVariables(args))); T f = delegate.callUF(funcType, args); if (logger.isTracked(f)) { logger.undoLast(); From 1c1108d8f7206474b4bc8e485ea38b69773237f3 Mon Sep 17 00:00:00 2001 From: Karlheinz Friedberger Date: Fri, 29 Aug 2025 00:47:16 +0200 Subject: [PATCH 70/89] enable tracing for all unit tests, testwise. --- src/org/sosy_lab/java_smt/test/SolverBasedTest0.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java index e96c7b39f1..b2a670f739 100644 --- a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java +++ b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java @@ -125,7 +125,9 @@ protected Logics logicToUse() { protected ConfigurationBuilder createTestConfigBuilder() { ConfigurationBuilder newConfig = - Configuration.builder().setOption("solver.solver", solverToUse().toString()); + Configuration.builder() + .setOption("solver.solver", solverToUse().toString()) + .setOption("solver.trace", "true"); if (solverToUse() == Solvers.OPENSMT) { newConfig.setOption("solver.opensmt.logic", logicToUse().toString()); } From 4129a90a960b7469f0769ad2c2dfc0a498e901ef Mon Sep 17 00:00:00 2001 From: Karlheinz Friedberger Date: Fri, 29 Aug 2025 00:58:40 +0200 Subject: [PATCH 71/89] fix invalid argument dump --- .../delegate/trace/TraceArrayFormulaManager.java | 2 +- .../trace/TraceBitvectorFormulaManager.java | 2 +- .../trace/TraceFloatingPointFormulaManager.java | 15 ++++++++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java index 666320e1b2..7a1da852dc 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java @@ -71,7 +71,7 @@ ArrayFormula makeArray(FTI pIndexType, FTE pElementType, TE defaultEleme return logger.logDef( "mgr.getArrayFormulaManager()", String.format( - "makeArray(\"%s\", %s, %s)", + "makeArray(%s, %s, %s)", logger.printFormulaType(pIndexType), logger.printFormulaType(pElementType), logger.toVariable(defaultElement)), diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java index 3f8ec26677..9b5d6b7f57 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceBitvectorFormulaManager.java @@ -31,7 +31,7 @@ public class TraceBitvectorFormulaManager implements BitvectorFormulaManager { public BitvectorFormula makeBitvector(int length, long pI) { return logger.logDef( "mgr.getBitvectorFormulaManager()", - String.format("makeBitvector(%s, %s)", length, pI), + String.format("makeBitvector(%s, %sL)", length, pI), () -> delegate.makeBitvector(length, pI)); } diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java index 8a82039fc1..cee2b6de54 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java @@ -48,10 +48,23 @@ public FloatingPointFormula makeNumber( "mgr.getFloatingPointFormulaManager()", String.format( "makeNumber(%s, %s, %s)", - n, logger.printFormulaType(type), printRoundingMode(pFloatingPointRoundingMode)), + toString(n), logger.printFormulaType(type), + printRoundingMode(pFloatingPointRoundingMode)), () -> delegate.makeNumber(n, type, pFloatingPointRoundingMode)); } + private String toString(double number) { + if (Double.isNaN(number)) { + return "Double.NaN"; + } else if (Double.isInfinite(number)) { + return number > 0 ? "Double.POSITIVE_INFINITY" : "Double.NEGATIVE_INFINITY"; + } else if (number == 0.0 && Double.doubleToRawLongBits(number) == Double.doubleToRawLongBits(-0.0)) { + return "-0.0"; + } else { + return Double.toString(number); + } + } + @Override public FloatingPointFormula makeNumber(BigDecimal n, FloatingPointType type) { return makeNumber(n, type, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); From 8bdc4752d4168eb869efe60096e62f1297d80ba6 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sat, 30 Aug 2025 18:45:46 +0200 Subject: [PATCH 72/89] Trace: Use makeApplication to handle non-UF calls to TraceUFManager.callUF --- .../delegate/trace/TraceUFManager.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java index 349c30cf5e..76d3950935 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java @@ -19,6 +19,7 @@ import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.FormulaType; import org.sosy_lab.java_smt.api.FunctionDeclaration; +import org.sosy_lab.java_smt.api.FunctionDeclarationKind; import org.sosy_lab.java_smt.api.UFManager; public class TraceUFManager implements UFManager { @@ -62,19 +63,23 @@ public FunctionDeclaration declareUF( @Override public T callUF( FunctionDeclaration funcType, List args) { - String var = logger.newVariable(); - logger.appendDef( - var, - String.format( - "callUF(%s, ImmutableList.of(%s))", - logger.toVariable(funcType), logger.toVariables(args))); - T f = delegate.callUF(funcType, args); - if (logger.isTracked(f)) { - logger.undoLast(); + if (funcType.getKind().equals(FunctionDeclarationKind.UF)) { + String var = logger.newVariable(); + logger.appendDef( + var, + String.format( + "callUF(%s, ImmutableList.of(%s))", + logger.toVariable(funcType), logger.toVariables(args))); + T f = delegate.callUF(funcType, args); + if (logger.isTracked(f)) { + logger.undoLast(); + } else { + logger.mapVariable(var, f); + } + return f; } else { - logger.mapVariable(var, f); + return mgr.makeApplication(funcType, args); } - return f; } @Override From 1168f3bf41620dba218a7ae6d1c5ccc8e3adcc42 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sat, 30 Aug 2025 18:46:42 +0200 Subject: [PATCH 73/89] Trace: Filter out values for local definitions from the Z3 model --- src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java index 7c188037b4..09a234625d 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceModel.java @@ -44,6 +44,8 @@ public ImmutableList asList() { ImmutableList result = delegate.asList(); logger.undoLast(); return FluentIterable.from(result) + // TODO Fix this in the Z3 model + .filter((ValueAssignment assignment) -> !assignment.getName().startsWith("#")) .transform( (ValueAssignment assigment) -> { var key = mgr.rebuild(assigment.getKey()); From 62766eaa418e8ded992384a7c029475862fe5943 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sat, 30 Aug 2025 18:49:00 +0200 Subject: [PATCH 74/89] Trace: Skip the division when creating an IntegerFormula from a Rational that is really integer --- .../delegate/trace/TraceIntegerFormulaManager.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java index 6a413d9238..a20edf6d60 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java @@ -46,9 +46,13 @@ public IntegerFormula makeNumber(String pI) { @Override public IntegerFormula makeNumber(Rational pRational) { - var num = makeNumber(pRational.getNum()); - var den = makeNumber(pRational.getDen()); - return divide(num, den); + if (pRational.isIntegral()) { + return makeNumber(pRational.getNum()); + } else { + var num = makeNumber(pRational.getNum()); + var den = makeNumber(pRational.getDen()); + return divide(num, den); + } } @Override From 7ed9a909f4ffc720816d983cdada4d432dfb8d27 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sat, 30 Aug 2025 18:50:34 +0200 Subject: [PATCH 75/89] Trace: Handle BigInteger values for RationalFormula constants Some solvers will return these when the value is really integer --- .../java_smt/delegate/trace/TraceFormulaManager.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 9218b023ef..c0670e1962 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -171,6 +171,13 @@ public Formula visitConstant(Formula f, Object value) { String.format("makeNumber(%s)", value), () -> delegate.getIntegerFormulaManager().makeNumber((BigInteger) value)); Preconditions.checkArgument(g.equals(f)); + } else if (f instanceof RationalFormula && value instanceof BigInteger) { + var g = + logger.logDef( + "mgr.getRationalFormulaManager()", + String.format("makeNumber(%s)", value), + () -> delegate.getRationalFormulaManager().makeNumber((BigInteger) value)); + Preconditions.checkArgument(g.equals(f)); } else if (f instanceof RationalFormula && value instanceof Rational) { var g = logger.logDef( From 1f562f1f94fe134c03310136dffcbbfbcb11278c Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sat, 30 Aug 2025 18:51:10 +0200 Subject: [PATCH 76/89] Trace: Restore the check in the function visitor that makes sure the recreated formula is identical to the old formula --- .../java_smt/delegate/trace/TraceFormulaManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index c0670e1962..4b889be930 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -195,14 +195,14 @@ public Formula visitConstant(Formula f, Object value) { return f; } - @SuppressWarnings("unused") @Override public Formula visitFunction( Formula f, List args, FunctionDeclaration functionDeclaration) { if (!logger.isTracked(f)) { Formula g = makeApplication(functionDeclaration, args); - // FIXME Remove the assertion? Argument order can change, f.ex (and a b) becomes (and b a) - // Preconditions.checkArgument(g.equals(f)); + if (!g.equals(f)) { + Preconditions.checkArgument(g.equals(f), "%s (should be: %s)", g, f); + } } return f; } From 243fdd904531ecad65a9124bbc9059541eb8527b Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sat, 30 Aug 2025 18:52:16 +0200 Subject: [PATCH 77/89] Trace: Fix floating point operations and skip the rounding mode argument --- .../delegate/trace/TraceFormulaManager.java | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 4b889be930..7161603247 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -32,7 +32,6 @@ import org.sosy_lab.java_smt.api.FloatingPointFormula; import org.sosy_lab.java_smt.api.FloatingPointFormulaManager; import org.sosy_lab.java_smt.api.FloatingPointRoundingMode; -import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula; import org.sosy_lab.java_smt.api.Formula; import org.sosy_lab.java_smt.api.FormulaManager; import org.sosy_lab.java_smt.api.FormulaType; @@ -740,19 +739,19 @@ public T makeApplication( getFloatingPointFormulaManager() .min((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); case FP_SQRT: - return (T) getFloatingPointFormulaManager().sqrt((FloatingPointFormula) args.get(0)); + return (T) getFloatingPointFormulaManager().sqrt((FloatingPointFormula) args.get(1)); case FP_SUB: return (T) getFloatingPointFormulaManager() - .subtract((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + .subtract((FloatingPointFormula) args.get(1), (FloatingPointFormula) args.get(2)); case FP_ADD: return (T) getFloatingPointFormulaManager() - .add((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + .add((FloatingPointFormula) args.get(1), (FloatingPointFormula) args.get(2)); case FP_DIV: return (T) getFloatingPointFormulaManager() - .divide((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + .divide((FloatingPointFormula) args.get(1), (FloatingPointFormula) args.get(2)); case FP_REM: return (T) getFloatingPointFormulaManager() @@ -761,7 +760,7 @@ public T makeApplication( case FP_MUL: return (T) getFloatingPointFormulaManager() - .multiply((FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); + .multiply((FloatingPointFormula) args.get(1), (FloatingPointFormula) args.get(2)); case FP_LT: return (T) getFloatingPointFormulaManager() @@ -800,15 +799,11 @@ public T makeApplication( break; */ case FP_ROUND_TO_INTEGRAL: - { - var rm = (FloatingPointRoundingModeFormula) args.get(1); - System.out.println("Rounding Mode: " + rm); - return (T) - getFloatingPointFormulaManager() - .round( - (FloatingPointFormula) args.get(0), - FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); - } + return (T) + getFloatingPointFormulaManager() + .round( + (FloatingPointFormula) args.get(1), + FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); case FP_IS_NAN: return (T) getFloatingPointFormulaManager().isNaN((FloatingPointFormula) args.get(0)); case FP_IS_INF: From da7582ef8c296835fd525aa6c3e7e1744b217300 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sat, 30 Aug 2025 18:52:35 +0200 Subject: [PATCH 78/89] Trace: Remove a todo about rounding mode kinds --- .../delegate/trace/TraceFormulaManager.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 7161603247..8e18f3ba71 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -785,19 +785,6 @@ public T makeApplication( getFloatingPointFormulaManager() .equalWithFPSemantics( (FloatingPointFormula) args.get(0), (FloatingPointFormula) args.get(1)); - // TODO - /* - case FP_ROUND_EVEN: - break; - case FP_ROUND_AWAY: - break; - case FP_ROUND_POSITIVE: - break; - case FP_ROUND_NEGATIVE: - break; - case FP_ROUND_ZERO: - break; - */ case FP_ROUND_TO_INTEGRAL: return (T) getFloatingPointFormulaManager() From 9d23d094fcc7a07e197e38238c7d2ce5fc4b4525 Mon Sep 17 00:00:00 2001 From: Karlheinz Friedberger Date: Fri, 29 Aug 2025 14:41:21 +0200 Subject: [PATCH 79/89] add "/traces" to gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b1ff17c08b..b075b89ddb 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ solvers_maven_conf/*.asc /Javadoc /Javadoc-z3 /gh-pages +/traces .idea/ From 817ba2003b7e488765ff2ac7c57188840c7790c1 Mon Sep 17 00:00:00 2001 From: Karlheinz Friedberger Date: Sat, 30 Aug 2025 23:23:47 +0200 Subject: [PATCH 80/89] Trace: implement tracing for EnumerationFMgr. --- .../trace/TraceEnumerationFormulaManager.java | 66 +++++++++++++++++++ .../delegate/trace/TraceFormulaManager.java | 2 +- 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/org/sosy_lab/java_smt/delegate/trace/TraceEnumerationFormulaManager.java diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceEnumerationFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceEnumerationFormulaManager.java new file mode 100644 index 0000000000..0fc41909cc --- /dev/null +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceEnumerationFormulaManager.java @@ -0,0 +1,66 @@ +// This file is part of JavaSMT, +// an API wrapper for a collection of SMT solvers: +// https://github.com/sosy-lab/java-smt +// +// SPDX-FileCopyrightText: 2025 Dirk Beyer +// +// SPDX-License-Identifier: Apache-2.0 + +package org.sosy_lab.java_smt.delegate.trace; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Joiner; +import java.util.Set; +import org.sosy_lab.java_smt.api.BooleanFormula; +import org.sosy_lab.java_smt.api.EnumerationFormula; +import org.sosy_lab.java_smt.api.EnumerationFormulaManager; +import org.sosy_lab.java_smt.api.FormulaType.EnumerationFormulaType; + +public class TraceEnumerationFormulaManager implements EnumerationFormulaManager { + + private final EnumerationFormulaManager delegate; + private final TraceLogger logger; + + TraceEnumerationFormulaManager(EnumerationFormulaManager pDelegate, TraceLogger pLogger) { + delegate = checkNotNull(pDelegate); + logger = checkNotNull(pLogger); + } + + @Override + public EnumerationFormulaType declareEnumeration(String name, Set elementNames) { + return logger.logDefKeep( + "mgr.getEnumerationFormulaManager()", + String.format( + "declareEnumeration(\"%s\", Set.of(\"%s\"))", + name, Joiner.on("\", \"").join(elementNames)), + () -> delegate.declareEnumeration(name, elementNames)); + } + + @Override + public EnumerationFormula makeConstant(String pName, EnumerationFormulaType pType) { + return logger.logDef( + "mgr.getEnumerationFormulaManager()", + String.format("makeConstant(\"%s\", %s)", pName, logger.toVariable(pType)), + () -> delegate.makeConstant(pName, pType)); + } + + @Override + public EnumerationFormula makeVariable(String pVar, EnumerationFormulaType pType) { + return logger.logDef( + "mgr.getEnumerationFormulaManager()", + String.format("makeVariable(\"%s\", %s)", pVar, logger.toVariable(pType)), + () -> delegate.makeVariable(pVar, pType)); + } + + @Override + public BooleanFormula equivalence( + EnumerationFormula pEnumeration1, EnumerationFormula pEnumeration2) { + return logger.logDef( + "mgr.getEnumerationFormulaManager()", + String.format( + "equivalence(%s, %s)", + logger.toVariable(pEnumeration1), logger.toVariable(pEnumeration2)), + () -> delegate.equivalence(pEnumeration1, pEnumeration2)); + } +} diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 8e18f3ba71..a8a3647c67 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -119,7 +119,7 @@ public StringFormulaManager getStringFormulaManager() { @Override public EnumerationFormulaManager getEnumerationFormulaManager() { - throw new UnsupportedOperationException(); + return new TraceEnumerationFormulaManager(delegate.getEnumerationFormulaManager(), logger); } private class Rebuilder extends FormulaTransformationVisitor { From e4bf4d57363893c3a13f3e264306226f4d3e934c Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sat, 30 Aug 2025 22:43:23 +0200 Subject: [PATCH 81/89] Trace: Avoid upcasting to rational if both sides of an equation are integers --- .../delegate/trace/TraceFormulaManager.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index a8a3647c67..a3decef3c9 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -520,10 +520,17 @@ public T makeApplication( return (T) getBooleanFormulaManager() .equivalence((BooleanFormula) args.get(0), (BooleanFormula) args.get(1)); - } else if (declaration.getArgumentTypes().get(0).isNumeralType()) { - return (T) - getRationalFormulaManager() - .equal((NumeralFormula) args.get(0), (NumeralFormula) args.get(1)); + } else if (declaration.getArgumentTypes().get(1).isNumeralType()) { + if (declaration.getArgumentTypes().get(0).isRationalType() + || declaration.getArgumentTypes().get(1).isRationalType()) { + return (T) + getRationalFormulaManager() + .equal((NumeralFormula) args.get(0), (NumeralFormula) args.get(1)); + } else { + return (T) + getIntegerFormulaManager() + .equal((IntegerFormula) args.get(0), (IntegerFormula) args.get(1)); + } } else if (declaration.getArgumentTypes().get(0).isBitvectorType()) { return (T) getBitvectorFormulaManager() From c593988d78f7d7ae0e06abedf1ec36f88ab7b089 Mon Sep 17 00:00:00 2001 From: Karlheinz Friedberger Date: Sat, 30 Aug 2025 22:15:41 +0200 Subject: [PATCH 82/89] Add more methods for Trace-*-FormulaManager to directly dump usage of methods. --- .../TraceFloatingPointFormulaManager.java | 105 +++++++++++++----- .../trace/TraceIntegerFormulaManager.java | 26 +++-- 2 files changed, 92 insertions(+), 39 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java index cee2b6de54..632b8073a1 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFloatingPointFormulaManager.java @@ -32,42 +32,50 @@ public class TraceFloatingPointFormulaManager implements FloatingPointFormulaMan logger = pLogger; } - @Override - public FloatingPointFormula makeNumber(double n, FloatingPointType type) { - return makeNumber(n, type, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); - } - private String printRoundingMode(FloatingPointRoundingMode pRoundingMode) { return "FloatingPointRoundingMode." + pRoundingMode.name(); } - @Override - public FloatingPointFormula makeNumber( - double n, FloatingPointType type, FloatingPointRoundingMode pFloatingPointRoundingMode) { - return logger.logDef( - "mgr.getFloatingPointFormulaManager()", - String.format( - "makeNumber(%s, %s, %s)", - toString(n), logger.printFormulaType(type), - printRoundingMode(pFloatingPointRoundingMode)), - () -> delegate.makeNumber(n, type, pFloatingPointRoundingMode)); - } - private String toString(double number) { if (Double.isNaN(number)) { return "Double.NaN"; } else if (Double.isInfinite(number)) { return number > 0 ? "Double.POSITIVE_INFINITY" : "Double.NEGATIVE_INFINITY"; - } else if (number == 0.0 && Double.doubleToRawLongBits(number) == Double.doubleToRawLongBits(-0.0)) { + } else if (number == 0.0 + && Double.doubleToRawLongBits(number) == Double.doubleToRawLongBits(-0.0)) { return "-0.0"; } else { return Double.toString(number); } } + @Override + public FloatingPointFormula makeNumber(double n, FloatingPointType type) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("makeNumber(%s, %s)", toString(n), logger.printFormulaType(type)), + () -> delegate.makeNumber(n, type)); + } + + @Override + public FloatingPointFormula makeNumber( + double n, FloatingPointType type, FloatingPointRoundingMode pFloatingPointRoundingMode) { + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "makeNumber(%s, %s, %s)", + toString(n), + logger.printFormulaType(type), + printRoundingMode(pFloatingPointRoundingMode)), + () -> delegate.makeNumber(n, type, pFloatingPointRoundingMode)); + } + @Override public FloatingPointFormula makeNumber(BigDecimal n, FloatingPointType type) { - return makeNumber(n, type, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("makeNumber(new BigDecimal(\"%s\"), %s)", n, logger.printFormulaType(type)), + () -> delegate.makeNumber(n, type)); } @Override @@ -83,7 +91,10 @@ public FloatingPointFormula makeNumber( @Override public FloatingPointFormula makeNumber(String n, FloatingPointType type) { - return makeNumber(n, type, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("makeNumber(\"%s\", %s)", n, logger.printFormulaType(type)), + () -> delegate.makeNumber(n, type)); } @Override @@ -99,13 +110,24 @@ public FloatingPointFormula makeNumber( @Override public FloatingPointFormula makeNumber(Rational n, FloatingPointType type) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("makeNumber(Rational.of(\"%s\"), %s)", n, logger.printFormulaType(type)), + () -> delegate.makeNumber(n, type)); } @Override public FloatingPointFormula makeNumber( Rational n, FloatingPointType type, FloatingPointRoundingMode pFloatingPointRoundingMode) { - throw new UnsupportedOperationException(); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "makeNumber(Rational.of(%s, %s), %s, %s)", + n.getNum(), + n.getDen(), + logger.printFormulaType(type), + printRoundingMode(pFloatingPointRoundingMode)), + () -> delegate.makeNumber(n, type, pFloatingPointRoundingMode)); } private String printSign(Sign pSign) { @@ -158,7 +180,12 @@ public FloatingPointFormula makeNaN(FloatingPointType type) { @Override public T castTo( FloatingPointFormula source, boolean signed, FormulaType targetType) { - return castTo(source, signed, targetType, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "castTo(%s, %s, %s)", + logger.toVariable(source), signed, logger.printFormulaType(targetType)), + () -> delegate.castTo(source, signed, targetType)); } @Override @@ -181,7 +208,12 @@ public T castTo( @Override public FloatingPointFormula castFrom( Formula source, boolean signed, FloatingPointType targetType) { - return castFrom(source, signed, targetType, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format( + "castFrom(%s, %s, %s)", + logger.toVariable(source), signed, logger.printFormulaType(targetType)), + () -> delegate.castFrom(source, signed, targetType)); } @Override @@ -263,7 +295,10 @@ public FloatingPointFormula min(FloatingPointFormula number1, FloatingPointFormu @Override public FloatingPointFormula sqrt(FloatingPointFormula number) { - return sqrt(number, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("sqrt(%s)", logger.toVariable(number)), + () -> delegate.sqrt(number)); } @Override @@ -277,7 +312,10 @@ public FloatingPointFormula sqrt( @Override public FloatingPointFormula add(FloatingPointFormula number1, FloatingPointFormula number2) { - return add(number1, number2, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("add(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.add(number1, number2)); } @Override @@ -297,7 +335,10 @@ public FloatingPointFormula add( @Override public FloatingPointFormula subtract(FloatingPointFormula number1, FloatingPointFormula number2) { - return subtract(number1, number2, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("subtract(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.subtract(number1, number2)); } @Override @@ -317,7 +358,10 @@ public FloatingPointFormula subtract( @Override public FloatingPointFormula divide(FloatingPointFormula number1, FloatingPointFormula number2) { - return divide(number1, number2, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("divide(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.divide(number1, number2)); } @Override @@ -337,7 +381,10 @@ public FloatingPointFormula divide( @Override public FloatingPointFormula multiply(FloatingPointFormula number1, FloatingPointFormula number2) { - return multiply(number1, number2, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN); + return logger.logDef( + "mgr.getFloatingPointFormulaManager()", + String.format("multiply(%s, %s)", logger.toVariable(number1), logger.toVariable(number2)), + () -> delegate.multiply(number1, number2)); } @Override diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java index a20edf6d60..6d512f7dd9 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceIntegerFormulaManager.java @@ -31,28 +31,34 @@ public class TraceIntegerFormulaManager @Override public IntegerFormula makeNumber(double number) { - return makeNumber(BigDecimal.valueOf(number)); + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("makeNumber(%s)", number), + () -> delegate.makeNumber(number)); } @Override public IntegerFormula makeNumber(BigDecimal number) { - return makeNumber(Rational.ofBigDecimal(number)); + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("makeNumber(new BigDecimal(\"%s\"))", number), + () -> delegate.makeNumber(number)); } @Override public IntegerFormula makeNumber(String pI) { - return makeNumber(new BigDecimal(pI)); + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("makeNumber(\"%s\")", pI), + () -> delegate.makeNumber(pI)); } @Override public IntegerFormula makeNumber(Rational pRational) { - if (pRational.isIntegral()) { - return makeNumber(pRational.getNum()); - } else { - var num = makeNumber(pRational.getNum()); - var den = makeNumber(pRational.getDen()); - return divide(num, den); - } + return logger.logDef( + "mgr.getIntegerFormulaManager()", + String.format("makeNumber(Rational.of(\"%s\"))", pRational), + () -> delegate.makeNumber(pRational)); } @Override From f3c083bd7fea4ba1d601e1cf99bacf5037b26d97 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 31 Aug 2025 00:15:17 +0200 Subject: [PATCH 83/89] Trace: Error-prone, checkstyle --- .../java_smt/delegate/trace/TraceFormulaManager.java | 7 +++++-- src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java | 8 ++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index a3decef3c9..14f526df64 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -10,6 +10,9 @@ package org.sosy_lab.java_smt.delegate.trace; +import static org.sosy_lab.common.collect.Collections3.transformedImmutableListCopy; +import static org.sosy_lab.common.collect.Collections3.transformedImmutableSetCopy; + import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; @@ -221,11 +224,11 @@ public T rebuild(T f) { } public List rebuildAll(List formulas) { - return FluentIterable.from(formulas).transform(this::rebuild).toList(); + return transformedImmutableListCopy(formulas, this::rebuild); } public Set rebuildAll(Set formulas) { - return FluentIterable.from(formulas).transform(this::rebuild).toSet(); + return transformedImmutableSetCopy(formulas, this::rebuild); } @Override diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java index 1fdaf64a19..a289ff9e5d 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceLogger.java @@ -101,8 +101,8 @@ public void appendStmt(String pStmt) { try { lastLines.push(output.length()); output.write(String.format("%s;%n", pStmt).getBytes(StandardCharsets.UTF_8)); - } catch (IOException pIOException) { - throw new RuntimeException(pIOException); + } catch (IOException e) { + throw new RuntimeException(e); } } @@ -110,8 +110,8 @@ public void undoLast() { Preconditions.checkArgument(!lastLines.isEmpty(), "Cannot undo last trace"); try { output.setLength(lastLines.pop()); - } catch (IOException pE) { - throw new RuntimeException(pE); + } catch (IOException e) { + throw new RuntimeException(e); } } From fc625ad7338bea2edaf196f23575346a2e3d71f5 Mon Sep 17 00:00:00 2001 From: Karlheinz Friedberger Date: Sun, 31 Aug 2025 00:09:45 +0200 Subject: [PATCH 84/89] Trace: rename trace-files in Junit-tests to match the corresponding test-name. --- .../java_smt/test/ModelEvaluationTest.java | 3 ++- .../test/NonLinearArithmeticTest.java | 3 ++- .../NonLinearArithmeticWithModuloTest.java | 3 ++- .../java_smt/test/OptimizationTest.java | 3 ++- .../java_smt/test/SolverBasedTest0.java | 23 +++++++++++++++++-- 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/org/sosy_lab/java_smt/test/ModelEvaluationTest.java b/src/org/sosy_lab/java_smt/test/ModelEvaluationTest.java index 8974490f3d..50730295c7 100644 --- a/src/org/sosy_lab/java_smt/test/ModelEvaluationTest.java +++ b/src/org/sosy_lab/java_smt/test/ModelEvaluationTest.java @@ -17,6 +17,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.junit.Test; import org.sosy_lab.common.configuration.ConfigurationBuilder; +import org.sosy_lab.common.configuration.InvalidConfigurationException; import org.sosy_lab.common.rationals.Rational; import org.sosy_lab.java_smt.SolverContextFactory.Solvers; import org.sosy_lab.java_smt.api.BooleanFormula; @@ -51,7 +52,7 @@ public class ModelEvaluationTest extends SolverBasedTest0.ParameterizedSolverBas private static int problemSize; @Override - protected ConfigurationBuilder createTestConfigBuilder() { + protected ConfigurationBuilder createTestConfigBuilder() throws InvalidConfigurationException { problemSize = solverToUse() == Solvers.PRINCESS ? 10 : 50; // Princess is too slow. ConfigurationBuilder builder = super.createTestConfigBuilder(); if (solverToUse() == Solvers.MATHSAT5) { diff --git a/src/org/sosy_lab/java_smt/test/NonLinearArithmeticTest.java b/src/org/sosy_lab/java_smt/test/NonLinearArithmeticTest.java index 74e9fec1b9..b33bdab575 100644 --- a/src/org/sosy_lab/java_smt/test/NonLinearArithmeticTest.java +++ b/src/org/sosy_lab/java_smt/test/NonLinearArithmeticTest.java @@ -25,6 +25,7 @@ import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import org.sosy_lab.common.configuration.ConfigurationBuilder; +import org.sosy_lab.common.configuration.InvalidConfigurationException; import org.sosy_lab.java_smt.SolverContextFactory.Solvers; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.FormulaType; @@ -91,7 +92,7 @@ public void chooseNumeralFormulaManager() { public NonLinearArithmetic nonLinearArithmetic; @Override - protected ConfigurationBuilder createTestConfigBuilder() { + protected ConfigurationBuilder createTestConfigBuilder() throws InvalidConfigurationException { return super.createTestConfigBuilder() .setOption("solver.nonLinearArithmetic", nonLinearArithmetic.name()); } diff --git a/src/org/sosy_lab/java_smt/test/NonLinearArithmeticWithModuloTest.java b/src/org/sosy_lab/java_smt/test/NonLinearArithmeticWithModuloTest.java index c4b595d93d..eff809358d 100644 --- a/src/org/sosy_lab/java_smt/test/NonLinearArithmeticWithModuloTest.java +++ b/src/org/sosy_lab/java_smt/test/NonLinearArithmeticWithModuloTest.java @@ -22,6 +22,7 @@ import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; import org.sosy_lab.common.configuration.ConfigurationBuilder; +import org.sosy_lab.common.configuration.InvalidConfigurationException; import org.sosy_lab.java_smt.SolverContextFactory.Solvers; import org.sosy_lab.java_smt.api.BooleanFormula; import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; @@ -53,7 +54,7 @@ protected Solvers solverToUse() { public NonLinearArithmetic nonLinearArithmetic; @Override - protected ConfigurationBuilder createTestConfigBuilder() { + protected ConfigurationBuilder createTestConfigBuilder() throws InvalidConfigurationException { return super.createTestConfigBuilder() .setOption("solver.nonLinearArithmetic", nonLinearArithmetic.name()); } diff --git a/src/org/sosy_lab/java_smt/test/OptimizationTest.java b/src/org/sosy_lab/java_smt/test/OptimizationTest.java index ca2beefc6d..efc7646b6e 100644 --- a/src/org/sosy_lab/java_smt/test/OptimizationTest.java +++ b/src/org/sosy_lab/java_smt/test/OptimizationTest.java @@ -16,6 +16,7 @@ import org.junit.Before; import org.junit.Test; import org.sosy_lab.common.configuration.ConfigurationBuilder; +import org.sosy_lab.common.configuration.InvalidConfigurationException; import org.sosy_lab.common.rationals.Rational; import org.sosy_lab.java_smt.SolverContextFactory.Solvers; import org.sosy_lab.java_smt.api.Model; @@ -29,7 +30,7 @@ public class OptimizationTest extends SolverBasedTest0.ParameterizedSolverBasedTest0 { @Override - protected ConfigurationBuilder createTestConfigBuilder() { + protected ConfigurationBuilder createTestConfigBuilder() throws InvalidConfigurationException { return super.createTestConfigBuilder().setOption("solver.mathsat5.loadOptimathsat5", "true"); } diff --git a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java index b2a670f739..2e970f93f1 100644 --- a/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java +++ b/src/org/sosy_lab/java_smt/test/SolverBasedTest0.java @@ -19,6 +19,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.After; import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TestName; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; @@ -27,7 +29,10 @@ import org.sosy_lab.common.ShutdownNotifier; import org.sosy_lab.common.configuration.Configuration; import org.sosy_lab.common.configuration.ConfigurationBuilder; +import org.sosy_lab.common.configuration.FileOption; import org.sosy_lab.common.configuration.InvalidConfigurationException; +import org.sosy_lab.common.configuration.converters.FileTypeConverter; +import org.sosy_lab.common.io.PathTemplate; import org.sosy_lab.common.log.LogManager; import org.sosy_lab.java_smt.SolverContextFactory; import org.sosy_lab.java_smt.SolverContextFactory.Solvers; @@ -88,6 +93,8 @@ @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification = "test code") public abstract class SolverBasedTest0 { + @Rule public TestName testName = new TestName(); + protected Configuration config; protected final LogManager logger = LogManager.createTestLogManager(); @@ -123,14 +130,26 @@ protected Logics logicToUse() { return Logics.QF_AUFLIRA; } - protected ConfigurationBuilder createTestConfigBuilder() { + protected ConfigurationBuilder createTestConfigBuilder() throws InvalidConfigurationException { + String tracefile = + String.format( + "traces/%s/trace_%s_%s.java", + this.getClass().getSimpleName(), testName.getMethodName(), System.nanoTime()); + ConfigurationBuilder newConfig = Configuration.builder() .setOption("solver.solver", solverToUse().toString()) - .setOption("solver.trace", "true"); + .setOption("solver.trace", "true") + .setOption("solver.tracefile", tracefile); if (solverToUse() == Solvers.OPENSMT) { newConfig.setOption("solver.opensmt.logic", logicToUse().toString()); } + + Configuration configForFiles = Configuration.builder().setOption("output.path", "./").build(); + FileTypeConverter fileTypeConverter = FileTypeConverter.create(configForFiles); + Configuration.getDefaultConverters().put(FileOption.class, fileTypeConverter); + newConfig.addConverter(PathTemplate.class, fileTypeConverter); + return newConfig; } From e4694aed612f9694e1cf8f0743fb10c5addf3868 Mon Sep 17 00:00:00 2001 From: Karlheinz Friedberger Date: Sun, 31 Aug 2025 00:18:37 +0200 Subject: [PATCH 85/89] Trace: use traces as test artifact. --- .appveyor.yml | 4 ++++ build/gitlab-ci.yml | 2 ++ 2 files changed, 6 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index 797eb36576..d5be0d5474 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -77,6 +77,10 @@ on_finish: echo "Compressing and uploading JUnit HTML report..." 7z a JUnit.html.zip JUnit.html Push-AppveyorArtifact JUnit.html.zip -DeploymentName "JUnit Report" + - ps: | + echo "Compressing and uploading trace files..." + 7z a traces.zip .\traces + Push-AppveyorArtifact traces.zip -DeploymentName "Traces" cache: - C:\ant diff --git a/build/gitlab-ci.yml b/build/gitlab-ci.yml index 292167666f..98a5ebc0f2 100644 --- a/build/gitlab-ci.yml +++ b/build/gitlab-ci.yml @@ -130,6 +130,7 @@ spotbugs: - "JUnit.html" - "JUnit-coverage/" - "junit/coverage.xml" + - "traces/" when: always reports: junit: "junit/TESTS-TestSuites.xml" @@ -141,6 +142,7 @@ spotbugs: artifacts: paths: - "JUnit.html" # no coverage files available + - "traces/" unit-tests:x86_64:jdk-11: extends: .unit-tests From 0efb1531d2491b46f041e67bbb54d48ee7918768 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 31 Aug 2025 09:35:30 +0200 Subject: [PATCH 86/89] Trace: Add python script for trace reduction --- scripts/reduceTrace.py | 128 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100755 scripts/reduceTrace.py diff --git a/scripts/reduceTrace.py b/scripts/reduceTrace.py new file mode 100755 index 0000000000..1645b4c648 --- /dev/null +++ b/scripts/reduceTrace.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 + +# This file is part of JavaSMT, +# an API wrapper for a collection of SMT solvers: +# https://github.com/sosy-lab/java-smt +# +# SPDX-FileCopyrightText: 2025 Dirk Beyer +# +# SPDX-License-Identifier: Apache-2.0 + +import re +import sys +from collections import defaultdict +from pathlib import Path + + +# Read a trace file +def readTrace(path): + with open(path) as file: + return [line.rstrip() for line in file] + + +# Build a map with line numbers for all variable definitions +def getLinesForDefinitions(trace): + lineNumber = 1 + lineDefs = dict() + for line in trace: + if line.find('=') >= 0: + leftSide = line[0:(line.find('=') - 1)] + name = re.match('var (.*)', leftSide) + lineDefs[name.group(1)] = lineNumber + lineNumber = lineNumber + 1 + return lineDefs + + +# Build a dependency graph for the definitions +# Maps from variables to the places where they are used +def buildDependencies(lineDefs, trace): + lineNumber = 1 + deps = defaultdict(list) + for line in trace: + expr = line[(line.find('=') + 2):] if line.find('=') >= 0 else line + object = expr[0:expr.find('.')] + if object[0].islower(): + deps[lineDefs[object]].append(lineNumber) + # FIXME Parse the expression to get the variables + for m in re.finditer('(config|logger|notifier|var[0-9]+)', expr): + deps[lineDefs[m.group()]].append(lineNumber) + lineNumber += 1 + return deps + + +# Collect all top-level statements +# Top-level statements are: +# *.addConstraint(*) +# *.isUnsat() +# *.getModel() +# *.asList() +# FIXME Finish this list +def usedTopLevel(lineDefs, trace): + tl = set() + for line in trace: + m = re.fullmatch( + 'var (var[0-9]+) = (var[0-9]+).(isUnsat\\(\\)|getModel\\(\\)|asList\\(\\)|addConstraint\\((var[0-9]+)\\));', + line) + if m != None: + tl.add(lineDefs[m.group(1)]) + return tl + + +# Calculate the closure of all used definitions, starting with the top-level statements +def usedClosure(tl, deps): + cl = set() + st = set(tl) + while cl.union(st) != cl: + cl = cl.union(st) + st = set() + for (key, val) in deps.items(): + if set(val).intersection(cl) != set(): + st.add(key) + return cl + + +# Keep only statements and definitions that are used +def filterUnused(used, trace): + lineNumber = 1 + reduced = [] + for line in trace: + if line.find('=') == -1 or lineNumber in used: + reduced.append(line) + lineNumber += 1 + return reduced + + +# Remove all definitions that are not used (recursively) +def removeDeadCode(trace): + lineDefs = getLinesForDefinitions(trace) + deps = buildDependencies(lineDefs, trace) + tl = usedTopLevel(lineDefs, trace) + cl = usedClosure(tl, deps) + return filterUnused(cl, trace) + + +if __name__ == '__main__': + arg = sys.argv + if not len(sys.argv) == 2: + print('Expecting a path to a trace file as argument') + exit(-1) + + path = Path(sys.argv[1]) + if not (path.is_file()): + print(f'Could not find file "{path}"') + exit(-1) + + # We'll use multiple passes to reduce the size of the trace: + # 1. Read the trace + # 2. Remove unused code + # 3. Remove unnecessary toplevel commands + # 4. Loop: Remove aliasing (by duplicating the definitions) + # 5. Loop: Reduce terms + # 6. Remove unused prover environments + + # TODO Implement steps 3-6 + # TODO Check that the reduced trace still crashes + + trace = readTrace(path) + for line in removeDeadCode(trace): + print(line) From c34023fd082aad02fad37c969978074aebc0a135 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 31 Aug 2025 12:11:44 +0200 Subject: [PATCH 87/89] Trace: Rewrite to_real as unary sum --- .../java_smt/delegate/trace/TraceFormulaManager.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java index 14f526df64..a3664711c7 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceFormulaManager.java @@ -555,9 +555,10 @@ public T makeApplication( break; case GTE_ZERO: break; - case TO_REAL: - break; */ + case TO_REAL: + return (T) + getRationalFormulaManager().sum(ImmutableList.of((NumeralFormula) args.get(0))); case FLOOR: { if (args.get(0) instanceof IntegerFormula) { From 4aa4c4eef72b25842b520629774bacd556cacf7a Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 31 Aug 2025 12:20:39 +0200 Subject: [PATCH 88/89] Trace: Skip the 0 term when building sums --- .../basicimpl/AbstractNumeralFormulaManager.java | 13 +++++++++---- .../solvers/z3/Z3NumeralFormulaManager.java | 2 ++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractNumeralFormulaManager.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractNumeralFormulaManager.java index 72d3e65574..70318fea94 100644 --- a/src/org/sosy_lab/java_smt/basicimpl/AbstractNumeralFormulaManager.java +++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractNumeralFormulaManager.java @@ -207,11 +207,16 @@ public ResultFormulaType sum(List operands) { } protected TFormulaInfo sumImpl(List operands) { - TFormulaInfo result = makeNumberImpl(0); - for (TFormulaInfo operand : operands) { - result = add(result, operand); + if (operands.isEmpty()) { + return makeNumberImpl(0); + } else { + TFormulaInfo result = operands.get(0); + ; + for (TFormulaInfo operand : operands.subList(1, operands.size())) { + result = add(result, operand); + } + return result; } - return result; } @Override diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3NumeralFormulaManager.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3NumeralFormulaManager.java index ea834fbdb1..218e50a8e1 100644 --- a/src/org/sosy_lab/java_smt/solvers/z3/Z3NumeralFormulaManager.java +++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3NumeralFormulaManager.java @@ -74,6 +74,8 @@ protected Long add(Long pNumber1, Long pNumber2) { protected Long sumImpl(List operands) { if (operands.isEmpty()) { return makeNumberImpl(0); + } else if (operands.size() == 1) { + return operands.get(0); } else { return Native.mkAdd(z3context, operands.size(), Longs.toArray(operands)); } From aa7d584184e7c7e2ab6069fd291d059a95377591 Mon Sep 17 00:00:00 2001 From: Daniel Raffler Date: Sun, 31 Aug 2025 12:21:16 +0200 Subject: [PATCH 89/89] Trace: Simplify the arguments in UF calls --- .../java_smt/delegate/trace/TraceUFManager.java | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java index 76d3950935..4620c6e8f9 100644 --- a/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java +++ b/src/org/sosy_lab/java_smt/delegate/trace/TraceUFManager.java @@ -64,19 +64,12 @@ public FunctionDeclaration declareUF( public T callUF( FunctionDeclaration funcType, List args) { if (funcType.getKind().equals(FunctionDeclarationKind.UF)) { - String var = logger.newVariable(); - logger.appendDef( - var, + return logger.logDef( + "mgr.getUFManager", String.format( "callUF(%s, ImmutableList.of(%s))", - logger.toVariable(funcType), logger.toVariables(args))); - T f = delegate.callUF(funcType, args); - if (logger.isTracked(f)) { - logger.undoLast(); - } else { - logger.mapVariable(var, f); - } - return f; + logger.toVariable(funcType), logger.toVariables(args)), + () -> delegate.callUF(funcType, args)); } else { return mgr.makeApplication(funcType, args); }