pub struct Acyclic<G: Visitable> { /* private fields */ }
Expand description
A directed acyclic graph.
Wrap directed acyclic graphs and expose an API that ensures the invariant is maintained, i.e. no cycles can be created. This uses a topological order that is dynamically updated when edges are added. In the worst case, the runtime may be linear in the number of vertices, but it has been shown to be fast in practice, particularly on sparse graphs (Pierce and Kelly, 2004).
To be modifiable (and hence to be useful), the graphs of generic type G
should implement the Build
trait. Good candidates for G
are thus
crate::graph::DiGraph
and [crate::stable_graph::StableDiGraph
].
§Algorithm
This implements the PK algorithm for dynamic topological sort described in “A Dynamic Topological Sort Algorithm for Directed Acyclic Graphs” by D. Pierce and P. Kelly, JEA, 2004. It maintains a topological order of the nodes that can be efficiently updated when edges are added. Achieves a good balance between simplicity and performance in practice, see the paper for discussions of the running time.
§Graph traits
All graph traits are delegated to the inner graph, with the exception of
the graph construction trait Build
. The wrapped graph can thus only
be modified through the wrapped API that ensures no cycles are created.
§Behaviour on cycles
By design, edge additions to this datatype may fail. It is recommended to
prefer the dedicated Acyclic::try_add_edge
and
Acyclic::try_update_edge
methods whenever possible. The
Build::update_edge
methods will panic if it is attempted to add an edge
that would create a cycle. The Build::add_edge
on the other hand method
will return None
if the edge cannot be added (either it already exists on
a graph type that does not support it or would create a cycle).
Implementations§
Source§impl<G: Visitable> Acyclic<G>
impl<G: Visitable> Acyclic<G>
Sourcepub fn get_position<'a>(&'a self, id: G::NodeId) -> TopologicalPosition
pub fn get_position<'a>(&'a self, id: G::NodeId) -> TopologicalPosition
Get the position of a node in the topological sort.
Panics if the node index is out of bounds.
Sourcepub fn at_position(&self, pos: TopologicalPosition) -> Option<G::NodeId>
pub fn at_position(&self, pos: TopologicalPosition) -> Option<G::NodeId>
Get the node at a given position in the topological sort, if it exists.
Source§impl<G: Visitable> Acyclic<G>
impl<G: Visitable> Acyclic<G>
Sourcepub fn nodes_iter(&self) -> impl Iterator<Item = G::NodeId> + '_
pub fn nodes_iter(&self) -> impl Iterator<Item = G::NodeId> + '_
Get an iterator over the nodes, ordered by their position.
Sourcepub fn range<'r>(
&'r self,
range: impl RangeBounds<TopologicalPosition> + 'r,
) -> impl Iterator<Item = G::NodeId> + 'r
pub fn range<'r>( &'r self, range: impl RangeBounds<TopologicalPosition> + 'r, ) -> impl Iterator<Item = G::NodeId> + 'r
Get an iterator over the nodes within the range of positions.
The nodes are ordered by their position in the topological sort.
Sourcepub fn into_inner(self) -> G
pub fn into_inner(self) -> G
Consume the Acyclic
wrapper and return the underlying graph.
Source§impl<G: Visitable + NodeIndexable> Acyclic<G>
impl<G: Visitable + NodeIndexable> Acyclic<G>
Sourcepub fn try_from_graph(graph: G) -> Result<Self, Cycle<G::NodeId>>
pub fn try_from_graph(graph: G) -> Result<Self, Cycle<G::NodeId>>
Sourcepub fn try_add_edge(
&mut self,
a: G::NodeId,
b: G::NodeId,
weight: G::EdgeWeight,
) -> Result<G::EdgeId, AcyclicEdgeError<G::NodeId>>
pub fn try_add_edge( &mut self, a: G::NodeId, b: G::NodeId, weight: G::EdgeWeight, ) -> Result<G::EdgeId, AcyclicEdgeError<G::NodeId>>
Add an edge to the graph using Build::add_edge
.
Returns the id of the added edge, or an AcyclicEdgeError
if the edge
would create a cycle, a self-loop or if the edge addition failed in
the underlying graph.
In cases where edge addition cannot fail in the underlying graph (e.g.
when multi-edges are allowed, as in DiGraph
and [StableDiGraph
]),
this will return an error if and only if Self::is_valid_edge
returns false
.
Sourcepub fn try_update_edge(
&mut self,
a: G::NodeId,
b: G::NodeId,
weight: G::EdgeWeight,
) -> Result<G::EdgeId, AcyclicEdgeError<G::NodeId>>
pub fn try_update_edge( &mut self, a: G::NodeId, b: G::NodeId, weight: G::EdgeWeight, ) -> Result<G::EdgeId, AcyclicEdgeError<G::NodeId>>
Update an edge in a graph using Build::update_edge
.
Returns the id of the updated edge, or an AcyclicEdgeError
if the edge
would create a cycle or a self-loop. If the edge does not exist, the
edge is created.
This will return an error if and only if Self::is_valid_edge
returns
false
.
Trait Implementations§
Source§impl<G: Build + Visitable + NodeIndexable> Build for Acyclic<G>where
for<'a> &'a G: IntoNeighborsDirected + IntoNodeIdentifiers + Visitable<Map = G::Map> + GraphBase<NodeId = G::NodeId>,
G::NodeId: IndexType,
impl<G: Build + Visitable + NodeIndexable> Build for Acyclic<G>where
for<'a> &'a G: IntoNeighborsDirected + IntoNodeIdentifiers + Visitable<Map = G::Map> + GraphBase<NodeId = G::NodeId>,
G::NodeId: IndexType,
fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId
Source§fn add_edge(
&mut self,
a: Self::NodeId,
b: Self::NodeId,
weight: Self::EdgeWeight,
) -> Option<Self::EdgeId>
fn add_edge( &mut self, a: Self::NodeId, b: Self::NodeId, weight: Self::EdgeWeight, ) -> Option<Self::EdgeId>
None
.Source§fn update_edge(
&mut self,
a: Self::NodeId,
b: Self::NodeId,
weight: Self::EdgeWeight,
) -> Self::EdgeId
fn update_edge( &mut self, a: Self::NodeId, b: Self::NodeId, weight: Self::EdgeWeight, ) -> Self::EdgeId
a
to b
. Return the id of the affected
edge.Source§impl<G: Create + Visitable + NodeIndexable> Create for Acyclic<G>where
for<'a> &'a G: IntoNeighborsDirected + IntoNodeIdentifiers + Visitable<Map = G::Map> + GraphBase<NodeId = G::NodeId>,
G::NodeId: IndexType,
impl<G: Create + Visitable + NodeIndexable> Create for Acyclic<G>where
for<'a> &'a G: IntoNeighborsDirected + IntoNodeIdentifiers + Visitable<Map = G::Map> + GraphBase<NodeId = G::NodeId>,
G::NodeId: IndexType,
fn with_capacity(nodes: usize, edges: usize) -> Self
Source§impl<G: Visitable + Data> Data for Acyclic<G>
impl<G: Visitable + Data> Data for Acyclic<G>
type NodeWeight = <G as Data>::NodeWeight
type EdgeWeight = <G as Data>::EdgeWeight
Source§impl<G: Visitable + DataMap> DataMap for Acyclic<G>
impl<G: Visitable + DataMap> DataMap for Acyclic<G>
fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight>
fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight>
Source§impl<G: Visitable + DataMapMut> DataMapMut for Acyclic<G>
impl<G: Visitable + DataMapMut> DataMapMut for Acyclic<G>
fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight>
fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight>
Source§impl<G: Visitable + EdgeCount> EdgeCount for Acyclic<G>
impl<G: Visitable + EdgeCount> EdgeCount for Acyclic<G>
Source§fn edge_count(&self) -> usize
fn edge_count(&self) -> usize
Source§impl<G: Visitable + EdgeIndexable> EdgeIndexable for Acyclic<G>
impl<G: Visitable + EdgeIndexable> EdgeIndexable for Acyclic<G>
Source§fn edge_bound(&self) -> usize
fn edge_bound(&self) -> usize
Source§fn from_index(&self, i: usize) -> Self::EdgeId
fn from_index(&self, i: usize) -> Self::EdgeId
i
to an edge index. i
must be a valid value in the graph.Source§impl<G: Visitable + GetAdjacencyMatrix> GetAdjacencyMatrix for Acyclic<G>
impl<G: Visitable + GetAdjacencyMatrix> GetAdjacencyMatrix for Acyclic<G>
Source§type AdjMatrix = <G as GetAdjacencyMatrix>::AdjMatrix
type AdjMatrix = <G as GetAdjacencyMatrix>::AdjMatrix
Source§fn adjacency_matrix(&self) -> Self::AdjMatrix
fn adjacency_matrix(&self) -> Self::AdjMatrix
Source§impl<'a, N, E, Ix: IndexType> IntoEdgeReferences for &'a Acyclic<DiGraph<N, E, Ix>>
impl<'a, N, E, Ix: IndexType> IntoEdgeReferences for &'a Acyclic<DiGraph<N, E, Ix>>
type EdgeRef = <&'a Graph<N, E, Directed, Ix> as IntoEdgeReferences>::EdgeRef
type EdgeReferences = <&'a Graph<N, E, Directed, Ix> as IntoEdgeReferences>::EdgeReferences
fn edge_references(self) -> Self::EdgeReferences
Source§impl<'a, N, E, Ix: IndexType> IntoEdgesDirected for &'a Acyclic<DiGraph<N, E, Ix>>
impl<'a, N, E, Ix: IndexType> IntoEdgesDirected for &'a Acyclic<DiGraph<N, E, Ix>>
type EdgesDirected = <&'a Graph<N, E, Directed, Ix> as IntoEdgesDirected>::EdgesDirected
fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected
Source§impl<'a, N, E, Ix: IndexType> IntoNeighborsDirected for &'a Acyclic<DiGraph<N, E, Ix>>
impl<'a, N, E, Ix: IndexType> IntoNeighborsDirected for &'a Acyclic<DiGraph<N, E, Ix>>
type NeighborsDirected = <&'a Graph<N, E, Directed, Ix> as IntoNeighborsDirected>::NeighborsDirected
fn neighbors_directed( self, n: Self::NodeId, d: Direction, ) -> Self::NeighborsDirected
Source§impl<'a, N, E, Ix: IndexType> IntoNodeIdentifiers for &'a Acyclic<DiGraph<N, E, Ix>>
impl<'a, N, E, Ix: IndexType> IntoNodeIdentifiers for &'a Acyclic<DiGraph<N, E, Ix>>
type NodeIdentifiers = <&'a Graph<N, E, Directed, Ix> as IntoNodeIdentifiers>::NodeIdentifiers
fn node_identifiers(self) -> Self::NodeIdentifiers
Source§impl<'a, N, E, Ix: IndexType> IntoNodeReferences for &'a Acyclic<DiGraph<N, E, Ix>>
impl<'a, N, E, Ix: IndexType> IntoNodeReferences for &'a Acyclic<DiGraph<N, E, Ix>>
type NodeRef = <&'a Graph<N, E, Directed, Ix> as IntoNodeReferences>::NodeRef
type NodeReferences = <&'a Graph<N, E, Directed, Ix> as IntoNodeReferences>::NodeReferences
fn node_references(self) -> Self::NodeReferences
Source§impl<G: Visitable + NodeIndexable> NodeIndexable for Acyclic<G>
impl<G: Visitable + NodeIndexable> NodeIndexable for Acyclic<G>
Source§fn node_bound(&self) -> usize
fn node_bound(&self) -> usize
Source§fn from_index(&self, i: usize) -> Self::NodeId
fn from_index(&self, i: usize) -> Self::NodeId
i
to a node index. i
must be a valid value in the graph.