use crate::algorithm::search::direction::Direction;
use crate::model::property::edge::Edge;
use crate::model::property::vertex::Vertex;
use crate::model::road_network::graph_error::GraphError;
use crate::model::road_network::{edge_id::EdgeId, vertex_id::VertexId};
use crate::util::compact_ordered_hash_map::CompactOrderedHashMap;
use std::path::Path;
use super::graph_loader::graph_from_files;
use allocative::Allocative;
#[derive(Debug, Allocative)]
pub struct Graph {
pub adj: Box<[CompactOrderedHashMap<EdgeId, VertexId>]>,
pub rev: Box<[CompactOrderedHashMap<EdgeId, VertexId>]>,
pub edges: Box<[Edge]>,
pub vertices: Box<[Vertex]>,
}
impl Graph {
pub fn from_files<P: AsRef<Path>>(
edge_list_csv: &P,
vertex_list_csv: &P,
n_edges: Option<usize>,
n_vertices: Option<usize>,
verbose: Option<bool>,
) -> Result<Graph, GraphError> {
graph_from_files(edge_list_csv, vertex_list_csv, n_edges, n_vertices, verbose)
}
pub fn n_edges(&self) -> usize {
self.edges.len()
}
pub fn n_vertices(&self) -> usize {
self.vertices.len()
}
pub fn edge_ids(&self) -> Box<dyn Iterator<Item = EdgeId>> {
let range = (0..self.n_edges()).map(EdgeId);
Box::new(range)
}
pub fn vertex_ids(&self) -> Box<dyn Iterator<Item = VertexId>> {
let range = (0..self.n_vertices()).map(VertexId);
Box::new(range)
}
pub fn get_edge(&self, edge_id: EdgeId) -> Result<&Edge, GraphError> {
match self.edges.get(edge_id.0) {
None => Err(GraphError::EdgeAttributeNotFound { edge_id }),
Some(edge) => Ok(edge),
}
}
pub fn get_vertex(&self, vertex_id: VertexId) -> Result<&Vertex, GraphError> {
match self.vertices.get(vertex_id.0) {
None => Err(GraphError::VertexAttributeNotFound { vertex_id }),
Some(vertex) => Ok(vertex),
}
}
pub fn out_edges(&self, src: VertexId) -> Result<Vec<EdgeId>, GraphError> {
match self.adj.get(src.0) {
None => Err(GraphError::VertexWithoutOutEdges { vertex_id: src }),
Some(out_map) => {
let edge_ids = out_map.keys().cloned().collect();
Ok(edge_ids)
}
}
}
pub fn out_edges_iter(
&self,
src: VertexId,
) -> Result<impl Iterator<Item = &EdgeId>, GraphError> {
match self.adj.get(src.0) {
None => Err(GraphError::VertexWithoutOutEdges { vertex_id: src }),
Some(out_map) => {
let edge_ids = out_map.keys();
Ok(edge_ids)
}
}
}
pub fn in_edges(&self, dst: VertexId) -> Result<Vec<EdgeId>, GraphError> {
match self.rev.get(dst.0) {
None => Err(GraphError::VertexWithoutInEdges { vertex_id: dst }),
Some(in_map) => {
let edge_ids = in_map.keys().cloned().collect();
Ok(edge_ids)
}
}
}
pub fn in_edges_iter(
&self,
dst: VertexId,
) -> Result<impl Iterator<Item = &EdgeId>, GraphError> {
match self.rev.get(dst.0) {
None => Err(GraphError::VertexWithoutInEdges { vertex_id: dst }),
Some(in_map) => {
let edge_ids = in_map.keys();
Ok(edge_ids)
}
}
}
pub fn src_vertex_id(&self, edge_id: EdgeId) -> Result<VertexId, GraphError> {
self.get_edge(edge_id).map(|e| e.src_vertex_id)
}
pub fn dst_vertex_id(&self, edge_id: EdgeId) -> Result<VertexId, GraphError> {
self.get_edge(edge_id).map(|e| e.dst_vertex_id)
}
pub fn incident_edges(
&self,
vertex_id: VertexId,
direction: Direction,
) -> Result<Vec<EdgeId>, GraphError> {
match direction {
Direction::Forward => self.out_edges(vertex_id),
Direction::Reverse => self.in_edges(vertex_id),
}
}
pub fn incident_vertex(
&self,
edge_id: EdgeId,
direction: Direction,
) -> Result<VertexId, GraphError> {
match direction {
Direction::Forward => self.dst_vertex_id(edge_id),
Direction::Reverse => self.src_vertex_id(edge_id),
}
}
pub fn edge_triplet_attrs(
&self,
edge_id: EdgeId,
) -> Result<(&Vertex, &Edge, &Vertex), GraphError> {
let edge = self.get_edge(edge_id)?;
let src = self.get_vertex(edge.src_vertex_id)?;
let dst = self.get_vertex(edge.dst_vertex_id)?;
Ok((src, edge, dst))
}
pub fn incident_triplets(
&self,
vertex_id: VertexId,
direction: Direction,
) -> Result<Vec<(VertexId, EdgeId, VertexId)>, GraphError> {
self.incident_edges(vertex_id, direction)?
.into_iter()
.map(|edge_id| {
let terminal_vid = self.incident_vertex(edge_id, direction)?;
Ok((vertex_id, edge_id, terminal_vid))
})
.collect()
}
pub fn incident_triplet_attributes(
&self,
vertex_id: VertexId,
direction: Direction,
) -> Result<Vec<(&Vertex, &Edge, &Vertex)>, GraphError> {
self.incident_triplets(vertex_id, direction)?
.iter()
.map(|(src_id, edge_id, dst_id)| {
let src = self.get_vertex(*src_id)?;
let edge = self.get_edge(*edge_id)?;
let dst = self.get_vertex(*dst_id)?;
Ok((src, edge, dst))
})
.collect()
}
}