problem_generator/problem/
configuration.rs1use structopt::StructOpt;
6use rand_chacha::ChaChaRng;
7use rand::SeedableRng;
8
9use std::{error::Error, path::Path};
10
11use super::{clique_tree::InputParameters, codomain_subclasses::CodomainFunction};
12
13#[derive(Debug, Clone)]
15pub struct ConfigurationParameters {
16 pub m_begin: u32,
17 pub m_end: u32,
18 pub k_begin: u32,
19 pub k_end: u32,
20 pub o_begin: u32,
21 pub o_end: u32,
22 pub b_begin: u32,
23 pub b_end: u32,
24 pub codomain_function: CodomainFunction,
25}
26
27impl ConfigurationParameters {
28 pub fn new(
29 m_begin: u32,
30 m_end: u32,
31 k_begin: u32,
32 k_end: u32,
33 o_begin: u32,
34 o_end: u32,
35 b_begin: u32,
36 b_end: u32,
37 codomain_function: CodomainFunction,
38 ) -> ConfigurationParameters {
39 ConfigurationParameters {
40 m_begin,
41 m_end,
42 k_begin,
43 k_end,
44 o_begin,
45 o_end,
46 b_begin,
47 b_end,
48 codomain_function,
49 }
50 }
51
52 pub fn from_file(input_file_path: &Path) -> Result<ConfigurationParameters, Box<dyn Error>> {
54 let contents = std::fs::read_to_string(&input_file_path)?;
55 let mut content_iterator = contents.lines();
56
57 let mut split_line = content_iterator.next().unwrap().split(' ');
58 let m_or_n = split_line.next().unwrap();
59 let m_or_n_begin: u32 = split_line.next().unwrap().parse()?;
61 let m_or_n_end: u32 = split_line.next().unwrap().parse()?;
62
63 let mut split_line = content_iterator.next().unwrap().split(' ').skip(1);
64 let k_begin: u32 = split_line.next().unwrap().parse()?;
65 let k_end: u32 = split_line.next().unwrap().parse()?;
66
67 let mut split_line = content_iterator.next().unwrap().split(' ').skip(1);
68 let o_begin: u32 = split_line.next().unwrap().parse()?;
69 let o_end: i32 = split_line.next().unwrap().trim().parse()?;
70 let o_end: u32 = o_end as u32;
71
72 let mut split_line = content_iterator.next().unwrap().split(' ').skip(1);
73 let b_begin: u32 = split_line.next().unwrap().parse()?;
74 let b_end: u32 = split_line.next().unwrap().parse()?;
75
76 let (m_begin, m_end) = if m_or_n == "M" {
77 (m_or_n_begin, m_or_n_end)
78 } else if m_or_n == "N" {
79 if k_end - k_begin > 1 || o_end - o_begin > 1 {
80 return Err("Can not use problem size in configuration when k and o are not one fixed value".into());
81 }
82 (
83 get_m_for_min_problem_size(m_or_n_begin, k_begin, o_begin),
84 get_m_for_max_problem_size(m_or_n_end, k_begin, o_begin),
85 )
86 } else {
87 return Err("First letter in configuration not recognized; not M or N".into());
88 };
89
90 let codomain_functions_split_line: Vec<&str> =
91 content_iterator.next().unwrap().split(',').collect();
92
93 assert_eq!(codomain_functions_split_line.len(), 1);
94
95 let codomain_function_string = String::from(codomain_functions_split_line[0]);
96 let mut iter_list = vec![" "];
97 iter_list.extend(codomain_function_string.split(' '));
98 let codomain_function = CodomainFunction::from_iter(iter_list);
99
100 Ok(ConfigurationParameters::new(
101 m_begin,
102 m_end,
103 k_begin,
104 k_end,
105 o_begin,
106 o_end,
107 b_begin,
108 b_end,
109 codomain_function,
110 ))
111 }
112}
113
114impl IntoIterator for ConfigurationParameters {
116 type Item = InputParameters;
117 type IntoIter = ConfigurationParametersIterator;
118
119 fn into_iter(self) -> Self::IntoIter {
120 ConfigurationParametersIterator::from_configuration_parameters(&self)
121 }
122}
123
124pub struct ConfigurationParametersIterator {
126 pub m_begin: u32,
127 pub m_end: u32,
128 pub k_begin: u32,
129 pub k_end: u32,
130 pub o_begin: u32,
131 pub o_end: u32,
132 pub b_begin: u32,
133 pub b_end: u32,
134 pub codomain_function: CodomainFunction,
135
136 pub current_parameters: InputParameters,
137}
138
139impl ConfigurationParametersIterator {
140 pub fn new(
141 m_begin: u32,
142 m_end: u32,
143 k_begin: u32,
144 k_end: u32,
145 o_begin: u32,
146 o_end: u32,
147 b_begin: u32,
148 b_end: u32,
149 codomain_function: CodomainFunction,
150 ) -> ConfigurationParametersIterator {
151 ConfigurationParametersIterator {
152 m_begin,
153 m_end,
154 k_begin,
155 k_end,
156 o_begin,
157 o_end,
158 b_begin,
159 b_end,
160 codomain_function,
161 current_parameters: InputParameters::new_from_primitives(0, 0, 0, 0),
162 }
163 }
164
165 pub fn from_configuration_parameters(
166 configuration_parameters: &ConfigurationParameters,
167 ) -> ConfigurationParametersIterator {
168 ConfigurationParametersIterator::new(
169 configuration_parameters.m_begin,
170 configuration_parameters.m_end,
171 configuration_parameters.k_begin,
172 configuration_parameters.k_end,
173 configuration_parameters.o_begin,
174 configuration_parameters.o_end,
175 configuration_parameters.b_begin,
176 configuration_parameters.b_end,
177 configuration_parameters.codomain_function.clone(),
178 )
179 }
180}
181
182impl Iterator for ConfigurationParametersIterator {
184 type Item = InputParameters;
185
186 fn next(&mut self) -> Option<Self::Item> {
187 if self.current_parameters.m == 0 {
188 self.current_parameters = InputParameters::new_from_primitives(
189 self.m_begin,
190 self.k_begin,
191 self.o_begin,
192 self.b_begin,
193 );
194 } else if self.current_parameters.b < self.b_end - 1 {
195 self.current_parameters.b += 1;
196 } else if self.current_parameters.o < self.o_end - 1 {
197 self.current_parameters.o += 1;
198 self.current_parameters.b = self.b_begin;
199 } else if self.current_parameters.k < self.k_end - 1 {
200 self.current_parameters.k += 1;
201 self.current_parameters.o = self.o_begin;
202 self.current_parameters.b = self.b_begin;
203 } else if self.current_parameters.m < self.m_end - 1 {
204 self.current_parameters.m += 1;
205 self.current_parameters.k = self.k_begin;
206 self.current_parameters.o = self.o_begin;
207 self.current_parameters.b = self.b_begin;
208 } else {
209 return None;
210 }
211 Some(self.current_parameters.clone())
212 }
213}
214
215fn get_m_for_min_problem_size(min_problem_size: u32, k: u32, o: u32) -> u32 {
217 let a = (min_problem_size as i32 + (k - o) as i32 - k as i32) as f32 / (k - o) as f32;
218 (a.ceil() as i32).max(1) as u32
219}
220
221fn get_m_for_max_problem_size(max_problem_size: u32, k: u32, o: u32) -> u32 {
223 let a = (max_problem_size + (k - o) - k) as f32 / (k - o) as f32;
224 (a.ceil() as u32).max(2)
225}
226
227pub fn get_rng(seed: Option<u64>) -> ChaChaRng {
228 match seed {
229 Some(seed) => ChaChaRng::seed_from_u64(seed),
230 None => ChaChaRng::from_entropy(),
231 }
232}