pub mod edge;
pub mod graph;
pub mod node;
pub mod restriction;
pub use edge::{EdgeId, SheafEdge, SheafEdgeBuilder};
pub use graph::{
CoherenceEnergy, CoherenceFingerprint, GraphStats, IncrementalCoherence, Namespace, ScopeId,
SheafGraph, SheafGraphBuilder,
};
pub use node::{NodeId, NodeMetadata, SheafNode, SheafNodeBuilder, StateVector};
pub use restriction::{
CsrMatrix, MatrixStorage, RestrictionMap, RestrictionMapBuilder, RestrictionMapError,
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SheafSubgraph {
pub nodes: HashMap<NodeId, SheafNode>,
pub edges: HashMap<EdgeId, SheafEdge>,
pub center: Option<NodeId>,
pub hops: Option<usize>,
}
impl SheafSubgraph {
pub fn new() -> Self {
Self {
nodes: HashMap::new(),
edges: HashMap::new(),
center: None,
hops: None,
}
}
pub fn centered(center: NodeId, hops: usize) -> Self {
Self {
nodes: HashMap::new(),
edges: HashMap::new(),
center: Some(center),
hops: Some(hops),
}
}
pub fn add_node(&mut self, node: SheafNode) {
self.nodes.insert(node.id, node);
}
pub fn add_edge(&mut self, edge: SheafEdge) {
self.edges.insert(edge.id, edge);
}
pub fn has_node(&self, id: NodeId) -> bool {
self.nodes.contains_key(&id)
}
pub fn has_edge(&self, id: EdgeId) -> bool {
self.edges.contains_key(&id)
}
pub fn node_count(&self) -> usize {
self.nodes.len()
}
pub fn edge_count(&self) -> usize {
self.edges.len()
}
pub fn compute_energy(&self) -> f32 {
let mut total = 0.0;
for edge in self.edges.values() {
if let (Some(source), Some(target)) =
(self.nodes.get(&edge.source), self.nodes.get(&edge.target))
{
total +=
edge.weighted_residual_energy(source.state.as_slice(), target.state.as_slice());
}
}
total
}
pub fn from_graph(graph: &SheafGraph, center: NodeId, hops: usize) -> Self {
let mut subgraph = Self::centered(center, hops);
let mut visited = std::collections::HashSet::new();
let mut frontier = vec![center];
let mut depth = 0;
while depth <= hops && !frontier.is_empty() {
let mut next_frontier = Vec::new();
for node_id in frontier {
if visited.contains(&node_id) {
continue;
}
visited.insert(node_id);
if let Some(node) = graph.get_node(node_id) {
subgraph.add_node(node);
}
if depth < hops {
for edge_id in graph.edges_incident_to(node_id) {
if let Some(edge) = graph.get_edge(edge_id) {
let neighbor = if edge.source == node_id {
edge.target
} else {
edge.source
};
if !visited.contains(&neighbor) {
next_frontier.push(neighbor);
}
}
}
}
}
frontier = next_frontier;
depth += 1;
}
for node_id in &visited {
for edge_id in graph.edges_incident_to(*node_id) {
if let Some(edge) = graph.get_edge(edge_id) {
if visited.contains(&edge.source) && visited.contains(&edge.target) {
if !subgraph.has_edge(edge_id) {
subgraph.add_edge(edge);
}
}
}
}
}
subgraph
}
}
impl Default for SheafSubgraph {
fn default() -> Self {
Self::new()
}
}