Skip to content

Prepare 0.8.1 #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions .github/workflows/daggy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,32 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
toolchain: nightly
components: rustfmt
- name: Run rustfmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
run: cargo fmt --all -- --check

clippy:
name: Clippy
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly
components: clippy

- name: 'Run clippy'
run: cargo clippy --all-features -- -D warnings

cargo-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: cargo test
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose
run: cargo test --verbose

cargo-test-all-features:
runs-on: ubuntu-latest
Expand Down
11 changes: 4 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@

* Add `Dag::transitive_reduce` ([#36][#36], [#41][#41]).
* Add `Dag::{reserve_*, shrink_*}` functions ([#38][#38]).
- `reserve_nodes`
- `reserve_exact_nodes`
- `reserve_edges`
- `reserve_exact_edges`
- `shrink_to_fit`
- `shrink_to_fit_nodes`
- `shrink_to_fit_edges`
* Add `Dag::transitive_reduce` ([#36][#36], [#41][#41]).
* Add `Dag::{reserve_*, shrink_*}` functions ([#38][#38]).
* Update `petgraph` to `0.7` ([#40][#40])

[#36]: https://github.com/mitchmindtree/daggy/pull/36
[#38]: https://github.com/mitchmindtree/daggy/pull/38
[#40]: https://github.com/mitchmindtree/daggy/pull/40
[#41]: https://github.com/mitchmindtree/daggy/pull/41
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "daggy"
version = "0.8.0"
version = "0.8.1"
authors = ["mitchmindtree <mitchell.nordine@gmail.com>"]
description = "A directed acyclic graph data structure library. It is Implemented on top of petgraph's Graph data structure and attempts to follow similar conventions where suitable."
readme = "README.md"
Expand Down
71 changes: 61 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,77 @@

A [directed acyclic graph](https://en.wikipedia.org/wiki/Directed_acyclic_graph) data structure for Rust.

It is Implemented on top of [petgraph](https://github.com/petgraph/petgraph)'s [Graph](https://docs.rs/petgraph/latest/petgraph/graph/struct.Graph.html) data structure and attempts to follow similar conventions where suitable.
It is implemented on top of [petgraph](https://github.com/petgraph/petgraph)'s [Graph](https://docs.rs/petgraph/latest/petgraph/graph/struct.Graph.html) data structure and attempts to follow similar conventions where suitable.


Usage
-----
## Usage

Please see the [tests directory](https://github.com/mitchmindtree/daggy/tree/master/tests) for some basic usage examples.

Use daggy in your project by adding it to your Cargo.toml dependencies like so:
Use daggy in your project by adding it to your `Cargo.toml` dependencies:

```toml
[dependencies]
daggy = "*"
daggy = "0.8.1"

# Enables the `StableDag` type.
daggy = { version = "0.8.1", features = ["stable_dag"] }

# Allows the `Dag` to be serialized and deserialized.
daggy = { version = "0.8.1", features = ["serde-1"] }
```

## Examples

> Please see the [tests directory](https://github.com/mitchmindtree/daggy/tree/master/tests) for some basic usage examples.

Transitive reduction:

```rust
use daggy::Dag;

let mut dag = Dag::<&str, &str>::new();

// Reduce edges:
//
// ```text
// # Before: | # After:
// |
// a -> b ----. | a -> b ----.
// | | | | |
// |-> c ----|----. | '-> c |
// | \ | | | \ |
// | \ v | | \ v
// |------>> d | | '> d
// | \ v | \
// '----------->> e | '> e
// ```

let a = dag.add_node("a");

let (_, b) = dag.add_child(a, "a->b", "b");
let (_, c) = dag.add_child(a, "a->c", "c");
let (_, d) = dag.add_child(a, "a->d", "d");
let (_, e) = dag.add_child(a, "a->e", "e");

License
-------
dag.add_edge(b, d, "b->d").unwrap();

dag.add_edge(c, d, "c->d").unwrap();
dag.add_edge(c, e, "c->e").unwrap();

dag.add_edge(d, e, "d->e").unwrap();

assert_eq!(dag.edge_count(), 8);

dag.transitive_reduce(vec![a]);

let mut edges = dag.graph().edge_weights().copied().collect::<Vec<_>>();
edges.sort();
assert_eq!(dag.edge_count(), 5);
assert_eq!(&edges, &["a->b", "a->c", "b->d", "c->d", "d->e"]);
```


## License

Dual-licensed to be compatible with the petgraph and Rust projects.

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.

98 changes: 79 additions & 19 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,77 @@
//! methods behave similarly to iterator types, however **Walker**s do not require borrowing the
//! graph. This means that we can still safely mutably borrow from the graph whilst we traverse it.
//!
//!
//! [1]: Dag
//! [2]: petgraph
//! [3]: petgraph::graph::Graph
//!
//!
//! ## Usage
//!
//! Use daggy in your project by adding it to your `Cargo.toml` dependencies:
//!
//! ```toml
//! [dependencies]
//! daggy = "0.8.1"
//!
//! # Enables the `StableDag` type.
//! daggy = { version = "0.8.1", features = ["stable_dag"] }
//!
//! # Allows the `Dag` to be serialized and deserialized.
//! daggy = { version = "0.8.1", features = ["serde-1"] }
//! ```
//!
//! # Examples
//!
//! > Please see the [tests directory][4] for some basic usage examples.
//!
//! Transitive reduction:
//!
//! ```rust
//! use daggy::Dag;
//!
//! let mut dag = Dag::<&str, &str>::new();
//!
//! // Reduce edges:
//! //
//! // ```text
//! // # Before: | # After:
//! // |
//! // a -> b ----. | a -> b ----.
//! // | | | | |
//! // |-> c ----|----. | '-> c |
//! // | \ | | | \ |
//! // | \ v | | \ v
//! // |------>> d | | '> d
//! // | \ v | \
//! // '----------->> e | '> e
//! // ```
//!
//! let a = dag.add_node("a");
//!
//! let (_, b) = dag.add_child(a, "a->b", "b");
//! let (_, c) = dag.add_child(a, "a->c", "c");
//! let (_, d) = dag.add_child(a, "a->d", "d");
//! let (_, e) = dag.add_child(a, "a->e", "e");
//!
//! dag.add_edge(b, d, "b->d").unwrap();
//!
//! dag.add_edge(c, d, "c->d").unwrap();
//! dag.add_edge(c, e, "c->e").unwrap();
//!
//! dag.add_edge(d, e, "d->e").unwrap();
//!
//! assert_eq!(dag.edge_count(), 8);
//!
//! dag.transitive_reduce(vec![a]);
//!
//! let mut edges = dag.graph().edge_weights().copied().collect::<Vec<_>>();
//! edges.sort();
//! assert_eq!(dag.edge_count(), 5);
//! assert_eq!(&edges, &["a->b", "a->c", "b->d", "c->d", "d->e"]);
//! ```
//!
//! [4]: https://github.com/mitchmindtree/daggy/tree/master/tests

#![forbid(unsafe_code)]
#![warn(missing_docs)]
Expand Down Expand Up @@ -211,10 +278,7 @@ where
{
let graph = self.graph.map(node_map, edge_map);
let cycle_state = self.cycle_state.clone();
Dag {
graph: graph,
cycle_state: cycle_state,
}
Dag { graph, cycle_state }
}

/// Create a new `Dag` by mapping node and edge weights. A node or edge may be mapped to `None`
Expand All @@ -237,10 +301,7 @@ where
{
let graph = self.graph.filter_map(node_map, edge_map);
let cycle_state = DfsSpace::new(&graph);
Dag {
graph: graph,
cycle_state: cycle_state,
}
Dag { graph, cycle_state }
}

/// Removes all nodes and edges from the **Dag**.
Expand Down Expand Up @@ -434,10 +495,8 @@ where

for (a, b, weight) in edges {
// Check whether or not we'll need to check for cycles.
if !should_check_for_cycle {
if must_check_for_cycle(self, a, b) {
should_check_for_cycle = true;
}
if !should_check_for_cycle && must_check_for_cycle(self, a, b) {
should_check_for_cycle = true;
}

self.graph.add_edge(a, b, weight);
Expand Down Expand Up @@ -614,6 +673,7 @@ where
/// Both indices can be either `NodeIndex`s, `EdgeIndex`s or a combination of the two.
///
/// **Panics** if the indices are equal or if they are out of bounds.
#[allow(clippy::type_complexity)]
pub fn index_twice_mut<A, B>(
&mut self,
a: A,
Expand Down Expand Up @@ -657,7 +717,7 @@ where
pub fn parents(&self, child: NodeIndex<Ix>) -> Parents<N, E, Ix> {
let walk_edges = self.graph.neighbors_directed(child, pg::Incoming).detach();
Parents {
walk_edges: walk_edges,
walk_edges,
_node: PhantomData,
_edge: PhantomData,
}
Expand All @@ -675,7 +735,7 @@ where
pub fn children(&self, parent: NodeIndex<Ix>) -> Children<N, E, Ix> {
let walk_edges = self.graph.neighbors_directed(parent, pg::Outgoing).detach();
Children {
walk_edges: walk_edges,
walk_edges,
_node: PhantomData,
_edge: PhantomData,
}
Expand Down Expand Up @@ -749,12 +809,12 @@ where

// Dag implementations.

impl<N, E, Ix> Into<DiGraph<N, E, Ix>> for Dag<N, E, Ix>
impl<N, E, Ix> From<Dag<N, E, Ix>> for DiGraph<N, E, Ix>
where
Ix: IndexType,
{
fn into(self) -> DiGraph<N, E, Ix> {
self.into_graph()
fn from(val: Dag<N, E, Ix>) -> Self {
val.into_graph()
}
}

Expand Down Expand Up @@ -890,7 +950,7 @@ where
}
}

impl<'a, N, E, Ix> IntoNodeIdentifiers for &'a Dag<N, E, Ix>
impl<N, E, Ix> IntoNodeIdentifiers for &Dag<N, E, Ix>
where
Ix: IndexType,
{
Expand Down
5 changes: 1 addition & 4 deletions src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ where
{
let graph = Deserialize::deserialize(deserializer)?;
let cycle_state = DfsSpace::new(&graph);
let dag = Dag {
graph: graph,
cycle_state: cycle_state,
};
let dag = Dag { graph, cycle_state };
Ok(dag)
}
}
Loading