3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-02-22 16:27:37 +00:00

Merge pull request #8702 from Z3Prover/copilot/fix-issues-in-discussion-8701

Add missing solver/optimizer API bindings across language targets
This commit is contained in:
Nikolaj Bjorner 2026-02-20 09:28:50 -08:00 committed by GitHub
commit e2129a7b81
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 399 additions and 0 deletions

View file

@ -2147,6 +2147,79 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
return new AstVectorImpl(check(Z3.solver_get_trail(contextPtr, this.ptr)));
}
trailLevels(): number[] {
const trailVec = check(Z3.solver_get_trail(contextPtr, this.ptr));
const n = Z3.ast_vector_size(contextPtr, trailVec);
return check(Z3.solver_get_levels(contextPtr, this.ptr, trailVec, n));
}
async cube(vars?: AstVector<Name, Bool<Name>>, cutoff: number = 0xFFFFFFFF): Promise<AstVector<Name, Bool<Name>>> {
const tempVars = vars ?? new AstVectorImpl();
const result = await asyncMutex.runExclusive(() =>
check(Z3.solver_cube(contextPtr, this.ptr, tempVars.ptr, cutoff)),
);
return new AstVectorImpl(result);
}
async getConsequences(
assumptions: (Bool<Name> | AstVector<Name, Bool<Name>>)[],
variables: Expr<Name>[],
): Promise<[CheckSatResult, AstVector<Name, Bool<Name>>]> {
const asmsVec = new AstVectorImpl();
const varsVec = new AstVectorImpl();
const consVec = new AstVectorImpl<Bool<Name>>();
_flattenArgs(assumptions).forEach(expr => {
_assertContext(expr);
Z3.ast_vector_push(contextPtr, asmsVec.ptr, expr.ast);
});
variables.forEach(v => {
_assertContext(v);
Z3.ast_vector_push(contextPtr, varsVec.ptr, v.ast);
});
const r = await asyncMutex.runExclusive(() =>
check(Z3.solver_get_consequences(contextPtr, this.ptr, asmsVec.ptr, varsVec.ptr, consVec.ptr)),
);
let status: CheckSatResult;
switch (r) {
case Z3_lbool.Z3_L_FALSE:
status = 'unsat';
break;
case Z3_lbool.Z3_L_TRUE:
status = 'sat';
break;
default:
status = 'unknown';
}
return [status, consVec];
}
solveFor(variables: Expr<Name>[], terms: Expr<Name>[], guards: Bool<Name>[]): void {
const varsVec = new AstVectorImpl();
const termsVec = new AstVectorImpl();
const guardsVec = new AstVectorImpl();
variables.forEach(v => {
_assertContext(v);
Z3.ast_vector_push(contextPtr, varsVec.ptr, v.ast);
});
terms.forEach(t => {
_assertContext(t);
Z3.ast_vector_push(contextPtr, termsVec.ptr, t.ast);
});
guards.forEach(g => {
_assertContext(g);
Z3.ast_vector_push(contextPtr, guardsVec.ptr, g.ast);
});
Z3.solver_solve_for(contextPtr, this.ptr, varsVec.ptr, termsVec.ptr, guardsVec.ptr);
throwIfError();
}
setInitialValue(variable: Expr<Name>, value: Expr<Name>): void {
_assertContext(variable);
_assertContext(value);
Z3.solver_set_initial_value(contextPtr, this.ptr, variable.ast, value.ast);
throwIfError();
}
congruenceRoot(expr: Expr<Name>): Expr<Name> {
_assertContext(expr);
return _toExpr(check(Z3.solver_congruence_root(contextPtr, this.ptr, expr.ast)));
@ -2267,6 +2340,13 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
return new StatisticsImpl(check(Z3.optimize_get_statistics(contextPtr, this.ptr)));
}
setInitialValue(variable: Expr<Name>, value: Expr<Name>): void {
_assertContext(variable);
_assertContext(value);
Z3.optimize_set_initial_value(contextPtr, this.ptr, variable.ast, value.ast);
throwIfError();
}
toString() {
return check(Z3.optimize_to_string(contextPtr, this.ptr));
}

View file

@ -1190,6 +1190,105 @@ export interface Solver<Name extends string = 'main'> {
*/
trail(): AstVector<Name, Bool<Name>>;
/**
* Retrieve the decision levels for each literal in the solver's trail.
* The returned array has one entry per trail literal, indicating at which
* decision level it was assigned.
*
* @returns An array of numbers where element i is the decision level of the i-th trail literal
*
* @example
* ```typescript
* const solver = new Solver();
* const x = Bool.const('x');
* solver.add(x);
* await solver.check();
* const levels = solver.trailLevels();
* console.log('Trail levels:', levels);
* ```
*/
trailLevels(): number[];
/**
* Extract cubes from the solver for cube-and-conquer parallel solving.
* Each call returns the next cube (conjunction of literals) from the solver.
* Returns an empty AstVector when the search space is exhausted.
*
* @param vars - Optional vector of variables to use as cube variables
* @param cutoff - Backtrack level cutoff for cube generation (default: 0xFFFFFFFF)
* @returns A promise resolving to an AstVector containing the cube literals
*
* @example
* ```typescript
* const solver = new Solver();
* const x = Bool.const('x');
* const y = Bool.const('y');
* solver.add(x.or(y));
* const cube = await solver.cube(undefined, 1);
* console.log('Cube length:', cube.length());
* ```
*/
cube(vars?: AstVector<Name, Bool<Name>>, cutoff?: number): Promise<AstVector<Name, Bool<Name>>>;
/**
* Retrieve fixed assignments to a set of variables as consequences given assumptions.
* Each consequence is an implication: assumptions => variable = value.
*
* @param assumptions - Assumptions to use during consequence finding
* @param variables - Variables to find consequences for
* @returns A promise resolving to the status and a vector of consequence expressions
*
* @example
* ```typescript
* const solver = new Solver();
* const x = Bool.const('x');
* const y = Bool.const('y');
* solver.add(x.implies(y));
* const [status, consequences] = await solver.getConsequences([], [x, y]);
* ```
*/
getConsequences(
assumptions: (Bool<Name> | AstVector<Name, Bool<Name>>)[],
variables: Expr<Name>[],
): Promise<[CheckSatResult, AstVector<Name, Bool<Name>>]>;
/**
* Solve constraints treating given variables symbolically, replacing their
* occurrences by terms. Guards condition the substitutions.
*
* @param variables - Variables to solve for
* @param terms - Substitution terms for the variables
* @param guards - Boolean guards for the substitutions
*
* @example
* ```typescript
* const solver = new Solver();
* const x = Int.const('x');
* const y = Int.const('y');
* solver.add(x.eq(y.add(1)));
* solver.solveFor([x], [y.add(1)], []);
* ```
*/
solveFor(variables: Expr<Name>[], terms: Expr<Name>[], guards: Bool<Name>[]): void;
/**
* Set an initial value hint for a variable to guide the solver's search heuristics.
* This can improve performance when a good initial value is known.
*
* @param variable - The variable to set an initial value for
* @param value - The initial value for the variable
*
* @example
* ```typescript
* const solver = new Solver();
* const x = Int.const('x');
* solver.setInitialValue(x, Int.val(42));
* solver.add(x.gt(0));
* await solver.check();
* ```
*/
setInitialValue(variable: Expr<Name>, value: Expr<Name>): void;
/**
* Retrieve the root of the congruence class containing the given expression.
* This is useful for understanding equality reasoning in the solver.
@ -1357,6 +1456,25 @@ export interface Optimize<Name extends string = 'main'> {
statistics(): Statistics<Name>;
/**
* Set an initial value hint for a variable to guide the optimizer's search heuristics.
* This can improve performance when a good initial value is known.
*
* @param variable - The variable to set an initial value for
* @param value - The initial value for the variable
*
* @example
* ```typescript
* const opt = new Optimize();
* const x = Int.const('x');
* opt.setInitialValue(x, Int.val(42));
* opt.add(x.gt(0));
* opt.maximize(x);
* await opt.check();
* ```
*/
setInitialValue(variable: Expr<Name>, value: Expr<Name>): void;
/**
* Manually decrease the reference count of the optimize
* This is automatically done when the optimize is garbage collected,