Git Product home page Git Product logo

smtlib-rs's Introduction

smtlib

Crates.io Docs Crates.io license shield

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 for construct SMT-LIB code and talking directly with SMT solvers.

Background

Satisfiability modulo theories (SMT) is the problem of determining whether or not a mathematical formula is satisfiable. SMT solvers (such as Z3 and cvc5) 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 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) 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. A solver takes as argument a smtlib::Backend. To see which backends are provided with the library check out the smtlib::backend module. Some backend is behind a feature flag, so for example to use the Z3 statically backend install smtlib by running cargo add smtlib -F z3-static, but otherwise add it by running:

cargo add smtlib

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

use smtlib::{backend::z3_binary::Z3Binary, Int, SatResultWithModel, Solver, prelude::*};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 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::new_const("x");
    let y = Int::new_const("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(())
}

smtlib-rs's People

Contributors

github-actions[bot] avatar oeb25 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

smtlib-rs's Issues

Feature request: SyGuS input format

Hi!

Since CVC5 has a Syntax-Guided-Synthesis (SyGuS) engine, it would be really nice if it could be used in Rust! Currently the SyGuS input format is closely modeled after the smtlib format (link here), may I ask if there is any plan to support it in this library?

Support retrieving values from get-model (i.e. extracting values from `Term`s)

Take the following example program:

use miette::IntoDiagnostic;
use smtlib::{backend::Z3Binary, Real, Solver, Sort};

fn main() -> miette::Result<()> {
    miette::set_panic_hook();

    let mut solver = Solver::new(Z3Binary::new("z3").into_diagnostic()?)?;
    let x = Real::from_name("x");
    let y = Real::from_name("y");
    let z = Real::from_name("z");

    solver.assert(x.lt(0))?;
    solver.assert(z.lt(0))?;
    solver.assert(y.gt(1))?;
    solver.assert((x * x - y * z * (-10))._eq(y))?;

    let m = solver.check_sat_with_model()?.expect_sat()?;
    eprintln!("{}", m);
    eprintln!("x = {:?}", m.eval(x).unwrap());
    eprintln!("y = {:?}", m.eval(y).unwrap());
    eprintln!("z = {:?}", m.eval(z).unwrap());

    Ok(())
}

In this case, say I would like to get the values of x, y, and z as f64. Z3 will return the values in terms of define-fun, so this would require some ability to interpret the AST in Rust, most likely?

{ z: (- (/ 1.0 4.0)), x: (- 2.0), y: (/ 8.0 7.0) }

That is, I would want z = -0.25, x = -2, y = 1.14285714286 or some similar approximation, with the understanding that Real and f64 are not exactly equivalent.

Maybe this is already possible?

Support mixing low-level and high-level SMT APIs

Since not all of the functions are supported in the high-level API (e.g. bvsgt for bitvectors), would it be possible to allow exposing those by having the low-level AST be usable mixed with the high-level API?

Support Real Division

Hi,

smtlib::theories::reals::Real currently only supports floor division (div) but not real division (/). I'm wondering if there is a way to use real division. Thank you!

Simple examples to demonstrate the difference:

(declare-const a Real)
(assert (= a (div 1.0 2.0)))
(check-sat)
(get-model)
sat
(
  (define-fun a () Real
    0.0)
)
(declare-const a Real)
(assert (= a (/ 1.0 2.0)))
(check-sat)
(get-model)
sat
(
  (define-fun a () Real
    (/ 1.0 2.0))
)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.