Agents/Uncategorized
stalmarck
Agent Stalmarck
A crate implementing Stålmarck's method for efficiently proving propositional logic formulas and verifying logical validity.
Portrait pending: this agent's prompt is in agents/prompts.md. Its colour is a stand-in until the portrait arrives.
Downloads per day
Last 90 days · 36 total · peak 24
Dossier
What stalmarck does.
A crate implementing Stålmarck's method for efficiently proving propositional logic formulas and verifying logical validity.
From the crate: “A crate implementing Stålmarck's method for efficiently proving propositional logic formulas and verifying logical validity.”
- Codename
- Agent Stalmarck
- Role
- Logic
- Character
- Quiet, exact, and new here.
- Domain
- Uncategorized
- Enlisted
- 28 October 2026
- Last release
- v0.4.0, 31 October 2026
- Keywords
logic,propositional,sat,stalmarck,theorem-proving
Getting started
Call it in.
Add it to a Rust project, then follow the example. The full API is on docs.rs.
Install
cargo add stalmarck cargo install stalmarck
Example
use stalmarck::{Config, Formula, ProofResult, SatResult, Solver};
let (a, b, c) = (Formula::var("a"), Formula::var("b"), Formula::var("c"));
// (a ∧ b) ∨ (a ∧ c) → a ∧ (b ∨ c) is valid, with hardness 1.
let f = ((a.clone() & b.clone()) | (a.clone() & c.clone()))
.implies(a.clone() & (b.clone() | c));
let solver = Solver::new(Config::default().with_max_depth(1));
assert_eq!(solver.prove(&f).result, ProofResult::Valid);
// a ∧ ¬b is satisfiable.
match solver.check_sat(&(a & !b)).result {
SatResult::Sat(model) => assert_eq!(model.get("b"), Some(false)),
other => panic!("{other:?}"),
}Build with a prompt
Add the Rust crate `stalmarck` (version 0.4.0) to this project with `cargo add stalmarck`. I want to use it for this: A crate implementing Stålmarck's method for efficiently proving propositional logic formulas and verifying logical validity. Before writing code, read its README at https://crates.io/crates/stalmarck and the API docs at https://docs.rs/stalmarck. Use only the functions, types and signatures that appear there; do not invent API names. Write a minimal working example and one test that runs it.
Paste this into Claude Code or another coding agent.
Specs
- Version
- 0.4.0
- License
- AGPL-3.0-only
- Edition
- Rust 2024
- MSRV
- 1.88
- Size
- 3,374 lines of code, 11 of comments
- Package
- 157.6 KB compressed
- Dependencies
- scryer-prolog
- Used by
- 0 crates on crates.io
- Features
- scryer
- Binaries
- stalmarck
- Docs
- docs.rs, built
- Repository
- cryptopatrick/stalmarck · 0★ · 0 forks · 0 open issues · pushed 31 Oct 2026
Release history
| Version | Date | Downloads |
|---|---|---|
| 0.4.0 | 31 Oct 2026 | 7 |
| 0.3.0 | 28 Oct 2026 | 9 |
| 0.2.0 | 28 Oct 2026 | 10 |
| 0.1.0 | 28 Oct 2026 | 10 |
Documentation
The manual.
The crate's README as published on crates.io. The full API reference is on docs.rs.
Read the README
stalmarck
Stålmarck's proof procedure for propositional logic, in Rust.
Overview
Stålmarck's method decides whether a propositional formula is satisfiable, or valid, by reasoning about equivalences between subformulas instead of searching assignments. It works in three steps.
- Triples. The formula is decomposed into triples
x ↔ (a ∧ b)andx ↔ (a ↔ b)over literals. Identical subformulas are shared. - 0-saturation. A formula relation, which records equivalences between literals, is extended with every equivalence that one triple entails. This repeats until nothing changes or a contradiction appears.
- The Dilemma rule. The procedure assumes a node is ⊥, saturates,
assumes it is ⊤, saturates, and keeps only the equivalences both branches
agree on. Nesting this to depth
kis k-saturation.
Formulas that occur in practice often have low hardness: they are refuted at depth 0, 1 or 2.
This crate follows the procedure of M. Sheeran and G. Stålmarck, A Tutorial on Stålmarck's Proof Procedure for Propositional Logic (FMCAD '98, LNCS 1522). It implements a written formal specification exactly.
Key Features
- Satisfiability (
check_sat) and validity (prove), each with a verified model or counter-model. - Results are
Sat/Unsat/Unknown(orValid/Invalid/Unknown). The answer is never a guess.Unknownsays why: depth exhausted, branch limit, or timeout. - Configurable Dilemma depth, structural sharing, branch limit and timeout.
- Solver counters, and a canonical form of the final relation for differential testing.
- Input as Rust values, as text (
"a & (b | c) -> d".parse()), or as DIMACS CNF. A documented triple-file format is shared with other implementations. - Seeded instance generators and a truth-table oracle for testing.
- Pure safe Rust with no dependencies.
Quick Start
[dependencies]
stalmarck = "0.4"
use stalmarck::{Config, Formula, ProofResult, SatResult, Solver};
let (a, b, c) = (Formula::var("a"), Formula::var("b"), Formula::var("c"));
// (a ∧ b) ∨ (a ∧ c) → a ∧ (b ∨ c) is valid, with hardness 1.
let f = ((a.clone() & b.clone()) | (a.clone() & c.clone()))
.implies(a.clone() & (b.clone() | c));
let solver = Solver::new(Config::default().with_max_depth(1));
assert_eq!(solver.prove(&f).result, ProofResult::Valid);
// a ∧ ¬b is satisfiable.
match solver.check_sat(&(a & !b)).result {
SatResult::Sat(model) => assert_eq!(model.get("b"), Some(false)),
other => panic!("{other:?}"),
}
Run cargo run --example basic for a small demo that prints solver
counters.
Command line
$ cargo install stalmarck
$ echo '!((a & b) | (a & c) -> a & (b | c))' | stalmarck --format prop -
s UNSAT
c depth=2 branches=1 merges=12 solve=0.007ms
$ stalmarck --json --relation -k 3 problem.cnf # result-v1 JSON record
The exit status is 10 for SAT/INVALID, 20 for UNSAT/VALID and 0 for
unknown. See stalmarck --help for all options.
Rust + Scryer Prolog
With the scryer feature, stalmarck::scryer::ScryerSolver runs every
Dilemma branch in embedded Scryer Prolog.
It gives the same answers, final relations and counters as Solver. It
exists to compare implementation paradigms, not for speed.
stalmarck = { version = "0.4", features = ["scryer"] }
# scryer-prolog 0.10.0 trips a Rust safety check in debug builds:
[profile.dev.package.scryer-prolog]
debug-assertions = false
Status
0.4 contains the sequential pure-Rust reference implementation and the Rust + Scryer variant. Planned:
- optional parallel branch exploration;
The API may change before 1.0.
The procedure is complete only when the depth is at least the number of variables. At small depths it is a fast semi-decision procedure for easy formulas, by design.
Contributing
Contributions are welcome! Please see our contributing guidelines for details on:
- Code style and testing requirements
- Submitting bug reports and feature requests
- Development setup and workflow
License
This project is licensed under the GNU Affero General Public License v3.0 only (AGPL-3.0-only). See LICENSE for details.
Resources
Same unit