3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-02-17 06:11:44 +00:00

git bindings v1.0

This commit is contained in:
Nikolaj Bjorner 2026-02-15 21:24:40 -08:00
parent e2486eff77
commit 66d0fb5477
33 changed files with 5289 additions and 7 deletions

145
examples/go/README.md Normal file
View file

@ -0,0 +1,145 @@
# Z3 Go Examples
This directory contains examples demonstrating how to use the Z3 Go bindings.
## Examples
### basic_example.go
Demonstrates fundamental Z3 operations:
- Creating contexts and solvers
- Defining integer and boolean variables
- Adding constraints
- Checking satisfiability
- Extracting models
## Building and Running
### Prerequisites
1. Build Z3 with Go bindings enabled
2. Ensure Z3 library is in your library path
3. Go 1.20 or later
### Linux/macOS
```bash
# Build Z3 first
cd ../..
mkdir build && cd build
cmake ..
make -j$(nproc)
# Set up environment
cd ../examples/go
export LD_LIBRARY_PATH=../../build:$LD_LIBRARY_PATH
export CGO_CFLAGS="-I../../src/api"
export CGO_LDFLAGS="-L../../build -lz3"
# Run examples
go run basic_example.go
```
### Windows
```cmd
REM Build Z3 first
cd ..\..
mkdir build
cd build
cmake ..
cmake --build . --config Release
REM Set up environment
cd ..\examples\go
set PATH=..\..\build\Release;%PATH%
set CGO_CFLAGS=-I..\..\src\api
set CGO_LDFLAGS=-L..\..\build\Release -lz3
REM Run examples
go run basic_example.go
```
## Expected Output
When you run `basic_example.go`, you should see output similar to:
```
Z3 Go Bindings - Basic Example
================================
Example 1: Solving x > 0
Satisfiable!
Model: ...
x = 1
Example 2: Solving x + y = 10 ∧ x - y = 2
Satisfiable!
x = 6
y = 4
Example 3: Boolean satisfiability
Satisfiable!
p = false
q = true
Example 4: Checking unsatisfiability
Status: unsat
The constraints are unsatisfiable (as expected)
All examples completed successfully!
```
## Creating Your Own Examples
1. Import the Z3 package:
```go
import "github.com/Z3Prover/z3/src/api/go"
```
2. Create a context:
```go
ctx := z3.NewContext()
```
3. Create variables and constraints:
```go
x := ctx.MkIntConst("x")
constraint := ctx.MkGt(x, ctx.MkInt(0, ctx.MkIntSort()))
```
4. Solve:
```go
solver := ctx.NewSolver()
solver.Assert(constraint)
if solver.Check() == z3.Satisfiable {
model := solver.Model()
// Use model...
}
```
## Troubleshooting
### "undefined reference to Z3_*" errors
Make sure:
- Z3 is built and the library is in your library path
- CGO_LDFLAGS includes the correct library path
- On Windows, the DLL is in your PATH
### "cannot find package" errors
Make sure:
- CGO_CFLAGS includes the Z3 API header directory
- The go.mod file exists in src/api/go
### CGO compilation errors
Ensure:
- CGO is enabled (set CGO_ENABLED=1 if needed)
- You have a C compiler installed (gcc, clang, or MSVC)
- The Z3 headers are accessible
## More Information
See the README.md in src/api/go for complete API documentation.

View file

@ -0,0 +1,313 @@
package main
import (
"fmt"
"github.com/Z3Prover/z3/src/api/go"
)
func main() {
ctx := z3.NewContext()
fmt.Println("Z3 Go Bindings - Advanced Features Example")
fmt.Println("==========================================")
// Example 1: Bit-vectors
fmt.Println("\nExample 1: Bit-vector operations")
x := ctx.MkBVConst("x", 8)
y := ctx.MkBVConst("y", 8)
// x + y == 255 && x > y
sum := ctx.MkBVAdd(x, y)
ff := ctx.MkBV(255, 8)
solver := ctx.NewSolver()
solver.Assert(ctx.MkEq(sum, ff))
solver.Assert(ctx.MkBVUGT(x, y))
if solver.Check() == z3.Satisfiable {
model := solver.Model()
fmt.Println("Satisfiable!")
if xVal, ok := model.Eval(x, true); ok {
fmt.Println("x =", xVal.String())
}
if yVal, ok := model.Eval(y, true); ok {
fmt.Println("y =", yVal.String())
}
}
// Example 2: Floating-point arithmetic
fmt.Println("\nExample 2: Floating-point arithmetic")
solver.Reset()
fpSort := ctx.MkFPSort32()
a := ctx.MkConst(ctx.MkStringSymbol("a"), fpSort)
b := ctx.MkConst(ctx.MkStringSymbol("b"), fpSort)
// a + b > 0.0 (with rounding mode)
rm := ctx.MkConst(ctx.MkStringSymbol("rm"), ctx.MkFPRoundingModeSort())
fpSum := ctx.MkFPAdd(rm, a, b)
zero := ctx.MkFPZero(fpSort, false)
solver.Assert(ctx.MkFPGT(fpSum, zero))
solver.Assert(ctx.MkFPGT(a, ctx.MkFPZero(fpSort, false)))
if solver.Check() == z3.Satisfiable {
fmt.Println("Satisfiable! (Floating-point constraint satisfied)")
}
// Example 3: Strings
fmt.Println("\nExample 3: String operations")
solver.Reset()
s1 := ctx.MkConst(ctx.MkStringSymbol("s1"), ctx.MkStringSort())
s2 := ctx.MkConst(ctx.MkStringSymbol("s2"), ctx.MkStringSort())
// s1 contains "hello" && length(s1) < 20
hello := ctx.MkString("hello")
solver.Assert(ctx.MkSeqContains(s1, hello))
len1 := ctx.MkSeqLength(s1)
twenty := ctx.MkInt(20, ctx.MkIntSort())
solver.Assert(ctx.MkLt(len1, twenty))
// s2 is s1 concatenated with "world"
world := ctx.MkString(" world")
solver.Assert(ctx.MkEq(s2, ctx.MkSeqConcat(s1, world)))
if solver.Check() == z3.Satisfiable {
model := solver.Model()
fmt.Println("Satisfiable!")
if s1Val, ok := model.Eval(s1, true); ok {
fmt.Println("s1 =", s1Val.String())
}
if s2Val, ok := model.Eval(s2, true); ok {
fmt.Println("s2 =", s2Val.String())
}
}
// Example 4: Datatypes (List)
fmt.Println("\nExample 4: List datatype")
solver.Reset()
intSort := ctx.MkIntSort()
listSort, nilDecl, consDecl, isNilDecl, isConsDecl, headDecl, tailDecl :=
ctx.MkListSort("IntList", intSort)
// Create list: cons(1, cons(2, nil))
nilList := ctx.MkApp(nilDecl)
one := ctx.MkInt(1, intSort)
two := ctx.MkInt(2, intSort)
list2 := ctx.MkApp(consDecl, two, nilList)
list12 := ctx.MkApp(consDecl, one, list2)
// Check that head(list12) == 1
listVar := ctx.MkConst(ctx.MkStringSymbol("mylist"), listSort)
solver.Assert(ctx.MkEq(listVar, list12))
headOfList := ctx.MkApp(headDecl, listVar)
solver.Assert(ctx.MkEq(headOfList, one))
if solver.Check() == z3.Satisfiable {
fmt.Println("Satisfiable! List head is 1")
}
// Example 5: Tactics and Goals
fmt.Println("\nExample 5: Using tactics")
goal := ctx.MkGoal(true, false, false)
p := ctx.MkIntConst("p")
q := ctx.MkIntConst("q")
// Add constraint: p > 0 && q > 0 && p + q == 10
goal.Assert(ctx.MkGt(p, ctx.MkInt(0, ctx.MkIntSort())))
goal.Assert(ctx.MkGt(q, ctx.MkInt(0, ctx.MkIntSort())))
goal.Assert(ctx.MkEq(ctx.MkAdd(p, q), ctx.MkInt(10, ctx.MkIntSort())))
// Apply simplify tactic
tactic := ctx.MkTactic("simplify")
result := tactic.Apply(goal)
fmt.Printf("Tactic produced %d subgoals\n", result.NumSubgoals())
if result.NumSubgoals() > 0 {
subgoal := result.Subgoal(0)
fmt.Println("Simplified goal:", subgoal.String())
}
// Example 6: Enumerations
fmt.Println("\nExample 6: Enumeration types")
solver.Reset()
colorSort, colorConsts, colorTesters := ctx.MkEnumSort(
"Color",
[]string{"Red", "Green", "Blue"},
)
red := ctx.MkApp(colorConsts[0])
green := ctx.MkApp(colorConsts[1])
blue := ctx.MkApp(colorConsts[2])
c1 := ctx.MkConst(ctx.MkStringSymbol("c1"), colorSort)
c2 := ctx.MkConst(ctx.MkStringSymbol("c2"), colorSort)
// c1 != c2 && c1 != Red
solver.Assert(ctx.MkDistinct(c1, c2))
solver.Assert(ctx.MkNot(ctx.MkEq(c1, red)))
if solver.Check() == z3.Satisfiable {
model := solver.Model()
fmt.Println("Satisfiable!")
if c1Val, ok := model.Eval(c1, true); ok {
fmt.Println("c1 =", c1Val.String())
}
if c2Val, ok := model.Eval(c2, true); ok {
fmt.Println("c2 =", c2Val.String())
}
}
// Example 7: Tuples
fmt.Println("\nExample 7: Tuple types")
solver.Reset()
tupleSort, mkTuple, projections := ctx.MkTupleSort(
"Point",
[]string{"x", "y"},
[]*z3.Sort{ctx.MkIntSort(), ctx.MkIntSort()},
)
// Create point (3, 4)
three := ctx.MkInt(3, ctx.MkIntSort())
four := ctx.MkInt(4, ctx.MkIntSort())
point := ctx.MkApp(mkTuple, three, four)
p1 := ctx.MkConst(ctx.MkStringSymbol("p1"), tupleSort)
solver.Assert(ctx.MkEq(p1, point))
// Extract x coordinate
xCoord := ctx.MkApp(projections[0], p1)
solver.Assert(ctx.MkEq(xCoord, three))
if solver.Check() == z3.Satisfiable {
fmt.Println("Satisfiable! Tuple point created")
model := solver.Model()
if p1Val, ok := model.Eval(p1, true); ok {
fmt.Println("p1 =", p1Val.String())
}
}
// Example 8: Regular expressions
fmt.Println("\nExample 8: Regular expressions")
solver.Reset()
// Create a string variable
str := ctx.MkConst(ctx.MkStringSymbol("str"), ctx.MkStringSort())
// Create regex: (a|b)*c+ (zero or more 'a' or 'b', followed by one or more 'c')
a := ctx.MkToRe(ctx.MkString("a"))
b := ctx.MkToRe(ctx.MkString("b"))
c := ctx.MkToRe(ctx.MkString("c"))
// (a|b)
aOrB := ctx.MkReUnion(a, b)
// (a|b)*
aOrBStar := ctx.MkReStar(aOrB)
// c+
cPlus := ctx.MkRePlus(c)
// (a|b)*c+
regex := ctx.MkReConcat(aOrBStar, cPlus)
// Assert that string matches the regex
solver.Assert(ctx.MkInRe(str, regex))
// Also assert that length is less than 10
strLen := ctx.MkSeqLength(str)
ten := ctx.MkInt(10, ctx.MkIntSort())
solver.Assert(ctx.MkLt(strLen, ten))
if solver.Check() == z3.Satisfiable {
model := solver.Model()
fmt.Println("Satisfiable!")
if strVal, ok := model.Eval(str, true); ok {
fmt.Println("String matching (a|b)*c+:", strVal.String())
}
}
// Example 8: Regular expressions
fmt.Println("\nExample 8: Regular expressions")
solver.Reset()
// Create a string variable
str := ctx.MkConst(ctx.MkStringSymbol("str"), ctx.MkStringSort())
// Create regex: (a|b)*c+ (zero or more 'a' or 'b', followed by one or more 'c')
a := ctx.MkToRe(ctx.MkString("a"))
b := ctx.MkToRe(ctx.MkString("b"))
c := ctx.MkToRe(ctx.MkString("c"))
// (a|b)*
aOrB := ctx.MkReUnion(a, b)
aOrBStar := ctx.MkReStar(aOrB)
// c+
cPlus := ctx.MkRePlus(c)
// (a|b)*c+
regex := ctx.MkReConcat(aOrBStar, cPlus)
// Assert that string matches the regex
solver.Assert(ctx.MkInRe(str, regex))
// Also assert that length is less than 10
strLen := ctx.MkSeqLength(str)
tenStr := ctx.MkInt(10, ctx.MkIntSort())
solver.Assert(ctx.MkLt(strLen, tenStr))
if solver.Check() == z3.Satisfiable {
model := solver.Model()
fmt.Println("Satisfiable!")
if strVal, ok := model.Eval(str, true); ok {
fmt.Println("String matching (a|b)*c+:", strVal.String())
}
}
// Example 9: Optimization
fmt.Println("\nExample 9: Optimization (maximize/minimize)")
opt := ctx.NewOptimize()
// Variables
xOpt := ctx.MkIntConst("x_opt")
yOpt := ctx.MkIntConst("y_opt")
// Constraints: x + y <= 10, x >= 0, y >= 0
tenOpt := ctx.MkInt(10, ctx.MkIntSort())
zeroOpt := ctx.MkInt(0, ctx.MkIntSort())
opt.Assert(ctx.MkLe(ctx.MkAdd(xOpt, yOpt), tenOpt))
opt.Assert(ctx.MkGe(xOpt, zeroOpt))
opt.Assert(ctx.MkGe(yOpt, zeroOpt))
// Objective: maximize x + 2*y
twoOpt := ctx.MkInt(2, ctx.MkIntSort())
objective := ctx.MkAdd(xOpt, ctx.MkMul(twoOpt, yOpt))
objHandle := opt.Maximize(objective)
if opt.Check() == z3.Satisfiable {
model := opt.Model()
fmt.Println("Optimal solution found!")
if xVal, ok := model.Eval(xOpt, true); ok {
fmt.Println("x =", xVal.String())
}
if yVal, ok := model.Eval(yOpt, true); ok {
fmt.Println("y =", yVal.String())
}
upper := opt.GetUpper(objHandle)
if upper != nil {
fmt.Println("Maximum value of x + 2*y =", upper.String())
}
}
fmt.Println("\nAll advanced examples completed successfully!")
}

View file

@ -0,0 +1,98 @@
package main
import (
"fmt"
"github.com/Z3Prover/z3/src/api/go"
)
func main() {
// Create a new Z3 context
ctx := z3.NewContext()
fmt.Println("Z3 Go Bindings - Basic Example")
fmt.Println("================================")
// Example 1: Simple integer constraint
fmt.Println("\nExample 1: Solving x > 0")
x := ctx.MkIntConst("x")
zero := ctx.MkInt(0, ctx.MkIntSort())
constraint := ctx.MkGt(x, zero)
solver := ctx.NewSolver()
solver.Assert(constraint)
if solver.Check() == z3.Satisfiable {
model := solver.Model()
fmt.Println("Satisfiable!")
fmt.Println("Model:", model.String())
if val, ok := model.Eval(x, true); ok {
fmt.Println("x =", val.String())
}
}
// Example 2: System of equations
fmt.Println("\nExample 2: Solving x + y = 10 ∧ x - y = 2")
solver.Reset()
y := ctx.MkIntConst("y")
ten := ctx.MkInt(10, ctx.MkIntSort())
two := ctx.MkInt(2, ctx.MkIntSort())
eq1 := ctx.MkEq(ctx.MkAdd(x, y), ten)
eq2 := ctx.MkEq(ctx.MkSub(x, y), two)
solver.Assert(eq1)
solver.Assert(eq2)
if solver.Check() == z3.Satisfiable {
model := solver.Model()
fmt.Println("Satisfiable!")
if xVal, ok := model.Eval(x, true); ok {
fmt.Println("x =", xVal.String())
}
if yVal, ok := model.Eval(y, true); ok {
fmt.Println("y =", yVal.String())
}
}
// Example 3: Boolean logic
fmt.Println("\nExample 3: Boolean satisfiability")
solver.Reset()
p := ctx.MkBoolConst("p")
q := ctx.MkBoolConst("q")
// (p q) ∧ (¬p ¬q)
formula := ctx.MkAnd(
ctx.MkOr(p, q),
ctx.MkOr(ctx.MkNot(p), ctx.MkNot(q)),
)
solver.Assert(formula)
if solver.Check() == z3.Satisfiable {
model := solver.Model()
fmt.Println("Satisfiable!")
if pVal, ok := model.Eval(p, true); ok {
fmt.Println("p =", pVal.String())
}
if qVal, ok := model.Eval(q, true); ok {
fmt.Println("q =", qVal.String())
}
}
// Example 4: Unsatisfiable constraint
fmt.Println("\nExample 4: Checking unsatisfiability")
solver.Reset()
a := ctx.MkIntConst("a")
one := ctx.MkInt(1, ctx.MkIntSort())
// a > 0 ∧ a < 0 (unsatisfiable)
solver.Assert(ctx.MkGt(a, zero))
solver.Assert(ctx.MkLt(a, zero))
status := solver.Check()
fmt.Println("Status:", status.String())
if status == z3.Unsatisfiable {
fmt.Println("The constraints are unsatisfiable (as expected)")
}
fmt.Println("\nAll examples completed successfully!")
}

8
examples/go/go.mod Normal file
View file

@ -0,0 +1,8 @@
module z3-examples
go 1.20
require github.com/Z3Prover/z3/src/api/go v0.0.0
replace github.com/Z3Prover/z3/src/api/go => ../../src/api/go