3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-07-06 15:26:15 +00:00

Add AtMost, AtLeast, unsatCore, and reasonUnknown to JS/TS API (#8118)

* Initial plan

* Add AtMost, AtLeast, checkAssumptions, and unsatCore methods to JS/TS API

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* Format code with prettier

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* Add comprehensive documentation for Solver.check, checkAssumptions, and unsatCore methods

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* Remove redundant checkAssumptions method, use check() for assumptions

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* Enable unsat_core tracking in test to fix 'unknown' result

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* Add reasonUnknown() method and use it in test to debug unknown results

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
Co-authored-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Copilot 2026-01-08 19:53:08 -08:00 committed by Nikolaj Bjorner
parent b524f63957
commit c9528cc74e
3 changed files with 300 additions and 88 deletions

View file

@ -559,7 +559,10 @@ describe('high-level', () => {
const set = Z3.Set.const('set', Z3.Int.sort()); const set = Z3.Set.const('set', Z3.Int.sort());
const [a, b] = Z3.Int.consts('a b'); const [a, b] = Z3.Int.consts('a b');
const conjecture = set.contains(a).and(set.contains(b)).implies(Z3.Set.val([a, b], Z3.Int.sort()).subsetOf(set)); const conjecture = set
.contains(a)
.and(set.contains(b))
.implies(Z3.Set.val([a, b], Z3.Int.sort()).subsetOf(set));
await prove(conjecture); await prove(conjecture);
}); });
@ -569,7 +572,10 @@ describe('high-level', () => {
const set = Z3.Set.const('set', Z3.Int.sort()); const set = Z3.Set.const('set', Z3.Int.sort());
const [a, b] = Z3.Int.consts('a b'); const [a, b] = Z3.Int.consts('a b');
const conjecture = set.contains(a).and(set.contains(b)).and(Z3.Set.val([a, b], Z3.Int.sort()).eq(set)); const conjecture = set
.contains(a)
.and(set.contains(b))
.and(Z3.Set.val([a, b], Z3.Int.sort()).eq(set));
await solve(conjecture); await solve(conjecture);
}); });
@ -623,7 +629,7 @@ describe('high-level', () => {
const set = Z3.Set.const('set', Z3.Int.sort()); const set = Z3.Set.const('set', Z3.Int.sort());
const a = Z3.Int.const('a'); const a = Z3.Int.const('a');
const conjecture = set.complement().complement().eq(set) const conjecture = set.complement().complement().eq(set);
await prove(conjecture); await prove(conjecture);
}); });
it('Complement 2', async () => { it('Complement 2', async () => {
@ -632,7 +638,7 @@ describe('high-level', () => {
const set = Z3.Set.const('set', Z3.Int.sort()); const set = Z3.Set.const('set', Z3.Int.sort());
const a = Z3.Int.const('a'); const a = Z3.Int.const('a');
const conjecture = set.contains(a).implies(Z3.Not(set.complement().contains(a))) const conjecture = set.contains(a).implies(Z3.Not(set.complement().contains(a)));
await prove(conjecture); await prove(conjecture);
}); });
@ -642,7 +648,7 @@ describe('high-level', () => {
const [set1, set2] = Z3.Set.consts('set1 set2', Z3.Int.sort()); const [set1, set2] = Z3.Set.consts('set1 set2', Z3.Int.sort());
const a = Z3.Int.const('a'); const a = Z3.Int.const('a');
const conjecture = set1.contains(a).implies(Z3.Not(set2.diff(set1).contains(a))) const conjecture = set1.contains(a).implies(Z3.Not(set2.diff(set1).contains(a)));
await prove(conjecture); await prove(conjecture);
}); });
@ -793,6 +799,31 @@ describe('high-level', () => {
}); });
expect(results).toStrictEqual([1n, 2n, 3n, 4n, 5n]); expect(results).toStrictEqual([1n, 2n, 3n, 4n, 5n]);
}); });
it('can use check with assumptions and unsatCore', async () => {
const { Solver, Bool } = api.Context('main');
const solver = new Solver();
solver.set('unsat_core', true);
const x = Bool.const('x');
const y = Bool.const('y');
const z = Bool.const('z');
// Add conflicting assertions
solver.add(x.or(y));
solver.add(x.or(z));
// Check with assumptions that create a conflict
const result = await solver.check(x.not(), y.not(), z.not());
if (result === 'unknown') {
console.log('Solver returned unknown. Reason:', solver.reasonUnknown());
}
expect(result).toStrictEqual('unsat');
// Get the unsat core
const core = solver.unsatCore();
expect(core.length()).toBeGreaterThan(0);
expect(core.length()).toBeLessThanOrEqual(3);
});
}); });
describe('AstVector', () => { describe('AstVector', () => {

View file

@ -808,12 +808,12 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
sort<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSetSort<Name, ElemSort> { sort<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSetSort<Name, ElemSort> {
return Array.sort(sort, Bool.sort()); return Array.sort(sort, Bool.sort());
}, },
const<ElemSort extends AnySort<Name>>(name: string, sort: ElemSort) : SMTSet<Name, ElemSort> { const<ElemSort extends AnySort<Name>>(name: string, sort: ElemSort): SMTSet<Name, ElemSort> {
return new SetImpl<ElemSort>( return new SetImpl<ElemSort>(
check(Z3.mk_const(contextPtr, _toSymbol(name), Array.sort(sort, Bool.sort()).ptr)), check(Z3.mk_const(contextPtr, _toSymbol(name), Array.sort(sort, Bool.sort()).ptr)),
); );
}, },
consts<ElemSort extends AnySort<Name>>(names: string | string[], sort: ElemSort) : SMTSet<Name, ElemSort>[] { consts<ElemSort extends AnySort<Name>>(names: string | string[], sort: ElemSort): SMTSet<Name, ElemSort>[] {
if (typeof names === 'string') { if (typeof names === 'string') {
names = names.split(' '); names = names.split(' ');
} }
@ -822,14 +822,17 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
empty<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSet<Name, ElemSort> { empty<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSet<Name, ElemSort> {
return EmptySet(sort); return EmptySet(sort);
}, },
val<ElemSort extends AnySort<Name>>(values: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>[], sort: ElemSort): SMTSet<Name, ElemSort> { val<ElemSort extends AnySort<Name>>(
values: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>[],
sort: ElemSort,
): SMTSet<Name, ElemSort> {
var result = EmptySet(sort); var result = EmptySet(sort);
for (const value of values) { for (const value of values) {
result = SetAdd(result, value); result = SetAdd(result, value);
} }
return result; return result;
} },
} };
const Datatype = Object.assign( const Datatype = Object.assign(
(name: string): DatatypeImpl => { (name: string): DatatypeImpl => {
@ -838,8 +841,8 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
{ {
createDatatypes(...datatypes: DatatypeImpl[]): DatatypeSortImpl[] { createDatatypes(...datatypes: DatatypeImpl[]): DatatypeSortImpl[] {
return createDatatypes(...datatypes); return createDatatypes(...datatypes);
} },
} },
); );
//////////////// ////////////////
@ -1058,6 +1061,32 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
); );
} }
function AtMost(args: [Bool<Name>, ...Bool<Name>[]], k: number): Bool<Name> {
_assertContext(...args);
return new BoolImpl(
check(
Z3.mk_atmost(
contextPtr,
args.map(arg => arg.ast),
k,
),
),
);
}
function AtLeast(args: [Bool<Name>, ...Bool<Name>[]], k: number): Bool<Name> {
_assertContext(...args);
return new BoolImpl(
check(
Z3.mk_atleast(
contextPtr,
args.map(arg => arg.ast),
k,
),
),
);
}
function ForAll<QVarSorts extends NonEmptySortArray<Name>>( function ForAll<QVarSorts extends NonEmptySortArray<Name>>(
quantifiers: ArrayIndexType<Name, QVarSorts>, quantifiers: ArrayIndexType<Name, QVarSorts>,
body: Bool<Name>, body: Bool<Name>,
@ -1296,23 +1325,45 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
} }
function SetUnion<ElemSort extends AnySort<Name>>(...args: SMTSet<Name, ElemSort>[]): SMTSet<Name, ElemSort> { function SetUnion<ElemSort extends AnySort<Name>>(...args: SMTSet<Name, ElemSort>[]): SMTSet<Name, ElemSort> {
return new SetImpl<ElemSort>(check(Z3.mk_set_union(contextPtr, args.map(arg => arg.ast)))); return new SetImpl<ElemSort>(
check(
Z3.mk_set_union(
contextPtr,
args.map(arg => arg.ast),
),
),
);
} }
function SetIntersect<ElemSort extends AnySort<Name>>(...args: SMTSet<Name, ElemSort>[]): SMTSet<Name, ElemSort> { function SetIntersect<ElemSort extends AnySort<Name>>(...args: SMTSet<Name, ElemSort>[]): SMTSet<Name, ElemSort> {
return new SetImpl<ElemSort>(check(Z3.mk_set_intersect(contextPtr, args.map(arg => arg.ast)))); return new SetImpl<ElemSort>(
check(
Z3.mk_set_intersect(
contextPtr,
args.map(arg => arg.ast),
),
),
);
} }
function SetDifference<ElemSort extends AnySort<Name>>(a: SMTSet<Name, ElemSort>, b: SMTSet<Name, ElemSort>): SMTSet<Name, ElemSort> { function SetDifference<ElemSort extends AnySort<Name>>(
a: SMTSet<Name, ElemSort>,
b: SMTSet<Name, ElemSort>,
): SMTSet<Name, ElemSort> {
return new SetImpl<ElemSort>(check(Z3.mk_set_difference(contextPtr, a.ast, b.ast))); return new SetImpl<ElemSort>(check(Z3.mk_set_difference(contextPtr, a.ast, b.ast)));
} }
function SetAdd<ElemSort extends AnySort<Name>>(
function SetAdd<ElemSort extends AnySort<Name>>(set: SMTSet<Name, ElemSort>, elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): SMTSet<Name, ElemSort> { set: SMTSet<Name, ElemSort>,
elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>,
): SMTSet<Name, ElemSort> {
const arg = set.elemSort().cast(elem as any); const arg = set.elemSort().cast(elem as any);
return new SetImpl<ElemSort>(check(Z3.mk_set_add(contextPtr, set.ast, arg.ast))); return new SetImpl<ElemSort>(check(Z3.mk_set_add(contextPtr, set.ast, arg.ast)));
} }
function SetDel<ElemSort extends AnySort<Name>>(set: SMTSet<Name, ElemSort>, elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): SMTSet<Name, ElemSort> { function SetDel<ElemSort extends AnySort<Name>>(
set: SMTSet<Name, ElemSort>,
elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>,
): SMTSet<Name, ElemSort> {
const arg = set.elemSort().cast(elem as any); const arg = set.elemSort().cast(elem as any);
return new SetImpl<ElemSort>(check(Z3.mk_set_del(contextPtr, set.ast, arg.ast))); return new SetImpl<ElemSort>(check(Z3.mk_set_del(contextPtr, set.ast, arg.ast)));
} }
@ -1326,11 +1377,17 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
function FullSet<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSet<Name, ElemSort> { function FullSet<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSet<Name, ElemSort> {
return new SetImpl<ElemSort>(check(Z3.mk_full_set(contextPtr, sort.ptr))); return new SetImpl<ElemSort>(check(Z3.mk_full_set(contextPtr, sort.ptr)));
} }
function isMember<ElemSort extends AnySort<Name>>(elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>, set: SMTSet<Name, ElemSort>): Bool<Name> { function isMember<ElemSort extends AnySort<Name>>(
elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>,
set: SMTSet<Name, ElemSort>,
): Bool<Name> {
const arg = set.elemSort().cast(elem as any); const arg = set.elemSort().cast(elem as any);
return new BoolImpl(check(Z3.mk_set_member(contextPtr, arg.ast, set.ast))); return new BoolImpl(check(Z3.mk_set_member(contextPtr, arg.ast, set.ast)));
} }
function isSubset<ElemSort extends AnySort<Name>>(a: SMTSet<Name, ElemSort>, b: SMTSet<Name, ElemSort>): Bool<Name> { function isSubset<ElemSort extends AnySort<Name>>(
a: SMTSet<Name, ElemSort>,
b: SMTSet<Name, ElemSort>,
): Bool<Name> {
return new BoolImpl(check(Z3.mk_set_subset(contextPtr, a.ast, b.ast))); return new BoolImpl(check(Z3.mk_set_subset(contextPtr, a.ast, b.ast)));
} }
@ -1459,12 +1516,16 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
} }
} }
unsatCore(): AstVector<Name, Bool<Name>> {
return new AstVectorImpl(check(Z3.solver_get_unsat_core(contextPtr, this.ptr)));
}
model() { model() {
return new ModelImpl(check(Z3.solver_get_model(contextPtr, this.ptr))); return new ModelImpl(check(Z3.solver_get_model(contextPtr, this.ptr)));
} }
unsatCore(): AstVector<Name, Bool<Name>> { reasonUnknown(): string {
return new AstVectorImpl(check(Z3.solver_get_unsat_core(contextPtr, this.ptr))); return check(Z3.solver_get_reason_unknown(contextPtr, this.ptr));
} }
toString() { toString() {
@ -2629,7 +2690,10 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
} }
} }
class SetImpl<ElemSort extends Sort<Name>> extends ExprImpl<Z3_ast, ArraySortImpl<[ElemSort], BoolSort<Name>>> implements SMTSet<Name, ElemSort> { class SetImpl<ElemSort extends Sort<Name>>
extends ExprImpl<Z3_ast, ArraySortImpl<[ElemSort], BoolSort<Name>>>
implements SMTSet<Name, ElemSort>
{
declare readonly __typename: 'Array'; declare readonly __typename: 'Array';
elemSort(): ElemSort { elemSort(): ElemSort {
@ -2780,7 +2844,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
Z3.mk_string_symbol(contextPtr, `is_${constructorName}`), Z3.mk_string_symbol(contextPtr, `is_${constructorName}`),
fieldNames.map(name => Z3.mk_string_symbol(contextPtr, name)), fieldNames.map(name => Z3.mk_string_symbol(contextPtr, name)),
fieldSorts, fieldSorts,
fieldRefs fieldRefs,
); );
constructors.push(constructor); constructors.push(constructor);
scopedConstructors.push(constructor); scopedConstructors.push(constructor);
@ -2841,9 +2905,9 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
} }
class QuantifierImpl< class QuantifierImpl<
QVarSorts extends NonEmptySortArray<Name>, QVarSorts extends NonEmptySortArray<Name>,
QSort extends BoolSort<Name> | SMTArraySort<Name, QVarSorts>, QSort extends BoolSort<Name> | SMTArraySort<Name, QVarSorts>,
> >
extends ExprImpl<Z3_ast, QSort> extends ExprImpl<Z3_ast, QSort>
implements Quantifier<Name, QVarSorts, QSort> implements Quantifier<Name, QVarSorts, QSort>
{ {
@ -3243,6 +3307,8 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
PbEq, PbEq,
PbGe, PbGe,
PbLe, PbLe,
AtMost,
AtLeast,
ForAll, ForAll,
Exists, Exists,
Lambda, Lambda,

View file

@ -73,7 +73,13 @@ export type CoercibleToBitVec<Bits extends number = number, Name extends string
export type CoercibleRational = { numerator: bigint | number; denominator: bigint | number }; export type CoercibleRational = { numerator: bigint | number; denominator: bigint | number };
/** @hidden */ /** @hidden */
export type CoercibleToExpr<Name extends string = 'main'> = number | string | bigint | boolean | CoercibleRational | Expr<Name>; export type CoercibleToExpr<Name extends string = 'main'> =
| number
| string
| bigint
| boolean
| CoercibleRational
| Expr<Name>;
/** @hidden */ /** @hidden */
export type CoercibleToArith<Name extends string = 'main'> = number | string | bigint | CoercibleRational | Arith<Name>; export type CoercibleToArith<Name extends string = 'main'> = number | string | bigint | CoercibleRational | Arith<Name>;
@ -448,6 +454,12 @@ export interface Context<Name extends string = 'main'> {
/** @category Operations */ /** @category Operations */
PbLe(args: [Bool<Name>, ...Bool<Name>[]], coeffs: [number, ...number[]], k: number): Bool<Name>; PbLe(args: [Bool<Name>, ...Bool<Name>[]], coeffs: [number, ...number[]], k: number): Bool<Name>;
/** @category Operations */
AtMost(args: [Bool<Name>, ...Bool<Name>[]], k: number): Bool<Name>;
/** @category Operations */
AtLeast(args: [Bool<Name>, ...Bool<Name>[]], k: number): Bool<Name>;
// Quantifiers // Quantifiers
/** @category Operations */ /** @category Operations */
@ -629,13 +641,22 @@ export interface Context<Name extends string = 'main'> {
SetIntersect<ElemSort extends AnySort<Name>>(...args: SMTSet<Name, ElemSort>[]): SMTSet<Name, ElemSort>; SetIntersect<ElemSort extends AnySort<Name>>(...args: SMTSet<Name, ElemSort>[]): SMTSet<Name, ElemSort>;
/** @category Operations */ /** @category Operations */
SetDifference<ElemSort extends AnySort<Name>>(a: SMTSet<Name, ElemSort>, b: SMTSet<Name, ElemSort>): SMTSet<Name, ElemSort>; SetDifference<ElemSort extends AnySort<Name>>(
a: SMTSet<Name, ElemSort>,
b: SMTSet<Name, ElemSort>,
): SMTSet<Name, ElemSort>;
/** @category Operations */ /** @category Operations */
SetAdd<ElemSort extends AnySort<Name>>(set: SMTSet<Name, ElemSort>, elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): SMTSet<Name, ElemSort>; SetAdd<ElemSort extends AnySort<Name>>(
set: SMTSet<Name, ElemSort>,
elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>,
): SMTSet<Name, ElemSort>;
/** @category Operations */ /** @category Operations */
SetDel<ElemSort extends AnySort<Name>>(set: SMTSet<Name, ElemSort>, elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): SMTSet<Name, ElemSort>; SetDel<ElemSort extends AnySort<Name>>(
set: SMTSet<Name, ElemSort>,
elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>,
): SMTSet<Name, ElemSort>;
/** @category Operations */ /** @category Operations */
SetComplement<ElemSort extends AnySort<Name>>(set: SMTSet<Name, ElemSort>): SMTSet<Name, ElemSort>; SetComplement<ElemSort extends AnySort<Name>>(set: SMTSet<Name, ElemSort>): SMTSet<Name, ElemSort>;
@ -647,7 +668,10 @@ export interface Context<Name extends string = 'main'> {
FullSet<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSet<Name, ElemSort>; FullSet<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSet<Name, ElemSort>;
/** @category Operations */ /** @category Operations */
isMember<ElemSort extends AnySort<Name>>(elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>, set: SMTSet<Name, ElemSort>): Bool<Name>; isMember<ElemSort extends AnySort<Name>>(
elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>,
set: SMTSet<Name, ElemSort>,
): Bool<Name>;
/** @category Operations */ /** @category Operations */
isSubset<ElemSort extends AnySort<Name>>(a: SMTSet<Name, ElemSort>, b: SMTSet<Name, ElemSort>): Bool<Name>; isSubset<ElemSort extends AnySort<Name>>(a: SMTSet<Name, ElemSort>, b: SMTSet<Name, ElemSort>): Bool<Name>;
@ -709,12 +733,90 @@ export interface Solver<Name extends string = 'main'> {
fromString(s: string): void; fromString(s: string): void;
/**
* Check whether the assertions in the solver are consistent or not.
*
* Optionally, you can provide additional boolean expressions as assumptions.
* These assumptions are temporary and only used for this check - they are not
* permanently added to the solver.
*
* @param exprs - Optional assumptions to check in addition to the solver's assertions.
* These are temporary and do not modify the solver state.
* @returns A promise resolving to:
* - `'sat'` if the assertions (plus assumptions) are satisfiable
* - `'unsat'` if they are unsatisfiable
* - `'unknown'` if Z3 cannot determine satisfiability
*
* @example
* ```typescript
* const solver = new Solver();
* const x = Int.const('x');
* solver.add(x.gt(0));
*
* // Check without assumptions
* await solver.check(); // 'sat'
*
* // Check with temporary assumption (doesn't modify solver)
* await solver.check(x.lt(0)); // 'unsat'
* await solver.check(); // still 'sat' - assumption was temporary
* ```
*
* @see {@link unsatCore} - Retrieve unsat core after checking with assumptions
*/
check(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]): Promise<CheckSatResult>; check(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]): Promise<CheckSatResult>;
/**
* Retrieve the unsat core after a check that returned `'unsat'`.
*
* The unsat core is a (typically small) subset of the assumptions that were
* sufficient to determine unsatisfiability. This is useful for understanding
* which assumptions are conflicting.
*
* Note: To use unsat cores effectively, you should call {@link check} with
* assumptions (not just assertions added via {@link add}).
*
* @returns An AstVector containing the subset of assumptions that caused UNSAT
*
* @example
* ```typescript
* const solver = new Solver();
* const x = Bool.const('x');
* const y = Bool.const('y');
* const z = Bool.const('z');
* solver.add(x.or(y));
* solver.add(x.or(z));
*
* const result = await solver.check(x.not(), y.not(), z.not());
* if (result === 'unsat') {
* const core = solver.unsatCore();
* // core will contain a minimal set of conflicting assumptions
* console.log('UNSAT core size:', core.length());
* }
* ```
*
* @see {@link check} - Check with assumptions to use with unsat core
*/
unsatCore(): AstVector<Name, Bool<Name>>;
model(): Model<Name>; model(): Model<Name>;
unsatCore(): AstVector<Name, Bool<Name>>; unsatCore(): AstVector<Name, Bool<Name>>;
/**
* Return a string describing why the last call to {@link check} returned `'unknown'`.
*
* @returns A string explaining the reason, or an empty string if the last check didn't return unknown
*
* @example
* ```typescript
* const result = await solver.check();
* if (result === 'unknown') {
* console.log('Reason:', solver.reasonUnknown());
* }
* ```
*/
reasonUnknown(): string;
/** /**
* Manually decrease the reference count of the solver * Manually decrease the reference count of the solver
* This is automatically done when the solver is garbage collected, * This is automatically done when the solver is garbage collected,
@ -963,8 +1065,10 @@ export interface FuncDecl<
call(...args: CoercibleToArrayIndexType<Name, DomainSort>): SortToExprMap<RangeSort, Name>; call(...args: CoercibleToArrayIndexType<Name, DomainSort>): SortToExprMap<RangeSort, Name>;
} }
export interface Expr<Name extends string = 'main', S extends Sort<Name> = AnySort<Name>, Ptr = unknown> export interface Expr<Name extends string = 'main', S extends Sort<Name> = AnySort<Name>, Ptr = unknown> extends Ast<
extends Ast<Name, Ptr> { Name,
Ptr
> {
/** @hidden */ /** @hidden */
readonly __typename: readonly __typename:
| 'Expr' | 'Expr'
@ -1263,8 +1367,11 @@ export interface BitVecCreation<Name extends string> {
* Represents Bit Vector expression * Represents Bit Vector expression
* @category Bit Vectors * @category Bit Vectors
*/ */
export interface BitVec<Bits extends number = number, Name extends string = 'main'> export interface BitVec<Bits extends number = number, Name extends string = 'main'> extends Expr<
extends Expr<Name, BitVecSort<Bits, Name>, Z3_ast> { Name,
BitVecSort<Bits, Name>,
Z3_ast
> {
/** @hidden */ /** @hidden */
readonly __typename: 'BitVec' | BitVecNum['__typename']; readonly __typename: 'BitVec' | BitVecNum['__typename'];
@ -1618,8 +1725,11 @@ export interface SMTArray<
* @typeParam ElemSort The sort of the element of the set * @typeParam ElemSort The sort of the element of the set
* @category Sets * @category Sets
*/ */
export type SMTSetSort<Name extends string = 'main', ElemSort extends AnySort<Name> = Sort<Name>> = SMTArraySort<Name, [ElemSort], BoolSort<Name>>; export type SMTSetSort<Name extends string = 'main', ElemSort extends AnySort<Name> = Sort<Name>> = SMTArraySort<
Name,
[ElemSort],
BoolSort<Name>
>;
/** @category Sets*/ /** @category Sets*/
export interface SMTSetCreation<Name extends string> { export interface SMTSetCreation<Name extends string> {
@ -1631,7 +1741,10 @@ export interface SMTSetCreation<Name extends string> {
empty<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSet<Name, ElemSort>; empty<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSet<Name, ElemSort>;
val<ElemSort extends AnySort<Name>>(values: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>[], sort: ElemSort): SMTSet<Name, ElemSort>; val<ElemSort extends AnySort<Name>>(
values: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>[],
sort: ElemSort,
): SMTSet<Name, ElemSort>;
} }
/** /**
@ -1640,7 +1753,11 @@ export interface SMTSetCreation<Name extends string> {
* @typeParam ElemSort The sort of the element of the set * @typeParam ElemSort The sort of the element of the set
* @category Arrays * @category Arrays
*/ */
export interface SMTSet<Name extends string = 'main', ElemSort extends AnySort<Name> = Sort<Name>> extends Expr<Name, SMTSetSort<Name, ElemSort>, Z3_ast> { export interface SMTSet<Name extends string = 'main', ElemSort extends AnySort<Name> = Sort<Name>> extends Expr<
Name,
SMTSetSort<Name, ElemSort>,
Z3_ast
> {
readonly __typename: 'Array'; readonly __typename: 'Array';
elemSort(): ElemSort; elemSort(): ElemSort;
@ -1649,14 +1766,12 @@ export interface SMTSet<Name extends string = 'main', ElemSort extends AnySort<N
intersect(...args: SMTSet<Name, ElemSort>[]): SMTSet<Name, ElemSort>; intersect(...args: SMTSet<Name, ElemSort>[]): SMTSet<Name, ElemSort>;
diff(b: SMTSet<Name, ElemSort>): SMTSet<Name, ElemSort>; diff(b: SMTSet<Name, ElemSort>): SMTSet<Name, ElemSort>;
add(elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): SMTSet<Name, ElemSort>; add(elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): SMTSet<Name, ElemSort>;
del(elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): SMTSet<Name, ElemSort>; del(elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): SMTSet<Name, ElemSort>;
complement(): SMTSet<Name, ElemSort>; complement(): SMTSet<Name, ElemSort>;
contains(elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): Bool<Name>; contains(elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): Bool<Name>;
subsetOf(b: SMTSet<Name, ElemSort>): Bool<Name>; subsetOf(b: SMTSet<Name, ElemSort>): Bool<Name>;
} }
////////////////////////////////////////// //////////////////////////////////////////
// //