Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dedup v2 #5

Merged
merged 10 commits into from
Jan 19, 2018
26 changes: 26 additions & 0 deletions engine/src/as_slice.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use std::sync::Arc;

pub trait AsSlice<T> {
fn as_slice(&self) -> &[T];
}

impl<V> AsSlice<V> for Vec<V> where
{
fn as_slice(&self) -> &[V] {
&self[..]
}
}

impl<'a, V> AsSlice<V> for &'a [V] where
{
fn as_slice(&self) -> &[V] {
self
}
}

impl<V> AsSlice<V> for Arc<Vec<V>> where
{
fn as_slice(&self) -> &[V] {
&self[..]
}
}
140 changes: 70 additions & 70 deletions engine/src/graph/first_out_graph.rs
Original file line number Diff line number Diff line change
@@ -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<FirstOutContainer, HeadContainer, WeightContainer> where
FirstOutContainer: AsSlice<u32>,
HeadContainer: AsSlice<NodeId>,
WeightContainer: AsSlice<Weight>,
{
// index of first edge of each node +1 entry in the end
first_out: Vec<u32>,
first_out: FirstOutContainer,
// the node ids to which each edge points
head: Vec<NodeId>,
head: HeadContainer,
// the weight of each edge
weight: Vec<Weight>
weight: WeightContainer,
}

impl FirstOutGraph {
pub fn new(first_out: Vec<u32>, head: Vec<NodeId>, weight: Vec<Weight>) -> 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<u32>, Vec<NodeId>, Vec<Weight>>;

FirstOutGraph {
first_out, head, weight
}
impl<FirstOutContainer, HeadContainer, WeightContainer> FirstOutGraph<FirstOutContainer, HeadContainer, WeightContainer> where
FirstOutContainer: AsSlice<u32>,
HeadContainer: AsSlice<NodeId>,
WeightContainer: AsSlice<Weight>,
{
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<FirstOutContainer, HeadContainer, WeightContainer> {
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<Vec<Link>>) -> 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<Vec<Link>>) -> 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;
Expand All @@ -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::iter::Zip<std::slice::Iter<NodeId>, std::slice::Iter<Weight>>, 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<usize> {
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<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::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<u32>) -> (FirstOutGraph, FirstOutGraph) {
let mut up: Vec<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::new() ).collect();
let mut down: Vec<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::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<FirstOutContainer, HeadContainer, WeightContainer> Graph for FirstOutGraph<FirstOutContainer, HeadContainer, WeightContainer> where
FirstOutContainer: AsSlice<u32>,
HeadContainer: AsSlice<NodeId>,
WeightContainer: AsSlice<Weight>,
{
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<FirstOutContainer, HeadContainer, WeightContainer> where
FirstOutContainer: AsSlice<u32>,
HeadContainer: AsSlice<NodeId>,
WeightContainer: AsSlice<Weight>,
{
type Iter = std::iter::Map<std::iter::Zip<std::slice::Iter<'a, NodeId>, 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<FirstOutContainer, HeadContainer, WeightContainer> RandomLinkAccessGraph for FirstOutGraph<FirstOutContainer, HeadContainer, WeightContainer> where
FirstOutContainer: AsSlice<u32>,
HeadContainer: AsSlice<NodeId>,
WeightContainer: AsSlice<Weight>,
{
fn edge_index(&self, from: NodeId, to: NodeId) -> Option<usize> {
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 )
}
}

Expand Down
49 changes: 48 additions & 1 deletion engine/src/graph/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<Item = Link> + '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<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::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<u32>) -> (OwnedGraph, OwnedGraph) {
let mut up: Vec<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::new() ).collect();
let mut down: Vec<Vec<Link>> = (0..self.num_nodes()).map(|_| Vec::<Link>::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<usize>;
}
5 changes: 2 additions & 3 deletions engine/src/import/here/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use ::graph::*;
use ::graph::first_out_graph::FirstOutGraph;
use ::rank_select_map::RankSelectMap;
use std::iter;
use std::str::FromStr;
Expand Down Expand Up @@ -130,7 +129,7 @@ pub trait RdfDataSource {
fn link_geometries(&self) -> Vec<RdfLinkGeometry>;
}

pub fn read_graph(source: &RdfDataSource) -> (FirstOutGraph, Vec<f32>, Vec<f32>) {
pub fn read_graph(source: &RdfDataSource) -> (OwnedGraph, Vec<f32>, Vec<f32>) {
println!("read nav links");
// start with all nav links
let mut nav_links: Vec<RdfNavLink> = source.nav_links();
Expand Down Expand Up @@ -274,7 +273,7 @@ pub fn read_graph(source: &RdfDataSource) -> (FirstOutGraph, Vec<f32>, Vec<f32>)
// 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)
Expand Down
2 changes: 1 addition & 1 deletion engine/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub fn read_into_vector<T>(filename: &str) -> Result<Vec<T>> {
Ok(buffer)
}

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

Expand Down
1 change: 1 addition & 0 deletions engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
20 changes: 11 additions & 9 deletions engine/src/main.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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::<Graph, Graph>::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");
Expand Down
Loading