From 3fc48134aedd1cac36af4297ba7dbf091bdc24fa Mon Sep 17 00:00:00 2001 From: Alex Nathanail Date: Sun, 12 Mar 2023 04:09:36 +0000 Subject: [PATCH 1/3] Make import functions return Result --- benches/benchmarks.rs | 10 ++-- src/graphs/algorithms/shortest_path.rs | 2 +- src/graphs/input/pbf.rs | 32 +++++++---- src/graphs/input/tsplib.rs | 74 +++++++++++++++----------- src/main.rs | 18 ++++--- 5 files changed, 81 insertions(+), 55 deletions(-) diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs index 8ef8d62..3ffd93b 100644 --- a/benches/benchmarks.rs +++ b/benches/benchmarks.rs @@ -24,7 +24,7 @@ fn shortest_path_benchmark(c: &mut Criterion) { }, ); - let dimacs_g = load_tsplib_file("test_data/dimacs_tsp/d1291.tsp", usize::MAX); + let dimacs_g = load_tsplib_file("test_data/dimacs_tsp/d1291.tsp", usize::MAX).unwrap(); group.bench_with_input( BenchmarkId::new("DIMCAS d1291", &dimacs_g), &dimacs_g, @@ -36,7 +36,7 @@ fn shortest_path_benchmark(c: &mut Criterion) { }, ); - let monaco_g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf"); + let monaco_g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf").unwrap(); let mut monaco_cc = ConnectedComponents::new(&monaco_g); monaco_cc.run(); let monaco_largest_g = monaco_cc.get_largest_connected_subgraphs(); @@ -73,14 +73,14 @@ fn shortest_path_benchmark(c: &mut Criterion) { fn travelling_salesman_benchmark(c: &mut Criterion) { let mut group = c.benchmark_group("Travelling salesman"); - let dimacs_g = load_tsplib_file("test_data/dimacs_tsp/d1291.tsp", usize::MAX); + let dimacs_g = load_tsplib_file("test_data/dimacs_tsp/d1291.tsp", usize::MAX).unwrap(); group.bench_with_input( BenchmarkId::new("DIMCAS d1291", &dimacs_g), &dimacs_g, |b, g| b.iter(|| travelling_salesman(g, false)), ); - let monaco_g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf"); + let monaco_g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf").unwrap(); let mut monaco_cc = ConnectedComponents::new(&monaco_g); monaco_cc.run(); @@ -102,7 +102,7 @@ fn travelling_salesman_benchmark(c: &mut Criterion) { } fn connected_components_benchmark(c: &mut Criterion) { - let g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf"); + let g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf").unwrap(); let mut group = c.benchmark_group("Connected components"); diff --git a/src/graphs/algorithms/shortest_path.rs b/src/graphs/algorithms/shortest_path.rs index b7208a4..a5fec92 100644 --- a/src/graphs/algorithms/shortest_path.rs +++ b/src/graphs/algorithms/shortest_path.rs @@ -1,4 +1,4 @@ -use super::super::super::algorithms::PriorityQueue; +use crate::algorithms::PriorityQueue; use crate::graphs::datastructures::GraphPath; use crate::graphs::datastructures::{Digraph, NodeIndex}; diff --git a/src/graphs/input/pbf.rs b/src/graphs/input/pbf.rs index 35be59d..7d0173a 100644 --- a/src/graphs/input/pbf.rs +++ b/src/graphs/input/pbf.rs @@ -3,8 +3,21 @@ use crate::graphs::datastructures::{ALDigraph, LatLng}; use crate::graphs::datastructures::{Digraph, NodeID}; use osmpbf::{Element, ElementReader}; -pub fn load_pbf_file(pbf_path: &str) -> ALDigraph { - let reader = ElementReader::from_path(pbf_path).unwrap(); +#[derive(Debug)] +pub enum PBFImportError { + OSMPBFError(osmpbf::Error), +} + +impl From for PBFImportError { + fn from(err: osmpbf::Error) -> PBFImportError { + PBFImportError::OSMPBFError(err) + } +} + +type Result = std::result::Result; + +pub fn load_pbf_file(pbf_path: &str) -> Result { + let reader = ElementReader::from_path(pbf_path)?; let num_nodes = reader .par_map_reduce( @@ -15,8 +28,7 @@ pub fn load_pbf_file(pbf_path: &str) -> ALDigraph { }, || 0_u64, // Zero is the identity value for addition |a, b| a + b, // Sum the partial results - ) - .unwrap(); + )?; println!("Number of nodes: {num_nodes}"); @@ -24,7 +36,7 @@ pub fn load_pbf_file(pbf_path: &str) -> ALDigraph { println!("Graph initialised"); - let reader = ElementReader::from_path(pbf_path).unwrap(); + let reader = ElementReader::from_path(pbf_path)?; reader .for_each(|element| { @@ -45,14 +57,13 @@ pub fn load_pbf_file(pbf_path: &str) -> ALDigraph { }, ) } - }) - .unwrap(); + })?; println!("Nodes added"); let mut ways = 0_u64; - let reader = ElementReader::from_path(pbf_path).unwrap(); + let reader = ElementReader::from_path(pbf_path)?; reader .for_each(|element| { @@ -74,10 +85,9 @@ pub fn load_pbf_file(pbf_path: &str) -> ALDigraph { } ways += 1; } - }) - .unwrap(); + })?; println!("Edges added"); - g + Ok(g) } diff --git a/src/graphs/input/tsplib.rs b/src/graphs/input/tsplib.rs index 408d4b5..e74e117 100644 --- a/src/graphs/input/tsplib.rs +++ b/src/graphs/input/tsplib.rs @@ -3,42 +3,30 @@ use rand::{thread_rng, Rng}; use std::{cmp, fs, io::Cursor}; use tsplib::NodeCoord; -pub fn generate_random_tsplib_file(num_nodes: usize) -> String { - let mut rng = thread_rng(); - - let mut lines: Vec = Vec::with_capacity(num_nodes); - - lines.push("NAME : example".to_string()); - lines.push("TYPE : TSP".to_string()); - lines.push(format!("DIMENSION : {}", num_nodes + 1)); - lines.push("EDGE_WEIGHT_TYPE: EUC_2D".to_string()); - lines.push("NODE_COORD_SECTION".to_string()); +#[derive(Debug)] +pub enum TSPLIBImportError { + IOError(std::io::Error), + OtherError(String), +} - let grid_size = num_nodes * 10; - for i in 0..num_nodes { - lines.push(format!( - "{} {} {}", - i, - rng.gen::() * (grid_size as f32), - rng.gen::() * (grid_size as f32) - )) +impl From for TSPLIBImportError { + fn from(err: std::io::Error) -> TSPLIBImportError { + TSPLIBImportError::IOError(err) } - - lines.push("EOF".to_string()); - - lines.join("\n") } -pub fn load_tsplib_file(file_path: &str, num_nodes: usize) -> AMDigraph { - let tsp_string = fs::read_to_string(file_path).unwrap(); - let instance = tsplib::parse(Cursor::new(&tsp_string[..])).unwrap(); +type Result = std::result::Result; + +pub fn load_tsplib_file(file_path: &str, num_nodes: usize) -> Result { + let tsp_string = fs::read_to_string(file_path)?; + let instance = tsplib::parse(Cursor::new(&tsp_string[..]))?; let actual_num_nodes = cmp::min(num_nodes, instance.dimension); - let coords = match instance.node_coord.unwrap() { - NodeCoord::Two(x) => x, - _ => panic!("Wrong format"), - }; + let coords = match instance.node_coord.ok_or(TSPLIBImportError::OtherError("No node coords found".to_string()))? { + NodeCoord::Two(x) => Ok(x), + _ => Err(TSPLIBImportError::OtherError("No node coords found".to_string())), + }?; let mut g = AMDigraph::new(actual_num_nodes); @@ -64,5 +52,31 @@ pub fn load_tsplib_file(file_path: &str, num_nodes: usize) -> AMDigraph { } } - g + Ok(g) +} + +pub fn generate_random_tsplib_file(num_nodes: usize) -> String { + let mut rng = thread_rng(); + + let mut lines: Vec = Vec::with_capacity(num_nodes); + + lines.push("NAME : example".to_string()); + lines.push("TYPE : TSP".to_string()); + lines.push(format!("DIMENSION : {}", num_nodes + 1)); + lines.push("EDGE_WEIGHT_TYPE: EUC_2D".to_string()); + lines.push("NODE_COORD_SECTION".to_string()); + + let grid_size = num_nodes * 10; + for i in 0..num_nodes { + lines.push(format!( + "{} {} {}", + i, + rng.gen::() * (grid_size as f32), + rng.gen::() * (grid_size as f32) + )) + } + + lines.push("EOF".to_string()); + + lines.join("\n") } diff --git a/src/main.rs b/src/main.rs index d85b1df..38dec48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,19 @@ #[macro_use] extern crate rocket; +use std::ops::Deref; +use std::sync::{Arc, RwLock}; + +use rocket::fairing::{Fairing, Info, Kind}; +use rocket::http::Header; +use rocket::serde::{Deserialize, Serialize}; +use rocket::serde::json::Json; + use broute::graphs::algorithms::{ - form_abstracted_graph, travelling_salesman, ConnectedComponents, Dijkstra, + ConnectedComponents, Dijkstra, form_abstracted_graph, travelling_salesman, }; use broute::graphs::datastructures::{ALDigraph, Digraph, LatLng, NodeID}; use broute::graphs::input::load_pbf_file; -use rocket::fairing::{Fairing, Info, Kind}; -use rocket::http::Header; -use rocket::serde::json::Json; -use rocket::serde::{Deserialize, Serialize}; -use std::ops::Deref; -use std::sync::{Arc, RwLock}; #[cfg(test)] mod tests; @@ -170,7 +172,7 @@ impl Fairing for CORS { } async fn get_graph() -> ALDigraph { - let g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf"); + let g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf").unwrap(); println!("Original graph {:} nodes", g.num_vertices()); From c72f24d88600bd8f0ffa521d86347602e6fcd6e4 Mon Sep 17 00:00:00 2001 From: Alex Nathanail Date: Sun, 12 Mar 2023 04:25:06 +0000 Subject: [PATCH 2/3] Make simulated annealing use a struct Closes #88 --- benches/benchmarks.rs | 12 +- src/graphs/algorithms/travelling_salesman.rs | 144 ++++++++++--------- src/main.rs | 9 +- tests/graphs/shortest_path_tests.rs | 2 +- tests/graphs/travelling_salesman_tests.rs | 9 +- 5 files changed, 98 insertions(+), 78 deletions(-) diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs index 3ffd93b..96e655e 100644 --- a/benches/benchmarks.rs +++ b/benches/benchmarks.rs @@ -1,7 +1,7 @@ use std::time::Duration; use broute::graphs::algorithms::{ - form_abstracted_graph, travelling_salesman, ConnectedComponents, Dijkstra, + form_abstracted_graph, SimulatedAnnealing, ConnectedComponents, Dijkstra, }; use broute::graphs::datastructures::{Digraph, NodeIndex}; use broute::graphs::input::{get_random_graph, load_pbf_file, load_tsplib_file, load_xgmml_file}; @@ -77,7 +77,10 @@ fn travelling_salesman_benchmark(c: &mut Criterion) { group.bench_with_input( BenchmarkId::new("DIMCAS d1291", &dimacs_g), &dimacs_g, - |b, g| b.iter(|| travelling_salesman(g, false)), + |b, g| b.iter(|| { + let mut sa = SimulatedAnnealing::new(g); + sa.run(); + }), ); let monaco_g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf").unwrap(); @@ -95,7 +98,10 @@ fn travelling_salesman_benchmark(c: &mut Criterion) { group.bench_with_input( BenchmarkId::new("OSM Monaco - 5 random nodes", &abstracted_graph), &abstracted_graph, - |b, g| b.iter(|| travelling_salesman(g, false)), + |b, g| b.iter(|| { + let mut sa = SimulatedAnnealing::new(g); + sa.run(); + }), ); group.finish(); diff --git a/src/graphs/algorithms/travelling_salesman.rs b/src/graphs/algorithms/travelling_salesman.rs index ac71c03..9be323b 100644 --- a/src/graphs/algorithms/travelling_salesman.rs +++ b/src/graphs/algorithms/travelling_salesman.rs @@ -34,97 +34,109 @@ pub fn form_abstracted_graph(g: &dyn Digraph, node_ids: &Vec) -> AMDigra abstracted_graph } -fn get_potential_new_path( - rng: &mut ThreadRng, - g: &dyn Digraph, - current_path: &GraphPath, -) -> GraphPath { - let mut potential_new_path = current_path.clone(); - - let node_index_to_mutate = rng.gen_range(0..(g.num_vertices() - 1)); +pub struct SimulatedAnnealing<'a> { + g: &'a dyn Digraph, + result_data: Vec<(f64, f64)>, + current_path: GraphPath, + path_length: f64, + best_path: GraphPath, + rng: ThreadRng, +} - let reverse_or_transport: bool = rng.gen(); +impl<'a> SimulatedAnnealing<'a> { + pub fn new(g: &'a dyn Digraph) -> Self { + let mut rng = thread_rng(); - if reverse_or_transport { - let node_index_to_swap_with = if node_index_to_mutate < (g.num_vertices() - 1) { - node_index_to_mutate + 1 - } else { - 0 + let mut current_path = GraphPath { + path: (0..g.num_vertices()).map(NodeIndex).collect(), }; - potential_new_path - .path - .swap(node_index_to_mutate, node_index_to_swap_with); - } else { - // Cyclic permutation - let node_to_move = potential_new_path.path[node_index_to_mutate]; - // -2 because we are looking for new position with 1 node missing - let new_node_position = rng.gen_range(0..(g.num_vertices() - 2)); - potential_new_path.path.remove(node_index_to_mutate); - potential_new_path - .path - .insert(new_node_position, node_to_move) + current_path.path.shuffle(&mut rng); + + let path_length = current_path.get_length_on_graph(g); + + let best_path = current_path.clone(); + SimulatedAnnealing { + g, + result_data: vec![], + current_path, + path_length, + best_path, + rng, + } } - potential_new_path -} - -pub fn travelling_salesman(g: &dyn Digraph, output_graph: bool) -> GraphPath { - let mut result_data: Vec<(f64, f64)> = vec![]; - - let mut rng = thread_rng(); + pub fn run(&mut self) { + let mut temp = f64::sqrt(self.g.num_vertices() as f64); + let mut iterations = 0; + while temp > 1e-8_f64 && iterations < (100 * self.g.num_vertices()) { + let potential_new_path = self.get_potential_new_path(); + + let new_path_length = potential_new_path.get_length_on_graph(self.g); + if new_path_length < self.path_length { + self.current_path = potential_new_path; + self.best_path.clone_from(&self.current_path); + self.path_length = new_path_length; + } else { + // TODO: Is this between 0 and 1? + if f64::exp(-f64::abs(new_path_length - self.path_length) / temp) > self.rng.gen::() { + self.current_path = potential_new_path; + self.path_length = new_path_length; + } + } - let mut current_path = GraphPath { - path: (0..g.num_vertices()).map(NodeIndex).collect(), - }; - current_path.path.shuffle(&mut rng); - let mut path_length = current_path.get_length_on_graph(g); + temp *= 0.995; + iterations += 1; + self.result_data.push((temp, self.path_length)); + } + } - let mut best_path = current_path.clone(); + fn get_potential_new_path(&mut self) -> GraphPath { + let mut potential_new_path = self.current_path.clone(); - // println!("Initial state"); - // - // println!("\t{:?}", best_path.path); - // println!("\t{}", path_length); + let node_index_to_mutate = self.rng.gen_range(0..(self.g.num_vertices() - 1)); - let mut temp = f64::sqrt(g.num_vertices() as f64); - let mut iterations = 0; - while temp > 1e-8_f64 && iterations < (100 * g.num_vertices()) { - // println!("{}", temp); - let potential_new_path = get_potential_new_path(&mut rng, g, ¤t_path); + let reverse_or_transport: bool = self.rng.gen(); - let new_path_length = potential_new_path.get_length_on_graph(g); - if new_path_length < path_length { - current_path = potential_new_path; - best_path.clone_from(¤t_path); - path_length = new_path_length; + if reverse_or_transport { + let node_index_to_swap_with = if node_index_to_mutate < (self.g.num_vertices() - 1) { + node_index_to_mutate + 1 + } else { + 0 + }; + potential_new_path + .path + .swap(node_index_to_mutate, node_index_to_swap_with); } else { - // TODO: Is this between 0 and 1? - if f64::exp(-f64::abs(new_path_length - path_length) / temp) > rng.gen::() { - current_path = potential_new_path; - path_length = new_path_length; - } + // Cyclic permutation + let node_to_move = potential_new_path.path[node_index_to_mutate]; + // -2 because we are looking for new position with 1 node missing + let new_node_position = self.rng.gen_range(0..(self.g.num_vertices() - 2)); + potential_new_path.path.remove(node_index_to_mutate); + potential_new_path + .path + .insert(new_node_position, node_to_move) } - temp *= 0.995; - iterations += 1; - result_data.push((temp, path_length)); + potential_new_path + } + + pub fn get_best_path(&self) -> &GraphPath { + &self.best_path } - if output_graph { + pub fn output_graph(&self) { // We create our scatter plot from the data let s1: Plot = - Plot::new(result_data.clone()).line_style(LineStyle::new().colour("#DD3355")); + Plot::new(self.result_data.clone()).line_style(LineStyle::new().colour("#DD3355")); // The 'view' describes what set of data is drawn let v = ContinuousView::new() .add(s1) .x_label("Temperature") .y_label("Path length") - .y_range(0.0, result_data[0].1 + 100.0); + .y_range(0.0, self.result_data[0].1 + 100.0); // A page with a single view is then saved to an SVG file Page::single(&v).save("out/tsp_test_1.svg").unwrap(); } - - best_path } diff --git a/src/main.rs b/src/main.rs index 38dec48..f97617b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ use rocket::serde::{Deserialize, Serialize}; use rocket::serde::json::Json; use broute::graphs::algorithms::{ - ConnectedComponents, Dijkstra, form_abstracted_graph, travelling_salesman, + ConnectedComponents, Dijkstra, form_abstracted_graph, SimulatedAnnealing, }; use broute::graphs::datastructures::{ALDigraph, Digraph, LatLng, NodeID}; use broute::graphs::input::load_pbf_file; @@ -109,16 +109,17 @@ fn route_optimisation( println!("Abstracted graph constructed"); - let p = travelling_salesman(&abstracted_graph, false); + let mut sa = SimulatedAnnealing::new(&abstracted_graph); + sa.run(); println!("TSP ran"); let mut p_node_ids = vec![]; - for p_node_index in p.path { + for p_node_index in &sa.get_best_path().path { p_node_ids.push( abstracted_graph .nodes_data() - .get_node_id_by_index(&p_node_index), + .get_node_id_by_index(p_node_index), ) } diff --git a/tests/graphs/shortest_path_tests.rs b/tests/graphs/shortest_path_tests.rs index 61f0ce6..5a0254a 100644 --- a/tests/graphs/shortest_path_tests.rs +++ b/tests/graphs/shortest_path_tests.rs @@ -46,7 +46,7 @@ fn simple_dijkstra_test() { #[test] fn osm_dijkstra_test() { // Load graph - let g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf"); + let g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf").unwrap(); // Get largest connected subgraph let mut cc = ConnectedComponents::new(&g); cc.run(); diff --git a/tests/graphs/travelling_salesman_tests.rs b/tests/graphs/travelling_salesman_tests.rs index da315b4..c630c53 100644 --- a/tests/graphs/travelling_salesman_tests.rs +++ b/tests/graphs/travelling_salesman_tests.rs @@ -1,4 +1,4 @@ -use broute::graphs::algorithms::{form_abstracted_graph, travelling_salesman, ConnectedComponents}; +use broute::graphs::algorithms::{form_abstracted_graph, SimulatedAnnealing, ConnectedComponents}; use broute::graphs::datastructures::{Digraph, LatLng, NodeID, NodeIndex}; use broute::graphs::input::load_pbf_file; @@ -19,7 +19,7 @@ fn check_graph_adjacency( #[test] fn dijkstra_travelling_salesman_integration_test() { // Load graph - let g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf"); + let g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf").unwrap(); // Get largest connected subgraph let mut cc = ConnectedComponents::new(&g); @@ -130,8 +130,9 @@ fn dijkstra_travelling_salesman_integration_test() { // Run TSP let mut path_lengths: Vec = vec![]; for _ in 0..100 { - let best_path = travelling_salesman(&abstracted_graph, false); - path_lengths.push(best_path.get_length_on_graph(&abstracted_graph)); + let mut sa = SimulatedAnnealing::new(&abstracted_graph); + sa.run(); + path_lengths.push(sa.get_best_path().get_length_on_graph(&abstracted_graph)); } assert!((path_lengths.into_iter().sum::() / 100.0) < 8.0); From c8d3d084e84181a7e31f71d85c56ddee0b8992a3 Mon Sep 17 00:00:00 2001 From: Alex Nathanail Date: Sun, 12 Mar 2023 15:55:06 +0000 Subject: [PATCH 3/3] Format code with rustfmt --- benches/benchmarks.rs | 22 +++-- src/graphs/algorithms/travelling_salesman.rs | 4 +- src/graphs/input/pbf.rs | 97 ++++++++++---------- src/graphs/input/tsplib.rs | 8 +- src/main.rs | 4 +- tests/graphs/travelling_salesman_tests.rs | 2 +- 6 files changed, 72 insertions(+), 65 deletions(-) diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs index 96e655e..95eb3c8 100644 --- a/benches/benchmarks.rs +++ b/benches/benchmarks.rs @@ -1,7 +1,7 @@ use std::time::Duration; use broute::graphs::algorithms::{ - form_abstracted_graph, SimulatedAnnealing, ConnectedComponents, Dijkstra, + form_abstracted_graph, ConnectedComponents, Dijkstra, SimulatedAnnealing, }; use broute::graphs::datastructures::{Digraph, NodeIndex}; use broute::graphs::input::{get_random_graph, load_pbf_file, load_tsplib_file, load_xgmml_file}; @@ -77,10 +77,12 @@ fn travelling_salesman_benchmark(c: &mut Criterion) { group.bench_with_input( BenchmarkId::new("DIMCAS d1291", &dimacs_g), &dimacs_g, - |b, g| b.iter(|| { - let mut sa = SimulatedAnnealing::new(g); - sa.run(); - }), + |b, g| { + b.iter(|| { + let mut sa = SimulatedAnnealing::new(g); + sa.run(); + }) + }, ); let monaco_g = load_pbf_file("test_data/geofabrik/monaco-latest.osm.pbf").unwrap(); @@ -98,10 +100,12 @@ fn travelling_salesman_benchmark(c: &mut Criterion) { group.bench_with_input( BenchmarkId::new("OSM Monaco - 5 random nodes", &abstracted_graph), &abstracted_graph, - |b, g| b.iter(|| { - let mut sa = SimulatedAnnealing::new(g); - sa.run(); - }), + |b, g| { + b.iter(|| { + let mut sa = SimulatedAnnealing::new(g); + sa.run(); + }) + }, ); group.finish(); diff --git a/src/graphs/algorithms/travelling_salesman.rs b/src/graphs/algorithms/travelling_salesman.rs index 9be323b..5496f1d 100644 --- a/src/graphs/algorithms/travelling_salesman.rs +++ b/src/graphs/algorithms/travelling_salesman.rs @@ -78,7 +78,9 @@ impl<'a> SimulatedAnnealing<'a> { self.path_length = new_path_length; } else { // TODO: Is this between 0 and 1? - if f64::exp(-f64::abs(new_path_length - self.path_length) / temp) > self.rng.gen::() { + if f64::exp(-f64::abs(new_path_length - self.path_length) / temp) + > self.rng.gen::() + { self.current_path = potential_new_path; self.path_length = new_path_length; } diff --git a/src/graphs/input/pbf.rs b/src/graphs/input/pbf.rs index 7d0173a..1dedf5a 100644 --- a/src/graphs/input/pbf.rs +++ b/src/graphs/input/pbf.rs @@ -19,16 +19,15 @@ type Result = std::result::Result; pub fn load_pbf_file(pbf_path: &str) -> Result { let reader = ElementReader::from_path(pbf_path)?; - let num_nodes = reader - .par_map_reduce( - |element| match element { - Element::Node(_) => 1, - Element::DenseNode(_) => 1, - _ => 0, - }, - || 0_u64, // Zero is the identity value for addition - |a, b| a + b, // Sum the partial results - )?; + let num_nodes = reader.par_map_reduce( + |element| match element { + Element::Node(_) => 1, + Element::DenseNode(_) => 1, + _ => 0, + }, + || 0_u64, // Zero is the identity value for addition + |a, b| a + b, // Sum the partial results + )?; println!("Number of nodes: {num_nodes}"); @@ -38,26 +37,25 @@ pub fn load_pbf_file(pbf_path: &str) -> Result { let reader = ElementReader::from_path(pbf_path)?; - reader - .for_each(|element| { - if let Element::Node(n) = element { - g.mut_nodes_data().add_node_data_by_parts( - NodeID(n.id() as usize), - LatLng { - latitude: n.lat(), - longitude: n.lon(), - }, - ) - } else if let Element::DenseNode(dn) = element { - g.mut_nodes_data().add_node_data_by_parts( - NodeID(dn.id() as usize), - LatLng { - latitude: dn.lat(), - longitude: dn.lon(), - }, - ) - } - })?; + reader.for_each(|element| { + if let Element::Node(n) = element { + g.mut_nodes_data().add_node_data_by_parts( + NodeID(n.id() as usize), + LatLng { + latitude: n.lat(), + longitude: n.lon(), + }, + ) + } else if let Element::DenseNode(dn) = element { + g.mut_nodes_data().add_node_data_by_parts( + NodeID(dn.id() as usize), + LatLng { + latitude: dn.lat(), + longitude: dn.lon(), + }, + ) + } + })?; println!("Nodes added"); @@ -65,27 +63,26 @@ pub fn load_pbf_file(pbf_path: &str) -> Result { let reader = ElementReader::from_path(pbf_path)?; - reader - .for_each(|element| { - if let Element::Way(w) = element { - let node_ids = w.refs().collect::>(); - for i in 0..node_ids.len() - 1 { - let from_id = NodeID(node_ids[i] as usize); - let from_node_data = g.nodes_data().get_node_data_by_id(from_id); - - let to_id = NodeID(node_ids[i + 1] as usize); - let to_node_data = g.nodes_data().get_node_data_by_id(to_id); - - let weight = haversine(from_node_data.latlng, to_node_data.latlng); - g.add_edge_by_id( - NodeID(node_ids[i] as usize), - NodeID(node_ids[i + 1] as usize), - weight, - ); - } - ways += 1; + reader.for_each(|element| { + if let Element::Way(w) = element { + let node_ids = w.refs().collect::>(); + for i in 0..node_ids.len() - 1 { + let from_id = NodeID(node_ids[i] as usize); + let from_node_data = g.nodes_data().get_node_data_by_id(from_id); + + let to_id = NodeID(node_ids[i + 1] as usize); + let to_node_data = g.nodes_data().get_node_data_by_id(to_id); + + let weight = haversine(from_node_data.latlng, to_node_data.latlng); + g.add_edge_by_id( + NodeID(node_ids[i] as usize), + NodeID(node_ids[i + 1] as usize), + weight, + ); } - })?; + ways += 1; + } + })?; println!("Edges added"); diff --git a/src/graphs/input/tsplib.rs b/src/graphs/input/tsplib.rs index e74e117..a595d94 100644 --- a/src/graphs/input/tsplib.rs +++ b/src/graphs/input/tsplib.rs @@ -23,9 +23,13 @@ pub fn load_tsplib_file(file_path: &str, num_nodes: usize) -> Result let actual_num_nodes = cmp::min(num_nodes, instance.dimension); - let coords = match instance.node_coord.ok_or(TSPLIBImportError::OtherError("No node coords found".to_string()))? { + let coords = match instance.node_coord.ok_or(TSPLIBImportError::OtherError( + "No node coords found".to_string(), + ))? { NodeCoord::Two(x) => Ok(x), - _ => Err(TSPLIBImportError::OtherError("No node coords found".to_string())), + _ => Err(TSPLIBImportError::OtherError( + "No node coords found".to_string(), + )), }?; let mut g = AMDigraph::new(actual_num_nodes); diff --git a/src/main.rs b/src/main.rs index f97617b..61a497c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,11 +6,11 @@ use std::sync::{Arc, RwLock}; use rocket::fairing::{Fairing, Info, Kind}; use rocket::http::Header; -use rocket::serde::{Deserialize, Serialize}; use rocket::serde::json::Json; +use rocket::serde::{Deserialize, Serialize}; use broute::graphs::algorithms::{ - ConnectedComponents, Dijkstra, form_abstracted_graph, SimulatedAnnealing, + form_abstracted_graph, ConnectedComponents, Dijkstra, SimulatedAnnealing, }; use broute::graphs::datastructures::{ALDigraph, Digraph, LatLng, NodeID}; use broute::graphs::input::load_pbf_file; diff --git a/tests/graphs/travelling_salesman_tests.rs b/tests/graphs/travelling_salesman_tests.rs index c630c53..8873b65 100644 --- a/tests/graphs/travelling_salesman_tests.rs +++ b/tests/graphs/travelling_salesman_tests.rs @@ -1,4 +1,4 @@ -use broute::graphs::algorithms::{form_abstracted_graph, SimulatedAnnealing, ConnectedComponents}; +use broute::graphs::algorithms::{form_abstracted_graph, ConnectedComponents, SimulatedAnnealing}; use broute::graphs::datastructures::{Digraph, LatLng, NodeID, NodeIndex}; use broute::graphs::input::load_pbf_file;