Dynamic Toposort Support (#675)

Hi there,

I would like to add support for directed acyclic graphs (DAGs) in
petgraph. I propose adding a wrapper type `Acyclic<G>` that behaves like
the underlying graph `G`, but checks for acyclicity whenever an edge
addition is attempted. This functionality is provided through an
implementation of the `Build` trait, as well as the `try_add_edge`
method.

The idea is similar to the standalone crate
[daggy](https://github.com/mitchmindtree/daggy) except that i) this PR
implements a more efficient algorithm for this purpose and ii) I am
unsure whether daggy is still maintained.

## Algorithm
I looked at the literature to find the recommended way for doing dynamic
acyclicity checks (i.e. not run toposort everytime an edge is added). I
have settled (for now) on the PK algorithm from [1]. This seems to
strike a nice balance between simplicity and performance.

The idea is fairly straightforward: keep a Vec of toposorted nodes of
the graph. When an edge is added that does not respect the current
ordering, find all nodes in the order between the offending edge
endpoints and reorder them appropriately.

[1] "A Dynamic Topological Sort Algorithm for Directed Acyclic Graphs"
by D. Pierce and P. Kelly, JEA, 2004.

## Status of this PR
This is still work in progress, and you might be able to help me here
(especially points 1-2).
- [x] I have attempted to implement the `Into{NodeIdentifiers, Edges,
etc}` for all reference types, giving me a bound of the type
```rust
impl<'a, G: GraphBase> IntoNodeReferences for &'a Acyclic<G>
where
    &'a G: IntoNodeReferences { ... }
```
However, this creates an infinite recursion in the compiler, with the
error:
```
error[E0275]: overflow evaluating the requirement `&visit::filter::NodeFiltered<_, _>: visit::IntoNodeIdentifiers`
```
I wonder if you have had this issue before when implementing other
types. Do you have any suggestions on how I should solve this? Unlike
`Reversed` and `NodeFiltered` (and others), the generic type `<G>` must
be the graph itself and not a reference, as it must be mutable.

- [x] Benchmarking shows that the implemention is currently slow,
dominated by memory allocations for the DFS traversals. Given that only
a small region of the graph is expected to be traversed at each run, it
is wasteful to reallocate a map the size of the graph at each call. The
current code structure makes this a bit hard to change. One solution I
can see is adding a `WithVisitMap(G)` wrapper type that can be used to
specify a custom `VisitMap` type for `G`.
- [x]  Add quickcheck tests.
7 files changed
tree: 9624d4e49aa2df49a6d310350dc39d36ff79f08c
  1. .github/
  2. assets/
  3. benches/
  4. serialization-tests/
  5. src/
  6. tests/
  7. .gitignore
  8. Cargo.toml
  9. clippy.toml
  10. CONTRIBUTING.rst
  11. custom.css
  12. graph-example.dot
  13. LICENSE-APACHE
  14. LICENSE-MIT
  15. Makefile
  16. README.md
  17. RELEASES.rst
README.md

petgraph

Graph data structure library. Please read the API documentation here.

Supports Rust 1.64 and later.

Crates.io docs.rs MSRV Discord chat build_status

Crate feature flags:

  • graphmap (default) enable GraphMap.
  • stable_graph (default) enable StableGraph.
  • matrix_graph (default) enable MatrixGraph.
  • serde-1 (optional) enable serialization for Graph, StableGraph, GraphMap using serde 1.0. Requires Rust version as required by serde.
  • rayon (optional) enable parallel iterators for the underlying data in GraphMap. Requires Rust version as required by Rayon.

Recent Changes

See RELEASES for a list of changes. The minimum supported rust version will only change on major releases.

Logo

The mascot is named “Sir Paul Rustory Graphosaurus” (close friends call him Paul). The logo has been created by the talented Aren.

License

Dual-licensed to be compatible with the Rust project.

Licensed under the Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 or the MIT license http://opensource.org/licenses/MIT, at your option. This file may not be copied, modified, or distributed except according to those terms.