Skip to content

Commit ec0f698

Browse files
authored
Merge pull request #5 from SDEagle/dedup_v2
Dedup v2
2 parents 5e3ae11 + 2310819 commit ec0f698

File tree

16 files changed

+235
-144
lines changed

16 files changed

+235
-144
lines changed

engine/src/as_slice.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use std::sync::Arc;
2+
3+
pub trait AsSlice<T> {
4+
fn as_slice(&self) -> &[T];
5+
}
6+
7+
impl<V> AsSlice<V> for Vec<V> where
8+
{
9+
fn as_slice(&self) -> &[V] {
10+
&self[..]
11+
}
12+
}
13+
14+
impl<'a, V> AsSlice<V> for &'a [V] where
15+
{
16+
fn as_slice(&self) -> &[V] {
17+
self
18+
}
19+
}
20+
21+
impl<V> AsSlice<V> for Arc<Vec<V>> where
22+
{
23+
fn as_slice(&self) -> &[V] {
24+
&self[..]
25+
}
26+
}

engine/src/graph/first_out_graph.rs

Lines changed: 70 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,57 @@
11
use super::*;
2+
use as_slice::AsSlice;
23
use ::io;
34
use std::io::Result;
45
use std::path::Path;
56

67
#[derive(Debug, Clone)]
7-
pub struct FirstOutGraph {
8+
pub struct FirstOutGraph<FirstOutContainer, HeadContainer, WeightContainer> where
9+
FirstOutContainer: AsSlice<u32>,
10+
HeadContainer: AsSlice<NodeId>,
11+
WeightContainer: AsSlice<Weight>,
12+
{
813
// index of first edge of each node +1 entry in the end
9-
first_out: Vec<u32>,
14+
first_out: FirstOutContainer,
1015
// the node ids to which each edge points
11-
head: Vec<NodeId>,
16+
head: HeadContainer,
1217
// the weight of each edge
13-
weight: Vec<Weight>
18+
weight: WeightContainer,
1419
}
1520

16-
impl FirstOutGraph {
17-
pub fn new(first_out: Vec<u32>, head: Vec<NodeId>, weight: Vec<Weight>) -> FirstOutGraph {
18-
assert_eq!(*first_out.first().unwrap(), 0);
19-
assert_eq!(*first_out.last().unwrap() as usize, head.len());
20-
assert_eq!(weight.len(), head.len());
21+
pub type OwnedGraph = FirstOutGraph<Vec<u32>, Vec<NodeId>, Vec<Weight>>;
2122

22-
FirstOutGraph {
23-
first_out, head, weight
24-
}
23+
impl<FirstOutContainer, HeadContainer, WeightContainer> FirstOutGraph<FirstOutContainer, HeadContainer, WeightContainer> where
24+
FirstOutContainer: AsSlice<u32>,
25+
HeadContainer: AsSlice<NodeId>,
26+
WeightContainer: AsSlice<Weight>,
27+
{
28+
fn first_out(&self) -> &[u32] { self.first_out.as_slice() }
29+
fn head(&self) -> &[u32] { self.head.as_slice() }
30+
fn weight(&self) -> &[u32] { self.weight.as_slice() }
31+
32+
pub fn new(first_out: FirstOutContainer, head: HeadContainer, weight: WeightContainer) -> FirstOutGraph<FirstOutContainer, HeadContainer, WeightContainer> {
33+
assert_eq!(*first_out.as_slice().first().unwrap(), 0);
34+
assert_eq!(*first_out.as_slice().last().unwrap() as usize, head.as_slice().len());
35+
assert_eq!(weight.as_slice().len(), head.as_slice().len());
36+
37+
FirstOutGraph { first_out, head, weight }
38+
}
39+
40+
pub fn write_to_dir(&self, dir: &str) -> Result<()> {
41+
let path = Path::new(dir);
42+
let res1 = io::write_vector_to_file(path.join("first_out").to_str().unwrap(), self.first_out());
43+
let res2 = io::write_vector_to_file(path.join("head").to_str().unwrap(), self.head());
44+
let res3 = io::write_vector_to_file(path.join("weights").to_str().unwrap(), self.weight());
45+
res1.and(res2).and(res3)
2546
}
2647

27-
pub fn from_adjancecy_lists(adjancecy_lists: Vec<Vec<Link>>) -> FirstOutGraph {
48+
pub fn decompose(self) -> (FirstOutContainer, HeadContainer, WeightContainer) {
49+
(self.first_out, self.head, self.weight)
50+
}
51+
}
52+
53+
impl OwnedGraph {
54+
pub fn from_adjancecy_lists(adjancecy_lists: Vec<Vec<Link>>) -> OwnedGraph {
2855
// create first_out array for reversed by doing a prefix sum over the adjancecy list sizes
2956
let first_out = std::iter::once(0).chain(adjancecy_lists.iter().scan(0, |state, incoming_links| {
3057
*state = *state + incoming_links.len() as u32;
@@ -37,70 +64,43 @@ impl FirstOutGraph {
3764
.flat_map(|neighbors| neighbors.into_iter().map(|Link { node, weight }| (node, weight) ) )
3865
.unzip();
3966

40-
FirstOutGraph::new(first_out, head, weight)
41-
}
42-
43-
pub fn neighbor_iter(&self, node: NodeId) -> std::iter::Map<std::iter::Zip<std::slice::Iter<NodeId>, std::slice::Iter<Weight>>, fn((&NodeId, &Weight))->Link> {
44-
let range = (self.first_out[node as usize] as usize)..(self.first_out[(node + 1) as usize] as usize);
45-
self.head[range.clone()].iter()
46-
.zip(self.weight[range].iter())
47-
.map( |(&neighbor, &weight)| Link { node: neighbor, weight: weight } )
48-
}
49-
50-
pub fn edge_index(&self, from: NodeId, to: NodeId) -> Option<usize> {
51-
let first_out = self.first_out[from as usize] as usize;
52-
self.neighbor_iter(from).enumerate().find(|&(_, Link { node, .. })| node == to).map(|(i, _)| first_out + i )
53-
}
54-
55-
pub fn reverse(&self) -> FirstOutGraph {
56-
// vector of adjacency lists for the reverse graph
57-
let mut reversed: Vec<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::new() ).collect();
58-
59-
// iterate over all edges and insert them in the reversed structure
60-
for node in 0..(self.num_nodes() as NodeId) {
61-
for Link { node: neighbor, weight } in self.neighbor_iter(node) {
62-
reversed[neighbor as usize].push(Link { node, weight });
63-
}
64-
}
65-
FirstOutGraph::from_adjancecy_lists(reversed)
66-
}
67-
68-
pub fn ch_split(self, node_ranks: &Vec<u32>) -> (FirstOutGraph, FirstOutGraph) {
69-
let mut up: Vec<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::new() ).collect();
70-
let mut down: Vec<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::new() ).collect();
71-
72-
// iterate over all edges and insert them in the reversed structure
73-
for node in 0..(self.num_nodes() as NodeId) {
74-
for Link { node: neighbor, weight } in self.neighbor_iter(node) {
75-
if node_ranks[node as usize] < node_ranks[neighbor as usize] {
76-
up[node as usize].push(Link { node: neighbor, weight });
77-
} else {
78-
down[neighbor as usize].push(Link { node, weight });
79-
}
80-
}
81-
}
82-
83-
(FirstOutGraph::from_adjancecy_lists(up), FirstOutGraph::from_adjancecy_lists(down))
67+
OwnedGraph::new(first_out, head, weight)
8468
}
69+
}
8570

86-
pub fn write_to_dir(&self, dir: &str) -> Result<()> {
87-
let path = Path::new(dir);
88-
let res1 = io::write_vector_to_file(path.join("first_out").to_str().unwrap(), &self.first_out);
89-
let res2 = io::write_vector_to_file(path.join("head").to_str().unwrap(), &self.head);
90-
let res3 = io::write_vector_to_file(path.join("weights").to_str().unwrap(), &self.weight);
91-
res1.and(res2).and(res3)
71+
impl<FirstOutContainer, HeadContainer, WeightContainer> Graph for FirstOutGraph<FirstOutContainer, HeadContainer, WeightContainer> where
72+
FirstOutContainer: AsSlice<u32>,
73+
HeadContainer: AsSlice<NodeId>,
74+
WeightContainer: AsSlice<Weight>,
75+
{
76+
fn num_nodes(&self) -> usize {
77+
self.first_out().len() - 1
9278
}
9379
}
9480

95-
impl DijkstrableGraph for FirstOutGraph {
96-
fn num_nodes(&self) -> usize {
97-
self.first_out.len() - 1
81+
impl<'a, FirstOutContainer, HeadContainer, WeightContainer> LinkIterGraph<'a> for FirstOutGraph<FirstOutContainer, HeadContainer, WeightContainer> where
82+
FirstOutContainer: AsSlice<u32>,
83+
HeadContainer: AsSlice<NodeId>,
84+
WeightContainer: AsSlice<Weight>,
85+
{
86+
type Iter = std::iter::Map<std::iter::Zip<std::slice::Iter<'a, NodeId>, std::slice::Iter<'a, Weight>>, fn((&NodeId, &Weight))->Link>;
87+
88+
fn neighbor_iter(&'a self, node: NodeId) -> Self::Iter {
89+
let range = (self.first_out()[node as usize] as usize)..(self.first_out()[(node + 1) as usize] as usize);
90+
self.head()[range.clone()].iter()
91+
.zip(self.weight()[range].iter())
92+
.map( |(&neighbor, &weight)| Link { node: neighbor, weight: weight } )
9893
}
94+
}
9995

100-
fn for_each_neighbor(&self, node: NodeId, f: &mut FnMut(Link)) {
101-
for link in self.neighbor_iter(node) {
102-
f(link);
103-
}
96+
impl<FirstOutContainer, HeadContainer, WeightContainer> RandomLinkAccessGraph for FirstOutGraph<FirstOutContainer, HeadContainer, WeightContainer> where
97+
FirstOutContainer: AsSlice<u32>,
98+
HeadContainer: AsSlice<NodeId>,
99+
WeightContainer: AsSlice<Weight>,
100+
{
101+
fn edge_index(&self, from: NodeId, to: NodeId) -> Option<usize> {
102+
let first_out = self.first_out()[from as usize] as usize;
103+
self.neighbor_iter(from).enumerate().find(|&(_, Link { node, .. })| node == to).map(|(i, _)| first_out + i )
104104
}
105105
}
106106

engine/src/graph/mod.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use std;
2-
use shortest_path::DijkstrableGraph;
32

43
pub mod first_out_graph;
54

5+
pub use self::first_out_graph::{OwnedGraph, FirstOutGraph};
6+
67
pub type NodeId = u32;
78
pub type Weight = u32;
89
pub const INFINITY: u32 = std::u32::MAX / 2;
@@ -12,3 +13,49 @@ pub struct Link {
1213
pub node: NodeId,
1314
pub weight: Weight
1415
}
16+
17+
pub trait Graph {
18+
fn num_nodes(&self) -> usize;
19+
}
20+
21+
pub trait LinkIterGraph<'a>: Graph {
22+
type Iter: Iterator<Item = Link> + 'a; // fix with https://github.com/rust-lang/rfcs/pull/1598
23+
24+
fn neighbor_iter(&'a self, node: NodeId) -> Self::Iter;
25+
26+
fn reverse(&'a self) -> OwnedGraph {
27+
// vector of adjacency lists for the reverse graph
28+
let mut reversed: Vec<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::new() ).collect();
29+
30+
// iterate over all edges and insert them in the reversed structure
31+
for node in 0..(self.num_nodes() as NodeId) {
32+
for Link { node: neighbor, weight } in self.neighbor_iter(node) {
33+
reversed[neighbor as usize].push(Link { node, weight });
34+
}
35+
}
36+
37+
OwnedGraph::from_adjancecy_lists(reversed)
38+
}
39+
40+
fn ch_split(&'a self, node_ranks: &Vec<u32>) -> (OwnedGraph, OwnedGraph) {
41+
let mut up: Vec<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::new() ).collect();
42+
let mut down: Vec<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::new() ).collect();
43+
44+
// iterate over all edges and insert them in the reversed structure
45+
for node in 0..(self.num_nodes() as NodeId) {
46+
for Link { node: neighbor, weight } in self.neighbor_iter(node) {
47+
if node_ranks[node as usize] < node_ranks[neighbor as usize] {
48+
up[node as usize].push(Link { node: neighbor, weight });
49+
} else {
50+
down[neighbor as usize].push(Link { node, weight });
51+
}
52+
}
53+
}
54+
55+
(OwnedGraph::from_adjancecy_lists(up), OwnedGraph::from_adjancecy_lists(down))
56+
}
57+
}
58+
59+
pub trait RandomLinkAccessGraph {
60+
fn edge_index(&self, from: NodeId, to: NodeId) -> Option<usize>;
61+
}

engine/src/import/here/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use ::graph::*;
2-
use ::graph::first_out_graph::FirstOutGraph;
32
use ::rank_select_map::RankSelectMap;
43
use std::iter;
54
use std::str::FromStr;
@@ -130,7 +129,7 @@ pub trait RdfDataSource {
130129
fn link_geometries(&self) -> Vec<RdfLinkGeometry>;
131130
}
132131

133-
pub fn read_graph(source: &RdfDataSource) -> (FirstOutGraph, Vec<f32>, Vec<f32>) {
132+
pub fn read_graph(source: &RdfDataSource) -> (OwnedGraph, Vec<f32>, Vec<f32>) {
134133
println!("read nav links");
135134
// start with all nav links
136135
let mut nav_links: Vec<RdfNavLink> = source.nav_links();
@@ -274,7 +273,7 @@ pub fn read_graph(source: &RdfDataSource) -> (FirstOutGraph, Vec<f32>, Vec<f32>)
274273
// insert a zero at the beginning - this will shift all values one to the right
275274
first_out.insert(0, 0);
276275

277-
let graph = FirstOutGraph::new(first_out, head, weights);
276+
let graph = OwnedGraph::new(first_out, head, weights);
278277
let lat = nodes.iter().map(|node| ((node.lat as f64) / 100000.) as f32).collect();
279278
let lng = nodes.iter().map(|node| ((node.lon as f64) / 100000.) as f32).collect();
280279
(graph, lat, lng)

engine/src/io.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn read_into_vector<T>(filename: &str) -> Result<Vec<T>> {
2323
Ok(buffer)
2424
}
2525

26-
pub fn write_vector_to_file<T>(filename: &str, vector: &Vec<T>) -> Result<()> {
26+
pub fn write_vector_to_file<T>(filename: &str, vector: &[T]) -> Result<()> {
2727
let mut buffer = File::create(filename)?;
2828
let num_bytes = vector.len() * mem::size_of::<T>();
2929

engine/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub mod io;
1515
mod index_heap;
1616
pub mod rank_select_map;
1717
pub mod import;
18+
mod as_slice;
1819

1920
#[cfg(test)]
2021
mod tests {

engine/src/main.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use std::env;
22
use std::path::Path;
3+
use std::sync::Arc;
34

45
extern crate bmw_routing_engine;
56

67
extern crate time;
78

89
use bmw_routing_engine::*;
9-
use graph::first_out_graph::FirstOutGraph as Graph;
10-
use graph::INFINITY;
10+
use graph::*;
11+
use graph::first_out_graph::OwnedGraph as Graph;
1112
use shortest_path::query::dijkstra::Server as DijkServer;
1213
use shortest_path::query::bidirectional_dijkstra::Server as BiDijkServer;
1314
use shortest_path::query::async::dijkstra::Server as AsyncDijkServer;
@@ -24,19 +25,20 @@ fn main() {
2425
let arg = &args.next().expect("No directory arg given");
2526
let path = Path::new(arg);
2627

27-
let first_out = read_into_vector(path.join("first_out").to_str().unwrap()).expect("could not read first_out");
28-
let head = read_into_vector(path.join("head").to_str().unwrap()).expect("could not read head");
29-
let travel_time = read_into_vector(path.join("travel_time").to_str().unwrap()).expect("could not read travel_time");
28+
let first_out = Arc::new(read_into_vector(path.join("first_out").to_str().unwrap()).expect("could not read first_out"));
29+
let head = Arc::new(read_into_vector(path.join("head").to_str().unwrap()).expect("could not read head"));
30+
let travel_time = Arc::new(read_into_vector(path.join("travel_time").to_str().unwrap()).expect("could not read travel_time"));
3031

3132
let from = read_into_vector(path.join("test/source").to_str().unwrap()).expect("could not read source");
3233
let to = read_into_vector(path.join("test/target").to_str().unwrap()).expect("could not read target");
3334
let ground_truth = read_into_vector(path.join("test/travel_time_length").to_str().unwrap()).expect("could not read travel_time_length");
3435

35-
let graph = Graph::new(first_out, head, travel_time);
36+
let graph = FirstOutGraph::new(&first_out[..], &head[..], &travel_time[..]);
37+
let arcd_graph = FirstOutGraph::new(first_out.clone(), head.clone(), travel_time.clone());
3638
let mut simple_server = DijkServer::new(graph.clone());
37-
let mut bi_dir_server = BiDijkServer::<Graph, Graph>::new(graph.clone());
38-
let async_server = AsyncDijkServer::new(graph.clone());
39-
let mut async_bi_dir_server = AsyncBiDijkServer::new(graph.clone());
39+
let mut bi_dir_server = BiDijkServer::new(graph.clone());
40+
let async_server = AsyncDijkServer::new(arcd_graph.clone());
41+
let mut async_bi_dir_server = AsyncBiDijkServer::new(arcd_graph);
4042

4143
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");
4244
let ch_head = read_into_vector(path.join("travel_time_ch/head").to_str().unwrap()).expect("could not read travel_time_ch/head");

0 commit comments

Comments
 (0)