https://github.com/tweag/smtlib-backends
A Haskell library providing low-level functions for SMTLIB-based interaction with SMT solvers.
https://github.com/tweag/smtlib-backends
haskell-library smtlib2
Last synced: 4 months ago
JSON representation
A Haskell library providing low-level functions for SMTLIB-based interaction with SMT solvers.
- Host: GitHub
- URL: https://github.com/tweag/smtlib-backends
- Owner: tweag
- License: mit
- Created: 2022-12-06T10:38:51.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2025-08-13T17:37:55.000Z (10 months ago)
- Last Synced: 2025-08-13T19:35:34.561Z (10 months ago)
- Topics: haskell-library, smtlib2
- Language: Haskell
- Homepage: https://hackage.haskell.org/package/smtlib-backends
- Size: 219 KB
- Stars: 18
- Watchers: 9
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# SMT-LIB backends
This Haskell library provides different low-level ways of interacting with SMT
solvers using [SMT-LIB](https://smtlib.cs.uiowa.edu/).
We currently provide the following backends:
* a classic backend, available in the `smtlib-backends-process` package, implemented by
running solvers as external processes,
* a faster backend, available in the `smtlib-backends-z3` package, implemented using Z3
as a library, and
* an experimental backend, available in the `smtlib-backends-cvc5` package, implemented
using an unstable version of CVC5 as a library.
In addition, the API allows for queuing commands so that they are sent to the backend
only when a response is needed, as we have observed this to reduce the communication
overhead. See the documentation of
[SMTLIB.Backends.Solver](src/SMTLIB/Backends.hs) for the details, and the
[announcement blog post][announcement] for further motivation.
[announcement]: https://www.tweag.io/blog/2023-02-14-smtlib-backends/
## Usage
Here is an example, using GHCi, of how to communicate with the solver
[Yices2](https://yices.csl.sri.com/) as an external process.
It requires the libraries `smtlib-backends` and `smtlib-backends-process`.
```haskell
> import qualified SMTLIB.Backends.Process as P
> import qualified SMTLIB.Backends as SMT
> :set -XOverloadedStrings
> let cfg = P.defaultConfig { P.exe = "yices-smt2", P.args = [] }
> yicesProcess <- P.new cfg
> yices <- SMT.initSolver SMT.NoQueuing (P.toBackend yicesProcess)
> SMT.command yices "(get-info :name)"
"(:name \"Yices\")"
```
More examples of how to use the different backends are included in their
respective test-suites:
- [examples for the `Process`
backend](smtlib-backends-process/tests/Examples.hs)
- [examples for the `Z3` backend](smtlib-backends-z3/tests/Examples.hs)
- [examples for the `CVC5` backend](smtlib-backends-cvc5/tests/Examples.hs)
## Building and testing
This repository provides a reproducible build environment through a [Nix
flake](https://www.tweag.io/blog/2020-05-25-flakes/).
Another option is to manually install Z3 to use the process backend, and the Z3
C library to use the Z3 backend. Then you can build and test the libraries using
`cabal build` and `cabal test`. It works analogously if using CVC5 as a library.
## Implementing backends
Currently, backends only need to provide a function to submit queries, as
documented in [SMTLIB.Backends.Backend](src/SMTLIB/Backends.hs). See
[SMTLIB.Backends.Process.toBackend](smtlib-backends-process/src/SMTLIB/Backends/Process.hs)
or [SMTLIB.Backends.Z3.toBackend](smtlib-backends-z3/src/SMTLIB/Backends/Z3.hs)
for examples.
## Motivation
This library was created because there are a lot of Haskell projects using SMT
solvers through SMT-LIB, but most of them only use solvers through external
processes and implement the interaction with the solver themselves. But running
solvers as external processes can be quite slow, hence this library aims to
provide other, more efficient ways to do so. We believe having one
well-optimized and safe library is more efficient than having the same code be
spread out between different projects.
## Contributing
### Code formatting
We format our code using [ormolu](https://github.com/tweag/ormolu)
retrieved from [NixOS/nixpkgs](https://github.com/NixOS/nixpkgs)
whose revision is defined in the [flake lock](./flake.lock).
The `.cabal` files are formatted using
[`cabal-fmt`](https://github.com/phadej/cabal-fmt). It is thus recommended to
add the following script as your `.git/hooks/pre-commit`:
```bash
#!/usr/bin/env bash
set -e
# command adapted from https://github.com/JLLeitschuh/ktlint-gradle task addKtlintFormatGitPreCommitHook
filesToFormat="$(git --no-pager diff --name-status --no-color --cached | \
awk '($1 == "M" || $1 == "A") && $2 ~ /\.hs/ { print $2} $1 ~ /R/ && $3 ~ /\.hs/ { print $3 } ')"
echo "files to format $filesToFormat"
for sourceFilePath in $filesToFormat
do
ormolu --mode inplace "$(pwd)/$sourceFilePath"
git add $sourceFilePath
done;
cabal-fmt --inplace $(find . -name '*.cabal')
```