pumpkin_core/api/outputs/
solution_iterator.rs1use std::fmt::Debug;
4
5use super::SatisfactionResult::Satisfiable;
6use super::SatisfactionResult::Unknown;
7use super::SatisfactionResult::Unsatisfiable;
8use super::SolutionReference;
9use crate::Solver;
10use crate::branching::Brancher;
11use crate::conflict_resolving::ConflictResolver;
12use crate::predicate;
13use crate::predicates::Predicate;
14use crate::results::ProblemSolution;
15use crate::results::Solution;
16use crate::termination::TerminationCondition;
17
18#[derive(Debug)]
20pub struct SolutionIterator<'solver, 'brancher, 'termination, 'resolver, B, T, R> {
21 solver: &'solver mut Solver,
22 brancher: &'brancher mut B,
23 termination: &'termination mut T,
24 resolver: &'resolver mut R,
25
26 next_blocking_clause: Option<Vec<Predicate>>,
27 has_solution: bool,
28}
29
30impl<
31 'solver,
32 'brancher,
33 'termination,
34 'resolver,
35 B: Brancher,
36 T: TerminationCondition,
37 R: ConflictResolver,
38> SolutionIterator<'solver, 'brancher, 'termination, 'resolver, B, T, R>
39{
40 pub(crate) fn new(
41 solver: &'solver mut Solver,
42 brancher: &'brancher mut B,
43 termination: &'termination mut T,
44 resolver: &'resolver mut R,
45 ) -> Self {
46 SolutionIterator {
47 solver,
48 brancher,
49 termination,
50 resolver,
51 next_blocking_clause: None,
52 has_solution: false,
53 }
54 }
55
56 pub fn next_solution(&mut self) -> IteratedSolution<'_, B, R> {
59 if let Some(blocking_clause) = self.next_blocking_clause.take() {
60 let constraint_tag = self.solver.new_constraint_tag();
63
64 self.solver.add_clause(blocking_clause, constraint_tag);
65 }
66
67 let result = match self
68 .solver
69 .satisfy(self.brancher, self.termination, self.resolver)
70 {
71 Satisfiable(satisfiable) => {
72 let solution: Solution = satisfiable.solution().into();
73 self.has_solution = true;
74 self.next_blocking_clause = Some(get_blocking_clause(solution.as_reference()));
75 IterationResult::Solution(solution)
76 }
77 Unsatisfiable(_, _, _) => {
78 if self.has_solution {
79 IterationResult::Finished
80 } else {
81 IterationResult::Unsatisfiable
82 }
83 }
84 Unknown(_, _, _) => IterationResult::Unknown,
85 };
86
87 match result {
88 IterationResult::Solution(solution) => {
89 IteratedSolution::Solution(solution, self.solver, self.brancher, self.resolver)
90 }
91 IterationResult::Finished => IteratedSolution::Finished,
92 IterationResult::Unsatisfiable => IteratedSolution::Unsatisfiable,
93 IterationResult::Unknown => IteratedSolution::Unknown,
94 }
95 }
96}
97
98enum IterationResult {
103 Solution(Solution),
104 Finished,
105 Unsatisfiable,
106 Unknown,
107}
108
109fn get_blocking_clause(solution: SolutionReference) -> Vec<Predicate> {
115 solution
116 .get_domains()
117 .map(|variable| predicate!(variable != solution.get_integer_value(variable)))
118 .collect::<Vec<_>>()
119}
120#[allow(
122 clippy::large_enum_variant,
123 reason = "these will not be stored in bulk, so this is not an issue"
124)]
125#[derive(Debug)]
126pub enum IteratedSolution<'a, B, R> {
127 Solution(Solution, &'a Solver, &'a B, &'a R),
129
130 Finished,
132
133 Unknown,
135
136 Unsatisfiable,
138}