1use crate::constraint::VarId;
4use crate::domain::Domain;
5use crate::variable::Variable;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum Ordering {
10 Chronological,
12 FailFirst,
14 Mrv,
18}
19
20pub fn select_variable<D: Domain>(
24 stack: &[VarId],
25 variables: &[Variable<D>],
26 ordering: Ordering,
27 constraint_weights: &[f64],
28 var_constraint_ids: &[Vec<usize>],
29) -> Option<usize> {
30 if stack.is_empty() {
31 return None;
32 }
33
34 match ordering {
35 Ordering::Chronological => Some(stack.len() - 1),
36
37 Ordering::FailFirst => {
38 let mut best_idx = 0;
39 let mut best_size = usize::MAX;
40 for (i, &var) in stack.iter().enumerate() {
41 let sz = variables[var as usize].domain.size();
42 if sz < best_size {
43 best_size = sz;
44 best_idx = i;
45 }
46 }
47 Some(best_idx)
48 }
49
50 Ordering::Mrv => {
52 let mut best_idx = 0;
53 let mut best_score = f64::MAX;
54 for (i, &var) in stack.iter().enumerate() {
55 let dom_size = variables[var as usize].domain.size() as f64;
56 let wdeg: f64 = var_constraint_ids[var as usize]
57 .iter()
58 .map(|&cid| constraint_weights[cid])
59 .sum();
60 let score = dom_size / wdeg.max(1e-9);
61 if score < best_score {
62 best_score = score;
63 best_idx = i;
64 }
65 }
66 Some(best_idx)
67 }
68 }
69}