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:
parent
e2486eff77
commit
66d0fb5477
33 changed files with 5289 additions and 7 deletions
145
examples/go/README.md
Normal file
145
examples/go/README.md
Normal 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.
|
||||
313
examples/go/advanced_example.go
Normal file
313
examples/go/advanced_example.go
Normal 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!")
|
||||
}
|
||||
|
||||
98
examples/go/basic_example.go
Normal file
98
examples/go/basic_example.go
Normal 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
8
examples/go/go.mod
Normal 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
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue