Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
0e4656f
Trace: Add API tracing
daniel-raffler Aug 14, 2025
f7ef298
Trace: Apply error-prone patch
daniel-raffler Aug 14, 2025
9acb1d7
Trace: Fix checkstyle issues
daniel-raffler Aug 14, 2025
63f2864
Trace: Log prover creation
daniel-raffler Aug 14, 2025
0b0e604
Trace: Write trace directly to a file
daniel-raffler Aug 15, 2025
4080a59
Trace: Fix prefix in ArrayFormulaManager.equivalence
daniel-raffler Aug 15, 2025
40d81d2
Trace: Use full path when printing ProverOptions in the trace
daniel-raffler Aug 15, 2025
84c7143
Trace: Log creation of the solver context
daniel-raffler Aug 15, 2025
28575eb
Trace: Log access to the model
daniel-raffler Aug 15, 2025
e7dfc70
Trace: Apply error-prone patch
daniel-raffler Aug 15, 2025
010fb1e
Trace: Remove ;
daniel-raffler Aug 15, 2025
8ac6c0c
Trace: Add "resource" annotation for TraceModel.getModel
daniel-raffler Aug 15, 2025
d2958ed
Trace: Add a superclass TraceBasicProverEnvironment for TraceProverEn…
daniel-raffler Aug 15, 2025
fb252cd
Trace: Apply error-prone patch
daniel-raffler Aug 15, 2025
fef1635
Trace: Add bitvector support
daniel-raffler Aug 19, 2025
cb7a7d2
Trace: Add floating point support
daniel-raffler Aug 19, 2025
7c432fc
Trace: Specify the solver backend in the trace when creating a new co…
daniel-raffler Aug 19, 2025
c676391
Trace: Add a note
daniel-raffler Aug 19, 2025
299c901
Trace: Add printing support for ArrayFormulaTypes
daniel-raffler Aug 20, 2025
d229219
Trace: Catch I/O exceptions directly in the logger
daniel-raffler Aug 20, 2025
a187568
Trace: Add support for visitors
daniel-raffler Aug 20, 2025
0590364
Trace: Allow parsing and printing
daniel-raffler Aug 20, 2025
b0dd829
Trace: Fix checkstyle issue
daniel-raffler Aug 21, 2025
2ed82e5
Trace: Throw an exception when trying to get the variable for an obje…
daniel-raffler Aug 21, 2025
3ce7e7b
Trace: Make TraceLogger package-private
daniel-raffler Aug 21, 2025
2d35c3d
Trace: Add support for printing more formula types
daniel-raffler Aug 21, 2025
b273c25
Trace: Apply refaster patch
daniel-raffler Aug 21, 2025
c7c15bf
Trace: Remove duplicate "." when creating a trace for the configurati…
daniel-raffler Aug 23, 2025
01cb338
Trace: Refactor code and rebuild all terms that are returned by the s…
daniel-raffler Aug 24, 2025
3df3d88
Trace: Add support for array constants
daniel-raffler Aug 24, 2025
6ad67ab
Trace: Avoid catching runtime exceptions while logging
daniel-raffler Aug 24, 2025
ab245e7
Trace: Add support for BooleanFormulaManager.xor
daniel-raffler Aug 24, 2025
f5f8f0f
Trace: Add support for BooleanFormulaManager.extractVariablesAndUFs
daniel-raffler Aug 24, 2025
018dbb8
Trace: Add support for creating integer constants from Strings
daniel-raffler Aug 24, 2025
01871ac
Trace: Add some missing logging for methods in TraceFormulaManager
daniel-raffler Aug 24, 2025
bfc4a76
Trace: Make constructor for TraceFloatingPointFormulaManager package-…
daniel-raffler Aug 24, 2025
adb0cbc
Trace: Add support for creating FloatingPointFormulas from BigDecimals
daniel-raffler Aug 24, 2025
73f6797
Trace: Fix default rounding mode for BigDecimals
daniel-raffler Aug 24, 2025
69f637e
Trace: Add support for equality on array formulas
daniel-raffler Aug 24, 2025
9208bb3
Trace: Add support for boolean formula visitors
daniel-raffler Aug 24, 2025
9065812
Trace: Add FormulaManager.simplify
daniel-raffler Aug 24, 2025
2c2ca35
Trace: Add UFManager.declareAndCallUF
daniel-raffler Aug 24, 2025
47e9376
Trace: Add modulo, distinct and sum from IntegerFormulaManager
daniel-raffler Aug 24, 2025
ac6486d
Trace: Add FormulaManager.substitute
daniel-raffler Aug 24, 2025
01cc106
Trace: Add ProverEnvironment.isUnsatWithAssumptions
daniel-raffler Aug 24, 2025
ff2faf2
Trace: Add FormulaManager.applyTactic
daniel-raffler Aug 24, 2025
cb53d59
Trace: Add isValidName, escape and unescape from FormulaManager
daniel-raffler Aug 24, 2025
22d532c
Trace: Avoid using String.split
daniel-raffler Aug 24, 2025
f30f694
Trace: Add toConjunctionArgs and toDisjunctionArgs from BooleanFormul…
daniel-raffler Aug 24, 2025
0b36ff2
Trace: Add toConjunction and toDisjunction
daniel-raffler Aug 24, 2025
d57db88
Trace: Extract terms from to model
daniel-raffler Aug 24, 2025
49cb3bd
Trace: Always print the term kind if we encounter an unsupported term…
daniel-raffler Aug 24, 2025
b2fda6d
Trace: Store backtracking points for the logger on a stack
daniel-raffler Aug 24, 2025
3e3540e
Trace: Add support for unsat core
daniel-raffler Aug 24, 2025
959abe9
Trace: Inline logger calls in addConstraint, isUnsat, isUnstaWithAssu…
daniel-raffler Aug 24, 2025
e7fae4e
Trace: Check operator arity in the visitor
daniel-raffler Aug 24, 2025
feb9e8f
Trace: Add guards for binary operators that should really allow an ar…
daniel-raffler Aug 24, 2025
3a56e85
Trace: Add missing "." when printing the names of Tactics to the log
daniel-raffler Aug 24, 2025
f00a5a0
Trace: Fix a bug in TraceLogger.logDef
daniel-raffler Aug 24, 2025
da00665
Trace: Improve error messages when checking the arity of an unknown o…
daniel-raffler Aug 24, 2025
7bcef2f
Trace: Don't rewrite and/or terms with more than 2 arguments
daniel-raffler Aug 24, 2025
7169aca
Trace: Fix a bug in TraceFormulaManager.makeVariable
daniel-raffler Aug 25, 2025
10c38f6
Trace: Add support for rational formulas
daniel-raffler Aug 25, 2025
e1dff26
Trace: Inline logging in FormulaManager.applyTactic to avoid catching…
daniel-raffler Aug 25, 2025
f6f477f
Trace: Suppress warnings
daniel-raffler Aug 25, 2025
e79a09e
Trace: Use ArrayDeque instead of Stack
daniel-raffler Aug 25, 2025
bdf22c0
TraceLogger: improve tracefiles with FileOption, and id with UniqueId…
kfriedberger Aug 28, 2025
33a9d03
fix Checkstyle warnings and improve code style
kfriedberger Aug 28, 2025
2db4144
shorten some code with utility methods.
kfriedberger Aug 28, 2025
1c1108d
enable tracing for all unit tests, testwise.
kfriedberger Aug 28, 2025
4129a90
fix invalid argument dump
kfriedberger Aug 28, 2025
8bdc475
Trace: Use makeApplication to handle non-UF calls to TraceUFManager.c…
daniel-raffler Aug 30, 2025
1168f3b
Trace: Filter out values for local definitions from the Z3 model
daniel-raffler Aug 30, 2025
62766ea
Trace: Skip the division when creating an IntegerFormula from a Ratio…
daniel-raffler Aug 30, 2025
7ed9a90
Trace: Handle BigInteger values for RationalFormula constants
daniel-raffler Aug 30, 2025
1f562f1
Trace: Restore the check in the function visitor that makes sure the …
daniel-raffler Aug 30, 2025
243fdd9
Trace: Fix floating point operations and skip the rounding mode argument
daniel-raffler Aug 30, 2025
da7582e
Trace: Remove a todo about rounding mode kinds
daniel-raffler Aug 30, 2025
36e8bc8
Merge remote-tracking branch 'origin/master' into HEAD
kfriedberger Aug 30, 2025
9d23d09
add "/traces" to gitignore.
kfriedberger Aug 29, 2025
817ba20
Trace: implement tracing for EnumerationFMgr.
kfriedberger Aug 30, 2025
e4bf4d5
Trace: Avoid upcasting to rational if both sides of an equation are i…
daniel-raffler Aug 30, 2025
c593988
Add more methods for Trace-*-FormulaManager to directly dump usage of…
kfriedberger Aug 30, 2025
f3c083b
Trace: Error-prone, checkstyle
daniel-raffler Aug 30, 2025
fc625ad
Trace: rename trace-files in Junit-tests to match the corresponding t…
kfriedberger Aug 30, 2025
e4694ae
Trace: use traces as test artifact.
kfriedberger Aug 30, 2025
0efb153
Trace: Add python script for trace reduction
daniel-raffler Aug 31, 2025
c34023f
Trace: Rewrite to_real as unary sum
daniel-raffler Aug 31, 2025
4aa4c4e
Trace: Skip the 0 term when building sums
daniel-raffler Aug 31, 2025
aa7d584
Trace: Simplify the arguments in UF calls
daniel-raffler Aug 31, 2025
98055ae
Merge remote-tracking branch 'origin/master' into HEAD
kfriedberger Sep 16, 2025
4b3f03f
fix compiler warning.
kfriedberger Sep 16, 2025
aa51b7e
simplify Trace*FormulaManagers by not overriding default methods from…
kfriedberger Aug 30, 2025
52b2040
Tracing: add TraceSLFormulaManager.
kfriedberger Sep 16, 2025
6919305
Tracing: add TraceQuantifiedFormulaManager.
kfriedberger Sep 16, 2025
9dd1f3e
Tracing: add TraceStringFormulaManager.
kfriedberger Sep 16, 2025
78a1176
Tracing: initial application for String formulas.
kfriedberger Sep 16, 2025
1262c65
Tracing: support more string operations.
kfriedberger Sep 16, 2025
b03045c
Tracing: simplify inherited methods.
kfriedberger Sep 16, 2025
0766916
fix CheckStyle warnings.
kfriedberger Sep 17, 2025
3be04cd
Tracing: more support for String theory.
kfriedberger Sep 17, 2025
f2531f5
Tracing: disable tracing for Boolector in tests.
kfriedberger Sep 17, 2025
29101ed
Tracing: extend FunctionDeclarationKind with UBV_TO_INT and SBV_TO_INT.
kfriedberger Sep 17, 2025
124d01c
Tracing: extend FunctionDeclarationKind with SL operations.
kfriedberger Sep 17, 2025
f60403b
Tracing: removing unneeded brackets.
kfriedberger Sep 17, 2025
304f064
Tracing: add support for visiting quantified formulas.
kfriedberger Sep 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ solvers_maven_conf/*.asc
/Javadoc
/Javadoc-z3
/gh-pages
/traces

.idea/

Expand Down
2 changes: 2 additions & 0 deletions build/gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ spotbugs:
- "JUnit.html"
- "JUnit-coverage/"
- "junit/coverage.xml"
- "traces/"
when: always
reports:
junit: "junit/TESTS-TestSuites.xml"
Expand All @@ -143,6 +144,7 @@ spotbugs:
artifacts:
paths:
- "JUnit.html" # no coverage files available
- "traces/"

unit-tests:x86_64:jdk-11:
extends: .unit-tests
Expand Down
128 changes: 128 additions & 0 deletions scripts/reduceTrace.py
Original file line number Diff line number Diff line change
@@ -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 <https://www.sosy-lab.org>
#
# 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)
9 changes: 9 additions & 0 deletions src/org/sosy_lab/java_smt/SolverContextFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.")
Expand Down Expand Up @@ -230,6 +236,9 @@ public SolverContext generateContext(Solvers solverToCreate)
if (useDebugMode) {
context = new DebuggingSolverContext(solverToCreate, config, context);
}
if (trace) {
context = new TraceSolverContext(solverToCreate, config, context);
}
if (collectStatistics) {
// statistics need to be the most outer wrapping layer.
context = new StatisticsSolverContext(context);
Expand Down
15 changes: 15 additions & 0 deletions src/org/sosy_lab/java_smt/api/FunctionDeclarationKind.java
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ public enum FunctionDeclarationKind {
/** Cast a signed bitvector to a floating-point number. */
BV_SCASTTO_FP,

/** Convert an unsigned bitvector to integer. The result is in [0, 2^size - 1]. */
UBV_TO_INT,

/** Convert a signed bitvector to integer. The result is in [-2^(size-1), 2^(size-1) - 1]. */
SBV_TO_INT,

// Simple floating point operations

/** Negation of a floating point. */
Expand Down Expand Up @@ -304,6 +310,8 @@ public enum FunctionDeclarationKind {
STR_TO_CODE,
STR_LT,
STR_LE,

RE_NONE,
RE_PLUS,
RE_STAR,
RE_OPTIONAL,
Expand All @@ -314,6 +322,13 @@ public enum FunctionDeclarationKind {
RE_COMPLEMENT,
RE_DIFFERENCE,

// Separation logic
SEP_EMP,
SEP_NIL,
SEP_PTO,
SEP_STAR,
SEP_WAND,

// default case

/**
Expand Down
4 changes: 2 additions & 2 deletions src/org/sosy_lab/java_smt/api/SLFormulaManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ public interface SLFormulaManager {
*
* @param <AF> the type of the address formula.
* @param <AT> the type of the address formula type.
* @param pAdressType the type of the address formula.
* @param pAddressType the type of the address formula.
* @return a formula representing the "nil" element for the given address type.
*/
<AF extends Formula, AT extends FormulaType<AF>> AF makeNilElement(AT pAdressType);
<AF extends Formula, AT extends FormulaType<AF>> AF makeNilElement(AT pAddressType);
}
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,15 @@ public ResultFormulaType sum(List<ParamFormulaType> operands) {
}

protected TFormulaInfo sumImpl(List<TFormulaInfo> 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
Expand Down
100 changes: 100 additions & 0 deletions src/org/sosy_lab/java_smt/delegate/trace/TraceArrayFormulaManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* 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 <https://www.sosy-lab.org>
*
* 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;

@SuppressWarnings("MethodTypeParameterName")
public class TraceArrayFormulaManager implements ArrayFormulaManager {
private final ArrayFormulaManager delegate;
private final TraceLogger logger;

TraceArrayFormulaManager(ArrayFormulaManager pDelegate, TraceLogger pLogger) {
delegate = pDelegate;
logger = pLogger;
}

@Override
public <TI extends Formula, TE extends Formula> TE select(
ArrayFormula<TI, TE> 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 <TI extends Formula, TE extends Formula> ArrayFormula<TI, TE> store(
ArrayFormula<TI, TE> 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<TI>,
FTE extends FormulaType<TE>>
ArrayFormula<TI, TE> 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<TI>,
FTE extends FormulaType<TE>>
ArrayFormula<TI, TE> makeArray(FTI pIndexType, FTE pElementType, TE defaultElement) {
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
public <TI extends Formula, TE extends Formula> BooleanFormula equivalence(
ArrayFormula<TI, TE> pArray1, ArrayFormula<TI, TE> pArray2) {
return logger.logDef(
"mgr.getArrayFormulaManager()",
String.format(
"equivalence(%s, %s)", logger.toVariable(pArray1), logger.toVariable(pArray2)),
() -> delegate.equivalence(pArray1, pArray2));
}

@Override
public <TI extends Formula> FormulaType<TI> getIndexType(ArrayFormula<TI, ?> pArray) {
return delegate.getIndexType(pArray);
}

@Override
public <TE extends Formula> FormulaType<TE> getElementType(ArrayFormula<?, TE> pArray) {
return delegate.getElementType(pArray);
}
}
Loading