use crate::index::{GraphIndex, GraphIndices, OptionalGraphIndex};
use crate::walks::{EdgeWalk, NodeWalk};
use std::iter::FromIterator;
pub mod subgraph;
pub trait GraphBase {
type NodeData;
type EdgeData;
type OptionalNodeIndex: OptionalGraphIndex<Self::NodeIndex>;
type OptionalEdgeIndex: OptionalGraphIndex<Self::EdgeIndex>;
type NodeIndex: GraphIndex<Self::OptionalNodeIndex>;
type EdgeIndex: GraphIndex<Self::OptionalEdgeIndex>;
fn new_none_optional_node_index(&self) -> Self::OptionalNodeIndex {
Self::OptionalNodeIndex::new_none()
}
fn new_none_optional_edge_index(&self) -> Self::OptionalEdgeIndex {
Self::OptionalEdgeIndex::new_none()
}
}
pub trait ImmutableGraphContainer: GraphBase {
fn node_indices(&self) -> GraphIndices<Self::NodeIndex, Self::OptionalNodeIndex>;
fn edge_indices(&self) -> GraphIndices<Self::EdgeIndex, Self::OptionalEdgeIndex>;
fn contains_node_index(&self, node_id: Self::NodeIndex) -> bool;
fn contains_edge_index(&self, edge_id: Self::EdgeIndex) -> bool;
fn node_count(&self) -> usize;
fn edge_count(&self) -> usize;
fn node_data(&self, node_id: Self::NodeIndex) -> &Self::NodeData;
fn edge_data(&self, edge_id: Self::EdgeIndex) -> &Self::EdgeData;
fn node_data_mut(&mut self, node_id: Self::NodeIndex) -> &mut Self::NodeData;
fn edge_data_mut(&mut self, edge_id: Self::EdgeIndex) -> &mut Self::EdgeData;
fn contains_edge_between(&self, from: Self::NodeIndex, to: Self::NodeIndex) -> bool;
fn edge_count_between(&self, from: Self::NodeIndex, to: Self::NodeIndex) -> usize;
fn edge_endpoints(&self, edge_id: Self::EdgeIndex) -> Edge<Self::NodeIndex>;
fn is_empty(&self) -> bool {
debug_assert!(self.node_count() != 0 || self.edge_count() == 0);
self.node_count() == 0
}
}
pub trait MutableGraphContainer: ImmutableGraphContainer {
fn add_node(&mut self, node_data: Self::NodeData) -> Self::NodeIndex;
fn add_edge(
&mut self,
from: Self::NodeIndex,
to: Self::NodeIndex,
edge_data: Self::EdgeData,
) -> Self::EdgeIndex;
fn remove_node(&mut self, node_id: Self::NodeIndex) -> Option<Self::NodeData>;
fn remove_edge(&mut self, edge_id: Self::EdgeIndex) -> Option<Self::EdgeData>;
fn remove_edges_sorted(&mut self, edge_ids: &[Self::EdgeIndex]);
fn clear(&mut self);
}
pub trait NavigableGraph<'a>: ImmutableGraphContainer + Sized {
type OutNeighbors: Iterator<Item = Neighbor<Self::NodeIndex, Self::EdgeIndex>>;
type InNeighbors: Iterator<Item = Neighbor<Self::NodeIndex, Self::EdgeIndex>>;
type EdgesBetween: Iterator<Item = Self::EdgeIndex>;
fn out_neighbors(&'a self, node_id: Self::NodeIndex) -> Self::OutNeighbors;
fn in_neighbors(&'a self, node_id: Self::NodeIndex) -> Self::InNeighbors;
fn edges_between(
&'a self,
from_node_id: Self::NodeIndex,
to_node_id: Self::NodeIndex,
) -> Self::EdgesBetween;
fn out_degree(&'a self, node_id: Self::NodeIndex) -> usize {
self.out_neighbors(node_id).count()
}
fn in_degree(&'a self, node_id: Self::NodeIndex) -> usize {
self.in_neighbors(node_id).count()
}
fn is_biunivocal_node(&'a self, node_id: Self::NodeIndex) -> bool {
self.in_degree(node_id) == 1 && self.out_degree(node_id) == 1
}
fn is_bivalent_node(&'a self, node_id: Self::NodeIndex) -> bool {
self.in_degree(node_id) > 1 && self.out_degree(node_id) > 1
}
fn is_split_edge(&'a self, edge_id: Self::EdgeIndex) -> bool {
self.out_degree(self.edge_endpoints(edge_id).from_node) > 1
}
fn is_join_edge(&'a self, edge_id: Self::EdgeIndex) -> bool {
self.in_degree(self.edge_endpoints(edge_id).to_node) > 1
}
fn is_split_node(&'a self, node_id: Self::NodeIndex) -> bool {
self.out_degree(node_id) > 1
}
fn is_join_node(&'a self, node_id: Self::NodeIndex) -> bool {
self.in_degree(node_id) > 1
}
}
pub trait WalkableGraph: GraphBase + Sized {
fn create_node_walk<
WalkType: for<'a> NodeWalk<'a, Self, SubwalkType> + FromIterator<Self::NodeIndex>,
SubwalkType: for<'a> NodeWalk<'a, Self, SubwalkType> + ?Sized,
>(
&self,
walk: &[Self::NodeIndex],
) -> WalkType {
walk.iter().copied().collect()
}
fn create_empty_node_walk<
WalkType: for<'a> NodeWalk<'a, Self, SubwalkType> + Default,
SubwalkType: for<'a> NodeWalk<'a, Self, SubwalkType> + ?Sized,
>(
&self,
) -> WalkType {
Default::default()
}
fn create_edge_walk<
WalkType: for<'a> EdgeWalk<'a, Self, SubwalkType> + FromIterator<Self::EdgeIndex>,
SubwalkType: for<'a> EdgeWalk<'a, Self, SubwalkType> + ?Sized,
>(
&self,
walk: &[Self::EdgeIndex],
) -> WalkType {
walk.iter().copied().collect()
}
fn create_empty_edge_walk<
WalkType: for<'a> EdgeWalk<'a, Self, SubwalkType> + Default,
SubwalkType: for<'a> EdgeWalk<'a, Self, SubwalkType> + ?Sized,
>(
&self,
) -> WalkType {
Default::default()
}
}
impl<Graph: GraphBase> WalkableGraph for Graph {}
pub trait StaticGraph:
ImmutableGraphContainer + for<'a> NavigableGraph<'a> + WalkableGraph
{
}
impl<T: ImmutableGraphContainer + for<'a> NavigableGraph<'a> + WalkableGraph> StaticGraph for T {}
pub trait DynamicGraph: StaticGraph + MutableGraphContainer {}
impl<T: StaticGraph + MutableGraphContainer> DynamicGraph for T {}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Edge<NodeIndex> {
pub from_node: NodeIndex,
pub to_node: NodeIndex,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Neighbor<NodeIndex, EdgeIndex> {
pub edge_id: EdgeIndex,
pub node_id: NodeIndex,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum NodeOrEdge<NodeIndex, EdgeIndex> {
Node(NodeIndex),
Edge(EdgeIndex),
}