diff --git a/engine/src/as_slice.rs b/engine/src/as_slice.rs new file mode 100644 index 00000000..d6722fbb --- /dev/null +++ b/engine/src/as_slice.rs @@ -0,0 +1,26 @@ +use std::sync::Arc; + +pub trait AsSlice { + fn as_slice(&self) -> &[T]; +} + +impl AsSlice for Vec where +{ + fn as_slice(&self) -> &[V] { + &self[..] + } +} + +impl<'a, V> AsSlice for &'a [V] where +{ + fn as_slice(&self) -> &[V] { + self + } +} + +impl AsSlice for Arc> where +{ + fn as_slice(&self) -> &[V] { + &self[..] + } +} diff --git a/engine/src/graph/first_out_graph.rs b/engine/src/graph/first_out_graph.rs index 318419aa..ec4c7f17 100644 --- a/engine/src/graph/first_out_graph.rs +++ b/engine/src/graph/first_out_graph.rs @@ -1,30 +1,57 @@ use super::*; +use as_slice::AsSlice; use ::io; use std::io::Result; use std::path::Path; #[derive(Debug, Clone)] -pub struct FirstOutGraph { +pub struct FirstOutGraph where + FirstOutContainer: AsSlice, + HeadContainer: AsSlice, + WeightContainer: AsSlice, +{ // index of first edge of each node +1 entry in the end - first_out: Vec, + first_out: FirstOutContainer, // the node ids to which each edge points - head: Vec, + head: HeadContainer, // the weight of each edge - weight: Vec + weight: WeightContainer, } -impl FirstOutGraph { - pub fn new(first_out: Vec, head: Vec, weight: Vec) -> FirstOutGraph { - assert_eq!(*first_out.first().unwrap(), 0); - assert_eq!(*first_out.last().unwrap() as usize, head.len()); - assert_eq!(weight.len(), head.len()); +pub type OwnedGraph = FirstOutGraph, Vec, Vec>; - FirstOutGraph { - first_out, head, weight - } +impl FirstOutGraph where + FirstOutContainer: AsSlice, + HeadContainer: AsSlice, + WeightContainer: AsSlice, +{ + fn first_out(&self) -> &[u32] { self.first_out.as_slice() } + fn head(&self) -> &[u32] { self.head.as_slice() } + fn weight(&self) -> &[u32] { self.weight.as_slice() } + + pub fn new(first_out: FirstOutContainer, head: HeadContainer, weight: WeightContainer) -> FirstOutGraph { + assert_eq!(*first_out.as_slice().first().unwrap(), 0); + assert_eq!(*first_out.as_slice().last().unwrap() as usize, head.as_slice().len()); + assert_eq!(weight.as_slice().len(), head.as_slice().len()); + + FirstOutGraph { first_out, head, weight } + } + + pub fn write_to_dir(&self, dir: &str) -> Result<()> { + let path = Path::new(dir); + let res1 = io::write_vector_to_file(path.join("first_out").to_str().unwrap(), self.first_out()); + let res2 = io::write_vector_to_file(path.join("head").to_str().unwrap(), self.head()); + let res3 = io::write_vector_to_file(path.join("weights").to_str().unwrap(), self.weight()); + res1.and(res2).and(res3) } - pub fn from_adjancecy_lists(adjancecy_lists: Vec>) -> FirstOutGraph { + pub fn decompose(self) -> (FirstOutContainer, HeadContainer, WeightContainer) { + (self.first_out, self.head, self.weight) + } +} + +impl OwnedGraph { + pub fn from_adjancecy_lists(adjancecy_lists: Vec>) -> OwnedGraph { // create first_out array for reversed by doing a prefix sum over the adjancecy list sizes let first_out = std::iter::once(0).chain(adjancecy_lists.iter().scan(0, |state, incoming_links| { *state = *state + incoming_links.len() as u32; @@ -37,70 +64,43 @@ impl FirstOutGraph { .flat_map(|neighbors| neighbors.into_iter().map(|Link { node, weight }| (node, weight) ) ) .unzip(); - FirstOutGraph::new(first_out, head, weight) - } - - pub fn neighbor_iter(&self, node: NodeId) -> std::iter::Map, std::slice::Iter>, fn((&NodeId, &Weight))->Link> { - let range = (self.first_out[node as usize] as usize)..(self.first_out[(node + 1) as usize] as usize); - self.head[range.clone()].iter() - .zip(self.weight[range].iter()) - .map( |(&neighbor, &weight)| Link { node: neighbor, weight: weight } ) - } - - pub fn edge_index(&self, from: NodeId, to: NodeId) -> Option { - let first_out = self.first_out[from as usize] as usize; - self.neighbor_iter(from).enumerate().find(|&(_, Link { node, .. })| node == to).map(|(i, _)| first_out + i ) - } - - pub fn reverse(&self) -> FirstOutGraph { - // vector of adjacency lists for the reverse graph - let mut reversed: Vec> = (0..self.num_nodes()).map(|_| Vec::::new() ).collect(); - - // iterate over all edges and insert them in the reversed structure - for node in 0..(self.num_nodes() as NodeId) { - for Link { node: neighbor, weight } in self.neighbor_iter(node) { - reversed[neighbor as usize].push(Link { node, weight }); - } - } - FirstOutGraph::from_adjancecy_lists(reversed) - } - - pub fn ch_split(self, node_ranks: &Vec) -> (FirstOutGraph, FirstOutGraph) { - let mut up: Vec> = (0..self.num_nodes()).map(|_| Vec::::new() ).collect(); - let mut down: Vec> = (0..self.num_nodes()).map(|_| Vec::::new() ).collect(); - - // iterate over all edges and insert them in the reversed structure - for node in 0..(self.num_nodes() as NodeId) { - for Link { node: neighbor, weight } in self.neighbor_iter(node) { - if node_ranks[node as usize] < node_ranks[neighbor as usize] { - up[node as usize].push(Link { node: neighbor, weight }); - } else { - down[neighbor as usize].push(Link { node, weight }); - } - } - } - - (FirstOutGraph::from_adjancecy_lists(up), FirstOutGraph::from_adjancecy_lists(down)) + OwnedGraph::new(first_out, head, weight) } +} - pub fn write_to_dir(&self, dir: &str) -> Result<()> { - let path = Path::new(dir); - let res1 = io::write_vector_to_file(path.join("first_out").to_str().unwrap(), &self.first_out); - let res2 = io::write_vector_to_file(path.join("head").to_str().unwrap(), &self.head); - let res3 = io::write_vector_to_file(path.join("weights").to_str().unwrap(), &self.weight); - res1.and(res2).and(res3) +impl Graph for FirstOutGraph where + FirstOutContainer: AsSlice, + HeadContainer: AsSlice, + WeightContainer: AsSlice, +{ + fn num_nodes(&self) -> usize { + self.first_out().len() - 1 } } -impl DijkstrableGraph for FirstOutGraph { - fn num_nodes(&self) -> usize { - self.first_out.len() - 1 +impl<'a, FirstOutContainer, HeadContainer, WeightContainer> LinkIterGraph<'a> for FirstOutGraph where + FirstOutContainer: AsSlice, + HeadContainer: AsSlice, + WeightContainer: AsSlice, +{ + type Iter = std::iter::Map, std::slice::Iter<'a, Weight>>, fn((&NodeId, &Weight))->Link>; + + fn neighbor_iter(&'a self, node: NodeId) -> Self::Iter { + let range = (self.first_out()[node as usize] as usize)..(self.first_out()[(node + 1) as usize] as usize); + self.head()[range.clone()].iter() + .zip(self.weight()[range].iter()) + .map( |(&neighbor, &weight)| Link { node: neighbor, weight: weight } ) } +} - fn for_each_neighbor(&self, node: NodeId, f: &mut FnMut(Link)) { - for link in self.neighbor_iter(node) { - f(link); - } +impl RandomLinkAccessGraph for FirstOutGraph where + FirstOutContainer: AsSlice, + HeadContainer: AsSlice, + WeightContainer: AsSlice, +{ + fn edge_index(&self, from: NodeId, to: NodeId) -> Option { + let first_out = self.first_out()[from as usize] as usize; + self.neighbor_iter(from).enumerate().find(|&(_, Link { node, .. })| node == to).map(|(i, _)| first_out + i ) } } diff --git a/engine/src/graph/mod.rs b/engine/src/graph/mod.rs index e1333759..a03258da 100644 --- a/engine/src/graph/mod.rs +++ b/engine/src/graph/mod.rs @@ -1,8 +1,9 @@ use std; -use shortest_path::DijkstrableGraph; pub mod first_out_graph; +pub use self::first_out_graph::{OwnedGraph, FirstOutGraph}; + pub type NodeId = u32; pub type Weight = u32; pub const INFINITY: u32 = std::u32::MAX / 2; @@ -12,3 +13,49 @@ pub struct Link { pub node: NodeId, pub weight: Weight } + +pub trait Graph { + fn num_nodes(&self) -> usize; +} + +pub trait LinkIterGraph<'a>: Graph { + type Iter: Iterator + 'a; // fix with https://github.com/rust-lang/rfcs/pull/1598 + + fn neighbor_iter(&'a self, node: NodeId) -> Self::Iter; + + fn reverse(&'a self) -> OwnedGraph { + // vector of adjacency lists for the reverse graph + let mut reversed: Vec> = (0..self.num_nodes()).map(|_| Vec::::new() ).collect(); + + // iterate over all edges and insert them in the reversed structure + for node in 0..(self.num_nodes() as NodeId) { + for Link { node: neighbor, weight } in self.neighbor_iter(node) { + reversed[neighbor as usize].push(Link { node, weight }); + } + } + + OwnedGraph::from_adjancecy_lists(reversed) + } + + fn ch_split(&'a self, node_ranks: &Vec) -> (OwnedGraph, OwnedGraph) { + let mut up: Vec> = (0..self.num_nodes()).map(|_| Vec::::new() ).collect(); + let mut down: Vec> = (0..self.num_nodes()).map(|_| Vec::::new() ).collect(); + + // iterate over all edges and insert them in the reversed structure + for node in 0..(self.num_nodes() as NodeId) { + for Link { node: neighbor, weight } in self.neighbor_iter(node) { + if node_ranks[node as usize] < node_ranks[neighbor as usize] { + up[node as usize].push(Link { node: neighbor, weight }); + } else { + down[neighbor as usize].push(Link { node, weight }); + } + } + } + + (OwnedGraph::from_adjancecy_lists(up), OwnedGraph::from_adjancecy_lists(down)) + } +} + +pub trait RandomLinkAccessGraph { + fn edge_index(&self, from: NodeId, to: NodeId) -> Option; +} diff --git a/engine/src/import/here/mod.rs b/engine/src/import/here/mod.rs index c03102f4..43eb958a 100644 --- a/engine/src/import/here/mod.rs +++ b/engine/src/import/here/mod.rs @@ -1,5 +1,4 @@ use ::graph::*; -use ::graph::first_out_graph::FirstOutGraph; use ::rank_select_map::RankSelectMap; use std::iter; use std::str::FromStr; @@ -130,7 +129,7 @@ pub trait RdfDataSource { fn link_geometries(&self) -> Vec; } -pub fn read_graph(source: &RdfDataSource) -> (FirstOutGraph, Vec, Vec) { +pub fn read_graph(source: &RdfDataSource) -> (OwnedGraph, Vec, Vec) { println!("read nav links"); // start with all nav links let mut nav_links: Vec = source.nav_links(); @@ -274,7 +273,7 @@ pub fn read_graph(source: &RdfDataSource) -> (FirstOutGraph, Vec, Vec) // insert a zero at the beginning - this will shift all values one to the right first_out.insert(0, 0); - let graph = FirstOutGraph::new(first_out, head, weights); + let graph = OwnedGraph::new(first_out, head, weights); let lat = nodes.iter().map(|node| ((node.lat as f64) / 100000.) as f32).collect(); let lng = nodes.iter().map(|node| ((node.lon as f64) / 100000.) as f32).collect(); (graph, lat, lng) diff --git a/engine/src/io.rs b/engine/src/io.rs index 5a06c7ed..0f7e9a24 100644 --- a/engine/src/io.rs +++ b/engine/src/io.rs @@ -23,7 +23,7 @@ pub fn read_into_vector(filename: &str) -> Result> { Ok(buffer) } -pub fn write_vector_to_file(filename: &str, vector: &Vec) -> Result<()> { +pub fn write_vector_to_file(filename: &str, vector: &[T]) -> Result<()> { let mut buffer = File::create(filename)?; let num_bytes = vector.len() * mem::size_of::(); diff --git a/engine/src/lib.rs b/engine/src/lib.rs index 5fe510b1..b75bfbd8 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -15,6 +15,7 @@ pub mod io; mod index_heap; pub mod rank_select_map; pub mod import; +mod as_slice; #[cfg(test)] mod tests { diff --git a/engine/src/main.rs b/engine/src/main.rs index 818755c4..b2d72370 100644 --- a/engine/src/main.rs +++ b/engine/src/main.rs @@ -1,13 +1,14 @@ use std::env; use std::path::Path; +use std::sync::Arc; extern crate bmw_routing_engine; extern crate time; use bmw_routing_engine::*; -use graph::first_out_graph::FirstOutGraph as Graph; -use graph::INFINITY; +use graph::*; +use graph::first_out_graph::OwnedGraph as Graph; use shortest_path::query::dijkstra::Server as DijkServer; use shortest_path::query::bidirectional_dijkstra::Server as BiDijkServer; use shortest_path::query::async::dijkstra::Server as AsyncDijkServer; @@ -24,19 +25,20 @@ fn main() { let arg = &args.next().expect("No directory arg given"); let path = Path::new(arg); - let first_out = read_into_vector(path.join("first_out").to_str().unwrap()).expect("could not read first_out"); - let head = read_into_vector(path.join("head").to_str().unwrap()).expect("could not read head"); - let travel_time = read_into_vector(path.join("travel_time").to_str().unwrap()).expect("could not read travel_time"); + let first_out = Arc::new(read_into_vector(path.join("first_out").to_str().unwrap()).expect("could not read first_out")); + let head = Arc::new(read_into_vector(path.join("head").to_str().unwrap()).expect("could not read head")); + let travel_time = Arc::new(read_into_vector(path.join("travel_time").to_str().unwrap()).expect("could not read travel_time")); let from = read_into_vector(path.join("test/source").to_str().unwrap()).expect("could not read source"); let to = read_into_vector(path.join("test/target").to_str().unwrap()).expect("could not read target"); let ground_truth = read_into_vector(path.join("test/travel_time_length").to_str().unwrap()).expect("could not read travel_time_length"); - let graph = Graph::new(first_out, head, travel_time); + let graph = FirstOutGraph::new(&first_out[..], &head[..], &travel_time[..]); + let arcd_graph = FirstOutGraph::new(first_out.clone(), head.clone(), travel_time.clone()); let mut simple_server = DijkServer::new(graph.clone()); - let mut bi_dir_server = BiDijkServer::::new(graph.clone()); - let async_server = AsyncDijkServer::new(graph.clone()); - let mut async_bi_dir_server = AsyncBiDijkServer::new(graph.clone()); + let mut bi_dir_server = BiDijkServer::new(graph.clone()); + let async_server = AsyncDijkServer::new(arcd_graph.clone()); + let mut async_bi_dir_server = AsyncBiDijkServer::new(arcd_graph); let ch_first_out = read_into_vector(path.join("travel_time_ch/first_out").to_str().unwrap()).expect("could not read travel_time_ch/first_out"); let ch_head = read_into_vector(path.join("travel_time_ch/head").to_str().unwrap()).expect("could not read travel_time_ch/head"); diff --git a/engine/src/shortest_path/contraction_hierarchy/mod.rs b/engine/src/shortest_path/contraction_hierarchy/mod.rs index 6ddc5b01..df402dd1 100644 --- a/engine/src/shortest_path/contraction_hierarchy/mod.rs +++ b/engine/src/shortest_path/contraction_hierarchy/mod.rs @@ -1,5 +1,4 @@ use super::*; -use self::first_out_graph::FirstOutGraph; #[derive(Debug, PartialEq)] enum ShortcutResult { @@ -58,7 +57,7 @@ struct ContractionGraph { } impl ContractionGraph { - fn new(graph: FirstOutGraph, node_order: Vec) -> ContractionGraph { + fn new LinkIterGraph<'a>>(graph: Graph, node_order: Vec) -> ContractionGraph { let n = graph.num_nodes(); let mut node_ranks = vec![0; n]; for (i, &node) in node_order.iter().enumerate() { @@ -110,7 +109,7 @@ impl ContractionGraph { } } - fn as_first_out_graphs(self) -> ((FirstOutGraph, FirstOutGraph), Option<(Vec, Vec)>) { + fn as_first_out_graphs(self) -> ((OwnedGraph, OwnedGraph), Option<(Vec, Vec)>) { let (outgoing, incoming): (Vec<(Vec, Vec)>, Vec<(Vec, Vec)>) = self.nodes.into_iter() .map(|node| { (node.outgoing.into_iter().unzip(), node.incoming.into_iter().unzip()) @@ -124,7 +123,7 @@ impl ContractionGraph { // currently we stick to the reordered graph and also translate the query node ids. // TODO make more explicit - ((FirstOutGraph::from_adjancecy_lists(outgoing), FirstOutGraph::from_adjancecy_lists(incoming)), Some((forward_shortcut_middles, backward_shortcut_middles))) + ((OwnedGraph::from_adjancecy_lists(outgoing), OwnedGraph::from_adjancecy_lists(incoming)), Some((forward_shortcut_middles, backward_shortcut_middles))) } } @@ -179,7 +178,7 @@ impl<'a> PartialContractionGraph<'a> { } } -pub fn contract(graph: FirstOutGraph, node_order: Vec) -> ((FirstOutGraph, FirstOutGraph), Option<(Vec, Vec)>) { +pub fn contract LinkIterGraph<'a>>(graph: Graph, node_order: Vec) -> ((OwnedGraph, OwnedGraph), Option<(Vec, Vec)>) { let mut graph = ContractionGraph::new(graph, node_order); graph.contract(); graph.as_first_out_graphs() @@ -190,31 +189,60 @@ struct ForwardWrapper<'a> { graph: &'a PartialContractionGraph<'a> } -impl<'a> DijkstrableGraph for ForwardWrapper<'a> { +#[derive(Debug)] +struct BackwardWrapper<'a> { + graph: &'a PartialContractionGraph<'a> +} + +impl<'a> Graph for ForwardWrapper<'a> { fn num_nodes(&self) -> usize { self.graph.nodes.len() } +} - fn for_each_neighbor(&self, node: NodeId, f: &mut FnMut(Link)) { - for &(Link { node: target, weight }, _) in self.graph.nodes[node as usize].outgoing.iter() { - f(Link { node: target - self.graph.id_offset, weight }); - } +impl<'a> Graph for BackwardWrapper<'a> { + fn num_nodes(&self) -> usize { + self.graph.nodes.len() } } +// workaround until we get an implementation of https://github.com/rust-lang/rfcs/pull/2071 #[derive(Debug)] -struct BackwardWrapper<'a> { - graph: &'a PartialContractionGraph<'a> +struct LinkMappingIterator<'a> { + iter: std::slice::Iter<'a, (Link, NodeId)>, + offset: NodeId, } -impl<'a> DijkstrableGraph for BackwardWrapper<'a> { - fn num_nodes(&self) -> usize { - self.graph.nodes.len() +impl<'a> Iterator for LinkMappingIterator<'a> { + type Item = Link; + + fn next(&mut self) -> Option { + match self.iter.next() { + Some(&(Link { node: target, weight }, _)) => Some(Link { node: target - self.offset, weight }), + None => None, + } } +} + +use std; +impl<'a, 'b> LinkIterGraph<'b> for ForwardWrapper<'a> { + type Iter = LinkMappingIterator<'b>; + + fn neighbor_iter(&'b self, node: NodeId) -> Self::Iter { + LinkMappingIterator { + iter: self.graph.nodes[node as usize].outgoing.iter(), + offset: self.graph.id_offset + } + } +} + +impl<'a, 'b> LinkIterGraph<'b> for BackwardWrapper<'a> { + type Iter = LinkMappingIterator<'b>; - fn for_each_neighbor(&self, node: NodeId, f: &mut FnMut(Link)) { - for &(Link { node: target, weight }, _) in self.graph.nodes[node as usize].incoming.iter() { - f(Link { node: target - self.graph.id_offset, weight }); + fn neighbor_iter(&'b self, node: NodeId) -> Self::Iter { + LinkMappingIterator { + iter: self.graph.nodes[node as usize].incoming.iter(), + offset: self.graph.id_offset } } } diff --git a/engine/src/shortest_path/mod.rs b/engine/src/shortest_path/mod.rs index 1d4cdb68..f42a1edf 100644 --- a/engine/src/shortest_path/mod.rs +++ b/engine/src/shortest_path/mod.rs @@ -1,8 +1,10 @@ -use super::graph::*; -use self::stepped_dijkstra::{SteppedDijkstra, QueryProgress, State}; +use graph::*; mod timestamped_vector; mod stepped_dijkstra; + +use self::stepped_dijkstra::{SteppedDijkstra, QueryProgress, State}; + pub mod contraction_hierarchy; pub mod query; @@ -11,13 +13,3 @@ pub struct Query { from: NodeId, to: NodeId } - -pub trait DijkstrableGraph { - fn num_nodes(&self) -> usize; - // not particularily liking this interface, would be much nicer to return an iterator - // sadly we would have to box it, which would be problematic in terms of performance - // even the impl trait functionality on nightly won't allow generic return types on traits - // which makes sense when you think about it, because it would need to return something - // which does dynamic dispath, which is exactly what the boxing would do... - fn for_each_neighbor(&self, node: NodeId, f: &mut FnMut(Link)); -} diff --git a/engine/src/shortest_path/query/async/bidirectional_dijkstra.rs b/engine/src/shortest_path/query/async/bidirectional_dijkstra.rs index ba1a3ec5..119a1f86 100644 --- a/engine/src/shortest_path/query/async/bidirectional_dijkstra.rs +++ b/engine/src/shortest_path/query/async/bidirectional_dijkstra.rs @@ -37,7 +37,7 @@ pub struct Server { } impl Server { - pub fn new(graph: Graph) -> Server { + pub fn new LinkIterGraph<'a> + Send + 'static>(graph: Graph) -> Server { let (forward_query_sender, forward_query_receiver) = channel(); let (forward_progress_sender, forward_progress_receiver) = channel(); let (backward_query_sender, backward_query_receiver) = channel(); @@ -69,7 +69,8 @@ impl Server { } } - fn spawn_direction_worker(graph: Graph, + fn spawn_direction_worker LinkIterGraph<'a> + Send + 'static>( + graph: Graph, query_receiver: Receiver<(ServerControl, u32)>, progress_sender: Sender<(QueryProgress, u32)>, distances_pointer: Arc>, diff --git a/engine/src/shortest_path/query/async/dijkstra.rs b/engine/src/shortest_path/query/async/dijkstra.rs index 5864d171..6366246a 100644 --- a/engine/src/shortest_path/query/async/dijkstra.rs +++ b/engine/src/shortest_path/query/async/dijkstra.rs @@ -7,7 +7,7 @@ pub struct Server { } impl Server { - pub fn new(graph: Graph) -> Server { + pub fn new LinkIterGraph<'a> + Send + 'static>(graph: Graph) -> Server { let (query_sender, query_receiver) = channel(); let (progress_sender, progress_receiver) = channel(); diff --git a/engine/src/shortest_path/query/bidirectional_dijkstra.rs b/engine/src/shortest_path/query/bidirectional_dijkstra.rs index 8e3e5525..8b6eb104 100644 --- a/engine/src/shortest_path/query/bidirectional_dijkstra.rs +++ b/engine/src/shortest_path/query/bidirectional_dijkstra.rs @@ -2,7 +2,7 @@ use std::collections::LinkedList; use super::*; #[derive(Debug)] -pub struct Server { +pub struct Server LinkIterGraph<'a>, H: for<'a> LinkIterGraph<'a>> { pub forward_dijkstra: SteppedDijkstra, pub backward_dijkstra: SteppedDijkstra, pub tentative_distance: Weight, @@ -10,8 +10,8 @@ pub struct Server { pub meeting_node: NodeId } -impl Server { - pub fn new(graph: Graph) -> Server { +impl LinkIterGraph<'a>> Server { + pub fn new(graph: G) -> Server { let reversed = graph.reverse(); Server { @@ -22,7 +22,9 @@ impl Server { meeting_node: 0 } } +} +impl LinkIterGraph<'a>, H: for<'a> LinkIterGraph<'a>> Server { pub fn distance(&mut self, from: NodeId, to: NodeId) -> Option { // initialize self.tentative_distance = INFINITY; diff --git a/engine/src/shortest_path/query/contraction_hierarchy.rs b/engine/src/shortest_path/query/contraction_hierarchy.rs index 3f84d100..52ea90b8 100644 --- a/engine/src/shortest_path/query/contraction_hierarchy.rs +++ b/engine/src/shortest_path/query/contraction_hierarchy.rs @@ -3,15 +3,15 @@ use super::*; #[derive(Debug)] pub struct Server { - forward_dijkstra: SteppedDijkstra, - backward_dijkstra: SteppedDijkstra, + forward_dijkstra: SteppedDijkstra, + backward_dijkstra: SteppedDijkstra, tentative_distance: Weight, meeting_node: NodeId, shortcut_middle_nodes: Option<(Vec, Vec)> } impl Server { - pub fn new(((up, down), shortcut_middle_nodes): ((Graph, Graph), Option<(Vec, Vec)>)) -> Server { + pub fn new(((up, down), shortcut_middle_nodes): ((OwnedGraph, OwnedGraph), Option<(Vec, Vec)>)) -> Server { Server { forward_dijkstra: SteppedDijkstra::new(up), backward_dijkstra: SteppedDijkstra::new(down), diff --git a/engine/src/shortest_path/query/dijkstra.rs b/engine/src/shortest_path/query/dijkstra.rs index b24caa39..6ce3a5af 100644 --- a/engine/src/shortest_path/query/dijkstra.rs +++ b/engine/src/shortest_path/query/dijkstra.rs @@ -3,12 +3,12 @@ use super::*; use std::collections::LinkedList; #[derive(Debug)] -pub struct Server { +pub struct Server LinkIterGraph<'a>> { dijkstra: SteppedDijkstra, } -impl Server { - pub fn new(graph: Graph) -> Server { +impl LinkIterGraph<'a>> Server { + pub fn new(graph: Graph) -> Server { Server { dijkstra: SteppedDijkstra::new(graph) } diff --git a/engine/src/shortest_path/query/mod.rs b/engine/src/shortest_path/query/mod.rs index d89ad29e..314241ca 100644 --- a/engine/src/shortest_path/query/mod.rs +++ b/engine/src/shortest_path/query/mod.rs @@ -1,5 +1,4 @@ use super::*; -use graph::first_out_graph::FirstOutGraph as Graph; pub mod async; pub mod dijkstra; diff --git a/engine/src/shortest_path/stepped_dijkstra.rs b/engine/src/shortest_path/stepped_dijkstra.rs index 8e567c21..ca965c60 100644 --- a/engine/src/shortest_path/stepped_dijkstra.rs +++ b/engine/src/shortest_path/stepped_dijkstra.rs @@ -1,6 +1,6 @@ use super::*; +use self::timestamped_vector::TimestampedVector; use index_heap::{IndexdMinHeap, Indexing}; -use super::timestamped_vector::TimestampedVector; #[derive(Debug, Clone)] pub enum QueryProgress { @@ -21,7 +21,7 @@ impl Indexing for State { } #[derive(Debug)] -pub struct SteppedDijkstra { +pub struct SteppedDijkstra LinkIterGraph<'a>> { graph: Graph, distances: TimestampedVector, predecessors: Vec, @@ -32,7 +32,7 @@ pub struct SteppedDijkstra { result: Option> } -impl SteppedDijkstra { +impl LinkIterGraph<'a>> SteppedDijkstra { pub fn new(graph: Graph) -> SteppedDijkstra { let n = graph.num_nodes(); @@ -80,29 +80,23 @@ impl SteppedDijkstra { return QueryProgress::Done(Some(distance)); } - // these are necessary because otherwise the borrow checker could not figure out - // that we're only borrowing parts of self - let closest_node_priority_queue = &mut self.closest_node_priority_queue; - let distances = &mut self.distances; - let predecessors = &mut self.predecessors; - // For each node we can reach, see if we can find a way with // a lower distance going through this node - self.graph.for_each_neighbor(node, &mut |edge: Link| { + for edge in self.graph.neighbor_iter(node) { let next = State { distance: distance + edge.weight, node: edge.node }; // If so, add it to the frontier and continue - if next.distance < distances[next.node as usize] { + if next.distance < self.distances[next.node as usize] { // Relaxation, we have now found a better way - distances.set(next.node as usize, next.distance); - predecessors[next.node as usize] = node; - if closest_node_priority_queue.contains_index(next.as_index()) { - closest_node_priority_queue.decrease_key(next); + self.distances.set(next.node as usize, next.distance); + self.predecessors[next.node as usize] = node; + if self.closest_node_priority_queue.contains_index(next.as_index()) { + self.closest_node_priority_queue.decrease_key(next); } else { - closest_node_priority_queue.push(next); + self.closest_node_priority_queue.push(next); } } - }); + } QueryProgress::Progress(State { distance, node }) } else {