pysat
pysat copied to clipboard
A toolkit for SAT-based prototyping in Python
PySAT: SAT technology in Python
PySAT is a Python (2.7, 3.4+) toolkit, which aims at providing a simple and
unified interface to a number of state-of-art Boolean satisfiability (SAT) <https://en.wikipedia.org/wiki/Boolean_satisfiability_problem>
__ solvers as
well as to a variety of cardinality and pseudo-Boolean encodings. The purpose
of PySAT is to enable researchers working on SAT and its applications and
generalizations to easily prototype with SAT oracles in Python while
exploiting incrementally the power of the original low-level implementations
of modern SAT solvers.
PySAT can be helpful when solving problems in NP <https://en.wikipedia.org/wiki/NP_(complexity)>
__ but also beyond NP <https://web.archive.org/web/http://beyondnp.org/>
__. For instance, PySAT is
handy when one needs to quickly implement a MaxSAT solver, an MUS/MCS
extractor or enumerator, an abstraction-based QBF solver, or any other kind of
tool solving an application problem with the (potentially multiple and/or
incremental) use of a SAT oracle.
.. image:: web/medals.svg :width: 270 px :align: right
Features
PySAT integrates a number of widely used state-of-the-art SAT solvers. All the provided solvers are the original low-level implementations installed along with PySAT. Note that the solvers' source code is not a part of the project's source tree and is downloaded and patched at every PySAT installation. Note that originally the solvers' source code was not distributed with PySAT, which resulted in sequence of download and patch operations for each solver during each installation of PySAT. This, however, causes serious issues in case of using a proxy. As a result and since version 0.1.6.dev1, PySAT includes the solvers' archive files in the distribution.
Currently, the following SAT solvers are supported (at this point, for Minisat-based solvers only core versions are integrated):
- CaDiCaL (
rel-1.0.3 <https://github.com/arminbiere/cadical>
__) - CaDiCaL (
rel-1.5.3 <https://github.com/arminbiere/cadical>
__) - CaDiCaL (
rel-1.9.5 <https://github.com/arminbiere/cadical>
__) - Glucose (
3.0 <http://www.labri.fr/perso/lsimon/glucose/>
__) - Glucose (
4.1 <http://www.labri.fr/perso/lsimon/glucose/>
__) - Glucose (
4.2.1 <http://www.labri.fr/perso/lsimon/glucose/>
__) - Lingeling (
bbc-9230380-160707 <http://fmv.jku.at/lingeling/>
__) - MapleLCMDistChronoBT (
SAT competition 2018 version <http://sat2018.forsyte.tuwien.ac.at/solvers/main_and_glucose_hack/>
__) - MapleCM (
SAT competition 2018 version <http://sat2018.forsyte.tuwien.ac.at/solvers/main_and_glucose_hack/>
__) - Maplesat (
MapleCOMSPS_LRB <https://sites.google.com/a/gsd.uwaterloo.ca/maplesat/>
__) - Mergesat (
3.0 <https://github.com/conp-solutions/mergesat>
__) - Minicard (
1.2 <https://github.com/liffiton/minicard>
__) - Minisat (
2.2 release <http://minisat.se/MiniSat.html>
__) - Minisat (
GitHub version <https://github.com/niklasso/minisat>
__)
In order to make SAT-based prototyping easier, PySAT integrates a variety of cardinality encodings. All of them are implemented from scratch in C++. The list of cardinality encodings included is the following:
- pairwise [8]_
- bitwise [8]_
- sequential counters [9]_
- sorting networks [4]_
- cardinality networks [2]_
- ladder/regular [1]_ [5]_
- totalizer [3]_
- modulo totalizer [7]_
- iterative totalizer [6]_
.. [1] Carlos Ansótegui, Felip Manyà. Mapping Problems with Finite-Domain Variables to Problems with Boolean Variables. SAT (Selected Papers) 2004. pp. 1-15
.. [2] Roberto Asin, Robert Nieuwenhuis, Albert Oliveras, Enric Rodriguez-Carbonell. Cardinality Networks and Their Applications. SAT 2009. pp. 167-180
.. [3] Olivier Bailleux, Yacine Boufkhad. Efficient CNF Encoding of Boolean Cardinality Constraints. CP 2003. pp. 108-122
.. [4] Kenneth E. Batcher. Sorting Networks and Their Applications. AFIPS Spring Joint Computing Conference 1968. pp. 307-314
.. [5] Ian P. Gent, Peter Nightingale. A New Encoding of Alldifferent Into SAT. In International workshop on modelling and reformulating constraint satisfaction problems 2004. pp. 95-110
.. [6] Ruben Martins, Saurabh Joshi, Vasco M. Manquinho, Inês Lynce. Incremental Cardinality Constraints for MaxSAT. CP 2014. pp. 531-548
.. [7] Toru Ogawa, Yangyang Liu, Ryuzo Hasegawa, Miyuki Koshimura, Hiroshi Fujita. Modulo Based CNF Encoding of Cardinality Constraints and Its Application to MaxSAT Solvers. ICTAI 2013. pp. 9-17
.. [8] Steven David Prestwich. CNF Encodings. Handbook of Satisfiability. 2009. pp. 75-97
.. [9] Carsten Sinz. Towards an Optimal CNF Encoding of Boolean Cardinality Constraints. CP 2005. pp. 827-831
Furthermore, PySAT supports a number of encodings of pseudo-Boolean
constraints listed below. This is done by exploiting a third-party library
PyPBLib <https://pypi.org/project/pypblib/>
__ developed by the Logic Optimization Group <http://ulog.udl.cat/>
__ of the University of Lleida.
(PyPBLib is a wrapper over the known PBLib library [10]_.)
- binary decision diagrams (BDD) [11]_ [12]_
- sequential weight counters [13]_
- sorting networks [11]_
- adder networks [11]_
- and binary merge [14]_
.. [10] Tobias Philipp, Peter Steinke. PBLib - A Library for Encoding Pseudo-Boolean Constraints into CNF. SAT 2015. pp. 9-16
.. [11] Niklas Eén, Niklas Sörensson. Translating Pseudo-Boolean Constraints into SAT. JSAT. vol. 2(1-4). 2006. pp. 1-26
.. [12] Ignasi Abío, Robert Nieuwenhuis, Albert Oliveras, Enric Rodríguez-Carbonell. BDDs for Pseudo-Boolean Constraints - Revisited. SAT. 2011. pp. 61-75
.. [13] Steffen Hölldobler, Norbert Manthey, Peter Steinke. A Compact Encoding of Pseudo-Boolean Constraints into SAT. KI. 2012. pp. 107-118
.. [14] Norbert Manthey, Tobias Philipp, Peter Steinke. A More Compact Translation of Pseudo-Boolean Constraints into CNF Such That Generalized Arc Consistency Is Maintained. KI. 2014. pp. 123-134
Finally, PySAT now supports arbitrary Boolean formulas with on-the-fly clausification [21]_ and provides (pre-)processing functionality [22]_ by exposing an interface to CaDiCaL's (version 1.5.3) preprocessor as well as external user-defined engines following the IPASIR-UP interface [23]_.
.. [21] G. S. Tseitin. On the complexity of derivations in the propositional calculus. Studies in Mathematics and Mathematical Logic, Part II. pp. 115–125, 1968
.. [22] Armin Biere, Matti Järvisalo, Benjamin Kiesl. Preprocessing in SAT Solving. In Handbook of Satisfiability - Second Edition. pp. 391-435
.. [23] Katalin Fazekas, Aina Niemetz, Mathias Preiner, Markus Kirchweger, Stefan Szeider, Armin Biere. IPASIR-UP: User Propagators for CDCL. SAT. 2023. pp. 8:1-8:13
Usage
Boolean variables in PySAT are represented as natural identifiers, e.g. numbers
from :math:\mathbb{N}_{>0}
. A literal in PySAT is assumed to be an integer,
e.g. -1
represents a literal :math:\neg{x_1}
while :math:5
represents a
literal :math:x_5
. A clause is a list of literals, e.g. [-3, -2]
is a
clause :math:(\neg{x_3} \vee \neg{x_2})
.
The following is a trivial example of PySAT usage:
.. code:: python
>>> from pysat.solvers import Glucose3
>>>
>>> g = Glucose3()
>>> g.add_clause([-1, 2])
>>> g.add_clause([-2, 3])
>>> print(g.solve())
>>> print(g.get_model())
...
True
[-1, -2, -3]
Another example shows how to extract unsatisfiable cores from a SAT solver given an unsatisfiable set of clauses:
.. code:: python
>>> from pysat.solvers import Minisat22
>>>
>>> with Minisat22(bootstrap_with=[[-1, 2], [-2, 3]]) as m:
... print(m.solve(assumptions=[1, -3]))
... print(m.get_core())
...
False
[-3, 1]
Finally, the following example gives an idea of how one can extract a proof (supported by Glucose3, Glucose4, and Lingeling only):
.. code:: python
>>> from pysat.formula import CNF
>>> from pysat.solvers import Lingeling
>>>
>>> formula = CNF()
>>> formula.append([-1, 2])
>>> formula.append([1, -2])
>>> formula.append([-1, -2])
>>> formula.append([1, 2])
>>>
>>> with Lingeling(bootstrap_with=formula.clauses, with_proof=True) as l:
... if l.solve() == False:
... print(l.get_proof())
...
['2 0', '1 0', '0']
PySAT usage is detailed in the provided examples <https://github.com/pysathq/pysat/tree/master/examples>
__. For instance, one
can find simple PySAT-based implementations of
- Fu&Malik algorithm for MaxSAT [15]_
- RC2/OLLITI algorithm for MaxSAT [19]_ [20]_
- CLD-like algorithm for MCS extraction and enumeration [17]_
- LBX-like algorithm for MCS extraction and enumeration [18]_
- Deletion-based MUS extraction [16]_
.. [15] Zhaohui Fu, Sharad Malik. On Solving the Partial MAX-SAT Problem. SAT 2006. pp. 252-265
.. [16] Joao Marques Silva. Minimal Unsatisfiability: Models, Algorithms and Applications. ISMVL 2010. pp. 9-14
.. [17] Joao Marques-Silva, Federico Heras, Mikolas Janota, Alessandro Previti, Anton Belov. On Computing Minimal Correction Subsets. IJCAI 2013. pp. 615-622
.. [18] Carlos Mencia, Alessandro Previti, Joao Marques-Silva. Literal-Based MCS Extraction. IJCAI 2015. pp. 1973-1979
.. [19] António Morgado, Carmine Dodaro, Joao Marques-Silva. Core-Guided MaxSAT with Soft Cardinality Constraints. CP 2014. pp. 564-573
.. [20] António Morgado, Alexey Ignatiev, Joao Marques-Silva. MSCG: Robust Core-Guided MaxSAT Solving. System Description. JSAT 2015. vol. 9, pp. 129-134
The examples are installed with PySAT as a subpackage and, thus, they can be accessed internally in Python:
.. code:: python
>>> from pysat.formula import CNF
>>> from pysat.examples.lbx import LBX
>>>
>>> formula = CNF(from_file='input.cnf')
>>> mcsls = LBX(formula)
>>>
>>> for mcs in mcsls.enumerate():
... print(mcs)
Alternatively, they can be used as standalone executables, e.g. like this:
::
$ lbx.py -e all -d -s g4 -v another-input.wcnf
Installation
There are several ways to install PySAT. At this point, either way assumes you
are using a POSIX-compliant operating system with GNU make <https://www.gnu.org/software/make/>
__ and patch <http://savannah.gnu.org/projects/patch/>
__ installed and available from the
command line. Installation also relies on a C/C++ compiler supporting C++11,
e.g. GCC <https://gcc.gnu.org/>
__ or Clang <https://clang.llvm.org/>
, as
well as the six
Python package <https://pypi.org/project/six/>
.
Finally, in order to compile "C extensions" included as modules, the installer
requires the headers of Python <https://www.python.org/>
__ and zlib <https://www.zlib.net/>
__. Both can be installed using the standard package
repositories.
Note that although version 0.1.5.dev1
of PySAT brings Microsoft Windows
support, the toolkit was not extensively tested on this system. If you find
out that something is broken on Windows, please, let us know <https://github.com/pysathq/pysat/issues>
__. Your input is important.
Also note that using Clang is preferred on MacOS as there may be an issue with
GCC being unaware of the command-line option --stdlib=libc++
. Clang is
available on MacOS by default. To enforce the installer to use it, you need to
set the environment variable CC
to /usr/bin/clang
. For that, do
export CC=/usr/bin/clang
if using Bash, or setenv CC /usr/bin/clang
if
using tsch. This is not needed on Linux!
Once all the prerequisites are installed, the simplest way to get and start
using PySAT is to install the latest stable release of the toolkit from PyPI <https://pypi.org/>
__:
::
$ pip install python-sat[aiger,approxmc,cryptosat,pblib]
We encourage you to install the optional dependencies pblib
, aiger
,
approxmc
, and cryptosat
as in the previous command. However, if it cannot
be done (e.g. if their installation fails), you can install PySAT with the
functionality of aiger
, approxmc
, cryptosat
, and pblib
disabled:
::
$ pip install python-sat
Once installed from PyPI, the toolkit at a later stage can be updated in the following way:
::
$ pip install -U python-sat
.. note::
For some shells, e.g. *zsh*, you may need to put the package names into
single quotes, i.e. use ``pip install 'python-sat[aiger,approxmc,pblib]'``.
Alternatively, one can clone the repository <https://github.com/pysathq/pysat>
__ and execute the following command in the
local copy:
::
$ python setup.py install
This will install the toolkit into the system's Python path. If another destination directory is preferred, it can be set by
::
$ python setup.py install --prefix=<where-to-install>
Both options (i.e. via pip
or setup.py
) are supposed to download
and compile all the supported SAT solvers as well as prepare the
installation of PySAT.
Citation
If PySAT has been significant to a project that leads to an academic publication, please, acknowledge that fact by citing PySAT:
::
@inproceedings{imms-sat18,
author = {Alexey Ignatiev and
Antonio Morgado and
Joao Marques{-}Silva},
title = {{PySAT:} {A} {Python} Toolkit for Prototyping
with {SAT} Oracles},
booktitle = {SAT},
pages = {428--437},
year = {2018},
url = {https://doi.org/10.1007/978-3-319-94144-8_26},
doi = {10.1007/978-3-319-94144-8_26}
}
To-Do
PySAT toolkit is a work in progress. Although it can already be helpful in many practical settings (and it was successfully applied by its authors for a number of times), it would be great if some of the following additional features were implemented:
-
more SAT solvers to support (e.g.
RISS <http://tools.computational-logic.org/content/riss.php>
,Intel (R) SAT Solver <https://github.com/alexander-nadel/intel_sat_solver>
among many others) -
lower level access to some of the solvers' internal parameters (e.g. variable activities, etc.)
These will require a significant effort to be made. Therefore, we would like to encourage the SAT community to contribute and make PySAT a tool for an easy and comfortable day-to-day use. :)
License
PySAT is licensed under MIT <LICENSE.txt>
__.