---
z3 --version
# Z3 version 4.13.3 - 64 bit
make clean && make all
erl -pa _build/ebin -s smt_process_test run -s smt_parser_test run -s init stop
# All 12 tests should pass
---
curesmtsolver.erl)cure_smt_solver:check_constraint(Constraint, Env).
% Returns: sat | unsat | unknown
cure_smt_solver:prove_constraint(Constraint, Env).
% Returns: true | false | unknown
cure_smt_solver:find_counterexample(Constraint, Env).
% Returns: {ok, Model} | none | unknown
{ok, Pid} = cure_smt_process:start_solver(z3, 5000).
% Solver: z3 | cvc5
% Timeout: milliseconds
Query = cure_smt_translator:generate_query(Constraint, Env),
Result = cure_smt_process:execute_query(Pid, Query).
% Returns: sat | unsat | {sat, Lines} | {error, Reason}
{ok, Model} = cure_smt_parser:parse_model(Lines).
% Returns: {ok, #{var => value}} | {error, Reason}
cure_smt_process:stop_solver(Pid).
---
% Constraint: x > 0
Constraint = #binary_op_expr{
op = '>',
left = #identifier_expr{name = x},
right = #literal_expr{value = 0}
},
Env = #{x => {type, int}},
% Check if satisfiable
cure_smt_solver:check_constraint(Constraint, Env).
% => sat (there exists x > 0)
% Find example
cure_smt_solver:find_counterexample(
#unary_op_expr{op = 'not', operand = Constraint},
Env
).
% => {ok, #{x => 0}} (x=0 is counterexample to x > 0)
% Constraint: y /= 0
Constraint = #binary_op_expr{
op = '/=',
left = #identifier_expr{name = y},
right = #literal_expr{value = 0}
},
Env = #{y => {type, int}},
% This is satisfiable (y can be non-zero)
cure_smt_solver:check_constraint(Constraint, Env).
% => sat
% But can we find y = 0? (violates constraint)
cure_smt_solver:find_counterexample(Constraint, Env).
% => {ok, #{y => 0}} (counterexample exists)
% Constraint: x + y == y + x (commutativity)
Constraint = #binary_op_expr{
op = '==',
left = #binary_op_expr{
op = '+',
left = #identifier_expr{name = x},
right = #identifier_expr{name = y}
},
right = #binary_op_expr{
op = '+',
left = #identifier_expr{name = y},
right = #identifier_expr{name = x}
}
},
Env = #{x => {type, int}, y => {type, int}},
% This should be proven true
cure_smt_solver:prove_constraint(Constraint, Env).
% => true (no counterexample exists)
% Constraint: (x > 0) and (y > 0) => (x + y > 0)
Constraint = #binary_op_expr{
op = '=>',
left = #binary_op_expr{
op = 'and',
left = #binary_op_expr{op = '>', left = var(x), right = lit(0)},
right = #binary_op_expr{op = '>', left = var(y), right = lit(0)}
},
right = #binary_op_expr{
op = '>',
left = #binary_op_expr{op = '+', left = var(x), right = var(y)},
right = lit(0)
}
},
Env = #{x => {type, int}, y => {type, int}},
cure_smt_solver:prove_constraint(Constraint, Env).
% => true (proven!)
---
+, -, → (+ x y), (- x y), ( x y)/ → (/ x y) (real division)div → (div x y) (integer division)rem → (mod x y) (remainder)==, /= → (= x y), (not (= x y))<, > → (< x y), (> x y)=<, >= → (<= x y), (>= x y)and, or, not → (and x y), (or x y), (not x)andalso, orelse → same as and, or=> → (=> x y) (implication)- (negation) → (- x)not (boolean) → (not x)Int, Nat → Int (SMT integer)Bool → Bool (SMT boolean)Float, Real → Real (SMT real)The translator automatically infers the SMT logic:
QF_LIA - Linear Integer Arithmetic (Int only)QF_LRA - Linear Real Arithmetic (Real only)QF_LIRA - Linear Mixed Integer/Real ArithmeticQF_NIA - Nonlinear Integer Arithmetic (with *, /)---
Default timeout is 5000ms. Configure per-solver:
{ok, Pid} = cure_smt_process:start_solver(z3, 10000). % 10 seconds
Or use default:
{ok, Pid} = cure_smt_process:start_solver(z3, 5000).
---
All functions have graceful error handling:
case cure_smt_solver:check_constraint(Constraint, Env) of
sat -> io:format("Satisfiable~n");
unsat -> io:format("Unsatisfiable~n");
unknown -> io:format("Solver could not determine~n");
{error, Reason} -> io:format("Error: ~p~n", [Reason])
end.
If SMT solver fails, the system falls back to symbolic evaluation.
---
erl -pa _build/ebin -s smt_process_test run -s smt_parser_test run -s init stop
erl -pa _build/ebin -s smt_process_test run -s init stop
erl -pa _build/ebin -s smt_parser_test run -s init stop
---
Error: Z3 solver not found
Solution: Install Z3
sudo apt install z3 # Ubuntu/Debian
brew install z3 # macOS
{error, timeout}
Solution: Increase timeout
{ok, Pid} = cure_smt_process:start_solver(z3, 30000). % 30 seconds
{error, {parse_error, Reason}}
Solution: Check constraint syntax and types in environment.
---
---
User Code
↓
cure_smt_solver (High-level API)
↓
cure_smt_translator (AST → SMT-LIB)
↓
cure_smt_process (Solver management)
↓
Z3 Solver (via Erlang port)
↓
cure_smt_parser (Model extraction)
↓
Result
---
src/smt/curesmtsolver.erl - High-level APIsrc/smt/curesmttranslator.erl - Constraint translationsrc/smt/curesmtprocess.erl - Solver process managementsrc/smt/curesmtparser.erl - Model parsertest/smtprocesstest.erl - Process management tests (7 tests)test/smtparsertest.erl - Parser tests (5 tests)docs/SMTINTEGRATIONCOMPLETE.md - Complete overviewdocs/SMTINTEGRATIONPLAN.md - Original plandocs/SMTCOMPLETIONPLAN.md - 4-step completion plandocs/SMTSOLVERINSTALLATION.md - Installation guide---
--smt-solver [z3|cvc5]--smt-timeout --no-smt---
Version: 1.0 Last Updated: October 31, 2025 Status: Production Ready ✅ Note: SMT solver integration is available at the Erlang API level. CLI integration is not yet implemented.