pumpkin_core/branching/variable_selection/
occurrence.rs1use log::warn;
2
3use crate::branching::brancher::BrancherEvent;
4use crate::branching::tie_breaking::Direction;
5use crate::branching::tie_breaking::InOrderTieBreaker;
6use crate::branching::tie_breaking::TieBreaker;
7use crate::branching::variable_selection::VariableSelector;
8use crate::branching::SelectionContext;
9use crate::engine::variables::DomainId;
10use crate::pumpkin_assert_eq_simple;
11
12pub struct Occurrence<Var, TieBreaking> {
16 variables: Vec<Var>,
17 tie_breaker: TieBreaking,
18 num_occurrences: Vec<u32>,
19}
20
21impl<Var, TieBreaking> std::fmt::Debug for Occurrence<Var, TieBreaking> {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 f.debug_struct("Occurrence").finish()
24 }
25}
26
27impl<Var: Copy> Occurrence<Var, InOrderTieBreaker<Var, u32>> {
28 pub fn new(variables: &[Var], num_occurrences: &[u32]) -> Self {
29 pumpkin_assert_eq_simple!(
30 variables.len(), num_occurrences.len(),
31 "The number of variables and the number of elements in num_occurrences for the Occurence variable selector should be the same"
32 );
33 if variables.is_empty() {
34 warn!("The Occurence variable selector was not provided with any variables");
35 }
36 Occurrence {
37 variables: variables.to_vec(),
38 tie_breaker: InOrderTieBreaker::new(Direction::Maximum),
39 num_occurrences: num_occurrences.to_vec(),
40 }
41 }
42}
43
44impl<TieBreaking> VariableSelector<DomainId> for Occurrence<DomainId, TieBreaking>
45where
46 TieBreaking: TieBreaker<DomainId, u32>,
47{
48 fn select_variable(&mut self, context: &mut SelectionContext) -> Option<DomainId> {
49 self.variables
50 .iter()
51 .enumerate()
52 .filter(|(_, variable)| !context.is_integer_fixed(**variable))
53 .for_each(|(index, variable)| {
54 self.tie_breaker
55 .consider(*variable, self.num_occurrences[index])
56 });
57 self.tie_breaker.select()
58 }
59
60 fn subscribe_to_events(&self) -> Vec<BrancherEvent> {
61 vec![]
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use crate::basic_types::tests::TestRandom;
69
70 #[test]
71 fn test_correctly_selected() {
72 let (assignments, _) = SelectionContext::create_for_testing(vec![(0, 10), (10, 20)]);
73 let mut test_rng = TestRandom::default();
74 let mut context = SelectionContext::new(&assignments, &mut test_rng);
75 let integer_variables = context.get_domains().collect::<Vec<_>>();
76
77 let mut strategy = Occurrence::new(&integer_variables, &[2, 1]);
78 let selected = strategy.select_variable(&mut context);
79 assert!(selected.is_some());
80 assert_eq!(selected.unwrap(), integer_variables[0])
81 }
82
83 #[test]
84 fn fixed_variables_are_not_selected() {
85 let (assignments, _) = SelectionContext::create_for_testing(vec![(10, 10), (20, 20)]);
86 let mut test_rng = TestRandom::default();
87 let mut context = SelectionContext::new(&assignments, &mut test_rng);
88 let integer_variables = context.get_domains().collect::<Vec<_>>();
89
90 let mut strategy = Occurrence::new(&integer_variables, &[1, 2]);
91 let selected = strategy.select_variable(&mut context);
92 assert!(selected.is_none());
93 }
94}