In Z3, all terms, formulas, and types are represented as Abstract Syntax Trees (ASTs). The expression system is the foundation for building and manipulating logical formulas.
from z3 import *x, y = Ints('x y')# Arithmetic operations are function applicationsexpr1 = x + y # Application of '+'expr2 = x * 2 # Application of '*'expr3 = x > y # Application of '>'# Uninterpreted functionf = Function('f', IntSort(), IntSort(), IntSort())expr4 = f(x, y) # Application of 'f'# Check structureprint(expr1.decl()) # +print(expr1.num_args()) # 2print(expr1.arg(0)) # xprint(expr1.arg(1)) # y
from z3 import *x, y, z = Ints('x y z')# Linear arithmeticlinear = 2*x + 3*y - z# Nonlinear arithmeticnonlinear = x * y + z * z# Comparisonsconstraint = And(x >= 0, x + y <= 10, z > x)# Division (integer)quot = x / y # Integer divisionrem = x % y # Remainder
from z3 import *def visit(e, seen=None): """Recursively visit all subexpressions""" if seen is None: seen = set() if e.get_id() in seen: return seen.add(e.get_id()) if is_app(e): print(f"Application of {e.decl().name()}: {e}") for child in e.children(): visit(child, seen) elif is_quantifier(e): print(f"Quantifier: {e}") visit(e.body(), seen) else: print(f"Leaf: {e}")# Example usagex, y = Ints('x y')f = x*x + x*x - y*y >= 0visit(f)
from z3 import *x, y = Ints('x y')b = Bool('b')# Conditional expressionresult = If(b, x, y)# Type must match both branchesresult2 = If(x > 0, x + 1, x - 1) # Both branches are Int
Z3 uses reference counting for memory management. In C/C++:
Always increment refs with Z3_inc_ref
Decrement with Z3_dec_ref when done
The C++ API handles this automatically
Python API is fully garbage-collected
// C API - manual reference countingZ3_context ctx = Z3_mk_context(cfg);Z3_ast x = Z3_mk_int_const(ctx, Z3_mk_string_symbol(ctx, "x"));Z3_inc_ref(ctx, x); // Increment ref// ... use x ...Z3_dec_ref(ctx, x); // Decrement when done