branch_and_bound/
candidate.rs1use crate::{Subproblem, SubproblemResolution};
2
3pub trait OrderedCandidate: Ord + Subproblem {
6 type Node: Subproblem;
7
8 fn new(root: Self::Node) -> Self;
11 fn node(&self) -> &Self::Node;
13 fn into_node(self) -> Self::Node;
15}
16
17pub(crate) struct BoundOrderedCandidate<Node: Subproblem<Score = Score>, Score: Ord> {
23 node: Node,
24 bound: Score,
25}
26
27pub(crate) struct DepthOrderedCandidate<Node: Subproblem<Score = Score>, Score: Ord> {
33 node: Node,
34 depth: u64,
35}
36
37impl<Score: Ord, Node: Subproblem<Score = Score>> PartialEq for BoundOrderedCandidate<Node, Score> {
38 fn eq(&self, other: &Self) -> bool {
39 self.bound == other.bound
40 }
41}
42
43impl<Score: Ord, Node: Subproblem<Score = Score>> Eq for BoundOrderedCandidate<Node, Score> {}
44
45impl<Score: Ord, Node: Subproblem<Score = Score>> PartialOrd
46 for BoundOrderedCandidate<Node, Score>
47{
48 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
49 Some(self.cmp(other))
50 }
51}
52
53impl<Score: Ord, Node: Subproblem<Score = Score>> Ord for BoundOrderedCandidate<Node, Score> {
54 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
55 self.bound.cmp(&other.bound)
56 }
57}
58
59impl<Score, Node> Subproblem for BoundOrderedCandidate<Node, Score>
60where
61 Score: Ord,
62 Node: Subproblem<Score = Score> + 'static,
63{
64 type Score = Score;
65
66 fn branch_or_evaluate(&self) -> crate::SubproblemResolution<Self, Self::Score> {
67 use SubproblemResolution::{Branched, Solved};
68
69 match self.node.branch_or_evaluate() {
70 Solved(score) => Solved(score),
71 Branched(subproblems) => Branched(Box::new(subproblems.map(|node| Self::new(node)))),
73 }
74 }
75
76 fn bound(&self) -> Self::Score {
77 self.node.bound()
78 }
79}
80
81impl<Score, Node> OrderedCandidate for BoundOrderedCandidate<Node, Score>
82where
83 Score: Ord,
84 Node: Subproblem<Score = Score> + 'static,
85{
86 type Node = Node;
87
88 fn new(root: Self::Node) -> Self {
89 Self {
90 bound: root.bound(),
91 node: root,
92 }
93 }
94
95 fn node(&self) -> &Self::Node {
96 &self.node
97 }
98
99 fn into_node(self) -> Self::Node {
100 self.node
101 }
102}
103
104impl<Score: Ord, Node: Subproblem<Score = Score>> PartialEq for DepthOrderedCandidate<Node, Score> {
105 fn eq(&self, other: &Self) -> bool {
106 self.depth == other.depth
107 }
108}
109
110impl<Score: Ord, Node: Subproblem<Score = Score>> Eq for DepthOrderedCandidate<Node, Score> {}
111
112impl<Score: Ord, Node: Subproblem<Score = Score>> PartialOrd
113 for DepthOrderedCandidate<Node, Score>
114{
115 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
116 Some(self.cmp(other))
117 }
118}
119
120impl<Score: Ord, Node: Subproblem<Score = Score>> Ord for DepthOrderedCandidate<Node, Score> {
121 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
122 self.depth.cmp(&other.depth)
123 }
124}
125
126impl<Score, Node> Subproblem for DepthOrderedCandidate<Node, Score>
127where
128 Score: Ord,
129 Node: Subproblem<Score = Score> + 'static,
130{
131 type Score = Score;
132
133 fn branch_or_evaluate(&self) -> SubproblemResolution<Self, Self::Score> {
134 use SubproblemResolution::{Branched, Solved};
135
136 let depth: u64 = self.depth;
137 match self.node.branch_or_evaluate() {
138 Solved(score) => Solved(score),
139 Branched(subproblems) => Branched(Box::new(subproblems.map(move |subnode| Self {
140 node: subnode,
141 depth: depth + 1,
142 }))),
143 }
144 }
145
146 fn bound(&self) -> Self::Score {
147 self.node.bound()
148 }
149}
150
151impl<Score, Node> OrderedCandidate for DepthOrderedCandidate<Node, Score>
152where
153 Score: Ord,
154 Node: Subproblem<Score = Score> + 'static,
155{
156 type Node = Node;
157
158 fn new(root: Self::Node) -> Self {
159 Self {
160 node: root,
161 depth: 0,
162 }
163 }
164
165 fn node(&self) -> &Self::Node {
166 &self.node
167 }
168
169 fn into_node(self) -> Self::Node {
170 self.node
171 }
172}