solverforge_solver/heuristic/selector/k_opt/
iterators.rs1use crate::heuristic::r#move::CutPoint;
4
5pub struct CutCombinationIterator {
7 k: usize,
8 len: usize,
9 min_seg: usize,
10 entity_idx: usize,
11 positions: Vec<usize>,
13 done: bool,
15}
16
17impl CutCombinationIterator {
18 pub fn new(k: usize, len: usize, min_seg: usize, entity_idx: usize) -> Self {
19 let min_len = (k + 1) * min_seg;
21
22 if len < min_len {
23 return Self {
24 k,
25 len,
26 min_seg,
27 entity_idx,
28 positions: vec![],
29 done: true,
30 };
31 }
32
33 let mut positions = Vec::with_capacity(k);
36 for i in 0..k {
37 positions.push(min_seg * (i + 1));
38 }
39
40 Self {
41 k,
42 len,
43 min_seg,
44 entity_idx,
45 positions,
46 done: false,
47 }
48 }
49
50 fn advance(&mut self) -> bool {
51 if self.done || self.positions.is_empty() {
52 return false;
53 }
54
55 let k = self.k;
57 let len = self.len;
58 let min_seg = self.min_seg;
59
60 for i in (0..k).rev() {
61 let max_pos = len - min_seg * (k - i);
65
66 if self.positions[i] < max_pos {
67 self.positions[i] += 1;
68 for j in (i + 1)..k {
70 self.positions[j] = self.positions[j - 1] + min_seg;
71 }
72 return true;
73 }
74 }
75
76 self.done = true;
77 false
78 }
79}
80
81impl Iterator for CutCombinationIterator {
82 type Item = Vec<CutPoint>;
83
84 fn next(&mut self) -> Option<Self::Item> {
85 if self.done {
86 return None;
87 }
88
89 let cuts: Vec<CutPoint> = self
90 .positions
91 .iter()
92 .map(|&pos| CutPoint::new(self.entity_idx, pos))
93 .collect();
94
95 self.advance();
96
97 Some(cuts)
98 }
99}
100
101pub fn count_cut_combinations(k: usize, len: usize, min_seg: usize) -> usize {
103 let min_len = (k + 1) * min_seg;
106 if len < min_len {
107 return 0;
108 }
109
110 let free_slots = len - min_len + k;
111 binomial(free_slots, k)
112}
113
114pub fn binomial(n: usize, k: usize) -> usize {
116 if k > n {
117 return 0;
118 }
119 if k == 0 || k == n {
120 return 1;
121 }
122
123 let k = k.min(n - k); let mut result = 1;
125 for i in 0..k {
126 result = result * (n - i) / (i + 1);
127 }
128 result
129}