pub trait Graph {
fn node_count(&self) -> usize;
fn neighbors(&self, node: usize) -> Vec<usize>;
fn out_degree(&self, node: usize) -> usize {
self.neighbors(node).len()
}
}
pub trait GraphRef {
fn node_count(&self) -> usize;
fn neighbors_ref(&self, node: usize) -> &[usize];
fn out_degree(&self, node: usize) -> usize {
self.neighbors_ref(node).len()
}
}
pub trait WeightedGraph: Graph {
fn edge_weight(&self, source: usize, target: usize) -> f64;
}
pub trait WeightedGraphRef {
fn node_count(&self) -> usize;
fn neighbors_and_weights_ref(&self, node: usize) -> (&[usize], &[f32]);
fn out_degree(&self, node: usize) -> usize {
self.neighbors_and_weights_ref(node).0.len()
}
}
pub struct AdjacencyMatrix<'a>(pub &'a [Vec<f64>]);
impl<'a> Graph for AdjacencyMatrix<'a> {
fn node_count(&self) -> usize {
self.0.len()
}
fn neighbors(&self, node: usize) -> Vec<usize> {
self.0[node]
.iter()
.enumerate()
.filter(|(_, &w)| w > 0.0)
.map(|(i, _)| i)
.collect()
}
}
impl<'a> WeightedGraph for AdjacencyMatrix<'a> {
fn edge_weight(&self, source: usize, target: usize) -> f64 {
self.0[source][target]
}
}
#[cfg(feature = "petgraph")]
impl<N, E, Ty, Ix> Graph for petgraph::Graph<N, E, Ty, Ix>
where
Ty: petgraph::EdgeType,
Ix: petgraph::graph::IndexType,
{
fn node_count(&self) -> usize {
self.node_count()
}
fn neighbors(&self, node: usize) -> Vec<usize> {
self.neighbors(petgraph::graph::NodeIndex::new(node))
.map(|idx| idx.index())
.collect()
}
}
#[cfg(feature = "petgraph")]
pub struct PetgraphRef {
neighbors: Vec<Vec<usize>>,
}
#[cfg(feature = "petgraph")]
impl PetgraphRef {
pub fn from_graph<N, E, Ty, Ix>(graph: &petgraph::Graph<N, E, Ty, Ix>) -> Self
where
Ty: petgraph::EdgeType,
Ix: petgraph::graph::IndexType,
{
let n = graph.node_count();
let neighbors: Vec<Vec<usize>> = (0..n)
.map(|i| {
graph
.neighbors(petgraph::graph::NodeIndex::new(i))
.map(|idx| idx.index())
.collect()
})
.collect();
Self { neighbors }
}
}
#[cfg(feature = "petgraph")]
impl GraphRef for PetgraphRef {
fn node_count(&self) -> usize {
self.neighbors.len()
}
fn neighbors_ref(&self, node: usize) -> &[usize] {
&self.neighbors[node]
}
}
#[cfg(feature = "petgraph")]
impl<N, Ty, Ix> WeightedGraph for petgraph::Graph<N, f64, Ty, Ix>
where
Ty: petgraph::EdgeType,
Ix: petgraph::graph::IndexType,
{
fn edge_weight(&self, source: usize, target: usize) -> f64 {
let s = petgraph::graph::NodeIndex::new(source);
let t = petgraph::graph::NodeIndex::new(target);
self.find_edge(s, t)
.map(|e| *self.edge_weight(e).unwrap_or(&0.0))
.unwrap_or(0.0)
}
}