pumpkin_solver/basic_types/
solution.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use crate::engine::propagation::propagation_context::HasAssignments;
use crate::engine::variables::Literal;
use crate::engine::variables::PropositionalVariable;
use crate::engine::AssignmentsInteger;
use crate::engine::AssignmentsPropositional;
use crate::pumpkin_assert_moderate;
use crate::variables::IntegerVariable;

/// A trait which specifies the common behaviours of [`Solution`] and [`SolutionReference`].
pub trait ProblemSolution: HasAssignments {
    /// Returns the number of defined [`PropositionalVariable`]s
    fn num_propositional_variables(&self) -> usize {
        self.assignments_propositional()
            .num_propositional_variables() as usize
    }

    /// Returns the number of domains.
    fn num_domains(&self) -> usize {
        self.assignments_integer().num_domains() as usize
    }

    /// Returns the assigned boolean value of the provided [`PropositionalVariable`].
    fn get_propositional_variable_value(
        &self,
        propositional_variable: PropositionalVariable,
    ) -> bool {
        pumpkin_assert_moderate!(
            self.assignments_propositional()
                .is_variable_assigned(propositional_variable),
            "Expected retrieved propositional variable from solution to be assigned"
        );
        self.assignments_propositional()
            .is_variable_assigned_true(propositional_variable)
    }

    /// Returns the assigned boolean value of the provided [`Literal`].
    fn get_literal_value(&self, literal: Literal) -> bool {
        pumpkin_assert_moderate!(
            self.assignments_propositional()
                .is_literal_assigned(literal),
            "Expected retrieved literal from solution to be assigned"
        );
        self.assignments_propositional()
            .is_literal_assigned_true(literal)
    }

    /// Returns the assigned integer value of the provided variable.
    fn get_integer_value(&self, variable: impl IntegerVariable) -> i32 {
        let lower_bound = variable.lower_bound(self.assignments_integer());
        let upper_bound = variable.upper_bound(self.assignments_integer());

        pumpkin_assert_moderate!(
            lower_bound == upper_bound,
            "Expected retrieved integer variable from solution to be assigned"
        );

        lower_bound
    }
}

/// A solution which keeps reference to its inner structures.
#[derive(Debug, Copy, Clone)]
pub struct SolutionReference<'a> {
    assignments_propositional: &'a AssignmentsPropositional,
    assignments_integer: &'a AssignmentsInteger,
}

impl<'a> SolutionReference<'a> {
    pub fn new(
        assignments_propositional: &'a AssignmentsPropositional,
        assignments_integer: &'a AssignmentsInteger,
    ) -> SolutionReference<'a> {
        SolutionReference {
            assignments_propositional,
            assignments_integer,
        }
    }

    pub fn get_propostional_variables(&self) -> impl Iterator<Item = PropositionalVariable> {
        self.assignments_propositional.get_propositional_variables()
    }
}

impl ProblemSolution for SolutionReference<'_> {}

/// A solution which takes ownership of its inner structures.
#[derive(Clone, Debug, Default)]
pub struct Solution {
    assignments_propositional: AssignmentsPropositional,
    assignments_integer: AssignmentsInteger,
}

impl Solution {
    pub fn new(
        assignments_propositional: AssignmentsPropositional,
        assignments_integer: AssignmentsInteger,
    ) -> Self {
        Self {
            assignments_propositional,
            assignments_integer,
        }
    }

    pub fn as_reference(&self) -> SolutionReference<'_> {
        SolutionReference {
            assignments_propositional: &self.assignments_propositional,
            assignments_integer: &self.assignments_integer,
        }
    }
}

impl ProblemSolution for Solution {}

impl From<SolutionReference<'_>> for Solution {
    fn from(value: SolutionReference) -> Self {
        Self {
            assignments_propositional: value.assignments_propositional.clone(),
            assignments_integer: value.assignments_integer.clone(),
        }
    }
}

impl<'a> HasAssignments for SolutionReference<'a> {
    fn assignments_integer(&self) -> &'a AssignmentsInteger {
        self.assignments_integer
    }

    fn assignments_propositional(&self) -> &'a AssignmentsPropositional {
        self.assignments_propositional
    }
}

impl HasAssignments for Solution {
    fn assignments_integer(&self) -> &AssignmentsInteger {
        &self.assignments_integer
    }

    fn assignments_propositional(&self) -> &AssignmentsPropositional {
        &self.assignments_propositional
    }
}