kdrag.utils
Various term manipulation helpers. Pattern matchers, unifiers, rewriters, term orderings, etc.
Functions
| 
 | Generate all values possible for an expression. | 
| 
 | Alpha equivalent equality. | 
| 
 | Recursively rename all variables in an expression to canonical names. | 
| 
 | Anti pattern matching. | 
| Get an approximate size of an AST node by its s-expression length. This is probably faster than any python layer traversal one can do. Pretty printed ast size will be correlated to expression size, maybe even DAG size, since Z3 inserts `let`s to avoid duplication. | |
| 
 | Bisect the by list to find a minimal set of premises that prove thm. | 
| 
 | Return all constants in a term. | 
| 
 | Return all function declarations in a term. | 
| 
 | Find subterms that are calls of decl in t. | 
| 
 | Returns True if none of the variables in vs exist unbound in t. | 
| 
 | Return free variables in an expression. | 
| 
 | A generator of values for a sort. | 
| 
 | |
| 
 | TODO: Not alpha invariant or going into binders | 
| 
 | |
| 
 | Scan all modules for Proof objects and return a dictionary of them. | 
| 
 | Does x occur in t? | 
| 
 | Open a quantifier with fresh variables. | 
| Do not use this. | |
| 
 | Apply function at position in term >>> x,y,z = smt.Ints("x y z") >>> pathmap(lambda t: t + 1, x + y * z, [1,0]) x + (y + 1)*z | 
| 
 | Pattern match t against pat considering vs as variables. | 
| 
 | First order pattern matching. | 
| 
 | |
| 
 | Pattern match pat against subterms of t, returning the context, matched term, and substitution if successful. | 
| 
 | Ask an AI. | 
| 
 | Prune the list of maybes to the ones implies by known | 
| 
 | Given a list of terms, propagate equalities among them that are implied by known. | 
| 
 | Prune the theorems used using unsat core. | 
| 
 | Check both quantifiers are of the same kind | 
| 
 | Sanity check theorems or proofs for consistency. | 
| 
 | Search for function declarations or expressions. | 
| 
 | Search for declarations in the proof database that contain function declaration f | 
| 
 | Search for expressions in the proof database that match e using pattern matching. | 
| 
 | Generate all sorts in a term | 
| 
 | Generate all subterms of a term | 
| 
 | Unification | 
| 
 | Unification using de Bruijn indices as variables | 
Classes
| 
 | |
| 
 | |
| 
 | A context of holes for an expression. | 
| 
 | |
| 
 | |
| 
 | |
| 
 | A zipper for traversing and modifying terms. | 
- class kdrag.utils.DeclHole(f: z3.z3.FuncDeclRef, _left: tuple[z3.z3.ExprRef, ...], _right: tuple[z3.z3.ExprRef, ...])
- Bases: - object- Parameters:
- f (FuncDeclRef) 
- _left (tuple[ExprRef, ...]) 
- _right (tuple[ExprRef, ...]) 
 
 - f: FuncDeclRef
 - has_left() bool
- Return type:
- bool 
 
 - has_right() bool
- Return type:
- bool 
 
 - left(t: ExprRef) tuple[DeclHole, ExprRef]
- Parameters:
- t (ExprRef) 
- Return type:
- tuple[DeclHole, ExprRef] 
 
 - right(t: ExprRef) tuple[DeclHole, ExprRef]
- Parameters:
- t (ExprRef) 
- Return type:
- tuple[DeclHole, ExprRef] 
 
 - wrap(e: ExprRef) ExprRef
- Parameters:
- e (ExprRef) 
- Return type:
- ExprRef 
 
 
- class kdrag.utils.ExistsHole(vs: list[ExprRef], orig_vs: list[ExprRef])
- Bases: - QuantifierHole- Parameters:
- vs (list[ExprRef]) 
- orig_vs (list[ExprRef]) 
 
 - has_right() bool
- Return type:
- bool 
 
 - orig_vs: list[ExprRef]
 - vs: list[ExprRef]
 - wrap(body: ExprRef) ExprRef
- Parameters:
- body (ExprRef) 
- Return type:
- ExprRef 
 
 
- class kdrag.utils.ExprCtx(iterable=(), /)
- Bases: - list- A context of holes for an expression. Similar to Zipper, but with a nonmutating api - append(object, /)
- Append object to the end of the list. 
 - arg(t: ExprRef, n: int) tuple[ExprCtx, ExprRef]
- >>> x,y,z = smt.Ints("x y z") >>> t = (x + y) * (y + z) >>> ExprCtx().arg(t, 1) ([DeclHole(f=*, _left=(x + y,), _right=())], y + z) - Parameters:
- t (ExprRef) 
- n (int) 
 
- Return type:
- tuple[ExprCtx, ExprRef] 
 
 - children(t) list[tuple[ExprCtx, ExprRef]]
- >>> x,y,z = smt.Ints("x y z") >>> t = (x + y) * (y + z) >>> ExprCtx().children(t) [([DeclHole(f=*, _left=(), _right=(y + z,))], x + y), ([DeclHole(f=*, _left=(x + y,), _right=())], y + z)] - Return type:
- list[tuple[ExprCtx, ExprRef]] 
 
 - clear()
- Remove all items from list. 
 - count(value, /)
- Return number of occurrences of value. 
 - extend(iterable, /)
- Extend list by appending elements from the iterable. 
 - index(value, start=0, stop=9223372036854775807, /)
- Return first index of value. - Raises ValueError if the value is not present. 
 - insert(index, object, /)
- Insert object before index. 
 - open_binder(t: QuantifierRef) tuple[ExprCtx, ExprRef]
- >>> x,y = smt.Ints("x y") >>> t = smt.Lambda([x], x + y) >>> ExprCtx().open_binder(t) ([LambdaHole(vs=[X!...], orig_vs=[x])], X!... + y) - Parameters:
- t (QuantifierRef) 
- Return type:
- tuple[ExprCtx, ExprRef] 
 
 - pop(index=-1, /)
- Remove and return item at index (default last). - Raises IndexError if list is empty or index is out of range. 
 - remove(value, /)
- Remove first occurrence of value. - Raises ValueError if the value is not present. 
 - reverse()
- Reverse IN PLACE. 
 - sort(*, key=None, reverse=False)
- Sort the list in ascending order and return None. - The sort is in-place (i.e. the list itself is modified) and stable (i.e. the order of two equal elements is maintained). - If a key function is given, apply it once to each list item and sort them, ascending or descending, according to their function values. - The reverse flag can be set to sort in descending order. 
 - wrap(t) ExprRef
- Wrap a term t in the context >>> x,y,z = smt.Ints(“x y z”) >>> t = (x + y) * (y + z) >>> ctx, t1 = ExprCtx().arg(t, 1) >>> ctx.wrap(t1) (x + y)*(y + z) - Return type:
- ExprRef 
 
 
- class kdrag.utils.ForAllHole(vs: list[ExprRef], orig_vs: list[ExprRef])
- Bases: - QuantifierHole- Parameters:
- vs (list[ExprRef]) 
- orig_vs (list[ExprRef]) 
 
 - has_right() bool
- Return type:
- bool 
 
 - orig_vs: list[ExprRef]
 - vs: list[ExprRef]
 - wrap(body: ExprRef) ExprRef
- Parameters:
- body (ExprRef) 
- Return type:
- ExprRef 
 
 
- class kdrag.utils.LambdaHole(vs: list[ExprRef], orig_vs: list[ExprRef])
- Bases: - QuantifierHole- Parameters:
- vs (list[ExprRef]) 
- orig_vs (list[ExprRef]) 
 
 - has_right() bool
- Return type:
- bool 
 
 - orig_vs: list[ExprRef]
 - vs: list[ExprRef]
 - wrap(body: ExprRef) ExprRef
- Parameters:
- body (ExprRef) 
- Return type:
- ExprRef 
 
 
- class kdrag.utils.QuantifierHole(vs: list[z3.z3.ExprRef], orig_vs: list[z3.z3.ExprRef])
- Bases: - object- Parameters:
- vs (list[ExprRef]) 
- orig_vs (list[ExprRef]) 
 
 - has_right() bool
- Return type:
- bool 
 
 - orig_vs: list[ExprRef]
 - vs: list[ExprRef]
 
- class kdrag.utils.Zipper(ctx: list[Hole], t: ExprRef)
- Bases: - object- A zipper for traversing and modifying terms. The Zipper retains a context stack of “holes” and the current term. https://en.wikipedia.org/wiki/Zipper_(data_structure) - >>> x,y,z = smt.Ints("x y z") >>> t = smt.Lambda([x,y], (x + y) * (y + z)) >>> z1 = Zipper.from_term(t) >>> z1.open_binder().arg(1).left().arg(0) Zipper(ctx=[LambdaHole(vs=[X!..., Y!...], orig_vs=[x, y]), DeclHole(f=*, _left=(), _right=(Y!... + z,)), DeclHole(f=+, _left=(), _right=(Y!...,))], t=X!...) >>> z1.up().up().up() Zipper(ctx=[], t=Lambda([x, y], (x + y)*(y + z))) - Parameters:
- ctx (list[Hole]) 
- t (ExprRef) 
 
 - __hash__()
- Warning: If you are hashing Zippers, make sure you are copying them. 
 - __next__() ExprRef
- All subterms of the term in a pre-order traversal. - >>> x,y,z = smt.Ints("x y z") >>> list(Zipper([], x + y*z)) [x, y*z, y, z] - Return type:
- ExprRef 
 
 - ctx: list[Hole]
 - pmatch(vs: list[ExprRef], pat: ExprRef) dict[ExprRef, ExprRef] | None
- Pattern match the current term against a pattern with variables vs. Leaves the zipper in a context state. This can be used to replace but rebuild using original context - >>> x,y,z,a,b,c = smt.Ints("x y z a b c") >>> zip = Zipper([], x + smt.Lambda([y], y*z)[x]) >>> (subst := zip.pmatch([a,b], a*b)) {b: z, a: Y!...} >>> zip.t = smt.IntVal(1) * subst[a] >>> zip.rebuild() x + Lambda(y, 1*y)[x] - Parameters:
- vs (list[ExprRef]) 
- pat (ExprRef) 
 
- Return type:
- dict[ExprRef, ExprRef] | None 
 
 - rebuild() ExprRef
- Return type:
- ExprRef 
 
 - t: ExprRef
 
- kdrag.utils.all_values(*es: ExprRef) Generator[list[ExprRef], None, None]
- Generate all values possible for an expression. Generator won’t terminate if there are infinite possible values. Concretization. - >>> assert set(all_values(smt.If(smt.Bool("x"), 2, 3))) == {smt.IntVal(2), smt.IntVal(3)} - Parameters:
- es (ExprRef) 
- Return type:
- Generator[list[ExprRef], None, None] 
 
- kdrag.utils.alpha_eq(t1, t2)
- Alpha equivalent equality. Z3’s fast built-in t.eq is not alpha invariant. - >>> x,y = smt.Ints("x y") >>> t1,t2 = smt.Lambda([x], x), smt.Lambda([y], y) >>> t1.eq(t2) # syntactic equality False >>> alpha_eq(t1, t2) True >>> alpha_eq(smt.Lambda([x], x)[3], smt.IntVal(3)) # No beta equivalence False 
- kdrag.utils.alpha_norm(expr: ExprRef) ExprRef
- Recursively rename all variables in an expression to canonical names. Printed form may become ambiguous because internally de Bruijn indices are used. - >>> x,y,z,w = smt.Consts("x y z w", smt.IntSort()) >>> p = smt.Real("p") >>> assert not smt.Lambda([x,y], x + y).eq(smt.Lambda([z,w], z + w)) >>> assert alpha_norm(smt.Lambda([x,y], x + y)).eq(alpha_norm(smt.Lambda([z,w], z + w))) >>> _ = kd.prove(alpha_norm(smt.Lambda([x,p], p)) == smt.Lambda([x,p], p)) - Parameters:
- expr (ExprRef) 
- Return type:
- ExprRef 
 
- kdrag.utils.antipattern(xs: list[ExprRef]) tuple[list[ExprRef], ExprRef]
- Anti pattern matching. Given a list of concrete examples, return the most specific pattern that matches them all. Returns tuple of list of pattern variables and pattern expression. - https://arxiv.org/pdf/2302.00277 Anti-unification and Generalization: A Survey https://arxiv.org/abs/2212.04596 babble: Learning Better Abstractions with E-Graphs and Anti-Unification https://ericlippert.com/2018/10/29/anti-unification-part-1/ - >>> a,b,c,d = smt.Ints("a b c d") >>> f = smt.Function("f", smt.IntSort(), smt.IntSort(), smt.IntSort()) >>> g = smt.Function("g", smt.IntSort(), smt.IntSort(), smt.IntSort()) >>> t1 = f(a,g(a,b)) >>> t2 = f(c,g(c,d)) >>> t3 = f(a,g(d,b)) >>> antipattern([t1,t2]) ([a!..., b!...], f(a!..., g(a!..., b!...))) >>> antipattern([t1,t2,t3]) ([a!..., a!..., b!...], f(a!..., g(a!..., b!...))) - Parameters:
- xs (list[ExprRef]) 
- Return type:
- tuple[list[ExprRef], ExprRef] 
 
- kdrag.utils.ast_size_sexpr(t: AstRef) int
- Get an approximate size of an AST node by its s-expression length. This is probably faster than any python layer traversal one can do. Pretty printed ast size will be correlated to expression size, maybe even DAG size, since Z3 inserts `let`s to avoid duplication. - >>> ast_size_sexpr(smt.Int("x")) 1 >>> ast_size_sexpr(smt.Int("x") + smt.Int("y")) 7 - Parameters:
- t (AstRef) 
- Return type:
- int 
 
- kdrag.utils.bysect(thm, by: list[Proof] | dict[object, Proof], **kwargs) Sequence[tuple[object, Proof]]
- Bisect the by list to find a minimal set of premises that prove thm. Presents the same interface as prove - >>> x,y,z = smt.Ints("x y z") >>> by = [kd.prove(x + 1 > x), kd.axiom(x == y), kd.prove(y + 1 > y), kd.axiom(y == z)] >>> bysect(x == z, by=by) [(1, |= x == y), (3, |= y == z)] 
- kdrag.utils.consts(t: ExprRef) set[ExprRef]
- Return all constants in a term. - >>> x,y = smt.Ints("x y") >>> consts(x + (y * y) + 1) == {smt.IntVal(1), x, y} True - Parameters:
- t (ExprRef) 
- Return type:
- set[ExprRef] 
 
- kdrag.utils.decls(t: ExprRef) set[FuncDeclRef]
- Return all function declarations in a term. - Parameters:
- t (ExprRef) 
- Return type:
- set[FuncDeclRef] 
 
- kdrag.utils.defined_decls(t: ExprRef) list[FuncDeclRef]
- >>> x,y = smt.Ints("x y") >>> f = kd.define("test_f", [x,y], x + y) >>> g = smt.Function("g", smt.IntSort(), smt.IntSort()) >>> defined_decls(f(x,y) + g(1)) [test_f] - Parameters:
- t (ExprRef) 
- Return type:
- list[FuncDeclRef] 
 
- kdrag.utils.find_calls(decl: FuncDeclRef, t: ExprRef) list[ExprRef]
- Find subterms that are calls of decl in t. - >>> f = smt.Function("f", smt.IntSort(), smt.IntSort()) >>> find_calls(f, f(f(4*f(3)) + 2)) [f(f(4*f(3)) + 2), f(4*f(3)), f(3)] - Parameters:
- decl (FuncDeclRef) 
- t (ExprRef) 
 
- Return type:
- list[ExprRef] 
 
- kdrag.utils.free_in(vs: list[ExprRef], t: ExprRef) bool
- Returns True if none of the variables in vs exist unbound in t. Distinct from occurs in that vs have to be constants, not general terms. - >>> x,y,z = smt.Ints("x y z") >>> assert not free_in([x], x + y + z) >>> assert free_in([x], y + z) >>> assert free_in([x], smt.Lambda([x], x + y + z)) - Parameters:
- vs (list[ExprRef]) 
- t (ExprRef) 
 
- Return type:
- bool 
 
- kdrag.utils.free_vars(t: ExprRef) set[ExprRef]
- Return free variables in an expression. Looks at kernel.defns to determine if contacts are free. If you have meaningful constants no registered there, this may not work. - >>> x,y = smt.Ints("x y") >>> free_vars(smt.Lambda([x], x + y + 1)) {y} - Parameters:
- t (ExprRef) 
- Return type:
- set[ExprRef] 
 
- kdrag.utils.generate(sort: SortRef, pred=None) Generator[ExprRef, None, None]
- A generator of values for a sort. Repeatedly calls z3 to get a new value. - >>> set(generate(smt.BoolSort())) {True, False} >>> sorted([v.as_long() for v in generate(smt.IntSort(), pred=lambda x: smt.And(0 <= x, x < 5))]) [0, 1, 2, 3, 4] >>> import itertools >>> len(list(itertools.islice(generate(smt.ArraySort(smt.IntSort(), smt.IntSort())), 3))) 3 - Parameters:
- sort (SortRef) 
- Return type:
- Generator[ExprRef, None, None] 
 
- kdrag.utils.is_strict_subterm(t: ExprRef, t2: ExprRef) bool
- Parameters:
- t (ExprRef) 
- t2 (ExprRef) 
 
- Return type:
- bool 
 
- kdrag.utils.is_subterm(t: ExprRef, t2: ExprRef) bool
- TODO: Not alpha invariant or going into binders - Parameters:
- t (ExprRef) 
- t2 (ExprRef) 
 
- Return type:
- bool 
 
- kdrag.utils.is_value(t: ExprRef)
- Parameters:
- t (ExprRef) 
 
- kdrag.utils.lemma_db() dict[str, Proof]
- Scan all modules for Proof objects and return a dictionary of them. - Return type:
- dict[str, Proof] 
 
- kdrag.utils.occurs(x: ExprRef, t: ExprRef) bool
- Does x occur in t? - >>> x,y,z = smt.Ints("x y z") >>> assert occurs(x + y, x + y + z) >>> assert not occurs(x + y, x + z) >>> assert occurs(x, x + y + z) >>> v0 = smt.Var(0, smt.IntSort()) >>> assert occurs(v0, v0 + x + y) - Parameters:
- x (ExprRef) 
- t (ExprRef) 
 
- Return type:
- bool 
 
- kdrag.utils.open_binder(lam: QuantifierRef) tuple[list[ExprRef], ExprRef]
- Open a quantifier with fresh variables. This achieves the locally nameless representation https://chargueraud.org/research/2009/ln/main.pdf where it is harder to go wrong. - The variables are schema variables which when used in a proof may be generalized - >>> x = smt.Int("x") >>> open_binder(smt.ForAll([x], x > 0)) ([X!...], X!... > 0) - Parameters:
- lam (QuantifierRef) 
- Return type:
- tuple[list[ExprRef], ExprRef] 
 
- kdrag.utils.open_binder_unhygienic(lam: QuantifierRef) tuple[list[ExprRef], ExprRef]
- Do not use this. Use open_binder. Opens a quantifier with unfresh variables. - >>> x = smt.Int("x") >>> open_binder_unhygienic(smt.ForAll([x], x > 0)) ([x], x > 0) - Parameters:
- lam (QuantifierRef) 
- Return type:
- tuple[list[ExprRef], ExprRef] 
 
- kdrag.utils.pathmap(function: Callable[[ExprRef], ExprRef], e: ExprRef, path: list[int] | None) ExprRef
- Apply function at position in term >>> x,y,z = smt.Ints(“x y z”) >>> pathmap(lambda t: t + 1, x + y * z, [1,0]) x + (y + 1)*z - Parameters:
- function (Callable[[ExprRef], ExprRef]) 
- e (ExprRef) 
- path (list[int] | None) 
 
- Return type:
- ExprRef 
 
- kdrag.utils.pmatch(vs: list[ExprRef], pat: ExprRef, t: ExprRef, subst=None) dict[ExprRef, ExprRef] | None
- Pattern match t against pat considering vs as variables. Returns substitution dictionary if succeeds https://www.philipzucker.com/ho_unify/ - Parameters:
- vs (list[ExprRef]) 
- pat (ExprRef) 
- t (ExprRef) 
 
- Return type:
- dict[ExprRef, ExprRef] | None 
 
- kdrag.utils.pmatch_fo(vs: list[ExprRef], pat: ExprRef, t: ExprRef, subst=None) dict[ExprRef, ExprRef] | None
- First order pattern matching. Faster and simpler. Pattern match t against pat considering vs as variables. Returns substitution dictionary if succeeds - >>> x, y = smt.Ints("x y") >>> pmatch_fo([x], x + x, y + y) {x: y} - Parameters:
- vs (list[ExprRef]) 
- pat (ExprRef) 
- t (ExprRef) 
 
- Return type:
- dict[ExprRef, ExprRef] | None 
 
- kdrag.utils.pmatch_rec(vs: list[ExprRef], pat: ExprRef, t: ExprRef, into_binder=False) tuple[ExprRef, dict[ExprRef, ExprRef]] | None
- Parameters:
- vs (list[ExprRef]) 
- pat (ExprRef) 
- t (ExprRef) 
 
- Return type:
- tuple[ExprRef, dict[ExprRef, ExprRef]] | None 
 
- kdrag.utils.pmatch_rec_ctx(vs: list[ExprRef], pat: ExprRef, t: ExprRef) tuple[ExprCtx, ExprRef, dict[ExprRef, ExprRef]] | None
- Pattern match pat against subterms of t, returning the context, matched term, and substitution if successful. >>> x,y,z,a,b = smt.Ints(“x y z a b”) >>> kd.utils.pmatch_rec_ctx([a,b], a*b, smt.Lambda([x], x * y)) ([LambdaHole(vs=[X!…], orig_vs=[x])], X!…*y, {b: y, a: X!…}) - Parameters:
- vs (list[ExprRef]) 
- pat (ExprRef) 
- t (ExprRef) 
 
- Return type:
- tuple[ExprCtx, ExprRef, dict[ExprRef, ExprRef]] | None 
 
- kdrag.utils.prompt(prompt: str)
- Ask an AI. - Get the root directory of the current package, find all .py files within that directory, and concatenate their contents into a single string separated by —. - Returns:
- A single string with all .py files concatenated, separated by —. 
- Return type:
- str 
- Parameters:
- prompt (str) 
 
- kdrag.utils.propagate(maybes: list[BoolRef], known: BoolRef) list[BoolRef]
- Prune the list of maybes to the ones implies by known - >>> p,q,r = smt.Bools("p q r") >>> propagate([p, q, r, smt.And(p,q)], p & q) [p, q, And(p, q)] - Parameters:
- maybes (list[BoolRef]) 
- known (BoolRef) 
 
- Return type:
- list[BoolRef] 
 
- kdrag.utils.propagate_eqs(terms: list[ExprRef], known: BoolRef) list[BoolRef]
- Given a list of terms, propagate equalities among them that are implied by known. >>> x,y,z = smt.Ints(“x y z”) >>> terms = [x, y, z, x + 1, y + 1] >>> known = smt.And(x == y, y == z) >>> propagate_eqs(terms, known) [y == x, z == x, z == y, y + 1 == x + 1] - Parameters:
- terms (list[ExprRef]) 
- known (BoolRef) 
 
- Return type:
- list[BoolRef] 
 
- kdrag.utils.prune(thm: BoolRef | QuantifierRef | Proof, by=[], timeout=1000) list[ExprRef | Proof]
- Prune the theorems used using unsat core. Helpful to speedup future proof verification. - >>> p,q,r = smt.Bools("p q r") >>> sorted(prune(p & q, [p, q, r]), key=lambda b: b.decl().name()) [p, q] 
- kdrag.utils.quant_kind_eq(t1: QuantifierRef, t2: QuantifierRef) bool
- Check both quantifiers are of the same kind - >>> x = smt.Int("x") >>> forall = smt.ForAll([x], x > 0) >>> exists = smt.Exists([x], x > 0) >>> lamb = smt.Lambda([x], x > 0) >>> assert quant_kind_eq(forall, forall) >>> assert quant_kind_eq(exists, exists) >>> assert quant_kind_eq(lamb, lamb) >>> assert not quant_kind_eq(forall, exists) - Parameters:
- t1 (QuantifierRef) 
- t2 (QuantifierRef) 
 
- Return type:
- bool 
 
- kdrag.utils.sanity_check_consistency(thms: list[ExprRef | Proof], timeout=1000)
- Sanity check theorems or proofs for consistency. If they are inconsistent, raise an error. Otherwise, return the result of the check. A sat result shows consistency, but an unknown result does not imply anything. - It may be nice to try and apply this function to your axioms or theory in CI. - >>> x,y = smt.Ints("x y") >>> sanity_check_consistency([x == y]) sat - Parameters:
- thms (list[ExprRef | Proof]) 
 
- kdrag.utils.search(*es: FuncDeclRef | ExprRef, db: dict[Any, Proof] = {}) dict[tuple[str, Proof], Any]
- Search for function declarations or expressions. Takes intersection of found results if given multiple arguments. Builds a database by scanning loaded modules by default. 
- kdrag.utils.search_decl(f: FuncDeclRef, db: dict[object, Proof]) dict[tuple[str, Proof], Any]
- Search for declarations in the proof database that contain function declaration f 
- kdrag.utils.search_expr(e: ExprRef, pfs: dict[object, Proof]) dict[tuple[str, Proof], Any]
- Search for expressions in the proof database that match e using pattern matching. - >>> x,z = smt.Ints("x z") >>> search_expr(z + 0, { "thm1": kd.prove(smt.ForAll([x], x + 0 == x)), "thm2" : kd.prove(z + 0 == z), "thm3" : kd.prove(smt.ForAll([x], x + 1 == 1 + x)), "thm4" : kd.prove(smt.BoolVal(True))}) {('thm1', |= ForAll(x, x + 0 == x)): [z], ('thm2', |= z + 0 == z): []} 
- kdrag.utils.sorts(t: ExprRef)
- Generate all sorts in a term - Parameters:
- t (ExprRef) 
 
- kdrag.utils.subterms(t: ExprRef, into_binder=False)
- Generate all subterms of a term - >>> x,y = smt.Ints("x y") >>> list(subterms(x + y == y)) [x + y == y, y, x + y, y, x] >>> list(subterms(smt.ForAll([x], x + y == y))) [ForAll(x, x + y == y)] >>> list(subterms(smt.ForAll([x], x + y == y), into_binder=True)) [ForAll(x, x + y == y), Var(0) + y == y, y, Var(0) + y, y, Var(0)] - Parameters:
- t (ExprRef) 
 
- kdrag.utils.unify(vs: list[ExprRef], p1: ExprRef, p2: ExprRef) dict[ExprRef, ExprRef] | None
- Unification - Parameters:
- vs (list[ExprRef]) 
- p1 (ExprRef) 
- p2 (ExprRef) 
 
- Return type:
- dict[ExprRef, ExprRef] | None 
 
- kdrag.utils.unify_db(p1: ExprRef, p2: ExprRef) dict[ExprRef, ExprRef] | None
- Unification using de Bruijn indices as variables - Parameters:
- p1 (ExprRef) 
- p2 (ExprRef) 
 
- Return type:
- dict[ExprRef, ExprRef] | None