pumpkin_solver/api/outputs/
solution_iterator.rsuse super::SolutionReference;
use crate::basic_types::CSPSolverExecutionFlag;
use crate::branching::Brancher;
use crate::engine::ConstraintSatisfactionSolver;
use crate::termination::TerminationCondition;
use crate::variables::Literal;
#[cfg(doc)]
use crate::Solver;
#[derive(Debug)]
pub struct SolutionIterator<'solver, 'brancher, 'termination, B: Brancher, T> {
solver: &'solver mut ConstraintSatisfactionSolver,
brancher: &'brancher mut B,
termination: &'termination mut T,
next_blocking_clause: Option<Vec<Literal>>,
has_solution: bool,
}
impl<'solver, 'brancher, 'termination, B: Brancher, T: TerminationCondition>
SolutionIterator<'solver, 'brancher, 'termination, B, T>
{
pub(crate) fn new(
solver: &'solver mut ConstraintSatisfactionSolver,
brancher: &'brancher mut B,
termination: &'termination mut T,
) -> Self {
SolutionIterator {
solver,
brancher,
termination,
next_blocking_clause: None,
has_solution: false,
}
}
pub fn next_solution(&mut self) -> IteratedSolution {
if let Some(blocking_clause) = self.next_blocking_clause.take() {
self.solver.restore_state_at_root(self.brancher);
if self.solver.add_clause(blocking_clause).is_err() {
return IteratedSolution::Finished;
}
}
match self.solver.solve(self.termination, self.brancher) {
CSPSolverExecutionFlag::Feasible => {
self.has_solution = true;
self.brancher
.on_solution(self.solver.get_solution_reference());
let solution = self.solver.get_solution_reference();
self.next_blocking_clause = Some(self.get_blocking_clause());
IteratedSolution::Solution(solution)
}
CSPSolverExecutionFlag::Infeasible if !self.has_solution => {
IteratedSolution::Unsatisfiable
}
CSPSolverExecutionFlag::Infeasible => IteratedSolution::Finished,
CSPSolverExecutionFlag::Timeout => IteratedSolution::Unknown,
}
}
fn get_blocking_clause(&self) -> Vec<Literal> {
#[allow(deprecated)]
self.solver
.get_propositional_assignments()
.get_propositional_variables()
.filter(|propositional_variable| {
self.solver
.get_propositional_assignments()
.is_variable_assigned(*propositional_variable)
})
.map(|propositional_variable| {
!Literal::new(
propositional_variable,
self.solver
.get_propositional_assignments()
.is_variable_assigned_true(propositional_variable),
)
})
.collect::<Vec<_>>()
}
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum IteratedSolution<'solver> {
Solution(SolutionReference<'solver>),
Finished,
Unknown,
Unsatisfiable,
}