1use std::cmp;
21use std::fmt;
22use std::fs::File;
23use std::io::{BufRead, BufReader, BufWriter, Write};
24
25#[cfg(test)]
26use rand::rngs::StdRng;
27#[cfg(test)]
28use rand::Rng;
29
30use serde::{Deserialize, Serialize};
31
32use crate::constants::NodeId;
33use crate::constants::Weight;
34
35#[derive(Serialize, Deserialize, Clone)]
36pub struct InputGraph {
37 edges: Vec<Edge>,
38 num_nodes: usize,
39 frozen: bool,
40}
41
42impl InputGraph {
43 pub fn new() -> Self {
44 InputGraph {
45 edges: Vec::new(),
46 num_nodes: 0,
47 frozen: false,
48 }
49 }
50
51 #[cfg(test)]
53 pub fn random(rng: &mut StdRng, num_nodes: usize, mean_degree: f32) -> Self {
54 InputGraph::build_random_graph(rng, num_nodes, mean_degree)
55 }
56
57 pub fn from_file(filename: &str) -> Self {
65 InputGraph::read_from_file(filename)
66 }
67
68 pub fn to_file(&self, filename: &str) -> Result<(), std::io::Error> {
72 let mut f = BufWriter::new(File::create(filename)?);
73 for edge in self.get_edges() {
74 writeln!(f, "a {} {} {}", edge.from, edge.to, edge.weight)?;
75 }
76 Ok(())
77 }
78
79 pub fn from_dimacs_file(filename: &str) -> Self {
95 InputGraph::read_from_dimacs(filename)
96 }
97
98 pub fn to_dimacs_file(&self, filename: &str) -> Result<(), std::io::Error> {
105 let mut f = BufWriter::new(File::create(filename)?);
106 writeln!(f, "p sp {} {}", self.get_num_nodes(), self.get_num_edges())?;
107 for edge in self.get_edges() {
108 writeln!(f, "a {} {} {}", edge.from + 1, edge.to + 1, edge.weight)?;
109 }
110 Ok(())
111 }
112
113 pub fn add_edge(&mut self, from: NodeId, to: NodeId, weight: Weight) -> usize {
114 self.do_add_edge(from, to, weight, false)
115 }
116
117 pub fn add_edge_bidir(&mut self, from: NodeId, to: NodeId, weight: Weight) -> usize {
118 self.do_add_edge(from, to, weight, true)
119 }
120
121 pub fn get_edges(&self) -> &Vec<Edge> {
122 self.check_frozen();
123 &self.edges
124 }
125
126 pub fn get_num_nodes(&self) -> usize {
127 self.check_frozen();
128 self.num_nodes
129 }
130
131 pub fn get_num_edges(&self) -> usize {
132 self.check_frozen();
133 self.edges.len()
134 }
135
136 pub fn freeze(&mut self) {
137 if self.frozen {
138 panic!("Input graph is already frozen");
139 }
140 self.sort();
141 self.remove_duplicate_edges();
142 self.frozen = true;
143 }
144
145 pub fn thaw(&mut self) {
146 self.frozen = false;
147 }
148
149 fn sort(&mut self) {
150 self.edges.sort_unstable_by(|a, b| {
151 a.from
152 .cmp(&b.from)
153 .then(a.to.cmp(&b.to))
154 .then(a.weight.cmp(&&b.weight))
155 });
156 }
157
158 fn remove_duplicate_edges(&mut self) {
159 let len_before = self.edges.len();
161 self.edges.dedup_by(|a, b| a.from == b.from && a.to == b.to);
162 if len_before != self.edges.len() {
163 warn!(
164 "There were {} duplicate edges, only the ones with lowest weight were kept",
165 len_before - self.edges.len()
166 );
167 }
168 }
169
170 pub fn unit_test_output_string(&self) -> String {
171 return self
172 .edges
173 .iter()
174 .map(|e| e.unit_test_output_string())
175 .collect::<Vec<String>>()
176 .join("\n")
177 + "\n";
178 }
179
180 fn check_frozen(&self) {
181 if !self.frozen {
182 panic!("You need to call freeze() before using the input graph")
183 }
184 }
185
186 fn do_add_edge(&mut self, from: NodeId, to: NodeId, weight: Weight, bidir: bool) -> usize {
187 if self.frozen {
188 panic!("Graph is frozen already, for further changes first use thaw()");
189 }
190 if from == to {
191 warn!(
192 "Loop edges are not allowed. Skipped edge! from: {}, to: {}, weight: {}",
193 from, to, weight
194 );
195 return 0;
196 }
197 if weight < 1 {
198 warn!(
199 "Zero weight edges are not allowed. Skipped edge! from: {}, to: {}, weight: {}",
200 from, to, weight
201 );
202 return 0;
203 }
204 self.num_nodes = cmp::max(self.num_nodes, cmp::max(from, to) + 1);
205 self.edges.push(Edge::new(from, to, weight));
206 if bidir {
207 self.edges.push(Edge::new(to, from, weight));
208 }
209 if bidir {
210 2
211 } else {
212 1
213 }
214 }
215
216 #[cfg(test)]
217 fn build_random_graph(rng: &mut StdRng, num_nodes: usize, mean_degree: f32) -> InputGraph {
218 let num_edges = (mean_degree * num_nodes as f32) as usize;
219 let mut result = InputGraph::new();
220 let mut edge_count = 0;
221 loop {
222 let head = rng.gen_range(0, num_nodes);
223 let tail = rng.gen_range(0, num_nodes);
224 let weight = rng.gen_range(1, 100);
227 edge_count += result.add_edge(tail, head, weight);
228 if edge_count == num_edges {
229 break;
230 }
231 }
232 result.freeze();
233 result
234 }
235
236 fn read_from_file(filename: &str) -> Self {
237 let file = File::open(filename).unwrap();
238 let reader = BufReader::new(file);
239 let mut g = InputGraph::new();
240 for (index, line) in reader.lines().enumerate() {
241 let s: String = line.unwrap();
242 if s.starts_with("a ") {
243 let (from, to, weight) = InputGraph::read_arc_line(index, &s);
244 g.add_edge(from, to, weight);
245 } else {
246 continue;
247 }
248 }
249 g.freeze();
250 g
251 }
252
253 fn read_from_dimacs(filename: &str) -> Self {
254 let file = File::open(filename).unwrap();
255 let reader = BufReader::new(file);
256 let mut g = InputGraph::new();
257 let mut nodes = 0;
258 let mut edges = 0;
259 let mut curr_edges = 0;
260 let mut found_problem_line = false;
261 for (index, line) in reader.lines().enumerate() {
262 let s: String = line.unwrap();
263 if s.is_empty() || s.starts_with("c") {
264 continue;
265 } else if s.starts_with("p sp ") {
266 if found_problem_line {
267 panic!(
268 "There should be only one problem line, but found: {} | {}",
269 index + 1,
270 s
271 );
272 }
273 let mut split = s[5..].split_whitespace();
274 nodes = split.next().unwrap().parse::<usize>().unwrap();
275 edges = split.next().unwrap().parse::<usize>().unwrap();
276 assert!(split.next().is_none(), "Invalid problem line: {}", s);
277 found_problem_line = true;
278 } else if s.starts_with("a ") {
279 assert!(
280 found_problem_line,
281 "The problem line must be written before the arc lines"
282 );
283 let (from, to, weight) = InputGraph::read_arc_line(index, &s);
284 assert!(
285 from <= nodes && to <= nodes,
286 "Invalid nodes in line: {} | {}",
287 index + 1,
288 s
289 );
290 assert!(
291 curr_edges < edges,
292 "Too many arc lines: {}, expected: {}",
293 curr_edges + 1,
294 edges
295 );
296
297 assert!(
298 from > 0 && to > 0,
299 "Invalid arc line: {} | {}",
300 index + 1,
301 s
302 );
303 g.add_edge(from - 1, to - 1, weight);
305 curr_edges += 1;
306 } else {
307 panic!(
308 "Invalid line: {} {}\nAll non-empty lines must start with 'c', 'p' or 'a'",
309 index, s
310 );
311 }
312 }
313 assert_eq!(
314 curr_edges, edges,
315 "Not enough arc lines: {}, expected: {}",
316 curr_edges, edges
317 );
318 g.freeze();
319 g
320 }
321
322 fn read_arc_line(index: usize, line: &String) -> (usize, usize, usize) {
323 let mut split = line[2..].split_whitespace();
324 let from = split.next().unwrap().parse::<usize>().unwrap();
325 let to = split.next().unwrap().parse::<usize>().unwrap();
326 let weight = split.next().unwrap().parse::<usize>().unwrap();
327 assert!(
328 split.next().is_none(),
329 "Invalid arc line: {} | {}",
330 index + 1,
331 line
332 );
333 (from, to, weight)
334 }
335}
336
337impl fmt::Debug for InputGraph {
338 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
339 write!(f, "{}", self.unit_test_output_string())
340 }
341}
342
343impl Default for InputGraph {
344 fn default() -> Self {
345 Self::new()
346 }
347}
348
349#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
350pub struct Edge {
351 pub from: NodeId,
352 pub to: NodeId,
353 pub weight: Weight,
354}
355
356impl Edge {
357 pub fn new(from: NodeId, to: NodeId, weight: Weight) -> Edge {
358 Edge { from, to, weight }
359 }
360
361 pub fn unit_test_output_string(&self) -> String {
362 return format!("g.add_edge({}, {}, {});", self.from, self.to, self.weight);
363 }
364}
365
366#[cfg(test)]
367mod tests {
368 use super::*;
369
370 #[test]
371 #[should_panic]
372 fn panic_if_not_frozen_get_edges() {
373 let mut g = InputGraph::new();
374 g.add_edge(0, 1, 3);
375 g.get_edges();
376 }
377
378 #[test]
379 #[should_panic]
380 fn panic_if_not_frozen_get_num_edges() {
381 let mut g = InputGraph::new();
382 g.add_edge(0, 1, 3);
383 g.get_num_edges();
384 }
385
386 #[test]
387 #[should_panic]
388 fn panic_if_not_frozen_get_num_nodes() {
389 let mut g = InputGraph::new();
390 g.add_edge(0, 1, 3);
391 g.get_num_nodes();
392 }
393
394 #[test]
395 #[should_panic]
396 fn panic_if_frozen_add_edge() {
397 let mut g = InputGraph::new();
398 g.add_edge(0, 1, 3);
399 g.freeze();
400 g.add_edge(2, 5, 4);
401 }
402
403 #[test]
404 fn freeze_and_thaw() {
405 let mut g = InputGraph::new();
406 g.add_edge(0, 5, 10);
407 g.add_edge(0, 5, 5);
408 g.freeze();
409 assert_eq!(1, g.get_num_edges());
410 g.thaw();
411 g.add_edge(0, 5, 1);
412 g.freeze();
413 assert_eq!(1, g.get_num_edges());
414 assert_eq!(1, g.get_edges()[0].weight);
415 }
416
417 #[test]
418 fn num_nodes() {
419 let mut g = InputGraph::new();
420 g.add_edge(7, 1, 2);
421 g.add_edge(5, 6, 4);
422 g.add_edge(11, 8, 3);
423 g.freeze();
424 assert_eq!(12, g.get_num_nodes());
425 }
426
427 #[test]
428 fn skips_loops() {
429 let mut g = InputGraph::new();
430 g.add_edge(0, 1, 3);
431 g.add_edge(4, 4, 2);
432 g.add_edge(2, 5, 4);
433 g.freeze();
434 assert_eq!(2, g.get_num_edges());
435 }
436
437 #[test]
438 fn skips_zero_weight_edges() {
439 let mut g = InputGraph::new();
440 g.add_edge(0, 1, 5);
441 g.add_edge(1, 2, 0);
442 g.add_edge(2, 3, 3);
443 g.freeze();
444 assert_eq!(2, g.get_num_edges());
445 }
446
447 #[test]
448 fn skips_duplicate_edges() {
449 let mut g = InputGraph::new();
450 g.add_edge(0, 1, 7);
451 g.add_edge(2, 3, 5);
452 g.add_edge(0, 2, 3);
453 g.add_edge(0, 1, 2);
454 g.add_edge(4, 6, 9);
455 g.add_edge(0, 1, 4);
456 g.freeze();
457 assert_eq!(4, g.get_num_edges());
458 let weights = g
461 .get_edges()
462 .iter()
463 .map(|e| e.weight)
464 .collect::<Vec<Weight>>();
465 assert_eq!(vec![2, 3, 5, 9], weights);
466 }
467
468 #[test]
469 fn skips_duplicate_edges_more() {
470 let mut g = InputGraph::new();
471 g.add_edge(1, 3, 43);
472 g.add_edge(3, 2, 90);
473 g.add_edge(3, 2, 88);
474 g.add_edge(2, 3, 87);
475 g.add_edge(3, 0, 75);
476 g.add_edge(0, 2, 45);
477 g.add_edge(1, 3, 71);
478 g.add_edge(4, 3, 5);
479 g.add_edge(1, 3, 91);
480 g.freeze();
481 assert_eq!(6, g.get_num_edges());
482 let weights = g
483 .get_edges()
484 .iter()
485 .map(|e| e.weight)
486 .collect::<Vec<Weight>>();
487 assert_eq!(vec![45, 43, 87, 75, 88, 5], weights);
488 }
489}