use crate::index::{GraphIndex, 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 {
type NodeIndices<'a>: Iterator<Item = Self::NodeIndex>
where
Self: 'a;
type EdgeIndices<'a>: Iterator<Item = Self::EdgeIndex>
where
Self: 'a;
type NodeIndicesCopied: Iterator<Item = Self::NodeIndex>;
type EdgeIndicesCopied: Iterator<Item = Self::EdgeIndex>;
fn node_indices(&self) -> Self::NodeIndices<'_>;
fn edge_indices(&self) -> Self::EdgeIndices<'_>;
fn node_indices_copied(&self) -> Self::NodeIndicesCopied;
fn edge_indices_copied(&self) -> Self::EdgeIndicesCopied;
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 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
}
fn do_all_edges_endpoints_exist(&self) -> bool {
for edge_id in self.edge_indices() {
let Edge { from_node, to_node } = self.edge_endpoints(edge_id);
if !self.contains_node_index(from_node) || !self.contains_node_index(to_node) {
return false;
}
}
true
}
}
pub trait MutableGraphContainer: ImmutableGraphContainer {
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 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_nodes_sorted_slice(&mut self, node_ids: &[Self::NodeIndex]) {
let mut previous_node_id = None;
for node_id in node_ids.iter().copied().rev() {
if let Some(previous_node_id) = previous_node_id {
debug_assert!(previous_node_id > node_id);
}
previous_node_id = Some(node_id);
self.remove_node(node_id);
}
}
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: ImmutableGraphContainer + Sized {
type OutNeighbors<'a>: Iterator<Item = Neighbor<Self::NodeIndex, Self::EdgeIndex>>
where
Self: 'a;
type InNeighbors<'a>: Iterator<Item = Neighbor<Self::NodeIndex, Self::EdgeIndex>>
where
Self: 'a;
type EdgesBetween<'a>: Iterator<Item = Self::EdgeIndex>
where
Self: 'a;
fn out_neighbors(&self, node_id: Self::NodeIndex) -> Self::OutNeighbors<'_>;
fn in_neighbors(&self, node_id: Self::NodeIndex) -> Self::InNeighbors<'_>;
fn edges_between(
&self,
from_node_id: Self::NodeIndex,
to_node_id: Self::NodeIndex,
) -> Self::EdgesBetween<'_>;
fn contains_edge_between(&self, from: Self::NodeIndex, to: Self::NodeIndex) -> bool {
self.edges_between(from, to).next().is_some()
}
fn edge_count_between(&self, from: Self::NodeIndex, to: Self::NodeIndex) -> usize {
self.edges_between(from, to).count()
}
fn out_degree(&self, node_id: Self::NodeIndex) -> usize {
self.out_neighbors(node_id).count()
}
fn in_degree(&self, node_id: Self::NodeIndex) -> usize {
self.in_neighbors(node_id).count()
}
fn is_biunivocal_node(&self, node_id: Self::NodeIndex) -> bool {
self.in_degree(node_id) == 1 && self.out_degree(node_id) == 1
}
fn is_bivalent_node(&self, node_id: Self::NodeIndex) -> bool {
self.in_degree(node_id) > 1 && self.out_degree(node_id) > 1
}
fn is_split_edge(&self, edge_id: Self::EdgeIndex) -> bool {
self.out_degree(self.edge_endpoints(edge_id).from_node) > 1
}
fn is_join_edge(&self, edge_id: Self::EdgeIndex) -> bool {
self.in_degree(self.edge_endpoints(edge_id).to_node) > 1
}
fn is_split_node(&self, node_id: Self::NodeIndex) -> bool {
self.out_degree(node_id) > 1
}
fn is_join_node(&self, node_id: Self::NodeIndex) -> bool {
self.in_degree(node_id) > 1
}
}
pub trait WalkableGraph: GraphBase + Sized {
fn create_node_walk<
WalkType: NodeWalk<Self, SubwalkType> + FromIterator<Self::NodeIndex>,
SubwalkType: NodeWalk<Self, SubwalkType> + ?Sized,
>(
&self,
walk: &[Self::NodeIndex],
) -> WalkType {
walk.iter().copied().collect()
}
fn create_empty_node_walk<
WalkType: NodeWalk<Self, SubwalkType> + Default,
SubwalkType: NodeWalk<Self, SubwalkType> + ?Sized,
>(
&self,
) -> WalkType {
Default::default()
}
fn create_edge_walk<
WalkType: EdgeWalk<Self, SubwalkType> + FromIterator<Self::EdgeIndex>,
SubwalkType: EdgeWalk<Self, SubwalkType> + ?Sized,
>(
&self,
walk: &[Self::EdgeIndex],
) -> WalkType {
walk.iter().copied().collect()
}
fn create_empty_edge_walk<
WalkType: EdgeWalk<Self, SubwalkType> + Default,
SubwalkType: EdgeWalk<Self, SubwalkType> + ?Sized,
>(
&self,
) -> WalkType {
Default::default()
}
}
impl<Graph: GraphBase> WalkableGraph for Graph {}
pub trait StaticGraph: ImmutableGraphContainer + NavigableGraph + WalkableGraph {}
impl<T: ImmutableGraphContainer + NavigableGraph + 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),
}