pumpkin_core/branching/variable_selection/
random.rs1use super::VariableSelector;
2use crate::branching::BrancherEvent;
3use crate::branching::SelectionContext;
4use crate::containers::SparseSet;
5use crate::containers::StorageKey;
6use crate::variables::DomainId;
7
8#[derive(Debug)]
10pub struct RandomSelector {
11 variables: SparseSet<DomainId>,
12}
13
14impl RandomSelector {
15 pub fn new(variables: impl IntoIterator<Item = DomainId>) -> Self {
16 Self {
18 variables: SparseSet::new(variables.into_iter().collect(), |element| {
19 element.index() - 1
20 }),
21 }
22 }
23}
24
25impl VariableSelector<DomainId> for RandomSelector {
26 fn select_variable(&mut self, context: &mut SelectionContext) -> Option<DomainId> {
27 if self.variables.is_empty() {
28 return None;
29 }
30
31 let mut variable = *self.variables.get(
32 context
33 .random()
34 .generate_usize_in_range(0..self.variables.len()),
35 );
36
37 while context.is_integer_fixed(variable) {
38 self.variables.remove_temporarily(&variable);
39 if self.variables.is_empty() {
40 return None;
41 }
42
43 variable = *self.variables.get(
44 context
45 .random()
46 .generate_usize_in_range(0..self.variables.len()),
47 );
48 }
49
50 Some(variable)
51 }
52
53 fn on_unassign_integer(&mut self, variable: DomainId, _value: i32) {
54 self.variables.insert(variable);
55 }
56
57 fn is_restart_pointless(&mut self) -> bool {
58 false
59 }
60
61 fn subscribe_to_events(&self) -> Vec<BrancherEvent> {
62 vec![BrancherEvent::UnassignInteger]
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use crate::basic_types::tests::TestRandom;
69 use crate::branching::variable_selection::RandomSelector;
70 use crate::branching::variable_selection::VariableSelector;
71 use crate::branching::SelectionContext;
72 use crate::predicate;
73
74 #[test]
75 fn test_selects_randomly() {
76 let (assignments, _) = SelectionContext::create_for_testing(vec![(0, 10), (5, 20), (1, 3)]);
77 let mut test_rng = TestRandom {
78 usizes: vec![1],
79 ..Default::default()
80 };
81 let integer_variables = assignments.get_domains().collect::<Vec<_>>();
82 let mut strategy = RandomSelector::new(assignments.get_domains());
83
84 let mut context = SelectionContext::new(&assignments, &mut test_rng);
85
86 let selected = strategy.select_variable(&mut context);
87 assert!(selected.is_some());
88 assert_eq!(selected.unwrap(), integer_variables[1]);
89 }
90
91 #[test]
92 fn test_selects_randomly_not_unfixed() {
93 let (assignments, _) = SelectionContext::create_for_testing(vec![(0, 10), (5, 5), (1, 3)]);
94 let mut test_rng = TestRandom {
95 usizes: vec![1, 0],
96 ..Default::default()
97 };
98 let integer_variables = assignments.get_domains().collect::<Vec<_>>();
99 let mut strategy = RandomSelector::new(assignments.get_domains());
100
101 let mut context = SelectionContext::new(&assignments, &mut test_rng);
102
103 let selected = strategy.select_variable(&mut context);
104 assert!(selected.is_some());
105 assert_eq!(selected.unwrap(), integer_variables[0]);
106 }
107
108 #[test]
109 fn test_select_nothing_if_all_fixed() {
110 let (assignments, _) = SelectionContext::create_for_testing(vec![(0, 0), (5, 5), (1, 1)]);
111 let mut test_rng = TestRandom {
112 usizes: vec![1, 0, 0],
113 ..Default::default()
114 };
115 let mut strategy = RandomSelector::new(assignments.get_domains());
116
117 let mut context = SelectionContext::new(&assignments, &mut test_rng);
118
119 let selected = strategy.select_variable(&mut context);
120 assert!(selected.is_none());
121 }
122
123 #[test]
124 fn test_select_unfixed_variable_after_fixing() {
125 let (mut assignments, mut notification_engine) =
126 SelectionContext::create_for_testing(vec![(0, 0), (5, 7), (1, 1)]);
127 let mut test_rng = TestRandom {
128 usizes: vec![2, 0, 0, 0, 0],
129 ..Default::default()
130 };
131 let integer_variables = assignments.get_domains().collect::<Vec<_>>();
132 let mut strategy = RandomSelector::new(assignments.get_domains());
133
134 {
135 let mut context = SelectionContext::new(&assignments, &mut test_rng);
136
137 let selected = strategy.select_variable(&mut context);
138 assert!(selected.is_some());
139 assert_eq!(selected.unwrap(), integer_variables[1]);
140 }
141
142 assignments.increase_decision_level();
143 let _ = assignments.post_predicate(
144 predicate!(integer_variables[1] >= 7),
145 None,
146 &mut notification_engine,
147 );
148
149 {
150 let mut context = SelectionContext::new(&assignments, &mut test_rng);
151
152 let selected = strategy.select_variable(&mut context);
153 assert!(selected.is_none());
154 }
155
156 let _ = assignments.synchronise(0, &mut notification_engine);
157 strategy.on_unassign_integer(integer_variables[1], 7);
158 let mut context = SelectionContext::new(&assignments, &mut test_rng);
159 let selected = strategy.select_variable(&mut context);
160 assert!(selected.is_some());
161 assert_eq!(selected.unwrap(), integer_variables[1]);
162 }
163}