wolf-graph 0.1.0

Data structures and algorithms for working with graphs with reference or value semantics.
Documentation
use std::borrow::Cow;

use anyhow::Result;

use crate::{EdgeID, Edges, Elements, NodeID, Nodes};

pub trait VisitableGraph {
    type GData;
    type NData: Clone;
    type EData: Clone;

    /// Returns a reference to the graph's data.
    fn data(&self) -> &Self::GData;
    /// Returns a reference to the node's data.
    fn node_data(&self, id: impl AsRef<NodeID>) -> Result<Cow<'static, Self::NData>>;
    /// Returns a reference to the edge's data.
    fn edge_data(&self, id: impl AsRef<EdgeID>) -> Result<Cow<'static, Self::EData>>;

    /// Returns `true` if the graph is empty.
    fn is_empty(&self) -> bool;
    /// Returns the number of nodes in the graph.
    fn node_count(&self) -> usize;
    /// Returns the number of edges in the graph.
    fn edge_count(&self) -> usize;

    /// Returns a set of all nodes in the graph.
    fn all_nodes(&self) -> Nodes;
    /// Returns a set of all edges in the graph.
    fn all_edges(&self) -> Edges;

    /// Returns the set of all elements in the graph.
    fn elements(&self) -> Elements {
        Elements::new(self.all_nodes(), self.all_edges())
    }

    /// Returns `true` if the graph contains the given node.
    fn has_node(&self, id: impl AsRef<NodeID>) -> bool;
    /// Returns `true` if the graph contains the given edge.
    fn has_edge(&self, id: impl AsRef<EdgeID>) -> bool;
    /// Returns `true` if the graph contains an edge from `source` to `target`.
    fn has_edge_from_to(&self, source: impl AsRef<NodeID>, target: impl AsRef<NodeID>) -> bool;
    /// Returns `true` if the graph contains an edge between `a` and `b`,
    /// regardless of direction.
    fn has_edge_between(&self, a: impl AsRef<NodeID>, b: impl AsRef<NodeID>) -> bool;

    /// Returns the edges that have the given source and target nodes.
    ///
    /// Only returns more than one edge in the case of codirected edges.
    fn edges_from_to(&self, source: impl AsRef<NodeID>, target: impl AsRef<NodeID>) -> Result<Edges> {
        Ok(self.out_edges(source)?
            .into_iter()
            .filter(|edge| self.target(edge).map(|id| &id == target.as_ref()).unwrap_or(false))
            .collect())
    }

    /// Returns the edges that have the given nodes as endpoints.
    ///
    /// Only returns more than one edge in the case of parallel edges.
    fn edges_between(&self, a: impl AsRef<NodeID>, b: impl AsRef<NodeID>) -> Result<Edges> {
        let a = a.as_ref();
        let b = b.as_ref();
        let mut edges = self.edges_from_to(a, b)?;
        edges.extend(self.edges_from_to(b, a)?);
        Ok(edges)
    }

    /// Returns the edges connecting the given source nodes to the given target nodes.
    fn edges_from_to_nodes(&self, sources: &Nodes, targets: &Nodes) -> Result<Edges> {
        let mut edges = Edges::new();

        for source in sources.iter() {
            for target in targets.iter() {
                edges.extend(self.edges_from_to(source, target)?);
            }
        }

        Ok(edges)
    }

    /// Returns the edges connecting the given sets of nodes.
    fn edges_between_nodes(&self, a: &Nodes, b: &Nodes) -> Result<Edges> {
        let mut edges = self.edges_from_to_nodes(a, b)?;
        edges.extend(self.edges_from_to_nodes(b, a)?);
        Ok(edges)
    }

    /// Returns the source node of the edge.
    fn source(&self, id: impl AsRef<EdgeID>) -> Result<NodeID>;
    /// Returns the target node of the edge.
    fn target(&self, id: impl AsRef<EdgeID>) -> Result<NodeID>;
    /// Returns the endpoints of the edge.
    fn endpoints(&self, id: impl AsRef<EdgeID>) -> Result<(NodeID, NodeID)>;

    /// Returns the out-edges of the node.
    fn out_edges(&self, id: impl AsRef<NodeID>) -> Result<Edges>;
    /// Returns the in-edges of the node.
    fn in_edges(&self, id: impl AsRef<NodeID>) -> Result<Edges>;
    /// Returns the incident edges of the node.
    fn incident_edges(&self, id: impl AsRef<NodeID>) -> Result<Edges>;

    /// Returns the number of out-edges of the node.
    fn out_degree(&self, id: impl AsRef<NodeID>) -> Result<usize>;
    /// Returns the number of in-edges of the node.
    fn in_degree(&self, id: impl AsRef<NodeID>) -> Result<usize>;
    /// Returns the number of incident edges of the node.
    fn degree(&self, id: impl AsRef<NodeID>) -> Result<usize>;

    /// Returns the immediate successors of the node.
    fn successors(&self, id: impl AsRef<NodeID>) -> Result<Nodes>;
    /// Returns the immediate predecessors of the node.
    fn predecessors(&self, id: impl AsRef<NodeID>) -> Result<Nodes>;
    /// Returns the immediate neighbors of the node.
    fn neighbors(&self, id: impl AsRef<NodeID>) -> Result<Nodes>;

    /// Returns `true` if the node has successors.
    fn has_successors(&self, id: impl AsRef<NodeID>) -> Result<bool>;
    /// Returns `true` if the node has predecessors.
    fn has_predecessors(&self, id: impl AsRef<NodeID>) -> Result<bool>;
    /// Returns `true` if the node has neighbors.
    fn has_neighbors(&self, id: impl AsRef<NodeID>) -> Result<bool>;

    /// Returns the immediate successors of all the given nodes.
    fn nodes_successors(&self, ids: &Nodes) -> Result<Nodes> {
        let mut result = Nodes::new();

        for id in ids.iter() {
            let successors = self.successors(id)?;
            for successor in successors.iter() {
                result.insert(successor.clone());
            }
        }

        Ok(result)
    }

    /// Returns the immediate predecessors of all the given nodes.
    fn nodes_predecessors(&self, ids: &Nodes) -> Result<Nodes> {
        let mut result = Nodes::new();

        for id in ids.iter() {
            let predecessors = self.predecessors(id)?;
            for predecessor in predecessors.iter() {
                result.insert(predecessor.clone());
            }
        }

        Ok(result)
    }

    /// Returns the transitive successors of all the given nodes (i.e., all the
    /// nodes reachable from the out-edges of the given nodes).
    ///
    /// The given nodes will not be included unless they are also reachable from
    /// the out-edges of other nodes.
    fn transitive_successors(&self, ids: &Nodes) -> Result<Nodes> {
        let mut result = Nodes::new();

        let mut ids = ids.clone();
        while !ids.is_empty() {
            let next_nodes = self.nodes_successors(&ids)?;

            if next_nodes.is_empty() {
                break;
            }

            let mut new_next = false;
            for node in next_nodes.iter() {
                if !result.contains(node) {
                    result.insert(node.clone());
                    new_next = true;
                }
            }

            if !new_next {
                break;
            }

            ids = next_nodes;
        }

        Ok(result)
    }

    /// Returns the transitive predecessors of all the given nodes (i.e., all
    /// the nodes reachable from the in-edges of the given nodes).
    ///
    /// The given nodes will not be included unless they are also reachable from
    /// the in-edges of other nodes.
    fn transitive_predecessors(&self, ids: &Nodes) -> Result<Nodes> {
        let mut result = Nodes::new();

        let mut ids = ids.clone();
        while !ids.is_empty() {
            let next_nodes = self.nodes_predecessors(&ids)?;

            if next_nodes.is_empty() {
                break;
            }

            let mut new_next = false;
            for node in next_nodes.iter() {
                if !result.contains(node) {
                    result.insert(node.clone());
                    new_next = true;
                }
            }

            if !new_next {
                break;
            }

            ids = next_nodes;
        }

        Ok(result)
    }

    /// The set of all "roots" (nodes with no predecessors) in the graph.
    fn all_roots(&self) -> Nodes;
    /// The set of all "leaves" (nodes with no successors) in the graph.
    fn all_leaves(&self) -> Nodes;

    /// The set of all nodes that are not roots (i.e., nodes with at least one predecessor).
    fn non_roots(&self) -> Nodes;
    /// The set of all nodes that are not leaves (i.e., nodes with at least one successor).
    fn non_leaves(&self) -> Nodes;

    /// The set of all nodes that are neither roots nor leaves (i.e., nodes with
    /// at least one predecessor and at least one successor).
    fn all_internals(&self) -> Nodes;

    /// Returns `true` if the node is a leaf (i.e., has no successors).
    fn is_leaf(&self, id: impl AsRef<NodeID>) -> Result<bool>;
    /// Returns `true` if the node is a root (i.e., has no predecessors).
    fn is_root(&self, id: impl AsRef<NodeID>) -> Result<bool>;
    /// Returns `true` if the node is neither a root nor a leaf (i.e., has at
    /// least one predecessor and at least one successor).
    fn is_internal(&self, id: impl AsRef<NodeID>) -> Result<bool>;
}