pub struct Cdcl<Config: SolverConfig = DefaultConfig> {
pub cnf: Cnf<Config::Literal, Config::LiteralStorage>,
/* private fields */
}Expand description
Represents a CDCL SAT solver instance.
The solver iteratively makes decisions (assigns a truth value to a variable), propagates their logical consequences, and if a conflict (a clause that becomes false under the current assignment) arises, it analyses the conflict to learn a new clause. This learned clause helps prune the search space and guide the solver towards a solution or a proof of unsatisfiability.
The solver’s behavior can be customised via the Config generic parameter,
which defines the specific implementations for various components like
literal representation, assignment tracking, propagation engine, variable
selection heuristic, restart strategies, and clause database management.
Fields§
§cnf: Cnf<Config::Literal, Config::LiteralStorage>The Conjunctive Normal Form (CNF) formula being solved. This stores both the original clauses provided by the user and clauses learned by the solver during conflict analysis.
Implementations§
Source§impl<Config: SolverConfig> Cdcl<Config>
impl<Config: SolverConfig> Cdcl<Config>
Sourcepub const fn all_assigned(&self) -> bool
pub const fn all_assigned(&self) -> bool
Checks if all variables in the CNF have been assigned a truth value.
The number of variables is determined by self.cnf.num_vars, which typically
corresponds to the highest variable index used in the problem + 1.
The trail length (self.trail.len()) reflects the number of currently
assigned literals.
§Returns
true if the number of assigned literals in the trail equals the total
number of variables considered by the solver, false otherwise.
Sourcepub fn add_clause(
&mut self,
clause: Clause<Config::Literal, Config::LiteralStorage>,
)
pub fn add_clause( &mut self, clause: Clause<Config::Literal, Config::LiteralStorage>, )
Adds a new clause to the solver’s CNF database.
Clauses that are empty (and thus trivially unsatisfiable if encountered this way)
or tautological (e.g. (x OR -x OR y)) are typically ignored as they provide
no useful constraints or can be simplified.
The new clause is added to the Cnf store and then registered with the Propagator
(e.g. for setting up watched literals).
§Arguments
clause: The clause to add.
Trait Implementations§
Source§impl<Config: Clone + SolverConfig> Clone for Cdcl<Config>where
Config::Assignment: Clone,
Config::Propagator: Clone,
Config::Literal: Clone,
Config::LiteralStorage: Clone,
Config::VariableSelector: Clone,
Config::Restarter: Clone,
Config::ClauseManager: Clone,
impl<Config: Clone + SolverConfig> Clone for Cdcl<Config>where
Config::Assignment: Clone,
Config::Propagator: Clone,
Config::Literal: Clone,
Config::LiteralStorage: Clone,
Config::VariableSelector: Clone,
Config::Restarter: Clone,
Config::ClauseManager: Clone,
Source§impl<Config: Debug + SolverConfig> Debug for Cdcl<Config>where
Config::Assignment: Debug,
Config::Propagator: Debug,
Config::Literal: Debug,
Config::LiteralStorage: Debug,
Config::VariableSelector: Debug,
Config::Restarter: Debug,
Config::ClauseManager: Debug,
impl<Config: Debug + SolverConfig> Debug for Cdcl<Config>where
Config::Assignment: Debug,
Config::Propagator: Debug,
Config::Literal: Debug,
Config::LiteralStorage: Debug,
Config::VariableSelector: Debug,
Config::Restarter: Debug,
Config::ClauseManager: Debug,
Source§impl<Config: SolverConfig> Solver<Config> for Cdcl<Config>
impl<Config: SolverConfig> Solver<Config> for Cdcl<Config>
Source§fn new<L: Literal, S: LiteralStorage<L>>(cnf: Cnf<L, S>) -> Self
fn new<L: Literal, S: LiteralStorage<L>>(cnf: Cnf<L, S>) -> Self
Creates a new Cdcl solver instance for the given CNF formula.
Initialises all internal components of the solver:
Assignment: To store variable assignments (initialised to Undefined).Trail: To track decisions and propagations.Propagator: Set up with the initial clauses for watched literal schemes.Cnf: Stores the clauses of the problem.VariableSelector: Initialised with variable information (e.g. for VSIDS).Restarter: Initialised with default restart strategy parameters.Analyser: For conflict analysis.ClauseManager: For managing learned clauses. The decision level is initialised to 0.
§Arguments
cnf: The Conjunctive Normal Form (CNF) formula to be solved.
Source§fn solve(&mut self) -> Option<Solutions>
fn solve(&mut self) -> Option<Solutions>
Attempts to solve the SAT problem for the loaded CNF formula using the CDCL algorithm.
The main loop proceeds as follows:
-
Initial Check & Propagation:
- If the CNF is empty, it’s trivially SAT.
- Perform initial unit propagation (BCP) at decision level 0. If a conflict occurs, the formula is UNSAT.
- If any clause becomes empty (after initial setup or propagation), formula is UNSAT.
-
Main Loop: a. Propagation: Propagate assignments based on the current partial assignment.
-
If propagation leads to a conflict (a clause becomes falsified): i. Notify
ClauseManagerabout the conflict (e.g. to adjust clause activities). ii. PerformConflictAnalysis:- Generate a learned clause (lemma).
- Determine variables involved for activity bumping (e.g. VSIDS).
iii. Handle the conflict result:
Conflict::Ground: Conflict at level 0 implies the formula is UNSAT.Conflict::RestartorConflict::Unit: These might also indicate UNSAT or special handling.Conflict::Learned(assert_idx, learned_clause):- The learned clause is processed (e.g. LBD calculation, activity bump).
- Determine backtrack level (
bt_level) from the learned clause. - Bump activities of clauses involved in the conflict.
- Backtrack: Undo assignments on the trail up to
bt_level. Updatedecision_level. - Add the learned clause to the database.
- Enqueue the asserting literal from the learned clause for propagation.
- Optionally, clean the clause database (
manager.clean_clause_db).
iv. Update variable selection heuristics (
selector.bumps,selector.decay). v. Check for restart (should_restart). If so, reset trail, assignments, and decision level. - Generate a learned clause (lemma).
b. Decision (No Conflict): i. Increment
decision_level. ii. Check if all variables are assigned (all_assigned). If yes, a model is found; return SAT. iii. Select an unassigned variable usingselector.pick().- If a literal is picked, push it onto the trail as a decision.
- If no literal can be picked (e.g. all assigned but
all_assignedwas false, or selector gives up), it might imply a solution is found (thoughall_assignedshould be the primary check). Return current solutions.
- If no literal can be picked (e.g. all assigned but
-
The loop continues until a satisfying assignment is found (returns Some(Solutions))
or the formula is proven unsatisfiable (returns None).
§Returns
Some(Solutions): If a satisfying assignment is found. Contains the model.None: If the formula is unsatisfiable.
Source§fn solutions(&self) -> Solutions
fn solutions(&self) -> Solutions
Retrieves the current satisfying assignment if one has been found.
This method should typically be called after solve() returns Some(_).
If called before solving, or if the formula is unsatisfiable, the returned
assignment might be incomplete, empty, or reflect some intermediate state.
The Solutions object usually maps variable indices to their truth values.
§Returns
A Solutions object representing the variable assignments in a model.
Source§fn stats(&self) -> SolutionStats
fn stats(&self) -> SolutionStats
Gathers statistics about the solving process.
These statistics can be useful for analysing solver performance and heuristics.
§Returns
A SolutionStats struct containing:
conflicts: Total number of conflicts encountered.decisions: Total number of decisions made.propagations: Total number of propagations performed.restarts: Total number of restarts performed.learnt_clauses: Number of clauses currently in the learnt clause database.removed_clauses: Number of learnt clauses removed during database cleaning.
Source§fn debug(&mut self)
fn debug(&mut self)
Placeholder for a debugging function.
This function is intended for future use, possibly to print internal solver state or enable more verbose logging for debugging purposes. Currently, it is unimplemented.
Source§fn from_parts<L: Literal, S: LiteralStorage<L>>(
cnf: Cnf<L, S>,
assignment: Config::Assignment,
manager: Config::ClauseManager,
propagator: Config::Propagator,
restarter: Config::Restarter,
selector: Config::VariableSelector,
) -> Self
fn from_parts<L: Literal, S: LiteralStorage<L>>( cnf: Cnf<L, S>, assignment: Config::Assignment, manager: Config::ClauseManager, propagator: Config::Propagator, restarter: Config::Restarter, selector: Config::VariableSelector, ) -> Self
Auto Trait Implementations§
impl<Config> Freeze for Cdcl<Config>where
<Config as SolverConfig>::Assignment: Freeze,
<Config as SolverConfig>::Propagator: Freeze,
<Config as SolverConfig>::VariableSelector: Freeze,
<Config as SolverConfig>::Restarter: Freeze,
<Config as SolverConfig>::ClauseManager: Freeze,
<Config as SolverConfig>::Literal: Freeze,
impl<Config> RefUnwindSafe for Cdcl<Config>where
<Config as SolverConfig>::Assignment: RefUnwindSafe,
<Config as SolverConfig>::Propagator: RefUnwindSafe,
<Config as SolverConfig>::VariableSelector: RefUnwindSafe,
<Config as SolverConfig>::Restarter: RefUnwindSafe,
<Config as SolverConfig>::ClauseManager: RefUnwindSafe,
<Config as SolverConfig>::LiteralStorage: RefUnwindSafe,
<Config as SolverConfig>::Literal: RefUnwindSafe,
impl<Config = DefaultConfig> !Send for Cdcl<Config>
impl<Config = DefaultConfig> !Sync for Cdcl<Config>
impl<Config> Unpin for Cdcl<Config>where
<Config as SolverConfig>::Assignment: Unpin,
<Config as SolverConfig>::Propagator: Unpin,
<Config as SolverConfig>::VariableSelector: Unpin,
<Config as SolverConfig>::Restarter: Unpin,
<Config as SolverConfig>::ClauseManager: Unpin,
<Config as SolverConfig>::Literal: Unpin,
<Config as SolverConfig>::LiteralStorage: Unpin,
impl<Config> UnwindSafe for Cdcl<Config>where
<Config as SolverConfig>::Assignment: UnwindSafe,
<Config as SolverConfig>::Propagator: UnwindSafe,
<Config as SolverConfig>::VariableSelector: UnwindSafe,
<Config as SolverConfig>::Restarter: UnwindSafe,
<Config as SolverConfig>::ClauseManager: UnwindSafe,
<Config as SolverConfig>::LiteralStorage: RefUnwindSafe + UnwindSafe,
<Config as SolverConfig>::Literal: UnwindSafe + RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more