Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2be6e8d
Started reworking multiplication for consistency checkers.
maartenflippo May 18, 2026
4ca596a
feat(pumpkin-solver): Implement consistency checker infrastructure
maartenflippo May 20, 2026
f7c9b69
Fix multiline test command syntax
maartenflippo May 20, 2026
11511e2
Implement domain consistency checker
maartenflippo May 20, 2026
70a2c31
Avoid copying domains when doing domain consistency checks
maartenflippo May 20, 2026
1d32565
Refactor PropagatorConstructor to remove `add_inference_checkers`
maartenflippo May 22, 2026
a9324b9
Fix conditional compilation errors and split up reified propagator
maartenflippo May 22, 2026
5fc57f9
Fix formatting
maartenflippo May 22, 2026
dee4887
Implement the checkers for nogood propagator
maartenflippo May 22, 2026
1c9f258
Cleanup code
maartenflippo May 22, 2026
893989d
Various cleanup
maartenflippo May 23, 2026
2d999b7
Rename 'ConsistencyChecker' to 'RetentionChecker'
maartenflippo May 24, 2026
2bbdd59
Explicitly introduce the concept of 'PropagationChecker'
maartenflippo May 24, 2026
12e8f2b
refactor: split up maximum propagator
ImkoMarijnissen May 26, 2026
5dbb7e1
feat: adding consistency checker for maximum
ImkoMarijnissen May 26, 2026
d220a64
feat: adding weak consistency checker
ImkoMarijnissen May 26, 2026
11713ff
feat: adding consistency checker for time-tabling
ImkoMarijnissen May 26, 2026
ca935d0
chore: add proper error logging to weak retention checker
ImkoMarijnissen May 26, 2026
4d22b09
fix: test cases
ImkoMarijnissen May 26, 2026
c676757
Squashed commit of the following:
maartenflippo May 27, 2026
f2169ee
refactor: simplify disjunctive propagation checker
ImkoMarijnissen May 28, 2026
a5b2548
feat: add consistency checker for disjunctive
ImkoMarijnissen May 28, 2026
2d8f33b
chore: add back commented out lines
ImkoMarijnissen May 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ jobs:
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- uses: dtolnay/rust-toolchain@stable
- run: cargo test --release --no-fail-fast --features pumpkin-solver/check-propagations --features pumpkin-core/check-deductions
- run: |
cargo test \
--release \
--no-fail-fast \
--features pumpkin-solver/check-propagations \
--features pumpkin-core/check-consistency \
--features pumpkin-core/check-deductions

wasm-test:
name: Test Suite for pumpkin-core in WebAssembly
Expand Down
30 changes: 28 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 19 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ A unique feature of Pumpkin is that it can produce a certificate of unsatisfiabi

The solver currently supports integer variables and a number of (global) constraints:

- [Cumulative global constraint](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/core/src/propagators/cumulative).
- [Disjunctive global constraint](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/core/src/propagators/disjunctive)
- [Element global constraint](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/core/src/propagators/element.rs).
- [Arithmetic constraints](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/core/src/propagators/arithmetic): [linear integer (in)equalities](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/core/src/propagators/arithmetic/linear_less_or_equal.rs), [integer division](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/core/src/propagators/arithmetic/integer_division.rs), [integer multiplication](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/core/src/propagators/arithmetic/integer_multiplication.rs), [maximum](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/core/src/propagators/arithmetic/maximum.rs), [absolute value](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/core/src/propagators/arithmetic/absolute_value.rs).
- [Cumulative global constraint](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/propagators/src/propagators/cumulative).
- [Disjunctive global constraint](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/propagators/src/propagators/disjunctive)
- [Element global constraint](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/propagators/src/propagators/element.rs).
- [Arithmetic constraints](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/propagators/src/propagators/arithmetic): [linear integer (in)equalities](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/propagators/src/propagators/arithmetic/linear_less_or_equal.rs), [integer division](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/propagators/src/propagators/arithmetic/integer_division.rs), [integer multiplication](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/propagators/src/propagators/arithmetic/integer_multiplication.rs), [maximum](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/propagators/src/propagators/arithmetic/maximum.rs), [absolute value](https://github.com/ConSol-Lab/Pumpkin/blob/main/pumpkin-crates/propagators/src/propagators/arithmetic/absolute_value.rs).
- Clausal constraints.

We are actively developing Pumpkin and would be happy to hear from you should you have any questions or feature requests!
Expand Down Expand Up @@ -98,13 +98,22 @@ To use it as such a backend, follow the following steps:
- Step 3: Add the following to the `MZN_SOLVER_PATH` environment variable: `<path_to_pumpkin>/minizinc` (see [this thread](https://askubuntu.com/questions/58814/how-do-i-add-environment-variables) on how to do this using a shell).
- Step 4: Check whether the installation worked using the command `minizinc --help pumpkin`.

## Components
Pumpkin consists of 3 different crates:
This will add Pumpkin and PumpkinProof (which uses a flattening library specific for proof logging).

- The library contained in [core](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/core); defines the API through which the solver can be used via Rust.
- The CLI contained in [pumpkin-solver](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-solver/src/bin/pumpkin-solver); defines the usage of Pumpkin through a command line.
- The proof logging contained in [drcp-format](https://github.com/ConSol-Lab/Pumpkin/tree/main/drcp-format); defines proof logging which can be used in combination with Pumpkin.
- The python bindings contained in [pumpkin-solver-py](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-solver-py); defines the python interface for Pumpkin
## Components
Pumpkin consists of several different components:

- The crates contained in [pumpkin-crates](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates):
- [pumpkin-core](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/core); defines the API through which the solver can be used via Rust.
- [pumpkin-propagators](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/propagators); contains (most of) the propagators used by Pumpkin.
- [pumpkin-constraints](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/constraints); contains convenient ways to add one or more propagators modelling certain constraints to the solver.
- [pumpkin-conflict-resolvers](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/conflict-resolvers); contains the conflict resolvers (e.g., 1UIP or All-Decision conflit resolvers) used by Pumpkin.
- [pumpkin-checking](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-crates/checking); contains the types used for checking the soundness of propagators in Pumpkin.
- The CLI contained in [pumpkin-solver](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-solver).
- The python bindings contained in [pumpkin-solver-py](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-solver-py).
- The proof logging contained in [drcp-format](https://github.com/ConSol-Lab/Pumpkin/tree/main/drcp-format); a file reader and writer for the DRCP proof format (the proof format used by Pumpkin).
- The (unverified) proof processor contained in [pumpkin-proof-processor](https://github.com/ConSol-Lab/Pumpkin/tree/main/pumpkin-proof-processor).
- A debugger for DRCP proofs contained in [drcp-debugger](https://github.com/ConSol-Lab/Pumpkin/tree/main/drcp-debugger).

The easiest way to get to know the different modules is through the documentation. This documentation can be created automatically using the command:
```sh
Expand Down
4 changes: 2 additions & 2 deletions minizinc/pumpkin-for-proofs.msc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Pumpkin",
"id": "nl.tudelft.algorithmics.pumpkin",
"name": "PumpkinProof",
"id": "nl.tudelft.algorithmics.pumpkin_proof",
"version": "0.1",
"executable": "../target/release/pumpkin-solver",
"mznlib": "./lib-for-proofs/",
Expand Down
11 changes: 6 additions & 5 deletions pumpkin-crates/constraints/src/constraints/arithmetic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ mod inequality;

pub use equality::*;
pub use inequality::*;
use pumpkin_core::checkers::support::SupportsValue;
use pumpkin_core::constraints::Constraint;
use pumpkin_core::proof::ConstraintTag;
use pumpkin_core::variables::IntegerVariable;
use pumpkin_propagators::arithmetic::AbsoluteValueArgs;
use pumpkin_propagators::arithmetic::DivisionArgs;
use pumpkin_propagators::arithmetic::IntegerMultiplicationArgs;
use pumpkin_propagators::arithmetic::MaximumArgs;
use pumpkin_propagators::arithmetic::MaximumConstructor;

/// Creates the [`Constraint`] `a + b = c`.
pub fn plus<Var: IntegerVariable + 'static>(
Expand All @@ -23,9 +24,9 @@ pub fn plus<Var: IntegerVariable + 'static>(

/// Creates the [`Constraint`] `a * b = c`.
pub fn times(
a: impl IntegerVariable + 'static,
b: impl IntegerVariable + 'static,
c: impl IntegerVariable + 'static,
a: impl IntegerVariable + SupportsValue<f32> + 'static,
b: impl IntegerVariable + SupportsValue<f32> + 'static,
c: impl IntegerVariable + SupportsValue<f32> + 'static,
constraint_tag: ConstraintTag,
) -> impl Constraint {
IntegerMultiplicationArgs {
Expand Down Expand Up @@ -75,7 +76,7 @@ pub fn maximum<Var: IntegerVariable + 'static>(
rhs: impl IntegerVariable + 'static,
constraint_tag: ConstraintTag,
) -> impl Constraint {
MaximumArgs {
MaximumConstructor {
array: array.into_iter().collect(),
rhs,
constraint_tag,
Expand Down
5 changes: 4 additions & 1 deletion pumpkin-crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pumpkin-checking = { version = "0.3.0", path = "../checking" }
thiserror = "2.0.12"
log = "0.4.17"
bitfield = "0.19.4"
enumset = "1.1.12"
enumset = "1.1.13"
fnv = "1.0.7" # We require features which are on the `main` branch of the repository but are not on crates.io
rand = { version = "0.10.1", features = [ "alloc" ] }
once_cell = "1.19.0"
Expand All @@ -30,6 +30,8 @@ clap = { version = "4.5.40", optional = true, features=["derive"] }
indexmap = "2.10.0"
dyn-clone = "1.0.20"
flate2 = { version = "1.1.2" }
bit-set = "0.10.0"
replace_with = "0.1.8"

[target.'cfg(target_arch = "wasm32")'.dependencies]
web-time = "1.1"
Expand All @@ -39,6 +41,7 @@ getrandom = { version = "0.4.2", features = ["wasm_js"] }
wasm-bindgen-test = "0.3"

[features]
check-consistency = []
check-propagations = []
check-deductions = []
debug-checks = []
Expand Down
2 changes: 1 addition & 1 deletion pumpkin-crates/core/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ pub mod options {
pub use crate::engine::ConflictResolverType;
pub use crate::engine::RestartOptions;
pub use crate::engine::SatisfactionSolverOptions as SolverOptions;
pub use crate::propagators::ReifiedPropagatorArgs;
pub use crate::propagators::nogoods::LearningOptions;
pub use crate::propagators::reified_propagator::ReifiedPropagatorArgs;
}

pub mod termination {
Expand Down
2 changes: 0 additions & 2 deletions pumpkin-crates/core/src/basic_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ mod function;
mod predicate_id_generators;
mod propositional_conjunction;
mod random;
mod ref_or_owned;
pub(crate) mod sequence_generators;
mod solution;
mod stored_conflict_info;
Expand All @@ -19,7 +18,6 @@ pub use predicate_id_generators::PredicateId;
pub use predicate_id_generators::PredicateIdGenerator;
pub use propositional_conjunction::PropositionalConjunction;
pub use random::*;
pub(crate) use ref_or_owned::*;
pub use solution::ProblemSolution;
pub use solution::Solution;
pub use solution::SolutionReference;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ impl Deref for PropositionalConjunction {
}
}

impl From<PropositionalConjunction> for Box<[Predicate]> {
fn from(val: PropositionalConjunction) -> Self {
val.predicates_in_conjunction.into()
}
}

impl PropositionalConjunction {
pub fn new(predicates_in_conjunction: Vec<Predicate>) -> Self {
PropositionalConjunction {
Expand Down
49 changes: 0 additions & 49 deletions pumpkin-crates/core/src/basic_types/ref_or_owned.rs

This file was deleted.

16 changes: 16 additions & 0 deletions pumpkin-crates/core/src/checkers/mod.rs
Comment thread
maartenflippo marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
mod propagation_checker;
mod retention_checker;
mod scope;
mod self_disabling;
mod store;
mod strong_retention_checker;
pub mod support;
mod weak_retention_checker;

pub use propagation_checker::*;
pub use retention_checker::*;
pub use scope::*;
pub use self_disabling::*;
pub use store::*;
pub use strong_retention_checker::*;
pub use weak_retention_checker::*;
64 changes: 64 additions & 0 deletions pumpkin-crates/core/src/checkers/propagation_checker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use pumpkin_checking::BoxedChecker;
use pumpkin_checking::VariableState;

use crate::predicates::Predicate;
use crate::propagation::Domains;
use crate::propagation::ReadDomains;
use crate::variables::DomainId;

/// Tests whether an inference is correct given the solver state.
///
/// An inference is correct when:
/// 1. All premises are satisfied.
/// 2. The conjunction of the premises and negation of the consequent is consistent.
/// 3. The consequent is logically entailed given the inference code.
#[derive(Clone, Debug)]
pub struct PropagationChecker {
inference_checker: BoxedChecker<Predicate>,
}

impl PropagationChecker {
/// Create a new propagation checker given an inference checker and inference code.
pub fn new(inference_checker: BoxedChecker<Predicate>) -> PropagationChecker {
PropagationChecker { inference_checker }
}

/// Run the propagation checker for the given inference.
pub fn check(
&self,
premises: &[Predicate],
consequent: Option<Predicate>,
domains: Domains<'_>,
) -> Result<(), InvalidInference> {
let premises_satisfied = premises
.iter()
.all(|&premise| domains.evaluate_predicate(premise) == Some(true));

if !premises_satisfied {
return Err(InvalidInference::UnsatisfiedPremises);
}

let variable_state =
VariableState::prepare_for_conflict_check(premises.iter().copied(), consequent)
.map_err(InvalidInference::InconsistentPredicates)?;

if self
.inference_checker
.check(variable_state, premises, consequent.as_ref())
{
Ok(())
} else {
Err(InvalidInference::Unsound)
}
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum InvalidInference {
/// Not all premises are true given the current state.
UnsatisfiedPremises,
/// The predicates that make up the inference are trivially inconsistent.
InconsistentPredicates(DomainId),
/// Cannot establish that the inference is sound.
Unsound,
}
Loading