Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/oeb25/smtlib-rs

A high-level API for interacting with SMT solvers.
https://github.com/oeb25/smtlib-rs

rust smt smtlib

Last synced: about 1 month ago
JSON representation

A high-level API for interacting with SMT solvers.

Lists

README

        

# smtlib

[![Crates.io](https://img.shields.io/crates/v/smtlib.svg)](https://crates.io/crates/smtlib)
[![Docs](https://docs.rs/smtlib/badge.svg)](https://docs.rs/smtlib)
[![Crates.io license shield](https://img.shields.io/crates/l/smtlib.svg)](https://crates.io/crates/smtlib)

> A high-level API for interacting with SMT solvers

_If you are looking for more control and less ergonomics, take a look at the [low-level crate `smtlib-lowlevel`](https://crates.io/crates/smtlib-lowlevel) for construct SMT-LIB code and talking directly with SMT solvers._

## Background

[Satisfiability modulo theories (SMT)](https://en.wikipedia.org/wiki/Satisfiability_modulo_theories) is the problem of determining whether or not a mathematical formula is satisfiable. SMT solvers (such as [Z3](https://github.com/Z3Prover/z3) and [cvc5](https://cvc5.github.io/)) are programs to automate this process. These are fantastic tools which are very powerful and can solve complex problems efficiently.

To communicate with the solvers, the [SMT-LIB](https://smtlib.cs.uiowa.edu/index.shtml) specification has been made to standardize the input/output language to all of the solvers.

Writing this format by-hand (or "programmatically by-hand") can at times be tedious and error prone. Even more so is interpreting the result produced by the solvers.

Thus the goal of `smtlib` (and [`smtlib-lowlevel`](https://crates.io/crates/smtlib-lowlevel)) is to provide ergonomic API's for communicating with the solvers, independent of the concrete solver.

## Usage

The primary way to use `smtlib` is by constructing a [`smtlib::Solver`](https://docs.rs/smtlib/latest/smtlib/struct.Solver.html). A solver takes as argument a [`smtlib::Backend`](https://docs.rs/smtlib/latest/smtlib/trait.Backend.html). To see which backends are provided with the library check out the [`smtlib::backend`](https://docs.rs/smtlib/latest/smtlib/backend/index.html) module. Some backend is behind a feature flag, so for example to use the [Z3](https://github.com/Z3Prover/z3) statically backend install `smtlib` by running `cargo add smtlib -F z3-static`, but otherwise add it by running:

```bash
cargo add smtlib
```

Now you can go ahead and use the library in your project.

```rust
use smtlib::{backend::z3_binary::Z3Binary, Int, SatResultWithModel, Solver, Sort};

fn main() -> Result<(), Box> {
// Initialize the solver with the Z3 backend. The "z3" string refers the
// to location of the already installed `z3` binary. In this case, the
// binary is in the path.
let mut solver = Solver::new(Z3Binary::new("z3")?)?;

// Declare two new variables
let x = Int::from_name("x");
let y = Int::from_name("y");

// Assert some constraints. This tells the solver that these expressions
// must be true, so any solution will satisfy these.
solver.assert(x._eq(y + 25))?;
solver.assert(x._eq(204))?;
// The constraints are thus:
// - x == y + 25
// - x == 204
// Note that we use `a._eq(b)` rather than `a == b`, since we want to
// express the mathematical relation of `a` and `b`, while `a == b` checks
// that the two **expressions** are structurally the same.

// Check for validity
match solver.check_sat_with_model()? {
SatResultWithModel::Sat(model) => {
// Since it is valid, we can extract the possible values of the
// variables using a model
println!("x = {}", model.eval(x).unwrap());
println!("y = {}", model.eval(y).unwrap());
}
SatResultWithModel::Unsat => println!("No valid solutions found!"),
SatResultWithModel::Unknown => println!("Satisfaction remains unknown..."),
}

Ok(())
}
```