use crate::prelude::*;
use hashbrown::{HashMap, HashSet};
use itertools::Itertools;
use std::{hash::Hash, ops::Deref};
pub mod undirected;
pub use undirected::*;
pub mod directed;
pub use directed::*;
pub mod linalg;
pub use linalg::*;
pub mod common;
pub use common::*;
pub mod weights;
pub use weights::*;
pub mod wrappers;
pub use wrappers::*;
pub trait GraphBasics<'a> {
type NodeRef: Eq + Hash + Copy;
type EdgeRef: Eq + Hash + Copy;
type NodeIndex: Copy + Eq + Hash + From<usize> + Into<usize>;
type EdgeIndex: Copy + Eq + Hash + From<usize> + Into<usize>;
fn nodes(&'a self) -> impl Iterator<Item = Self::NodeRef>;
fn node_count(&'a self) -> usize;
fn edges(&'a self) -> impl Iterator<Item = Self::EdgeRef>;
fn edge_count(&'a self) -> usize;
fn is_directed(&self) -> bool;
fn node(&'a self, node_index: Self::NodeIndex) -> Option<Self::NodeRef>;
fn edge(&'a self, edge_index: Self::EdgeIndex) -> Option<Self::EdgeRef>;
fn node_iter(
&'a self,
node_index: impl Iterator<Item = Self::NodeIndex>,
) -> impl Iterator<Item = Option<Self::NodeRef>>;
fn edge_iter(
&'a self,
edge_index: impl Iterator<Item = Self::EdgeIndex>,
) -> impl Iterator<Item = Option<Self::EdgeRef>>;
}
#[macro_export]
macro_rules! impl_graph_basics {
($graph:ty, $node:ty, $edge:ty, $dir:literal $(, <$($gens:tt),*>)? $(, |$(const $cgens:ident: $ity:ty),*|)? ) => {
impl<'a, N, E$(, $($gens),*)?$(, $(const $cgens: $ity),*)?> GraphBasics<'a>
for $graph
where N: 'a + Clone + Eq + Hash,
E: 'a + Clone + Eq + Hash,
{
type NodeRef = $node;
type EdgeRef = $edge;
type EdgeIndex = usize;
type NodeIndex = usize;
fn nodes(&'a self) -> impl Iterator<Item = Self::NodeRef> {
self.nodes.iter()
}
fn edges(&'a self) -> impl Iterator<Item = Self::EdgeRef> {
self.edges.iter()
}
fn node_count(&'a self) -> usize {
self.nodes.len()
}
fn edge_count(&'a self) -> usize {
self.edges.len()
}
fn is_directed(&self) -> bool {
$dir
}
fn node(&'a self, node_index: <Self as GraphBasics<'a>>::NodeIndex) -> Option<<Self as GraphBasics<'a>>::NodeRef> {
self.nodes.get(node_index)
}
fn edge(&'a self, edge_index: <Self as GraphBasics<'a>>::EdgeIndex) -> Option<<Self as GraphBasics<'a>>::EdgeRef> {
self.edges.get(edge_index)
}
fn node_iter(&'a self, node_index: impl Iterator<Item = <Self as GraphBasics<'a>>::NodeIndex>) -> impl Iterator<Item = Option<<Self as GraphBasics<'a>>::NodeRef>> {
node_index.map(|i| self.node(i))
}
fn edge_iter(&'a self, edge_index: impl Iterator<Item = <Self as GraphBasics<'a>>::EdgeIndex>) -> impl Iterator<Item = Option<<Self as GraphBasics<'a>>::EdgeRef>> {
edge_index.map(|i| self.edge(i))
}
}
};
}
#[macro_export]
macro_rules! impl_graph_basics_wrapper {
(
$graph:ty,
$inner_g:ty,
$dir:literal,
$(, <$($gens:tt),*>)?
$(, |$(const $cgens:ident: $ity:ty),*|)?
) => {
impl<'a, N, E$(, $($gens),*)?$(, $(const $cgens: $ity),*)?> GraphBasics<'a>
for $graph
where N: 'a + Clone + Eq + Hash,
E: 'a + Clone + Eq + Hash,
{
type NodeRef = <$inner_g as GraphBasics<'a>>::NodeRef;
type EdgeRef = <$inner_g as GraphBasics<'a>>::EdgeRef;
type EdgeIndex = <$inner_g as GraphBasics<'a>>::EdgeIndex;
type NodeIndex = <$inner_g as GraphBasics<'a>>::NodeIndex;
fn nodes(&'a self) -> impl Iterator<Item = Self::NodeRef> {
self.inner.nodes.iter()
}
fn edges(&'a self) -> impl Iterator<Item = Self::EdgeRef> {
self.inner.edges.iter()
}
fn node_count(&'a self) -> usize {
self.inner.nodes.len()
}
fn edge_count(&'a self) -> usize {
self.inner.edges.len()
}
fn is_directed(&self) -> bool {
$dir
}
fn node(&'a self, node_index: <Self as GraphBasics<'a>>::NodeIndex) -> Option<<Self as GraphBasics<'a>>::NodeRef> {
self.inner.nodes.get(node_index)
}
fn edge(&'a self, edge_index: <Self as GraphBasics<'a>>::EdgeIndex) -> Option<<Self as GraphBasics<'a>>::EdgeRef> {
self.inner.edges.get(edge_index)
}
fn node_iter(&'a self, node_index: impl Iterator<Item = <Self as GraphBasics<'a>>::NodeIndex>) -> impl Iterator<Item = Option<<Self as GraphBasics<'a>>::NodeRef>> {
node_index.map(|i| self.inner.node(i))
}
fn edge_iter(&'a self, edge_index: impl Iterator<Item = <Self as GraphBasics<'a>>::EdgeIndex>) -> impl Iterator<Item = Option<<Self as GraphBasics<'a>>::EdgeRef>> {
edge_index.map(|i| self.inner.edge(i))
}
}
impl<'a, N: 'a, E: 'a$(, $($gens),*)?$(, $(const $cgens: $ity),*)?> GraphWrapper<'a> for $graph
where $inner_g: GraphBasics<'a>,
N: 'a + Clone + Eq + Hash,
E: 'a + Clone + Eq + Hash,{
type Inner = $inner_g;
fn into_inner(&'a self) -> &'a Self::Inner {
&self.inner
}
}
};
(
$graph:ty,
$inner_g:ty,
$dir:literal,
reduce E = $edge_weight:tt
$(, <$($gens:tt),*>)?
$(, |$(const $cgens:ident: $ity:ty),*|)?
) => {
impl<'a, N$(, $($gens),*)?$(, $(const $cgens: $ity),*)?> GraphBasics<'a>
for $graph
where N: 'a + Clone + Eq + Hash,
{
type NodeRef = <$inner_g as GraphBasics<'a>>::NodeRef;
type EdgeRef = <$inner_g as GraphBasics<'a>>::EdgeRef;
type EdgeIndex = <$inner_g as GraphBasics<'a>>::EdgeIndex;
type NodeIndex = <$inner_g as GraphBasics<'a>>::NodeIndex;
fn nodes(&'a self) -> impl Iterator<Item = Self::NodeRef> {
self.inner.nodes.iter()
}
fn edges(&'a self) -> impl Iterator<Item = Self::EdgeRef> {
self.inner.edges.iter()
}
fn node_count(&'a self) -> usize {
self.inner.nodes.len()
}
fn edge_count(&'a self) -> usize {
self.inner.edges.len()
}
fn is_directed(&self) -> bool {
$dir
}
fn node(&'a self, node_index: <Self as GraphBasics<'a>>::NodeIndex) -> Option<<Self as GraphBasics<'a>>::NodeRef> {
self.inner.nodes.get(node_index)
}
fn edge(&'a self, edge_index: <Self as GraphBasics<'a>>::EdgeIndex) -> Option<<Self as GraphBasics<'a>>::EdgeRef> {
self.inner.edges.get(edge_index)
}
fn node_iter(&'a self, node_index: impl Iterator<Item = <Self as GraphBasics<'a>>::NodeIndex>) -> impl Iterator<Item = Option<<Self as GraphBasics<'a>>::NodeRef>> {
node_index.map(|i| self.inner.node(i))
}
fn edge_iter(&'a self, edge_index: impl Iterator<Item = <Self as GraphBasics<'a>>::EdgeIndex>) -> impl Iterator<Item = Option<<Self as GraphBasics<'a>>::EdgeRef>> {
edge_index.map(|i| self.inner.edge(i))
}
}
impl<'a, N: 'a$(, $($gens),*)?$(, $(const $cgens: $ity),*)?> GraphWrapper<'a> for $graph
where $inner_g: GraphBasics<'a>,
N: 'a + Clone + Eq + Hash,{
type Inner = $inner_g;
fn into_inner(&'a self) -> &'a Self::Inner {
&self.inner
}
}
};
(
$graph:ty,
$inner_g:ty,
$dir:literal,
reduce N = $node_weight:tt
$(, <$($gens:tt),*>)?
$(, |$(const $cgens:ident: $ity:ty),*|)?
) => {
impl<'a, E$(, $($gens),*)?$(, $(const $cgens: $ity),*)?> GraphBasics<'a>
for $graph
where E: 'a + Clone + Eq + Hash,
{
type NodeRef = <$inner_g as GraphBasics<'a>>::NodeRef;
type EdgeRef = <$inner_g as GraphBasics<'a>>::EdgeRef;
type EdgeIndex = <$inner_g as GraphBasics<'a>>::EdgeIndex;
type NodeIndex = <$inner_g as GraphBasics<'a>>::NodeIndex;
fn nodes(&'a self) -> impl Iterator<Item = Self::NodeRef> {
self.inner.nodes.iter()
}
fn edges(&'a self) -> impl Iterator<Item = Self::EdgeRef> {
self.inner.edges.iter()
}
fn node_count(&'a self) -> usize {
self.inner.nodes.len()
}
fn edge_count(&'a self) -> usize {
self.inner.edges.len()
}
fn is_directed(&self) -> bool {
$dir
}
fn node(&'a self, node_index: <Self as GraphBasics<'a>>::NodeIndex) -> Option<<Self as GraphBasics<'a>>::NodeRef> {
self.inner.nodes.get(node_index)
}
fn edge(&'a self, edge_index: <Self as GraphBasics<'a>>::EdgeIndex) -> Option<<Self as GraphBasics<'a>>::EdgeRef> {
self.inner.edges.get(edge_index)
}
fn node_iter(&'a self, node_index: impl Iterator<Item = <Self as GraphBasics<'a>>::NodeIndex>) -> impl Iterator<Item = Option<<Self as GraphBasics<'a>>::NodeRef>> {
node_index.map(|i| self.inner.node(i))
}
fn edge_iter(&'a self, edge_index: impl Iterator<Item = <Self as GraphBasics<'a>>::EdgeIndex>) -> impl Iterator<Item = Option<<Self as GraphBasics<'a>>::EdgeRef>> {
edge_index.map(|i| self.inner.edge(i))
}
}
impl<'a, E: 'a$(, $($gens),*)?$(, $(const $cgens: $ity),*)?> GraphWrapper<'a> for $graph
where $inner_g: GraphBasics<'a>,
E: 'a + Clone + Eq + Hash,{
type Inner = $inner_g;
fn into_inner(&'a self) -> &'a Self::Inner {
&self.inner
}
}
};
(
$graph:ty,
$inner_g:ty,
$dir:literal
$(, <$($gens:tt),*>)?
$(, |$(const $cgens:ident: $ity:ty),*|)?
) => {
impl<'a, N, E$(, $($gens),*)?$(, $(const $cgens: $ity),*)?> GraphBasics<'a>
for $graph
where N: 'a + Clone + Eq + Hash,
E: 'a + Clone + Eq + Hash,
{
type NodeRef = <$inner_g as GraphBasics<'a>>::NodeRef;
type EdgeRef = <$inner_g as GraphBasics<'a>>::EdgeRef;
type EdgeIndex = <$inner_g as GraphBasics<'a>>::EdgeIndex;
type NodeIndex = <$inner_g as GraphBasics<'a>>::NodeIndex;
fn nodes(&'a self) -> impl Iterator<Item = Self::NodeRef> {
self.inner.nodes.iter()
}
fn edges(&'a self) -> impl Iterator<Item = Self::EdgeRef> {
self.inner.edges.iter()
}
fn node_count(&'a self) -> usize {
self.inner.nodes.len()
}
fn edge_count(&'a self) -> usize {
self.inner.edges.len()
}
fn is_directed(&self) -> bool {
$dir
}
fn node(&'a self, node_index: <Self as GraphBasics<'a>>::NodeIndex) -> Option<<Self as GraphBasics<'a>>::NodeRef> {
self.inner.nodes.get(node_index)
}
fn edge(&'a self, edge_index: <Self as GraphBasics<'a>>::EdgeIndex) -> Option<<Self as GraphBasics<'a>>::EdgeRef> {
self.inner.edges.get(edge_index)
}
fn node_iter(&'a self, node_index: impl Iterator<Item = <Self as GraphBasics<'a>>::NodeIndex>) -> impl Iterator<Item = Option<<Self as GraphBasics<'a>>::NodeRef>> {
node_index.map(|i| self.inner.node(i))
}
fn edge_iter(&'a self, edge_index: impl Iterator<Item = <Self as GraphBasics<'a>>::EdgeIndex>) -> impl Iterator<Item = Option<<Self as GraphBasics<'a>>::EdgeRef>> {
edge_index.map(|i| self.inner.edge(i))
}
}
impl<'a, N: 'a, E: 'a$(, $($gens),*)?$(, $(const $cgens: $ity),*)?> GraphWrapper<'a> for $graph
where $inner_g: GraphBasics<'a>,
N: 'a + Clone + Eq + Hash,
E: 'a + Clone + Eq + Hash,{
type Inner = $inner_g;
fn into_inner(&'a self) -> &'a Self::Inner {
&self.inner
}
}
};
}
impl<'a, T, U> GraphBasics<'a> for U
where
T: GraphBasics<'a> + 'a,
U: Deref<Target = T>,
{
type NodeRef = T::NodeRef;
type EdgeRef = T::EdgeRef;
type NodeIndex = T::NodeIndex;
type EdgeIndex = T::EdgeIndex;
fn nodes(&'a self) -> impl Iterator<Item = Self::NodeRef> {
(**self).nodes()
}
fn node_count(&'a self) -> usize {
(**self).node_count()
}
fn edges(&'a self) -> impl Iterator<Item = Self::EdgeRef> {
(**self).edges()
}
fn edge_count(&'a self) -> usize {
(**self).edge_count()
}
fn is_directed(&self) -> bool {
(**self).is_directed()
}
fn node(&'a self, node_index: Self::NodeIndex) -> Option<Self::NodeRef> {
(**self).node(node_index)
}
fn edge(&'a self, edge_index: Self::EdgeIndex) -> Option<Self::EdgeRef> {
(**self).edge(edge_index)
}
fn node_iter(
&'a self,
node_index: impl Iterator<Item = Self::NodeIndex>,
) -> impl Iterator<Item = Option<Self::NodeRef>> {
node_index.map(|i| (**self).node(i))
}
fn edge_iter(
&'a self,
edge_index: impl Iterator<Item = Self::EdgeIndex>,
) -> impl Iterator<Item = Option<Self::EdgeRef>> {
edge_index.map(|i| (**self).edge(i))
}
}
#[cfg(feature = "temporal")]
pub trait TemporalProperties<'a>: GraphBasics<'a> {
type Inner: GraphBasics<'a>;
fn step(&mut self) {
*self.get_time_mut() += 1;
}
fn get_time(&self) -> usize;
fn get_time_mut(&mut self) -> &mut usize;
fn snapshot(&'a self) -> &'a Self::Inner;
fn temporal_behaviour(
&self,
edge_index: <Self as GraphBasics<'a>>::EdgeIndex,
) -> Option<TemporalBehaviour>;
}
pub trait HypergraphBasics<'a>: GraphBasics<'a> {
fn uniform(&'a self) -> bool;
type DualType;
fn dual(&'a self) -> Self::DualType;
}
pub trait Generate<N, E, T: GraphType> {
fn from_file<P: AsRef<std::path::Path>>(path: P) -> Self;
fn random_hypergraph(node_count: usize, edges_by_size: HashMap<usize, usize>) -> Self;
fn random_weighted_hypergraph(
node_count: usize,
edges_by_size: HashMap<usize, usize>,
node_weight_sampler: impl Fn() -> N,
edge_weight_sampler: impl Fn() -> E,
) -> Self;
}
pub trait StatisticalFilters {}
pub trait Dynamics {}