Meet the unified Kotlin/Java API for various SMT solvers.
Get the most out of SMT solving with KSMT features:
To start using KSMT, install it via Gradle:
// core
implementation("io.ksmt:ksmt-core:0.5.26")
// z3 solver
implementation("io.ksmt:ksmt-z3:0.5.26")
Find basic instructions in the Getting started guide and try it out with the Kotlin or Java examples.
To go beyond the basic scenarios, proceed to the Advanced usage guide and try the advanced example.
To get guided experience in KSMT, step through the detailed scenario for creating custom expressions.
Check the Roadmap to know more about current feature support and plans for the nearest future.
KSMT provides support for various solvers:
SMT solver | Linux-x64 | Windows-x64 | macOS-aarch64 | macOS-x64 |
---|---|---|---|---|
Z3 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
Bitwuzla | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | |
Yices2 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | |
cvc5 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
You can also use SMT solvers across multiple theories:
Theory | Z3 | Bitwuzla | Yices2 | cvc5 |
---|---|---|---|---|
Bitvectors | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
Arrays | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
IEEE Floats | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: [^1] | :heavy_check_mark: |
Uninterpreted Functions | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
Arithmetic | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
[^1]: IEEE Floats are supported in Yices2 using ksmt-symfpu
Various scenarios are available for using SMT solvers: you can use a single solver to determine whether a formula is satisfiable, or you can apply several solvers to the same expression successively. In the latter case, you need a solver-agnostic formula representation.
We implemented it in KSMT, so you can
Expression interning (hash consing) affords faster expression comparison: we do not need to compare the expression trees. Expressions are deduplicated, so we avoid redundant memory allocation.
KSMT provides you with a unified DSL for SMT expressions:
val array by mkArraySort(intSort, intSort)
val index by intSort
val value by intSort
val expr = (array.select(index - 1.expr) lt value) and
(array.select(index + 1.expr) gt value)
KSMT provides a simplification engine applicable to all supported expressions for all supported theories:
KSMT simplification engine implements more than 200 rules. By default, it attempts to apply simplifications when you create the expressions, but you can turn this feature off, if necessary. You can also simplify an arbitrary expression manually.
SMT solvers may differ in performance across different formulas: see the International Satisfiability Modulo Theories Competition.
With KSMT portfolio solving, you can run multiple solvers in parallel on the same formula — until you get the first (the fastest) result.
For detailed instructions on running multiple solvers, see Advanced usage.
Most of the SMT solvers are research projects — they are implemented via native libraries and are sometimes not production ready:
KSMT runs each solver in a separate process, which adds to stability of your application and provides support for portfolio mode.
Many solvers do not have prebuilt binaries, or binaries are for Linux only.
KSMT is distributed as JVM library with solver binaries provided. The library has been tested against the SMT-LIB benchmarks. Documentation and examples are also available.