dratify
Check a DRAT/DRUP proof of unsatisfiability, inside your Python process.
A SAT solver that answers "unsatisfiable" is asking to be trusted. A DRAT proof is how it stops asking: the solver logs every clause it derives, and a checker that shares no code with it replays the log and confirms the empty clause really follows.
Emitting those proofs is routine. PySAT exposes them from six solver families
with with_proof=True / get_proof(). Checking them from Python has not
been practical: drat-trim is C you compile and shell out to, and the only
checker on PyPI installs on Linux x86-64 under Python ≤ 3.10 alone.
pip install dratify # pure Python, zero dependencies
A Rust implementation of the same checker is published separately as the
dratify crate. Python bindings for it are
not packaged yet; engine="native" is wired up and will pick them up when they
are.
Check a proof from PySAT
from pysat.formula import CNF as PyCNF
from pysat.solvers import Glucose42
from dratify import parse_dimacs, check_proof
cnf = PyCNF(from_file="problem.cnf")
with Glucose42(bootstrap_with=cnf, with_proof=True) as s:
assert not s.solve()
proof = s.get_proof()
result = check_proof(parse_dimacs(cnf.to_dimacs()), "\n".join(proof))
print(result.ok) # True -- the refutation is genuine
No subprocess, no compiler, no temporary files.
Two engines, and that is the point
Proof checking is the one domain where two independent implementations agreeing is the evidence. This ships both:
| Pure Python | zero dependencies, runs anywhere Python does |
| Rust (crates.io) | ~18x faster; Python bindings not yet packaged |
Neither is the "real" one. They have been differentially tested against each other on acceptances and on rejections, and they agree.
check_proof(formula, proof, engine="python") # always available
check_proof(formula, proof, engine="native") # when bindings are installed
check_proof(formula, proof, engine="auto") # default: native when present
What it checks
- RUP (reverse unit propagation) — the common case.
- RAT (resolution asymmetric tautology) — the "A" in DRAT, checked properly: pivot on the first literal, resolvent against every clause containing its negation, RUP on each.
- Deletion, applied by default. Deletion is monotone-safe for RUP; RAT is not monotone, so RAT steps are checked against exactly the clauses present.
Checking is forward: every step is verified, rather than working backwards
from the empty clause as drat-trim does. That makes it slower on large proofs
and means a corrupted step is caught where it occurs.
Speed
Measured against drat-trim (which does backward checking by default):
| proof | steps | pure Python | Rust | drat-trim |
|---|---|---|---|---|
| uuf100-01 | 774 | 0.01s | 0.01s | 0.05s |
| uuf100-010 | 1,103 | 0.05s | 0.00s | 0.06s |
| uuf250-01 | 209,367 | 41.47s | 2.27s | 1.30s |
Rust wins on small proofs — drat-trim pays process startup and cannot be
called in-process — and loses 1.75x on the large one, while checking forward.
On 10 proofs from two solvers, dratify and drat-trim agreed on every case,
including four rejections.
Honest limitations
- Forward checking only. Backward checking would close the large-proof gap.
- No binary DRAT format yet; text proofs only.
- Not formally verified. It is carefully written, differentially tested against
a second implementation, and cross-validated against
drat-trim— which is not the same thing as a machine-checked proof of the checker itself. If you need that,cake_lpris CakeML-verified and consumes LRAT.
Related
cdclkit is a from-scratch CDCL SAT
solver by the same author that uses this package to check its own refutations.
You do not need it to use dratify — checking a proof should never require
installing a solver, which is why these are separate packages.
Licence
Apache-2.0. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dratify-0.1.1.tar.gz.
File metadata
- Download URL: dratify-0.1.1.tar.gz
- Upload date:
- Size: 23.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8a3cf2caa0ac9fe6bfeca8b60e5418f66f6c44a6e183bf976f434ff2ab04234
|
|
| MD5 |
f813327e2dc438c00a6e78251f37bf72
|
|
| BLAKE2b-256 |
ff4cc171b46d9444483d2a45b719d7474d08ecbeae24082ec5b08a2720f7a7ec
|
Provenance
The following attestation bundles were made for dratify-0.1.1.tar.gz:
Publisher:
release.yml on carlok/dratify
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dratify-0.1.1.tar.gz -
Subject digest:
d8a3cf2caa0ac9fe6bfeca8b60e5418f66f6c44a6e183bf976f434ff2ab04234 - Sigstore transparency entry: 2639495670
- Sigstore integration time:
-
Permalink:
carlok/dratify@e5bed3d33012025b3cfc1ed131eba94af9e8eb83 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/carlok
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e5bed3d33012025b3cfc1ed131eba94af9e8eb83 -
Trigger Event:
push
-
Statement type:
File details
Details for the file dratify-0.1.1-py3-none-any.whl.
File metadata
- Download URL: dratify-0.1.1-py3-none-any.whl
- Upload date:
- Size: 22.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9d1bc48c8cc44bb1e9a8784b86682eac1459cf380ea6025cb8ca9b8ad940e19
|
|
| MD5 |
794963e5fe2bea6bdb558b1b3200b7db
|
|
| BLAKE2b-256 |
9d7e7827f1d490bacc008283175705d775388f1bd77139f33ea8d1b691133d0c
|
Provenance
The following attestation bundles were made for dratify-0.1.1-py3-none-any.whl:
Publisher:
release.yml on carlok/dratify
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dratify-0.1.1-py3-none-any.whl -
Subject digest:
c9d1bc48c8cc44bb1e9a8784b86682eac1459cf380ea6025cb8ca9b8ad940e19 - Sigstore transparency entry: 2639496553
- Sigstore integration time:
-
Permalink:
carlok/dratify@e5bed3d33012025b3cfc1ed131eba94af9e8eb83 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/carlok
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e5bed3d33012025b3cfc1ed131eba94af9e8eb83 -
Trigger Event:
push
-
Statement type: