Skip to content

elsoroka/Satisfiability.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

build status docs codecov

Satisfiability.jl is a package for representing satisfiability modulo theories (SMT) problems in Julia. This package provides a simple front-end interface to common SMT solvers, including full support for vector-valued and matrix-valued expressions. Currently, the theories of propositional logic, uninterpreted functions, Integers, Reals and fixed-size BitVectors are supported. We will eventually add support for all SMT-LIB standard theories.

What you can do with this package:

  • Cleanly specify SMT expressions using Julia's built-in broadcasting and iteration capabilities to write concise expressions.
  • Generate files in the SMT-LIB specification language.
  • Interact with any solver that follows the SMT-LIB standard. We test with Z3, CVC5, and Yices.

You can read the documentation here.

Examples

Solving the vector-valued Boolean problem

(x1 ∧ y1) ∨ (¬x1 ∧ y1) ∧ ... ∧ (xn ∧ yn) ∨ (¬xn ∧ yn)

@satvariable(x[1:n], Bool)
@satvariable(y[1:n], Bool)
expr = (x .∧ y) .∨ (¬x .∧ y)
status = sat!(expr, solver=Z3())
println("x = $(value(x)), y = $(value(y))”)

Investigating rounding of real numbers

This problem (from Microsoft's Z3 tutorials) uses mixed integer and real variables to figure out whether there exists a constant a and two real numbers xR and yR such that round(xR) + round(yR) > a while xR + yR < a.

@satvariable(xR, Real)
@satvariable(yR, Real)
@satvariable(x, Int) # x represents a rounded version of xR
@satvariable(y, Int) # y represents a rounded version of yR
@satvariable(a, Int)

exprs = [xR + yR < a,
         x + y > a,
         or(x == xR, ((x < xR)  (xR < x+1)), ((x-1 < xR)  (xR < x))),
         or(y == yR, ((y < yR)  (yR < y+1)), ((y-1 < yR)  (yR < y))),
        ]
status = sat!(exprs)
println("status = $status, xR=$(value(xR)), yR=$(value(yR))")

Uninterpreted functions

An uninterpreted function is a function where the input-to-output mapping isn't known. The task of the SMT solver is to find this mapping such that some logical statements hole true. Let's find out if there exists a function f(x) such that f(f(x)) == x, f(x) == y and x != y.

@satvariable(x, Bool)
@satvariable(y, Bool)
@uninterpreted(f, Bool, Bool)

# Yices requires setting the logic manually. Here we set it to "QF_UFLIA" - "Quantifier free uninterpreted functions, linear integer arithmetic".
status = sat!(distinct(x,y), f(x) == y, f(f(x)) == x, solver=Yices(), logic="QF_UFLIA")
println("status = \$status")

The problem is :SAT, so there is such a function! Since the satisfying assignment for an uninterpreted function is itself a function, Satisfiability.jl sets the value of f to this function. Now calling f(value) returns the value of this satisfying assignment.

println(f(x.value))               # prints 0
println(f(x.value) == y.value)    # true
println(f(f(x.value)) == x.value) # true

Proving a bitwise version of de Morgan's law.

In this example we want to show there is NO possible value of x and y such that de Morgan's bitwise law doesn't hold.

@satvariable(x, BitVector, 64)
@satvariable(y, BitVector, 64)

expr = not((~x & ~y) == ~(x | y))

status = sat!(expr, solver=Z3())
println(status) # if status is UNSAT we proved it.

Development status

Release 0.1.1 is out! You can install it with the command using Pkg; Pkg.add("Satisfiability"). Please help make the Julia ecosystem better for everyone by opening a GitHub issue if you have feedback or find a bug.

About

Specify satisfiability modulo theories problems in Julia and use the SMT-LIB format to interact with SMT solvers.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages