UNPKG

z3-solver

Version:

This project provides high-level and low-level TypeScript bindings for the [Z3 theorem prover](https://github.com/Z3Prover/z3). It is available on npm as [z3-solver](https://www.npmjs.com/package/z3-solver).

1,168 lines 104 kB
import { Z3_ast, Z3_ast_map, Z3_ast_print_mode, Z3_ast_vector, Z3_context, Z3_decl_kind, Z3_fixedpoint, Z3_func_decl, Z3_func_entry, Z3_func_interp, Z3_model, Z3_probe, Z3_solver, Z3_optimize, Z3_sort, Z3_sort_kind, Z3_stats, Z3_tactic, Z3_goal, Z3_apply_result, Z3_goal_prec, Z3_param_descrs, Z3_params, Z3_simplifier } from '../low-level'; /** @hidden */ export type AnySort<Name extends string = 'main'> = Sort<Name> | BoolSort<Name> | ArithSort<Name> | BitVecSort<number, Name> | SMTArraySort<Name> | FPSort<Name> | FPRMSort<Name> | SeqSort<Name> | ReSort<Name>; /** @hidden */ export type AnyExpr<Name extends string = 'main'> = Expr<Name> | Bool<Name> | Arith<Name> | IntNum<Name> | RatNum<Name> | BitVec<number, Name> | BitVecNum<number, Name> | SMTArray<Name> | FP<Name> | FPNum<Name> | FPRM<Name> | Seq<Name> | Re<Name>; /** @hidden */ export type AnyAst<Name extends string = 'main'> = AnyExpr<Name> | AnySort<Name> | FuncDecl<Name>; /** @hidden */ export type SortToExprMap<S extends AnySort<Name>, Name extends string = 'main'> = S extends BoolSort ? Bool<Name> : S extends ArithSort<Name> ? Arith<Name> : S extends BitVecSort<infer Size, Name> ? BitVec<Size, Name> : S extends SMTArraySort<Name, infer DomainSort, infer RangeSort> ? SMTArray<Name, DomainSort, RangeSort> : S extends FPSort<Name> ? FP<Name> : S extends FPRMSort<Name> ? FPRM<Name> : S extends SeqSort<Name> ? Seq<Name> : S extends ReSort<Name> ? Re<Name> : S extends Sort<Name> ? Expr<Name, S, Z3_ast> : never; /** @hidden */ export type CoercibleFromMap<S extends CoercibleToExpr<Name>, Name extends string = 'main'> = S extends bigint ? Arith<Name> : S extends number | CoercibleRational ? RatNum<Name> : S extends boolean ? Bool<Name> : S extends Expr<Name> ? S : never; /** @hidden */ export type CoercibleToBitVec<Bits extends number = number, Name extends string = 'main'> = bigint | number | BitVec<Bits, Name>; /** @hidden */ export type CoercibleToFP<Name extends string = 'main'> = number | FP<Name>; export type CoercibleRational = { numerator: bigint | number; denominator: bigint | number; }; /** @hidden */ export type CoercibleToExpr<Name extends string = 'main'> = number | string | bigint | boolean | CoercibleRational | Expr<Name>; /** @hidden */ export type CoercibleToArith<Name extends string = 'main'> = number | string | bigint | CoercibleRational | Arith<Name>; /** @hidden */ export type CoercibleToMap<T extends AnyExpr<Name>, Name extends string = 'main'> = T extends Bool<Name> ? boolean | Bool<Name> : T extends IntNum<Name> ? bigint | number | IntNum<Name> : T extends RatNum<Name> ? bigint | number | CoercibleRational | RatNum<Name> : T extends Arith<Name> ? CoercibleToArith<Name> : T extends BitVec<infer Size, Name> ? CoercibleToBitVec<Size, Name> : T extends FP<Name> ? CoercibleToFP<Name> : T extends SMTArray<Name, infer DomainSort, infer RangeSort> ? SMTArray<Name, DomainSort, RangeSort> : T extends Expr<Name> ? Expr<Name> : never; /** * Used to create a Real constant * * ```typescript * const x = from({ numerator: 1, denominator: 3 }) * * x * // 1/3 * isReal(x) * // true * isRealVal(x) * // true * x.asNumber() * // 0.3333333333333333 * ``` * @see {@link Context.from} * @category Global */ export declare class Z3Error extends Error { } export declare class Z3AssertionError extends Z3Error { } /** @category Global */ export type CheckSatResult = 'sat' | 'unsat' | 'unknown'; /** @hidden */ export interface ContextCtor { <Name extends string>(name: Name, options?: Record<string, any>): Context<Name>; new <Name extends string>(name: Name, options?: Record<string, any>): Context<Name>; } export interface Context<Name extends string = 'main'> { /** @hidden */ readonly ptr: Z3_context; /** * Name of the current Context * * ```typescript * const c = new Context('main') * * c.name * // 'main' * ``` */ readonly name: Name; /** @category Functions */ interrupt(): void; /** * Set the pretty printing mode for ASTs. * * @param mode - The print mode to use: * - Z3_PRINT_SMTLIB_FULL (0): Print AST nodes in SMTLIB verbose format. * - Z3_PRINT_LOW_LEVEL (1): Print AST nodes using a low-level format. * - Z3_PRINT_SMTLIB2_COMPLIANT (2): Print AST nodes in SMTLIB 2.x compliant format. * * @category Functions */ setPrintMode(mode: Z3_ast_print_mode): void; /** @category Functions */ isModel(obj: unknown): obj is Model<Name>; /** @category Functions */ isAst(obj: unknown): obj is Ast<Name>; /** @category Functions */ isSort(obj: unknown): obj is Sort<Name>; /** @category Functions */ isFuncDecl(obj: unknown): obj is FuncDecl<Name>; /** @category Functions */ isFuncInterp(obj: unknown): obj is FuncInterp<Name>; /** @category Functions */ isApp(obj: unknown): boolean; /** @category Functions */ isConst(obj: unknown): boolean; /** @category Functions */ isExpr(obj: unknown): obj is Expr<Name>; /** @category Functions */ isVar(obj: unknown): boolean; /** @category Functions */ isAppOf(obj: unknown, kind: Z3_decl_kind): boolean; /** @category Functions */ isBool(obj: unknown): obj is Bool<Name>; /** @category Functions */ isTrue(obj: unknown): boolean; /** @category Functions */ isFalse(obj: unknown): boolean; /** @category Functions */ isAnd(obj: unknown): boolean; /** @category Functions */ isOr(obj: unknown): boolean; /** @category Functions */ isImplies(obj: unknown): boolean; /** @category Functions */ isNot(obj: unknown): boolean; /** @category Functions */ isEq(obj: unknown): boolean; /** @category Functions */ isDistinct(obj: unknown): boolean; /** @category Functions */ isQuantifier(obj: unknown): obj is Quantifier<Name>; /** @category Functions */ isArith(obj: unknown): obj is Arith<Name>; /** @category Functions */ isArithSort(obj: unknown): obj is ArithSort<Name>; /** @category Functions */ isInt(obj: unknown): boolean; /** @category Functions */ isIntVal(obj: unknown): obj is IntNum<Name>; /** @category Functions */ isIntSort(obj: unknown): boolean; /** @category Functions */ isReal(obj: unknown): boolean; /** @category Functions */ isRealVal(obj: unknown): obj is RatNum<Name>; /** @category Functions */ isRealSort(obj: unknown): boolean; /** @category Functions */ isRCFNum(obj: unknown): obj is RCFNum<Name>; /** @category Functions */ isBitVecSort(obj: unknown): obj is BitVecSort<number, Name>; /** @category Functions */ isBitVec(obj: unknown): obj is BitVec<number, Name>; /** @category Functions */ isBitVecVal(obj: unknown): obj is BitVecNum<number, Name>; /** @category Functions */ isArraySort(obj: unknown): obj is SMTArraySort<Name>; /** @category Functions */ isArray(obj: unknown): obj is SMTArray<Name>; /** @category Functions */ isConstArray(obj: unknown): boolean; /** @category Functions */ isFPSort(obj: unknown): obj is FPSort<Name>; /** @category Functions */ isFP(obj: unknown): obj is FP<Name>; /** @category Functions */ isFPVal(obj: unknown): obj is FPNum<Name>; /** @category Functions */ isFPRMSort(obj: unknown): obj is FPRMSort<Name>; /** @category Functions */ isFPRM(obj: unknown): obj is FPRM<Name>; /** @category Functions */ isSeqSort(obj: unknown): obj is SeqSort<Name>; /** @category Functions */ isSeq(obj: unknown): obj is Seq<Name>; /** @category Functions */ isStringSort(obj: unknown): obj is SeqSort<Name>; /** @category Functions */ isString(obj: unknown): obj is Seq<Name>; /** @category Functions */ isProbe(obj: unknown): obj is Probe<Name>; /** @category Functions */ isTactic(obj: unknown): obj is Tactic<Name>; /** @category Functions */ isGoal(obj: unknown): obj is Goal<Name>; /** @category Functions */ isAstVector(obj: unknown): obj is AstVector<Name, AnyAst<Name>>; /** * Returns whether two Asts are the same thing * @category Functions */ eqIdentity(a: Ast<Name>, b: Ast<Name>): boolean; /** @category Functions */ getVarIndex(obj: Expr<Name>): number; /** * Coerce a boolean into a Bool expression * @category Functions */ from(primitive: boolean): Bool<Name>; /** * Coerce a number to an Int or Real expression (integral numbers become Ints) * @category Functions */ from(primitive: number): IntNum<Name> | RatNum<Name>; /** * Coerce a rational into a Real expression * @category Functions */ from(primitive: CoercibleRational): RatNum<Name>; /** * Coerce a big number into a Integer expression * @category Functions */ from(primitive: bigint): IntNum<Name>; /** * Returns whatever expression was given * @category Functions */ from<E extends Expr<Name>>(expr: E): E; /** @hidden */ from(value: CoercibleToExpr<Name>): AnyExpr<Name>; /** * Sugar function for getting a model for given assertions * * ```typescript * const x = Int.const('x'); * const y = Int.const('y'); * const result = await solve(x.le(y)); * if (isModel(result)) { * console.log('Z3 found a solution'); * console.log(`x=${result.get(x)}, y=${result.get(y)}`); * } else { * console.error('No solution found'); * } * ``` * * @see {@link Solver} * @category Functions */ solve(...assertions: Bool<Name>[]): Promise<Model<Name> | 'unsat' | 'unknown'>; /** * Creates a Solver * @param logic - Optional logic which the solver will use. Creates a general Solver otherwise * @category Classes */ readonly Solver: new (logic?: string) => Solver<Name>; readonly Optimize: new () => Optimize<Name>; readonly Fixedpoint: new () => Fixedpoint<Name>; /** * Creates an empty Model * @see {@link Solver.model} for common usage of Model * @category Classes */ readonly Model: new () => Model<Name>; /** @category Classes */ readonly AstVector: new <Item extends Ast<Name> = AnyAst<Name>>() => AstVector<Name, Item>; /** @category Classes */ readonly AstMap: new <Key extends Ast<Name> = AnyAst<Name>, Value extends Ast<Name> = AnyAst<Name>>() => AstMap<Name, Key, Value>; /** @category Classes */ readonly Tactic: new (name: string) => Tactic<Name>; /** @category Classes */ readonly Goal: new (models?: boolean, unsat_cores?: boolean, proofs?: boolean) => Goal<Name>; /** @category Classes */ readonly Params: new () => Params<Name>; /** @category Classes */ readonly Simplifier: new (name: string) => Simplifier<Name>; /** @category Expressions */ readonly Sort: SortCreation<Name>; /** @category Expressions */ readonly Function: FuncDeclCreation<Name>; /** @category Expressions */ readonly RecFunc: RecFuncCreation<Name>; /** @category Expressions */ readonly Bool: BoolCreation<Name>; /** @category Expressions */ readonly Int: IntCreation<Name>; /** @category Expressions */ readonly Real: RealCreation<Name>; /** @category Expressions */ readonly RCFNum: RCFNumCreation<Name>; /** @category Expressions */ readonly BitVec: BitVecCreation<Name>; /** @category Expressions */ readonly Float: FPCreation<Name>; /** @category Expressions */ readonly FloatRM: FPRMCreation<Name>; /** @category Expressions */ readonly String: StringCreation<Name>; /** @category Expressions */ readonly Seq: SeqCreation<Name>; /** @category Expressions */ readonly Re: ReCreation<Name>; /** @category Expressions */ readonly Array: SMTArrayCreation<Name>; /** @category Expressions */ readonly Set: SMTSetCreation<Name>; /** @category Expressions */ readonly Datatype: DatatypeCreation<Name>; /** @category Operations */ Const<S extends Sort<Name>>(name: string, sort: S): SortToExprMap<S, Name>; /** @category Operations */ Consts<S extends Sort<Name>>(name: string | string[], sort: S): SortToExprMap<S, Name>[]; /** @category Operations */ FreshConst<S extends Sort<Name>>(sort: S, prefix?: string): SortToExprMap<S, Name>; /** @category Operations */ Var<S extends Sort<Name>>(idx: number, sort: S): SortToExprMap<S, Name>; /** @category Operations */ If(condition: Probe<Name>, onTrue: Tactic<Name>, onFalse: Tactic<Name>): Tactic<Name>; /** @category Operations */ If<OnTrueRef extends CoercibleToExpr<Name>, OnFalseRef extends CoercibleToExpr<Name>>(condition: Bool<Name> | boolean, onTrue: OnTrueRef, onFalse: OnFalseRef): CoercibleFromMap<OnTrueRef | OnFalseRef, Name>; /** @category Operations */ Distinct(...args: CoercibleToExpr<Name>[]): Bool<Name>; /** @category Operations */ Implies(a: Bool<Name> | boolean, b: Bool<Name> | boolean): Bool<Name>; /** @category Operations */ Iff(a: Bool<Name> | boolean, b: Bool<Name> | boolean): Bool<Name>; /** @category Operations */ Eq(a: CoercibleToExpr<Name>, b: CoercibleToExpr<Name>): Bool<Name>; /** @category Operations */ Xor(a: Bool<Name> | boolean, b: Bool<Name> | boolean): Bool<Name>; /** @category Operations */ Not(a: Probe<Name>): Probe<Name>; /** @category Operations */ Not(a: Bool<Name> | boolean): Bool<Name>; /** @category Operations */ And(): Bool<Name>; /** @category Operations */ And(vector: AstVector<Name, Bool<Name>>): Bool<Name>; /** @category Operations */ And(...args: (Bool<Name> | boolean)[]): Bool<Name>; /** @category Operations */ And(...args: Probe<Name>[]): Probe<Name>; /** @category Operations */ Or(): Bool<Name>; /** @category Operations */ Or(vector: AstVector<Name, Bool<Name>>): Bool<Name>; /** @category Operations */ Or(...args: (Bool<Name> | boolean)[]): Bool<Name>; /** @category Operations */ Or(...args: Probe<Name>[]): Probe<Name>; /** @category Operations */ PbEq(args: [Bool<Name>, ...Bool<Name>[]], coeffs: [number, ...number[]], k: number): Bool<Name>; /** @category Operations */ PbGe(args: [Bool<Name>, ...Bool<Name>[]], coeffs: [number, ...number[]], k: number): Bool<Name>; /** @category Operations */ 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>; /** * Compose two tactics sequentially. Applies t1 to a goal, then t2 to each subgoal. * @category Tactics */ AndThen(t1: Tactic<Name> | string, t2: Tactic<Name> | string, ...ts: (Tactic<Name> | string)[]): Tactic<Name>; /** * Create a tactic that applies t1, and if it fails, applies t2. * @category Tactics */ OrElse(t1: Tactic<Name> | string, t2: Tactic<Name> | string, ...ts: (Tactic<Name> | string)[]): Tactic<Name>; /** * Repeat a tactic up to max times (default: unbounded). * @category Tactics */ Repeat(t: Tactic<Name> | string, max?: number): Tactic<Name>; /** * Apply tactic with a timeout in milliseconds. * @category Tactics */ TryFor(t: Tactic<Name> | string, ms: number): Tactic<Name>; /** * Apply tactic only if probe condition is true. * @category Tactics */ When(p: Probe<Name>, t: Tactic<Name> | string): Tactic<Name>; /** * Create a tactic that always succeeds and does nothing (skip). * @category Tactics */ Skip(): Tactic<Name>; /** * Create a tactic that always fails. * @category Tactics */ Fail(): Tactic<Name>; /** * Create a tactic that fails if probe condition is true. * @category Tactics */ FailIf(p: Probe<Name>): Tactic<Name>; /** * Apply tactics in parallel and return first successful result. * @category Tactics */ ParOr(...tactics: (Tactic<Name> | string)[]): Tactic<Name>; /** * Compose two tactics in parallel (t1 and then t2 in parallel). * @category Tactics */ ParAndThen(t1: Tactic<Name> | string, t2: Tactic<Name> | string): Tactic<Name>; /** * Apply tactic with given parameters. * @category Tactics */ With(t: Tactic<Name> | string, params: Record<string, any>): Tactic<Name>; /** @category Operations */ ForAll<QVarSorts extends NonEmptySortArray<Name>>(quantifiers: ArrayIndexType<Name, QVarSorts>, body: Bool<Name>, weight?: number): Quantifier<Name, QVarSorts, BoolSort<Name>> & Bool<Name>; /** @category Operations */ Exists<QVarSorts extends NonEmptySortArray<Name>>(quantifiers: ArrayIndexType<Name, QVarSorts>, body: Bool<Name>, weight?: number): Quantifier<Name, QVarSorts, BoolSort<Name>> & Bool<Name>; /** @category Operations */ Lambda<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name>>(quantifiers: ArrayIndexType<Name, DomainSort>, expr: SortToExprMap<RangeSort, Name>): Quantifier<Name, DomainSort, SMTArraySort<Name, DomainSort, RangeSort>> & SMTArray<Name, DomainSort, RangeSort>; /** @category Operations */ ToReal(expr: Arith<Name> | bigint): Arith<Name>; /** @category Operations */ ToInt(expr: Arith<Name> | number | CoercibleRational | string): Arith<Name>; /** * Create an IsInt Z3 predicate * * ```typescript * const x = Real.const('x'); * await solve(IsInt(x.add("1/2")), x.gt(0), x.lt(1)) * // x = 1/2 * await solve(IsInt(x.add("1/2")), x.gt(0), x.lt(1), x.neq("1/2")) * // unsat * ``` * @category Operations */ IsInt(expr: Arith<Name> | number | CoercibleRational | string): Bool<Name>; /** * Returns a Z3 expression representing square root of a * * ```typescript * const a = Real.const('a'); * * Sqrt(a); * // a**(1/2) * ``` * @category Operations */ Sqrt(a: CoercibleToArith<Name>): Arith<Name>; /** * Returns a Z3 expression representing cubic root of a * * ```typescript * const a = Real.const('a'); * * Cbrt(a); * // a**(1/3) * ``` * @category Operations */ Cbrt(a: CoercibleToArith<Name>): Arith<Name>; /** @category Operations */ BV2Int(a: BitVec<number, Name>, isSigned: boolean): Arith<Name>; /** @category Operations */ Int2BV<Bits extends number>(a: Arith<Name> | bigint | number, bits: Bits): BitVec<Bits, Name>; /** @category Operations */ Concat(...bitvecs: BitVec<number, Name>[]): BitVec<number, Name>; /** @category Operations */ Cond(probe: Probe<Name>, onTrue: Tactic<Name>, onFalse: Tactic<Name>): Tactic<Name>; /** @category Operations */ LT(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>; /** @category Operations */ GT(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>; /** @category Operations */ LE(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>; /** @category Operations */ GE(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>; /** @category Operations */ ULT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>; /** @category Operations */ UGT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>; /** @category Operations */ ULE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>; /** @category Operations */ UGE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>; /** @category Operations */ SLT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>; /** @category Operations */ SGT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>; /** @category Operations */ SGE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>; /** @category Operations */ SLE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>; /** @category Operations */ Sum(arg0: Arith<Name>, ...args: CoercibleToArith<Name>[]): Arith<Name>; Sum<Bits extends number>(arg0: BitVec<Bits, Name>, ...args: CoercibleToBitVec<Bits, Name>[]): BitVec<Bits, Name>; Sub(arg0: Arith<Name>, ...args: CoercibleToArith<Name>[]): Arith<Name>; Sub<Bits extends number>(arg0: BitVec<Bits, Name>, ...args: CoercibleToBitVec<Bits, Name>[]): BitVec<Bits, Name>; Product(arg0: Arith<Name>, ...args: CoercibleToArith<Name>[]): Arith<Name>; Product<Bits extends number>(arg0: BitVec<Bits, Name>, ...args: CoercibleToBitVec<Bits, Name>[]): BitVec<Bits, Name>; Div(arg0: Arith<Name>, arg1: CoercibleToArith<Name>): Arith<Name>; Div<Bits extends number>(arg0: BitVec<Bits, Name>, arg1: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name>; BUDiv<Bits extends number>(arg0: BitVec<Bits, Name>, arg1: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name>; Neg(a: Arith<Name>): Arith<Name>; Neg<Bits extends number>(a: BitVec<Bits, Name>): BitVec<Bits, Name>; Mod(a: Arith<Name>, b: CoercibleToArith<Name>): Arith<Name>; Mod<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name>; /** @category Operations */ Select<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name> = Sort<Name>>(array: SMTArray<Name, DomainSort, RangeSort>, ...indices: CoercibleToArrayIndexType<Name, DomainSort>): SortToExprMap<RangeSort, Name>; /** @category Operations */ Store<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name> = Sort<Name>>(array: SMTArray<Name, DomainSort, RangeSort>, ...indicesAndValue: [ ...CoercibleToArrayIndexType<Name, DomainSort>, CoercibleToMap<SortToExprMap<RangeSort, Name>, Name> ]): SMTArray<Name, DomainSort, RangeSort>; /** @category Operations */ Ext<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name> = Sort<Name>>(a: SMTArray<Name, DomainSort, RangeSort>, b: SMTArray<Name, DomainSort, RangeSort>): SortToExprMap<DomainSort[0], Name>; /** @category Operations */ Extract<Bits extends number>(hi: number, lo: number, val: BitVec<Bits, Name>): BitVec<number, Name>; /** @category Operations */ ast_from_string(s: string): Ast<Name>; /** @category Operations */ substitute(t: Expr<Name>, ...substitutions: [Expr<Name>, Expr<Name>][]): Expr<Name>; /** @category Operations */ substituteVars(t: Expr<Name>, ...to: Expr<Name>[]): Expr<Name>; /** @category Operations */ substituteFuns(t: Expr<Name>, ...substitutions: [FuncDecl<Name>, Expr<Name>][]): Expr<Name>; /** @category Operations */ updateField(t: DatatypeExpr<Name>, fieldAccessor: FuncDecl<Name>, newValue: Expr<Name>): DatatypeExpr<Name>; simplify(expr: Expr<Name>): Promise<Expr<Name>>; /** @category Operations */ SetUnion<ElemSort extends AnySort<Name>>(...args: SMTSet<Name, ElemSort>[]): SMTSet<Name, ElemSort>; /** @category Operations */ SetIntersect<ElemSort extends AnySort<Name>>(...args: SMTSet<Name, ElemSort>[]): SMTSet<Name, ElemSort>; /** @category Operations */ SetDifference<ElemSort extends AnySort<Name>>(a: SMTSet<Name, ElemSort>, b: SMTSet<Name, ElemSort>): SMTSet<Name, ElemSort>; /** @category Operations */ SetAdd<ElemSort extends AnySort<Name>>(set: SMTSet<Name, ElemSort>, elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): SMTSet<Name, ElemSort>; /** @category Operations */ SetDel<ElemSort extends AnySort<Name>>(set: SMTSet<Name, ElemSort>, elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>): SMTSet<Name, ElemSort>; /** @category Operations */ SetComplement<ElemSort extends AnySort<Name>>(set: SMTSet<Name, ElemSort>): SMTSet<Name, ElemSort>; /** @category Operations */ EmptySet<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSet<Name, ElemSort>; /** @category Operations */ FullSet<ElemSort extends AnySort<Name>>(sort: ElemSort): SMTSet<Name, ElemSort>; /** @category Operations */ isMember<ElemSort extends AnySort<Name>>(elem: CoercibleToMap<SortToExprMap<ElemSort, Name>, Name>, set: SMTSet<Name, ElemSort>): Bool<Name>; /** @category Operations */ isSubset<ElemSort extends AnySort<Name>>(a: SMTSet<Name, ElemSort>, b: SMTSet<Name, ElemSort>): Bool<Name>; /** @category RegularExpression */ InRe(seq: Seq<Name> | string, re: Re<Name>): Bool<Name>; /** @category RegularExpression */ Union<SeqSortRef extends SeqSort<Name>>(...res: Re<Name, SeqSortRef>[]): Re<Name, SeqSortRef>; /** @category RegularExpression */ Intersect<SeqSortRef extends SeqSort<Name>>(...res: Re<Name, SeqSortRef>[]): Re<Name, SeqSortRef>; /** @category RegularExpression */ ReConcat<SeqSortRef extends SeqSort<Name>>(...res: Re<Name, SeqSortRef>[]): Re<Name, SeqSortRef>; /** @category RegularExpression */ Plus<SeqSortRef extends SeqSort<Name>>(re: Re<Name, SeqSortRef>): Re<Name, SeqSortRef>; /** @category RegularExpression */ Star<SeqSortRef extends SeqSort<Name>>(re: Re<Name, SeqSortRef>): Re<Name, SeqSortRef>; /** @category RegularExpression */ Option<SeqSortRef extends SeqSort<Name>>(re: Re<Name, SeqSortRef>): Re<Name, SeqSortRef>; /** @category RegularExpression */ Complement<SeqSortRef extends SeqSort<Name>>(re: Re<Name, SeqSortRef>): Re<Name, SeqSortRef>; /** @category RegularExpression */ Diff<SeqSortRef extends SeqSort<Name>>(a: Re<Name, SeqSortRef>, b: Re<Name, SeqSortRef>): Re<Name, SeqSortRef>; /** @category RegularExpression */ Range<SeqSortRef extends SeqSort<Name>>(lo: Seq<Name, SeqSortRef> | string, hi: Seq<Name, SeqSortRef> | string): Re<Name, SeqSortRef>; /** * Create a bounded repetition regex * @param re The regex to repeat * @param lo Minimum number of repetitions * @param hi Maximum number of repetitions (0 means unbounded, i.e., at least lo) * @category RegularExpression */ Loop<SeqSortRef extends SeqSort<Name>>(re: Re<Name, SeqSortRef>, lo: number, hi?: number): Re<Name, SeqSortRef>; /** @category RegularExpression */ Power<SeqSortRef extends SeqSort<Name>>(re: Re<Name, SeqSortRef>, n: number): Re<Name, SeqSortRef>; /** @category RegularExpression */ AllChar<SeqSortRef extends SeqSort<Name>>(reSort: ReSort<Name, SeqSortRef>): Re<Name, SeqSortRef>; /** @category RegularExpression */ Empty<SeqSortRef extends SeqSort<Name>>(reSort: ReSort<Name, SeqSortRef>): Re<Name, SeqSortRef>; /** @category RegularExpression */ Full<SeqSortRef extends SeqSort<Name>>(reSort: ReSort<Name, SeqSortRef>): Re<Name, SeqSortRef>; /** * Create a partial order relation over a sort. * @param sort The sort of the relation * @param index The index of the relation * @category Operations */ mkPartialOrder(sort: Sort<Name>, index: number): FuncDecl<Name>; /** * Create the transitive closure of a binary relation. * The resulting relation is recursive. * @param f A binary relation represented as a function declaration * @category Operations */ mkTransitiveClosure(f: FuncDecl<Name>): FuncDecl<Name>; /** * Return the nonzero subresultants of p and q with respect to the "variable" x. * Note that any subterm that cannot be viewed as a polynomial is assumed to be a variable. * @param p Arithmetic term * @param q Arithmetic term * @param x Variable with respect to which subresultants are computed * @category Operations */ polynomialSubresultants(p: Arith<Name>, q: Arith<Name>, x: Arith<Name>): Promise<AstVector<Name, Arith<Name>>>; } export interface Ast<Name extends string = 'main', Ptr = unknown> { /** @hidden */ readonly __typename: 'Ast' | Sort['__typename'] | FuncDecl['__typename'] | Expr['__typename']; readonly ctx: Context<Name>; /** @hidden */ readonly ptr: Ptr; /** @virtual */ get ast(): Z3_ast; /** @virtual */ id(): number; eqIdentity(other: Ast<Name>): boolean; neqIdentity(other: Ast<Name>): boolean; sexpr(): string; hash(): number; } /** @hidden */ export interface SolverCtor<Name extends string> { new (): Solver<Name>; } export interface Solver<Name extends string = 'main'> { /** @hidden */ readonly __typename: 'Solver'; readonly ctx: Context<Name>; readonly ptr: Z3_solver; set(key: string, value: any): void; push(): void; pop(num?: number): void; numScopes(): number; reset(): void; add(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]): void; addAndTrack(expr: Bool<Name>, constant: Bool<Name> | string): void; /** * Attach a simplifier to the solver for incremental pre-processing. * The solver will use the simplifier for incremental pre-processing of assertions. * @param simplifier - The simplifier to attach */ addSimplifier(simplifier: Simplifier<Name>): void; assertions(): AstVector<Name, Bool<Name>>; 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>; /** * 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>; /** * Retrieve statistics for the solver. * Returns performance metrics, memory usage, decision counts, and other diagnostic information. * * @returns A Statistics object containing solver metrics * * @example * ```typescript * const solver = new Solver(); * const x = Int.const('x'); * solver.add(x.gt(0)); * await solver.check(); * const stats = solver.statistics(); * console.log('Statistics size:', stats.size()); * for (const entry of stats) { * console.log(`${entry.key}: ${entry.value}`); * } * ``` */ statistics(): Statistics<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; /** * Retrieve the set of literals that were inferred by the solver as unit literals. * These are boolean literals that the solver has determined must be true in all models. * * @returns An AstVector containing the unit literals * * @example * ```typescript * const solver = new Solver(); * const x = Bool.const('x'); * solver.add(x.or(x)); // simplifies to x * await solver.check(); * const units = solver.units(); * console.log('Unit literals:', units.length()); * ``` */ units(): AstVector<Name, Bool<Name>>; /** * Retrieve the set of tracked boolean literals that are not unit literals. * * @returns An AstVector containing the non-unit literals * * @example * ```typescript * const solver = new Solver(); * const x = Bool.const('x'); * const y = Bool.const('y'); * solver.add(x.or(y)); * await solver.check(); * const nonUnits = solver.nonUnits(); * ``` */ nonUnits(): AstVector<Name, Bool<Name>>; /** * Retrieve the trail of boolean literals assigned by the solver during solving. * The trail represents the sequence of decisions and propagations made by the solver. * * @returns An AstVector containing the trail of assigned literals * * @example * ```typescript * const solver = new Solver(); * const x = Bool.const('x'); * const y = Bool.const('y'); * solver.add(x.implies(y)); * solver.add(x); * await solver.check(); * const trail = solver.trail(); * console.log('Trail length:', trail.length()); * ``` */ trail(): AstVector<Name, Bool<Name>>; /** * Retrieve the root of the congruence class containing the given expression. * This is useful for understanding equality reasoning in the solver. * * Note: This works primarily with SimpleSolver and may not work with terms * eliminated during preprocessing. * * @param expr - The expression to find the congruence root for * @returns The root expression of the congruence class * * @example * ```typescript * const solver = new Solver(); * const x = Int.const('x'); * const y = Int.const('y'); * solver.add(x.eq(y)); * await solver.check(); * const root = solver.congruenceRoot(x); * ``` */ congruenceRoot(expr: Expr<Name>): Expr<Name>; /** * Retrieve the next expression in the congruence class containing the given expression. * The congruence class forms a circular linked list. * * Note: This works primarily with SimpleSolver and may not work with terms * eliminated during preprocessing. * * @param expr - The expression to find the next congruent expression for * @returns The next expression in the congruence class * * @example * ```typescript * const solver = new Solver(); * const x = Int.const('x'); * const y = Int.const('y'); * const z = Int.const('z'); * solver.add(x.eq(y)); * solver.add(y.eq(z)); * await solver.check(); * const next = solver.congruenceNext(x); * ``` */ congruenceNext(expr: Expr<Name>): Expr<Name>; /** * Explain why two expressions are congruent according to the solver's reasoning. * Returns a proof term explaining the congruence. * * Note: This works primarily with SimpleSolver and may not work with terms * eliminated during preprocessing. * * @param a - First expression * @param b - Second expression * @returns An expression representing the proof of congruence * * @example * ```typescript * const solver = new Solver(); * const x = Int.const('x'); * const y = Int.const('y'); * solver.add(x.eq(y)); * await solver.check(); * const explanation = solver.congruenceExplain(x, y); * ``` */ congruenceExplain(a: Expr<Name>, b: Expr<Name>): Expr<Name>; /** * Load SMT-LIB2 format assertions from a file into the solver. * * @param filename - Path to the file containing SMT-LIB2 format assertions * * @example * ```typescript * const solver = new Solver(); * solver.fromFile('problem.smt2'); * const result = await solver.check(); * ``` */ fromFile(filename: string): void; /** * Convert the solver's assertions to SMT-LIB2 format as a benchmark. * * This exports the current set of assertions in the solver as an SMT-LIB2 string, * which can be used for bug reporting, sharing problems, or benchmarking. * * @param status - Status string such as "sat", "unsat", or "unknown" (default: "unknown") * @returns A string representation of the solver's assertions in SMT-LIB2 format * * @example * ```typescript * const solver = new Solver(); * const x = Int.const('x'); * const y = Int.const('y'); * solver.add(x.gt(0)); * solver.add(y.eq(x.add(1))); * const smtlib2 = solver.toSmtlib2('unknown'); * console.log(smtlib2); // Prints SMT-LIB2 formatted problem * ``` */ toSmtlib2(status?: string): string; /** * Manually decrease the reference count of the solver * This is automatically done when the solver is garbage collected, * but calling this eagerly can help release memory sooner. */ release(): void; } export interface Optimize<Name extends string = 'main'> { /** @hidden */ readonly __typename: 'Optimize'; readonly ctx: Context<Name>; readonly ptr: Z3_optimize; set(key: string, value: any): void; push(): void; pop(num?: number): void; add(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]): void; addSoft(expr: Bool<Name>, weight: number | bigint | string | CoercibleRational, id?: number | string): void; addAndTrack(expr: Bool<Name>, constant: Bool<Name> | string): void; assertions(): AstVector<Name, Bool<Name>>; fromString(s: string): void; maximize(expr: Arith<Name>): void; minimize(expr: Arith<Name>): void; check(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]): Promise<CheckSatResult>; model(): Model<Name>; statistics(): Statistics<Name>; /** * Manually decrease the reference count of the optimize * This is automatically done when the optimize is garbage collected, * but calling this eagerly can help release memory sooner. */ release(): void; } export interface Fixedpoint<Name extends string = 'main'> { /** @hidden */ readonly __typename: 'Fixedpoint'; readonly ctx: Context<Name>; readonly ptr: Z3_fixedpoint; /** * Set a configuration option for the fixedpoint solver. * @param key - Configuration parameter name * @param value - Configuration parameter value */ set(key: string, value: any): void; /** * Return a string describing all available options. */ help(): string; /** * Assert a constraint (or multiple) into the fixedpoint solver as background axioms. */ add(...constraints: Bool<Name>[]): void; /** * Register a predicate as a recursive relation. * @param pred - Function declaration to register as a recursive relation */ registerRelation(pred: FuncDecl<Name>): void; /** * Add a rule (Horn clause) to the fixedpoint solver. * @param rule - The rule as a Boolean expression (implication) * @param name - Optional name for the rule */ addRule(rule: Bool<Name>, name?: string): void; /** * Add a table fact to the fixedpoint solver. * @param pred - The predicate (function declaration) * @param args - Arguments to the predicate as integers */ addFact(pred: FuncDecl<Name>, ...args: number[]): void; /** * Update a named rule in the fixedpoint solver. * @param rule - The rule as a Boolean expression (implication) * @param name - Name of the rule to update */ updateRule(rule: Bool<Name>, name: string): void; /** * Query the fixedpoint solver to determine if the formula is derivable. * @param query - The query as a Boolean expression * @returns A promise that resolves to 'sat', 'unsat', or 'unknown' */ query(query: Bool<Name>): Promise<CheckSatResult>; /** * Query the fixedpoint solver for a set of relations. * @param relations - Array of function declarations representing relations to query * @returns A promise that resolves to 'sat', 'unsat', or 'unknown' */ queryRelations(...relations: FuncDecl<Name>[]): Promise<CheckSatResult>; /** * Retrieve the answer (satisfying instance or proof of unsatisfiability) from the last query. * @returns Expression containing the answer, or null if not available */ getAnswer(): Expr<Name> | null; /** * Retrieve the reason why the fixedpoint engine returned 'unknown'. * @returns A string explaining why the result was unknown */ getReasonUnknown(): string; /** * Retrieve the number of levels explored for a given predicate. * @param pred - The predicate function declaration * @returns The number of levels */ getNumLevels(pred: FuncDecl<Name>): number; /** * Retrieve the cover of a predicate at a given level. * @param level - The level to query * @param pred - The predicate function declaration * @returns Expression representing the cover, or null if not available */ getCoverDelta(level: number, pred: FuncDecl<Name>): Expr<Name> | null; /** * Add a property about the predicate at the given level. * @param level - The level to add the property at * @param pred - The predicate function declaration * @param property - The property as an expression */ addCover(level: number, pred: FuncDecl<Name>, property: Expr<Name>): void; /** * Retrieve set of rules added to the fixedpoint context. * @returns Vector of rules */ getRules(): AstVector<Name, Bool<Name>>; /** * Retrieve set of assertions added to the fixedpoint context. * @returns Vector of assertions */ getAssertions(): AstVector<Name, Bool<Name>>; /** * Set predicate representation for the Datalog engine. * @param pred - The predicate function declaration * @param kinds - Array of representation kinds */ setPredicateRepresentation(pred: FuncDecl<Name>, kinds: string[]): void; /** * Convert the fixedpoint context to a string. * @returns String representation of the fixedpoint context */ toString(): string; /** * Parse an SMT-LIB2 string with fixedpoint rules and add them to the context. * @param s - SMT-LIB2 string to parse * @returns Vector of queries from the parsed string */ fromString(s: string): AstVector<Name, Bool<Name>>; /** * Parse an SMT-LIB2 file with fixedpoint rules and add them to the context. * @param file - Path to the file to parse * @returns Vector of queries from the parsed file */ fromFile(file: string): AstVector<Name, Bool<Name>>; /** * Retrieve statistics for the fixedpoint solver. * Returns performance metrics and diagnostic information. * @returns A Statistics object containing solver metrics */ statistics(): Statistics<Name>; /** * Manually decrease the reference count of the fixedpoint * This is automatically done when the fixedpoint is garbage collected, * but calling this eagerly can help release memory sooner. */ release(): void; } /** @hidden */ export interface ModelCtor<Name extends string> { new (): Model<Name>; } export interface Model<Name extends string = 'main'> extends Iterable<FuncDecl<Name>> { /** @hidden */ readonly __typename: 'Model'; readonly ctx: Context<Name>; readonly ptr: Z3_model; length(): number; entries(): IterableIterator<[number, FuncDecl<Name>]>; keys(): IterableIterator<number>; values(): IterableIterator<FuncDecl<Name>>; decls(): FuncDecl<Name>[]; sexpr(): string; eval(expr: Bool<Name>, modelCompletion?: boolean): Bool<Name>; eval(expr: Arith<Name>, modelCompletion?: boolean): Arith<Name>; eval<Bits extends number = number>(expr: BitVec<Bits, Name>, modelCompletion?: boolean): BitVecNum<Bits, Name>; eval(expr: Expr<Name>, modelCompletion?: boolean): Expr<Name>; get(i: number): FuncDecl<Name>; get(from: number, to: number): FuncDecl<Name>[]; get(declaration: FuncDecl<Name>): FuncInterp<Name> | Expr<Name>; get(constant: Expr<Name>): Expr<Name>; get(sort: Sort<Name>): AstVector<Name, AnyExpr<Name>>; updateValue(decl: FuncDecl<Name> | Expr<Name>, a: Ast<Name> | FuncInterp<Name>): void; addFuncInterp<DomainSort extends Sort<Name>[] = Sort<Name>[], RangeSort extends Sort<Name> = Sort<Name>>(decl: FuncDecl<Name, DomainSort, RangeSort>, defaultValue: CoercibleToMap<SortToExprMap<RangeSort, Name>, Name>): FuncInterp<Name>; /** * Return the number of uninterpreted sorts that have an interpretation in the model. * * @returns The number of uninterpreted sorts * * @example * ```typescript * const { Solver, Sort } = await init(); * const solver = new Solver(); * const A = Sort.declare('A'); * const x = Const('x', A); * solver.add(x.eq(x)); * await solver.check(); * const model = solver.model(); * console.log('Number of sorts:', model.numSorts()); * ``` */ numSorts(): number; /** * Return the uninterpreted sort at the given index. * * @param i - Index of the sort (must be less than numSorts()) * @returns The sort at the given index * * @example * ```typescript * const model = solver.model(); * for (let i = 0; i < model.numSorts(); i++) { * const sort = model.getSort(i); * console.log('Sort:', sort.toString()); * } * ``` */ getSort(i: number): Sort<Name>; /** * Return all uninterpreted sorts that have an interpretation in the model. * * @returns An array of all uninterpreted sorts * * @example * ```typescript * const model = solver.model(); * const sorts = model.getSorts(); * for (const sort of sorts) { * console.log('Sort:', sort.toString()); * const universe = model.sortUniverse(sort); * console.log('Universe size:', universe.length()); * } * ``` */ getSorts(): Sort<Name>[]; /** * Return the finite set of elements that represent the interpretation for the given sort. * This is only applicable to uninterpreted sorts with finite interpretations. * * @param sort - The sort to get the universe for * @returns An AstVector containing all elements in the sort's universe * * @example * ```typescript * const { Solver, Sort, Const } = await init(); * const solver = new Solver(); * const A = Sort.declare('A'); * const x = Const('x', A); * const y = Const('y', A); * solver.add(x.neq(y)); * await solver.check(); * const model = solver.model(); * const universe = model.sortUniverse(A); * console.log('Universe has', universe.length(), 'elements'); * for (let i = 0; i < universe.length(); i++) { * console.log('Element:', universe.get(i).toString()); * } * ``` */ sortUniverse(sort: Sort<Name>): AstVector<Name, AnyExpr<Name>>; /** * Manually decrease the reference count of the model * This is automatically done when the model is garbage collected, * but calling this eagerly can help release memory sooner. */ release(): void; } /** * Statistics entry representing a single key-value pair from solver statistics */ export interface StatisticsEntry<Name extends string = 'main'> { /** @hidden */ readonly __typename: 'StatisticsEntry'; /** The key/name of this statistic */ readonly key: string; /** The numeric value of this statistic */ readonly value: number; /** True if this statistic is stored as an unsigned integer */ readonly isUint: boolean; /** True if this statistic is stored as a double */ readonly isDouble: boolean; } export interface StatisticsCtor<Name extends string> { new (): Statistics<Name>; } /** * Statistics for solver operations * * Provides access to performance metrics, memory usage, decision counts, * and other diagnostic information from solver operations. */ export interface Statistics<Name extends string = 'main'> extends Iterable<StatisticsEntry<Name>> { /** @hidden */ readonly __typename: 'Statistics'; readonly ctx: