Getting Started
This tutorial will walk you through the basics of using SymbolicSMT.jl to solve symbolic constraint problems.
Installation and Setup
First, install the required packages:
using Pkg
Pkg.add(["SymbolicSMT", "Symbolics"])
Then load the packages:
using Symbolics, SymbolicSMT
Creating Symbolic Variables with Symbolics.jl
SymbolicSMT.jl works seamlessly with Symbolics.jl @variables
and Num
types:
@variables x::Real y::Real z::Integer p::Bool
This creates symbolic variables: x
and y
as real numbers, z
as an integer, and p
as a boolean.
Defining Constraints
Constraints are collections of boolean expressions that must be satisfied. Create constraints using the Constraints
constructor:
# Simple constraints with Symbolics.jl variables
constraints = Constraints([
x > 0, # x must be positive
y >= -2, # y must be at least -2
x + y < 10 # sum must be less than 10
])
Checking Satisfiability
Use issatisfiable
to check if an expression can be true given the constraints:
# Can x be greater than 5?
issatisfiable(x > 5, constraints) # true - possible
# Can x be negative?
issatisfiable(x < 0, constraints) # false - conflicts with x > 0
# Can x + y equal 15?
issatisfiable(x + y == 15, constraints) # false - conflicts with x + y < 10
Checking Provability
Use isprovable
to check if an expression is always true given the constraints:
# Is x always positive?
isprovable(x > 0, constraints) # true - follows from constraints
# Is x always greater than y?
isprovable(x > y, constraints) # false - not necessarily true
Expression Resolution
The resolve
function attempts to simplify expressions to boolean constants:
@variables t::Real
time_constraints = Constraints([t >= 0, t <= 24]) # Time in hours
# These resolve to constants
resolve(t >= 0, time_constraints) # true (always true)
resolve(t < 0, time_constraints) # false (never true)
# This cannot be resolved (returns original Num expression)
resolve(t > 12, time_constraints) # t > 12 (unchanged)
Working with Different Variable Types
Real Variables
@variables x::Real y::Real temperature::Real
constraints = Constraints([x >= 0, y >= 0, temperature > 273.15])
issatisfiable(x + y > temperature, constraints)
Integer Variables
@variables n::Integer count::Integer age::Integer
constraints = Constraints([n >= 1, count <= 100, age >= 0])
isprovable(n > 0, constraints) # true
Boolean Variables
@variables valid::Bool active::Bool
constraints = Constraints([valid, !active]) # valid is true, active is false
isprovable(valid | active, constraints) # true
Complex Expressions
SymbolicSMT.jl supports complex arithmetic and boolean expressions:
@variables a::Real b::Real
# Quadratic constraints
quadratic_constraints = Constraints([
a^2 + b^2 <= 1, # Inside unit circle
a >= 0 # First quadrant
])
# Check complex expressions
issatisfiable(a * b > 0.1, quadratic_constraints)
isprovable(a >= 0, quadratic_constraints) # true
Return Values
Understanding the return values:
true
: The expression is satisfiable/provablefalse
: The expression is unsatisfiable/not provablenothing
: The solver cannot determine the result (rare)
For resolve
, boolean results are returned as Bool
, while unresolved expressions are returned as Num
.
Alternative Interface: SymbolicUtils.jl
You can also use the lower-level SymbolicUtils.jl interface directly:
using SymbolicUtils, SymbolicSMT
@syms x::Real y::Real
constraints = Constraints([x > 0, y > 0])
issatisfiable(x + y > 1, constraints)
Next Steps
- Read the Manual for deeper understanding of concepts
- Check out Tutorials for more complex examples
- Browse the API Reference for complete function documentation