From f05c27cdd283282693d192df72ce3c4c9b44e9f9 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 12 Mar 2021 09:33:00 +0100 Subject: [PATCH] fmt, clippy, version updates --- Cargo.toml | 6 +- benches/haversine.rs | 16 +++-- benches/olc_classic.rs | 35 ++++++---- examples/cli.rs | 19 ++--- examples/geojson.rs | 21 +++--- src/flat.rs | 12 ++-- src/haversine.rs | 5 +- src/lib.rs | 4 +- src/olc.rs | 143 ++++++++++++++++++++++++++------------ tests/integration_test.rs | 31 +++++---- 10 files changed, 187 insertions(+), 105 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7b4e0c9..62890ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,9 @@ travis-ci = { repository = "Turbo87/aeroscore-rs", branch = "master" } default = ["rayon"] [dependencies] -cfg-if = "0.1" +cfg-if = "1.0" failure = "^0.1.1" -flat_projection = "0.3.0" +flat_projection = "0.4.0" log = "0.4.8" ord_subset = "^3.1.0" rayon = { version = "^1.0", optional = true } @@ -28,7 +28,7 @@ rayon = { version = "^1.0", optional = true } assert_approx_eq = "^1.0.0" criterion = "^0.3.0" igc = "0.2.2" -env_logger = "0.7.1" +env_logger = "0.8.3" serde_json = "^1.0.0" [[bench]] diff --git a/benches/haversine.rs b/benches/haversine.rs index c0dff7d..054cc55 100644 --- a/benches/haversine.rs +++ b/benches/haversine.rs @@ -4,8 +4,8 @@ extern crate criterion; extern crate aeroscore; extern crate igc; -use criterion::Criterion; use aeroscore::haversine::haversine_distance; +use criterion::Criterion; struct Point { latitude: f32, @@ -25,9 +25,17 @@ impl aeroscore::Point for Point { } fn criterion_benchmark(c: &mut Criterion) { - let point1 = Point { latitude: 51.301389, longitude: 6.953333 }; - let point2 = Point { latitude: 50.823194, longitude: 6.186389 }; - c.bench_function("haversine", |b| b.iter(|| haversine_distance(&point1, &point2))); + let point1 = Point { + latitude: 51.301389, + longitude: 6.953333, + }; + let point2 = Point { + latitude: 50.823194, + longitude: 6.186389, + }; + c.bench_function("haversine", |b| { + b.iter(|| haversine_distance(&point1, &point2)) + }); } criterion_group!(benches, criterion_benchmark); diff --git a/benches/olc_classic.rs b/benches/olc_classic.rs index 96aa0ce..83a1b46 100644 --- a/benches/olc_classic.rs +++ b/benches/olc_classic.rs @@ -4,8 +4,8 @@ extern crate criterion; extern crate aeroscore; extern crate igc; -use criterion::Criterion; use aeroscore::olc; +use criterion::Criterion; struct Point { latitude: f32, @@ -26,20 +26,25 @@ impl aeroscore::Point for Point { } fn criterion_benchmark(c: &mut Criterion) { - c.bench_function("olc_classic", |b| b.iter(|| { - let fixes = include_str!("../tests/fixtures/2017-08-14-fla-6ng-01.igc") - .lines() - .filter(|l| l.starts_with('B')) - .filter_map(|line| igc::records::BRecord::parse(&line).ok() - .map(|record| Point { - latitude: record.pos.lat.into(), - longitude: record.pos.lon.into(), - altitude: record.pressure_alt, - })) - .collect::>(); - - olc::optimize(&fixes).unwrap() - })); + c.bench_function("olc_classic", |b| { + b.iter(|| { + let fixes = include_str!("../tests/fixtures/2017-08-14-fla-6ng-01.igc") + .lines() + .filter(|l| l.starts_with('B')) + .filter_map(|line| { + igc::records::BRecord::parse(&line) + .ok() + .map(|record| Point { + latitude: record.pos.lat.into(), + longitude: record.pos.lon.into(), + altitude: record.pressure_alt, + }) + }) + .collect::>(); + + olc::optimize(&fixes).unwrap() + }) + }); } criterion_group! { diff --git a/examples/cli.rs b/examples/cli.rs index e45329c..58e92a9 100644 --- a/examples/cli.rs +++ b/examples/cli.rs @@ -2,9 +2,9 @@ extern crate aeroscore; extern crate igc; use std::env; +use std::fs::File; use std::io::prelude::*; use std::io::BufReader; -use std::fs::File; use aeroscore::olc; @@ -67,13 +67,16 @@ fn analyze(path: &str) { .lines() .filter_map(|l| l.ok()) .filter(|l| l.starts_with('B')) - .filter_map(|line| igc::records::BRecord::parse(&line).ok() - .map(|record| Point { - time: record.timestamp, - latitude: record.pos.lat.into(), - longitude: record.pos.lon.into(), - altitude: record.pressure_alt, - })) + .filter_map(|line| { + igc::records::BRecord::parse(&line) + .ok() + .map(|record| Point { + time: record.timestamp, + latitude: record.pos.lat.into(), + longitude: record.pos.lon.into(), + altitude: record.pressure_alt, + }) + }) .collect::>(); println!("num points: {}", fixes.len()); diff --git a/examples/geojson.rs b/examples/geojson.rs index ad8da0d..38c64e4 100644 --- a/examples/geojson.rs +++ b/examples/geojson.rs @@ -5,9 +5,9 @@ extern crate aeroscore; extern crate igc; use std::env; +use std::fs::File; use std::io::prelude::*; use std::io::BufReader; -use std::fs::File; use aeroscore::olc; @@ -46,17 +46,22 @@ fn analyze(path: &str) { .lines() .filter_map(|l| l.ok()) .filter(|l| l.starts_with('B')) - .filter_map(|line| igc::records::BRecord::parse(&line).ok() - .map(|record| Point { - latitude: record.pos.lat.into(), - longitude: record.pos.lon.into(), - altitude: record.pressure_alt, - })) + .filter_map(|line| { + igc::records::BRecord::parse(&line) + .ok() + .map(|record| Point { + latitude: record.pos.lat.into(), + longitude: record.pos.lon.into(), + altitude: record.pressure_alt, + }) + }) .collect::>(); let result = olc::optimize(&fixes).unwrap(); - let result_coords = result.path.iter() + let result_coords = result + .path + .iter() .map(|i| &fixes[*i]) .map(|p| (p.longitude, p.latitude)) .collect::>(); diff --git a/src/flat.rs b/src/flat.rs index 7b9047a..8bfe674 100644 --- a/src/flat.rs +++ b/src/flat.rs @@ -1,8 +1,8 @@ -use flat_projection::{FlatProjection, FlatPoint}; +use flat_projection::{FlatPoint, FlatProjection}; use ord_subset::OrdSubsetIterExt; -use crate::Point; use crate::parallel::*; +use crate::Point; /// Projects all geographic points onto a flat surface for faster geodesic calculation /// @@ -17,11 +17,11 @@ pub fn to_flat_points(points: &[T]) -> Vec> { } trait CenterLatitude { - fn center_lat(self: &Self) -> Option; + fn center_lat(&self) -> Option; } impl CenterLatitude for [T] { - fn center_lat(self: &Self) -> Option { + fn center_lat(&self) -> Option { let lat_min = self.iter().map(|fix| fix.latitude()).ord_subset_min()?; let lat_max = self.iter().map(|fix| fix.latitude()).ord_subset_max()?; @@ -30,11 +30,11 @@ impl CenterLatitude for [T] { } trait CenterLongitude { - fn center_lon(self: &Self) -> Option; + fn center_lon(&self) -> Option; } impl CenterLongitude for [T] { - fn center_lon(self: &Self) -> Option { + fn center_lon(&self) -> Option { let lon_min = self.iter().map(|fix| fix.longitude()).ord_subset_min()?; let lon_max = self.iter().map(|fix| fix.longitude()).ord_subset_max()?; diff --git a/src/haversine.rs b/src/haversine.rs index abfac1a..b8b2b2b 100644 --- a/src/haversine.rs +++ b/src/haversine.rs @@ -8,9 +8,8 @@ pub fn haversine_distance(fix1: &dyn Point, fix2: &dyn Point) -> f32 { let delta_phi = (fix2.latitude() - fix1.latitude()).to_radians(); let delta_rho = (fix2.longitude() - fix1.longitude()).to_radians(); - let a = (delta_phi / 2.).sin() * (delta_phi / 2.).sin() + - phi1.cos() * phi2.cos() * - (delta_rho / 2.).sin() * (delta_rho / 2.).sin(); + let a = (delta_phi / 2.).sin() * (delta_phi / 2.).sin() + + phi1.cos() * phi2.cos() * (delta_rho / 2.).sin() * (delta_rho / 2.).sin(); let c = 2. * a.sqrt().atan2((1. - a).sqrt()); diff --git a/src/lib.rs b/src/lib.rs index 49ac4c1..8c68300 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ -pub mod olc; pub mod flat; pub mod haversine; -mod point; +pub mod olc; mod parallel; +mod point; pub use crate::point::Point; diff --git a/src/olc.rs b/src/olc.rs index 30a4383..9fb5d6f 100644 --- a/src/olc.rs +++ b/src/olc.rs @@ -3,10 +3,10 @@ use flat_projection::FlatPoint; use log::{debug, trace}; use ord_subset::OrdVar; -use crate::Point; use crate::flat::to_flat_points; use crate::haversine::haversine_distance; use crate::parallel::*; +use crate::Point; const LEGS: usize = 6; @@ -30,40 +30,67 @@ pub fn optimize(route: &[T]) -> Result { debug!("Searching for best valid solution"); let mut best_valid = graph.find_best_valid_solution(&route); - debug!("-- New best solution: {:.3} km -> {:?}", calculate_distance(route, &best_valid.path), best_valid.path); + debug!( + "-- New best solution: {:.3} km -> {:?}", + calculate_distance(route, &best_valid.path), + best_valid.path + ); debug!("Searching for potentially better solutions"); - let mut start_candidates: Vec<_> = graph.g[LEGS - 1].iter() + let mut start_candidates: Vec<_> = graph.g[LEGS - 1] + .iter() .enumerate() .filter(|(_, cell)| cell.distance > best_valid.distance) - .map(|(start_index, cell)| StartCandidate { distance: cell.distance, start_index }) + .map(|(start_index, cell)| StartCandidate { + distance: cell.distance, + start_index, + }) .collect(); start_candidates.sort_by_key(|it| OrdVar::new_checked(it.distance)); - debug!("{} potentially better start points found", start_candidates.len()); + debug!( + "{} potentially better start points found", + start_candidates.len() + ); while let Some(candidate) = start_candidates.pop() { let finish_altitude = route[candidate.start_index].altitude(); - debug!("Calculating solution graph with start point at index {}", candidate.start_index); + debug!( + "Calculating solution graph with start point at index {}", + candidate.start_index + ); let candidate_graph = Graph::for_start_index(finish_altitude, &dist_matrix, route); let best_valid_for_candidate = candidate_graph.find_best_valid_solution(&route); if best_valid_for_candidate.distance > best_valid.distance { best_valid = best_valid_for_candidate; - debug!("-- New best solution: {:.3} km -> {:?}", calculate_distance(route, &best_valid.path), best_valid.path); + debug!( + "-- New best solution: {:.3} km -> {:?}", + calculate_distance(route, &best_valid.path), + best_valid.path + ); start_candidates.retain(|it| it.distance > best_valid.distance); } else { - debug!("Discarding solution with {:.3} km", calculate_distance(route, &best_valid_for_candidate.path)); + debug!( + "Discarding solution with {:.3} km", + calculate_distance(route, &best_valid_for_candidate.path) + ); } - debug!("{} potentially better start points left", start_candidates.len()); + debug!( + "{} potentially better start points left", + start_candidates.len() + ); } let distance = calculate_distance(route, &best_valid.path); debug!("Solution: {:?} ({:.3} km)", best_valid.path, distance); - Ok(OptimizationResult { distance, path: best_valid.path }) + Ok(OptimizationResult { + distance, + path: best_valid.path, + }) } #[derive(Debug)] @@ -78,9 +105,7 @@ struct StartCandidate { pub fn half_dist_matrix(flat_points: &[FlatPoint]) -> Vec> { opt_par_iter(flat_points) .enumerate() - .map(|(i, p1)| flat_points[i..].iter() - .map(|p2| p1.distance(p2)) - .collect()) + .map(|(i, p1)| flat_points[i..].iter().map(|p2| p1.distance(p2)).collect()) .collect() } @@ -102,11 +127,17 @@ impl Graph { let layer: Vec = opt_par_iter(dist_matrix) .enumerate() - .map(|(tp_index, distances)| distances.iter() - .enumerate() - .map(|(start_index, &distance)| GraphCell { prev_index: start_index+tp_index, distance }) - .max_by_key(|cell| OrdVar::new_checked(cell.distance)) - .unwrap()) + .map(|(tp_index, distances)| { + distances + .iter() + .enumerate() + .map(|(start_index, &distance)| GraphCell { + prev_index: start_index + tp_index, + distance, + }) + .max_by_key(|cell| OrdVar::new_checked(cell.distance)) + .unwrap() + }) .collect(); graph.push(layer); @@ -118,12 +149,16 @@ impl Graph { let layer: Vec = opt_par_iter(dist_matrix) .enumerate() .map(|(tp_index, distances)| { - distances.iter() + distances + .iter() .zip(last_layer.iter().skip(tp_index)) .enumerate() .map(|(prev_index, (&leg_dist, last_layer_cell))| { let distance = last_layer_cell.distance + leg_dist; - GraphCell { prev_index: prev_index+tp_index, distance } + GraphCell { + prev_index: prev_index + tp_index, + distance, + } }) .max_by_key(|cell| OrdVar::new_checked(cell.distance)) .unwrap() @@ -136,7 +171,11 @@ impl Graph { Graph { g: graph } } - fn for_start_index(start_altitude: i16, dist_matrix: &[Vec], points: &[T]) -> Self { + fn for_start_index( + start_altitude: i16, + dist_matrix: &[Vec], + points: &[T], + ) -> Self { let mut graph: Vec> = Vec::with_capacity(LEGS); trace!("-- Analyzing leg #{}", 6); @@ -147,19 +186,28 @@ impl Graph { let layer: Vec = opt_par_iter(dist_matrix) .enumerate() - .map(|(tp_index, distances)| distances.iter() - .enumerate() - .map(|(finish_index, &distance)| { - let finish = &points[finish_index+tp_index]; - let altitude_delta = start_altitude - finish.altitude(); - if altitude_delta <= 1000 { - GraphCell { prev_index: finish_index+tp_index, distance: distance } - } else { - GraphCell { prev_index: finish_index+tp_index, distance: distance - 100_000.0} - } - }) - .max_by_key(|cell| OrdVar::new_checked(cell.distance)) - .unwrap()) + .map(|(tp_index, distances)| { + distances + .iter() + .enumerate() + .map(|(finish_index, &distance)| { + let finish = &points[finish_index + tp_index]; + let altitude_delta = start_altitude - finish.altitude(); + if altitude_delta <= 1000 { + GraphCell { + prev_index: finish_index + tp_index, + distance, + } + } else { + GraphCell { + prev_index: finish_index + tp_index, + distance: distance - 100_000.0, + } + } + }) + .max_by_key(|cell| OrdVar::new_checked(cell.distance)) + .unwrap() + }) .collect(); // trace!("Layer: {:?}", layer); graph.push(layer); @@ -188,12 +236,16 @@ impl Graph { let layer: Vec = opt_par_iter(dist_matrix) .enumerate() .map(|(tp_index, distances)| { - distances.iter() + distances + .iter() .zip(last_layer.iter().skip(tp_index)) .enumerate() .map(|(prev_index, (&leg_dist, last_layer_cell))| { let distance = last_layer_cell.distance + leg_dist; - GraphCell { prev_index: prev_index+tp_index, distance } + GraphCell { + prev_index: prev_index + tp_index, + distance, + } }) .max_by_key(|cell| OrdVar::new_checked(cell.distance)) .unwrap() @@ -212,7 +264,8 @@ impl Graph { let offset = points.len() - last_graph_row.len(); - last_graph_row.iter() + last_graph_row + .iter() .enumerate() .filter_map(|(index, cell)| { let iter = GraphIterator { @@ -231,8 +284,11 @@ impl Graph { let start = &points[start_index]; let finish = &points[finish_index]; let altitude_delta = start.altitude() - finish.altitude(); - if altitude_delta <= 1000 { - Some(OptimizationResult { distance: cell.distance, path }) + if altitude_delta <= 1000 { + Some(OptimizationResult { + distance: cell.distance, + path, + }) } else { None } @@ -252,7 +308,7 @@ impl Iterator for GraphIterator<'_> { type Item = usize; fn next(&mut self) -> Option { - if self.next.is_none() { return None; } + self.next?; let (layer, index) = self.next.unwrap(); self.next = if layer == 0 { @@ -270,9 +326,10 @@ impl Iterator for GraphIterator<'_> { /// Calculates the total task distance (via haversine algorithm) from /// the original `route` and the array of indices /// -fn calculate_distance(points: &[T], path: &Path) -> f32 { - path.iter().zip(path.iter().skip(1)) +fn calculate_distance(points: &[T], path: &[usize]) -> f32 { + path.iter() + .zip(path.iter().skip(1)) .map(|(i1, i2)| (&points[*i1], &points[*i2])) .map(|(fix1, fix2)| haversine_distance(fix1, fix2)) .sum() -} \ No newline at end of file +} diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 0139aed..dab238d 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -54,20 +54,25 @@ fn distance_for_99b_7r9() { fn run_test(file: &str, release: Time) -> OptimizationResult { env_logger::try_init().ok(); - let fixes = file.lines() + let fixes = file + .lines() .filter(|l| l.starts_with('B')) - .filter_map(|line| igc::records::BRecord::parse(&line).ok() - .map_or(None, |record| { - if record.timestamp.seconds_since_midnight() >= release.seconds_since_midnight() { - Some(Point { - latitude: record.pos.lat.into(), - longitude: record.pos.lon.into(), - altitude: record.pressure_alt, - }) - } else { - None - } - })) + .filter_map(|line| { + igc::records::BRecord::parse(&line) + .ok() + .map_or(None, |record| { + if record.timestamp.seconds_since_midnight() >= release.seconds_since_midnight() + { + Some(Point { + latitude: record.pos.lat.into(), + longitude: record.pos.lon.into(), + altitude: record.pressure_alt, + }) + } else { + None + } + }) + }) .collect::>(); olc::optimize(&fixes).unwrap()