mirror of
https://github.com/Z3Prover/z3
synced 2026-02-22 16:27:37 +00:00
Add missing API methods across language bindings (discussion #8701)
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
parent
50f3051054
commit
8d79e21aa7
9 changed files with 406 additions and 1 deletions
8
src/api/js/package-lock.json
generated
8
src/api/js/package-lock.json
generated
|
|
@ -74,6 +74,7 @@
|
|||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz",
|
||||
"integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.1.0",
|
||||
"@babel/code-frame": "^7.18.6",
|
||||
|
|
@ -1552,7 +1553,8 @@
|
|||
"version": "17.0.45",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
|
||||
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@types/prettier": {
|
||||
"version": "2.7.1",
|
||||
|
|
@ -1926,6 +1928,7 @@
|
|||
"url": "https://tidelift.com/funding/github/npm/browserslist"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001400",
|
||||
"electron-to-chromium": "^1.4.251",
|
||||
|
|
@ -3312,6 +3315,7 @@
|
|||
"resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz",
|
||||
"integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/core": "^28.1.3",
|
||||
"@jest/types": "^28.1.3",
|
||||
|
|
@ -6540,6 +6544,7 @@
|
|||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
|
||||
"integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
|
|
@ -6659,6 +6664,7 @@
|
|||
"integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
|
|
|
|||
|
|
@ -2100,6 +2100,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();
|
||||
_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)));
|
||||
|
|
@ -2220,6 +2293,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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1158,6 +1158,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.
|
||||
|
|
@ -1304,6 +1403,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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue