rustsat/lib.rs
1//! # RustSAT - A Comprehensive SAT Library for Rust
2//!
3//! RustSAT is a collection of interfaces and utilities for working with the boolean satisfiability problem in Rust.
4//! This library aims to provide implementations of elements commonly used in the development of software in the area of satisfiability solving.
5//! The focus of the library is to provide as much ease of use without giving up on performance.
6//!
7//! ## Example
8//!
9//! ```
10//! # use rustsat::{instances::SatInstance, solvers::{Solve, SolverResult}, types::TernaryVal};
11//! let mut instance: SatInstance = SatInstance::new();
12//! let l1 = instance.new_lit();
13//! let l2 = instance.new_lit();
14//! instance.add_binary(l1, l2);
15//! instance.add_binary(!l1, l2);
16//! instance.add_unit(l1);
17//! let mut solver = rustsat_minisat::core::Minisat::default();
18//! solver.add_cnf(instance.into_cnf().0).unwrap();
19//! let res = solver.solve().unwrap();
20//! assert_eq!(res, SolverResult::Sat);
21//! let sol = solver.full_solution().unwrap();
22//! assert_eq!(sol[l1.var()], TernaryVal::True);
23//! assert_eq!(sol[l2.var()], TernaryVal::True);
24//! ```
25//!
26//! ## Crates
27//!
28//! The RustSAT project is split up into multiple crates that are all contained in [this repository](https://github.com/chrjabs/rustsat/).
29//! The general architecture is illustrated in [this architecture
30//! diagram](https://github.com/chrjabs/rustsat/blob/main/docs/architecture.png).
31//! These are the crates the project consists of:
32//!
33//! | Crate | Description |
34//! | --- | --- |
35//! | `rustsat` | The main library, containing basic types, traits, encodings, parsers, and more. |
36//! | `rustsat-tools` | A collection of small helpful tools based on RustSAT that can be installed as binaries. For a list of available tools, see [this directory](https://github.com/chrjabs/rustsat/tree/main/tools/src/bin) with short descriptions of the tools in the headers of the files. |
37//! | `rustsat-<satsolver>` | Interfaces to SAT solvers that can be used alongside RustSAT. Currently interfaces are available for `cadical`, `kissat`, `glucose`, and `minisat`. |
38//! | `rustsat-ipasir` | [IPASIR](https://github.com/biotomas/ipasir) bindings to use any compliant solver with RustSAT. |
39//! | `pigeons` | A library for writing [VeriPB](https://gitlab.com/MIAOresearch/software/VeriPB) proofs. Used by RustSAT with the `proof-logging` feature. |
40//!
41//! ## Comparison to Other Libraries
42//!
43//! For a basic comparison of RustSAT to other libraries, you can have a look at [this benchmark
44//! repository](https://github.com/chrjabs/rustsat-benchmarks/) and the [RustSAT tool
45//! paper](https://media.christophjabs.info/papers/Jabs2025RustsatLibrarySat.pdf).
46//!
47//! ## Citing
48//!
49//! If you use RustSAT in your research, please cite the following system description paper.
50//!
51//! ```bibtex
52//! @inproceedings{Jabs2025RustsatLibrarySat,
53//! title = {{RustSAT}: {A} Library For {SAT} Solving in Rust},
54//! author = {Jabs, Christoph},
55//! booktitle = {28th International Conference on Theory and Applications of Satisfiability
56//! Testing ({SAT} 2025)},
57//! editor = {Berg, Jeremias and Nordstr{\"o}m, Jakob},
58//! year = {2025},
59//! volume = {341},
60//! publisher = {Schloss Dagstuhl---Leibniz-Zentrum f{\"{u}}r Informatik},
61//! series = {Leibniz International Proceedings in Informatics ({LIPIcs})},
62//! pages = {15:1--15:13},
63//! doi = {10.4230/LIPIcs.SAT.2025.15},
64//! eprint = {2505.15221},
65//! }
66//! ```
67//!
68//! ## Installation
69//!
70//! To use the RustSAT library as a dependency in your project, simply run `cargo add rustsat`.
71//! To use an SAT solver interface in your project, run `cargo add rustsat-<satsolver>`.
72//! Typically, the version of the SAT solver can be selected via crate features, refer to the documentation of the respective SAT solver crate for details.
73//!
74//! To install the binary tools in `rustsat-tools` run `cargo install rustsat-tools`.
75//!
76//! ## Features
77//!
78//! | Feature name | Description |
79//! | --- | --- |
80//! | `optimization` | Include optimization (MaxSAT) data structures etc. |
81//! | `multiopt` | Include data structures etc. for multi-objective optimization. |
82//! | `compression` | Enable parsing and writing compressed input. |
83//! | `fxhash` | Use the faster firefox hash function from `rustc-hash` in RustSAT. |
84//! | `rand` | Enable randomization features. (Shuffling clauses etc.) |
85//! | `ipasir-display` | Changes `Display` trait for `Lit` and `Var` types to follow IPASIR variables indexing. |
86//! | `serde` | Add implementations for [`serde::Serialize`](https://docs.rs/serde/latest/serde/trait.Serialize.html) and [`serde::Deserialize`](https://docs.rs/serde/latest/serde/trait.Deserialize.html) for many library types |
87//! | `proof-logging` | Add proof logging / certification support to constraint encodings |
88//! | `verbose-proofs` | Make the generated proofs (see `proof-logging`) more verbose, for debugging and testing |
89//! | `bench` | Enable benchmark tests. Behind feature flag since it requires unstable Rust. |
90//! | `internals` | Make some internal data structures for e.g. encodings public. This is useful when basing a more complex encoding on the RustSAT implementation of another encoding. Note that the internal API might change between releases. |
91//!
92//! ## Examples
93//!
94//! For example usage refer to the small example tools in the [`rustsat-tools`
95//! crate](https://crates.io/crates/rustsat_tools) at `tools/src/bin`. For a bigger
96//! example you can look at this [multi-objective optimization
97//! solver](https://github.com/chrjabs/scuttle).
98//!
99//! ## Minimum Supported Rust Version (MSRV)
100//!
101//! Currently, the MSRV of RustSAT is 1.76.0, the plan is to always support an MSRV that is at
102//! least a year old.
103//!
104//! Bumps in the MSRV will _not_ be considered breaking changes. If you need a specific MSRV, make
105//! sure to pin a precise version of RustSAT.
106
107#![cfg_attr(docsrs, feature(doc_auto_cfg))]
108#![cfg_attr(docsrs, feature(doc_cfg))]
109#![cfg_attr(feature = "bench", feature(test))]
110#![warn(clippy::pedantic)]
111#![warn(missing_docs)]
112#![warn(missing_debug_implementations)]
113
114use std::collections::TryReserveError;
115
116use thiserror::Error;
117
118pub mod algs;
119pub mod encodings;
120pub mod instances;
121pub mod solvers;
122pub mod types;
123
124pub mod utils;
125
126/// Error returned if the user tries to perform an action that is not allowed
127///
128/// The parameter will hold an explanation of why the action is not allowed
129#[cfg(feature = "internals")]
130#[derive(Error, Debug)]
131#[error("action not allowed: {0}")]
132pub struct NotAllowed(&'static str);
133
134#[cfg(feature = "bench")]
135#[cfg(test)]
136mod bench;
137
138/// Error returned when an operation ran out of memory
139///
140/// The library is not _fully_ memory safe, meaning there are cases where memory allocation failing
141/// can lead to a panic instead to an error. Mainly add clauses to solvers and collecting clauses
142/// from encodings are done in a safe way. This is intended, e.g., for anytime solvers that might
143/// want a change to print a final output if they run out of memory.
144#[derive(Error, Debug, PartialEq, Eq)]
145pub enum OutOfMemory {
146 /// A `try_reserve` operation in Rust ran out of memory
147 #[error("try reserve error: {0}")]
148 TryReserve(TryReserveError),
149 /// An external API (typically a solver) ran out of memory
150 #[error("external API operation ran out of memory")]
151 ExternalApi,
152}
153
154impl From<TryReserveError> for OutOfMemory {
155 fn from(value: TryReserveError) -> Self {
156 OutOfMemory::TryReserve(value)
157 }
158}
159
160/// Error returned if an operation requires clausal constraints, but this is not the case
161#[derive(Error, Debug)]
162#[error("operation requires a clausal constraint(s) but it is not")]
163pub struct RequiresClausal;
164
165/// Error returned if an operation requires an objective represented as soft literals, but this is
166/// not the case
167#[derive(Error, Debug)]
168#[error("operation requires an objective only consisting of soft literals")]
169pub struct RequiresSoftLits;