Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
0cbf059
Indices: Extend the API to support indexed function symbols, such as …
daniel-raffler Aug 25, 2025
ded5888
Indices: Add support for indexed functions symbols to the solver back…
daniel-raffler Aug 25, 2025
d6b07be
Merge branch 'master' into indexed_functions
daniel-raffler Dec 2, 2025
ad9d945
Fix merge
daniel-raffler Dec 2, 2025
38655e6
Indices: Fix handling of bv_extract and bv_concat in Princess
daniel-raffler Dec 2, 2025
25335f3
Indices: Fix CVC5 visitor for sep.nil
daniel-raffler Dec 2, 2025
ff489e0
Merge branch 'refs/heads/master' into indexed_functions
daniel-raffler Feb 27, 2026
1c90042
Indices: Add support for new solver "Z3 with interpolation"
daniel-raffler Feb 27, 2026
a0fdbc1
Indices: Add tests for visiting indexed functions
daniel-raffler Feb 27, 2026
493cd94
Indices: Fix indices in CVC5 visitor
daniel-raffler Mar 28, 2026
699b0ba
Merge branch 'refs/heads/master' into indexed_functions
daniel-raffler Mar 28, 2026
b5406d7
Indices: Add support for indexed functions in the tracer
daniel-raffler Mar 28, 2026
8a5f5d3
Indices: Add support for indices in Yices, and update the tests
daniel-raffler Mar 28, 2026
ca554e3
Merge branch 'refs/heads/master' into indexed_functions
daniel-raffler Mar 29, 2026
0e184c2
Indices: Remove duplicate code
daniel-raffler Mar 29, 2026
bbae8f0
Apply refaster patch
daniel-raffler Mar 29, 2026
80ee861
Merge branch 'refs/heads/master' into indexed_functions
daniel-raffler Mar 29, 2026
2620a91
Merge branch 'master' into indexed_functions
daniel-raffler Jun 5, 2026
9cbe382
Merge branch 'master' into indexed_functions
daniel-raffler Aug 2, 2026
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
5 changes: 5 additions & 0 deletions src/org/sosy_lab/java_smt/api/FunctionDeclaration.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public interface FunctionDeclaration<E extends Formula> {
*/
String getName();

/**
* @return List of indices for the function
*/
ImmutableList<Integer> getIndices();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please extend the documentation for this interface method.
Here, we need some strong argument and description for differentiation between args and indices.


/**
* @return Sort of the function output.
*/
Expand Down
127 changes: 126 additions & 1 deletion src/org/sosy_lab/java_smt/api/FunctionDeclarationKind.java
Original file line number Diff line number Diff line change
Expand Up @@ -320,5 +320,130 @@ public enum FunctionDeclarationKind {
* Solvers support a lot of different built-in theories. We enforce standardization only across a
* small subset.
*/
OTHER
OTHER;

public static int getArity(FunctionDeclarationKind pKind) {
// TODO Add missing kinds
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));
}
}

public static int getNumIndices(FunctionDeclarationKind pKind) {
// TODO Add missing kinds
switch (pKind) {
case BV_ROTATE_LEFT_BY_INT:
case BV_ROTATE_RIGHT_BY_INT:
case BV_SIGN_EXTENSION:
case BV_ZERO_EXTENSION:
return 1;
case BV_EXTRACT:
return 2;
default:
return 0;
}
}
}
17 changes: 16 additions & 1 deletion src/org/sosy_lab/java_smt/basicimpl/FunctionDeclarationImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,26 @@ public abstract class FunctionDeclarationImpl<F extends Formula, T>
public static <F extends Formula, T> FunctionDeclaration<F> of(
String name,
FunctionDeclarationKind kind,
List<Integer> pIndices,
List<FormulaType<?>> pArgumentTypes,
FormulaType<F> pReturnType,
T pDeclaration) {
return new AutoValue_FunctionDeclarationImpl<>(
kind, name, pReturnType, ImmutableList.copyOf(pArgumentTypes), pDeclaration);
kind,
name,
ImmutableList.copyOf(pIndices),
pReturnType,
ImmutableList.copyOf(pArgumentTypes),
pDeclaration);
}

public static <F extends Formula, T> FunctionDeclaration<F> of(
String name,
FunctionDeclarationKind kind,
List<FormulaType<?>> pArgumentTypes,
FormulaType<F> pReturnType,
T pDeclaration) {
return of(name, kind, ImmutableList.of(), pArgumentTypes, pReturnType, pDeclaration);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,12 @@ public <R> R visit(FormulaVisitor<R> visitor, Formula formula, Term f)
formula,
arguments.build(),
FunctionDeclarationImpl.of(
name, getDeclarationKind(f), argumentTypes.build(), getFormulaType(f), decl));
name,
getDeclarationKind(f),
ImmutableList.copyOf(f.indices()),
argumentTypes.build(),
getFormulaType(f),
decl));
}
}

Expand Down
23 changes: 17 additions & 6 deletions src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,17 @@ public <R> R visit(FormulaVisitor<R> visitor, Formula formula, final Term f) {

List<FormulaType<?>> argsTypes = new ArrayList<>();

// Term operator = normalize(f.getSort());
// Collect indices
Op operator = f.getOp();
ImmutableList.Builder<Integer> indexBuilder = ImmutableList.builder();
for (int p = 0; p < operator.getNumIndices(); p++) {
Term index = operator.get(p);
if (index.isIntegerValue()) {
indexBuilder.add(index.getIntegerValue().intValueExact());
}
}

// Collect arguments
Kind kind = f.getKind();
if (sort.isFunction() || kind == Kind.APPLY_UF) {
// The arguments are all children except the first one
Expand All @@ -468,10 +478,6 @@ public <R> R visit(FormulaVisitor<R> visitor, Formula formula, final Term f) {
}
}

// TODO some operations (BV_SIGN_EXTEND, BV_ZERO_EXTEND, maybe more) encode information as
// part of the operator itself, thus the arity is one too small and there might be no
// possibility to access the information from user side. Should we encode such information
// as additional parameters? We do so for some methods of Princess.
if (sort.isFunction()) {
return visitor.visitFunction(
formula,
Expand All @@ -494,7 +500,12 @@ public <R> R visit(FormulaVisitor<R> visitor, Formula formula, final Term f) {
formula,
argsBuilder.build(),
FunctionDeclarationImpl.of(
getName(f), getDeclarationKind(f), argsTypes, getFormulaType(f), normalize(f)));
getName(f),
getDeclarationKind(f),
indexBuilder.build(),
argsTypes,
getFormulaType(f),
normalize(f)));
}
}
} catch (CVC5ApiException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_type_repr;

import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Longs;
Expand Down Expand Up @@ -348,6 +349,18 @@ public <R> R visit(FormulaVisitor<R> visitor, Formula formula, final Long f) {
return visitor.visitFreeVariable(formula, name);
}

// Collect indices: We need to extract them from the term name in MathSAT
FunctionDeclarationKind kind = getDeclarationKind(f);
List<String> tokens =
Splitter.on('_')
.splitToList(name.startsWith("`") ? name.substring(1, name.length() - 1) : name);

ImmutableList.Builder<Integer> indices = ImmutableList.builder();
for (int p = 1; p <= FunctionDeclarationKind.getNumIndices(kind); p++) {
indices.add(Integer.valueOf(tokens.get(p)));
}

// Now collect the arguments
ImmutableList.Builder<Formula> args = ImmutableList.builder();
ImmutableList.Builder<FormulaType<?>> argTypes = ImmutableList.builder();
for (int i = 0; i < arity; i++) {
Expand All @@ -365,7 +378,8 @@ public <R> R visit(FormulaVisitor<R> visitor, Formula formula, final Long f) {
args.build(),
FunctionDeclarationImpl.of(
name,
getDeclarationKind(f),
kind,
indices.build(),
argTypes.build(),
getFormulaType(f),
msat_term_get_decl(f)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -488,16 +488,13 @@ public <R> R visit(FormulaVisitor<R> visitor, final Formula f, final IExpression
}
}

ImmutableList.Builder<Formula> args = ImmutableList.builder();
ImmutableList.Builder<FormulaType<?>> argTypes = ImmutableList.builder();
int arity = input.length();
int arityStart = 0;
int numSortParameters = getNumSortParameters(kind);
int numIndices = FunctionDeclarationKind.getNumIndices(kind);

PrincessFunctionDeclaration solverDeclaration;
if (isBitvectorOperationWithAdditionalArgument(kind)) {
if (numSortParameters > 0) {
// the first argument is the bitsize, and it is not relevant for the user.
// we do not want type/sort information as arguments.
arityStart = 1;
if (input instanceof IAtom) {
solverDeclaration = new PrincessBitvectorToBooleanDeclaration(((IAtom) input).pred());
} else if (input instanceof IFunApp) {
Expand All @@ -518,7 +515,17 @@ public <R> R visit(FormulaVisitor<R> visitor, final Formula f, final IExpression
solverDeclaration = new PrincessByExampleDeclaration(input);
}

for (int i = arityStart; i < arity; i++) {
ImmutableList.Builder<Integer> indices = ImmutableList.builder();

for (int i = numSortParameters; i < numSortParameters + numIndices; i++) {
IExpression term = input.apply(i);
indices.add(((IIntLit) term).value().intValue());
}

ImmutableList.Builder<Formula> args = ImmutableList.builder();
ImmutableList.Builder<FormulaType<?>> argTypes = ImmutableList.builder();

for (int i = numSortParameters + numIndices; i < input.length(); i++) {
IExpression arg = input.apply(i);
FormulaType<?> argumentType = getFormulaType(arg);
args.add(encapsulate(argumentType, arg));
Expand All @@ -529,7 +536,12 @@ public <R> R visit(FormulaVisitor<R> visitor, final Formula f, final IExpression
f,
args.build(),
FunctionDeclarationImpl.of(
getName(input), kind, argTypes.build(), getFormulaType(f), solverDeclaration));
getName(input),
kind,
indices.build(),
argTypes.build(),
getFormulaType(f),
solverDeclaration));
}

private <R> R visitQuantifier(FormulaVisitor<R> visitor, BooleanFormula f, IQuantified input) {
Expand Down Expand Up @@ -569,7 +581,8 @@ private String getFreshVariableNameForBody(IFormula body) {
body, k -> "__JAVASMT__BOUND_VARIABLE_" + boundVariableNames.size());
}

private boolean isBitvectorOperationWithAdditionalArgument(FunctionDeclarationKind kind) {
private int getNumSortParameters(FunctionDeclarationKind kind) {
// TODO Check that his is still right
switch (kind) {
case BV_NOT:
case BV_NEG:
Expand All @@ -593,9 +606,14 @@ private boolean isBitvectorOperationWithAdditionalArgument(FunctionDeclarationKi
case BV_UGE:
case BV_SGE:
case BV_EQ:
return true;
case BV_LSHR:
case BV_ASHR:
case BV_SHL:
return 1;
case BV_CONCAT:
return 2;
default:
return false;
return 0;
}
}

Expand Down
13 changes: 12 additions & 1 deletion src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.microsoft.z3.Z3Exception;
import com.microsoft.z3.enumerations.Z3_ast_kind;
import com.microsoft.z3.enumerations.Z3_decl_kind;
import com.microsoft.z3.enumerations.Z3_param_kind;
import com.microsoft.z3.enumerations.Z3_sort_kind;
import com.microsoft.z3.enumerations.Z3_symbol_kind;
import java.lang.ref.PhantomReference;
Expand Down Expand Up @@ -492,7 +493,8 @@ public <R> R visit(FormulaVisitor<R> visitor, final Formula formula, final Long
return visitor.visitConstant(formula, convertValue(f));
case Z3_APP_AST:
int arity = Native.getAppNumArgs(environment, f);
int declKind = Native.getDeclKind(environment, Native.getAppDecl(environment, f));
long decl = Native.getAppDecl(environment, f);
int declKind = Native.getDeclKind(environment, decl);

if (arity == 0) {
// constants
Expand Down Expand Up @@ -538,6 +540,14 @@ public <R> R visit(FormulaVisitor<R> visitor, final Formula formula, final Long
}
}

ImmutableList.Builder<Integer> indexBuilder = ImmutableList.builder();
for (int p = 0; p < Native.getDeclNumParameters(environment, decl); p++) {
int kind = Native.getDeclParameterKind(environment, decl, p);
if (kind == Z3_param_kind.Z3_PK_UINT.toInt()) {
indexBuilder.add(Native.getDeclIntParameter(environment, decl, p));
}
}

// Function application with zero or more parameters
ImmutableList.Builder<Formula> args = ImmutableList.builder();
ImmutableList.Builder<FormulaType<?>> argTypes = ImmutableList.builder();
Expand All @@ -553,6 +563,7 @@ public <R> R visit(FormulaVisitor<R> visitor, final Formula formula, final Long
FunctionDeclarationImpl.of(
getAppName(f),
getDeclarationKind(f),
indexBuilder.build(),
argTypes.build(),
getFormulaType(f),
Native.getAppDecl(environment, f)));
Expand Down