Skip to content

Conversation

@Bromind
Copy link
Contributor

@Bromind Bromind commented Jul 10, 2024

This is a PR that adds support for Dot/Graphviz parsing. Parsing can happen both at runtime and at compile time (i.e. there are functions and macros).

It fixes #446 and #466 .

Internally, it uses the dot_parser crate (https://crates.io/crates/dot-parser), the implementation is simply a thin wrapper over that crate. This wrapper is a trait (ParseFromDot), introduced in a new module crate::dot::dot_parser. I also added a feature dot_parser to gate this module.

The modifications do not introduce breaking changes.

TODO List (this is just what I have on the top of my head right now, feel free to edit if you think of other items):

  • Add more tests.
  • Implement ParseFromDot for existing graph types.
  • Discuss on exposed (and re-exported) items.
  • Improve the documentation. (If need be, I'll also improve the doc on the dot_parser crate side).

@Bromind
Copy link
Contributor Author

Bromind commented Jul 13, 2024

I added tests for parsing from both a string and an existing file (I used graph-example.dot in the root of the project).

@Bromind
Copy link
Contributor Author

Bromind commented Jul 13, 2024

In addition, I implemented ParseFromDot for StableGraph (trivially, there's nothing to do).

Cargo.toml Outdated
serde = { version = "1.0", optional = true }
serde_derive = { version = "1.0", optional = true }
rayon = { version = "1.5.3", optional = true }
dot-parser = { version = "0.3", optional = true}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, I don't have full bandwidth to review well, but I hope others do.

dot-parser already optionally depends on petgraph. How does it all interact, when petgraph optionally depends on dot-parser?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi bluss,

dot-parser depends on petgraph for a single thing: to export parsed graphs as petgraph's Graph. (see here : https://codeberg.org/bromind/dot-parser/src/branch/master/src/canonical.rs#L156 ).

Basically, this is a poor attempt to do what I intend to do (in a cleaner way) with this PR: to get petgraphs directly from Dot files. However, implementing that in dot-parser is intrinsically bad (imho), since it wouldn't be very flexible in terms of petgraph's version (e.g. as of today, dot-parser exports Graphs from petgraph 0.6.5, which causes issues if the user wants/needs to use an other version).

Eventually, if this PR gets accepted, I'll removed the dependency.

From a more practical aspect, the current status is not so much of a problem, since the PR does not uses the petgraph feature of dot-parser, so petgraph should not even appear down the dependency tree/there is not cyclic dependency issue.

@Bromind
Copy link
Contributor Author

Bromind commented Oct 20, 2024

Hi, I've been looking to implement the trait for other graph types. However, I think it is reasonable to have it implemented only for Graph and StableGraph. The reason is that the trait extends Create which has only 3 implementors: Graph, StableGraph and GraphMap. For GraphMap, the node weight must implement Copy, which graph payloads from the Dot-parser library do not.
Therefore, I think it simpler to keep it that way. If a user wants GraphMap, if think it is reasonible to leave them the burden to create a Graph or a StableGraph with the default weights (i.e. dot-parser's Node<...> and Edge<...>), to convert those types into the type they want (which they'll probably do anyways), and then to create a GraphMap from the Graph.

@Bromind
Copy link
Contributor Author

Bromind commented Oct 20, 2024

I would like your opinion on re-exported items. So far, this PR re-export/show the following types from the dot-parser crate:

  • Node and AList, which appear in the weights of Nodes and Edges bounds of Create, when extending the trait with `
  • AstGraph, i.e. dot_parser::ast::Graph. It is not re-exported, but it is visible in the signature of from_dot_graph.

I'm also thinking about making pest errors directly visible, or nesting them in a wrapper.

Is there any opinion on those re-exports? I haven't think about it too much yet, and I'm not really happy with the current situation. Any suggestion?

@Bromind Bromind changed the title Parsing from Dot/Graphviz files feat(parser): allow persing graphs from Dot/Graphviz files Mar 27, 2025
@Bromind Bromind changed the title feat(parser): allow persing graphs from Dot/Graphviz files feat(parser): allow parsing graphs from Dot/Graphviz files Mar 27, 2025
@Bromind
Copy link
Contributor Author

Bromind commented Mar 27, 2025

So, regarding my previous comment about reexported items from the dot-parser library, I hid them behind type aliases. I think it is a good tradeoff. Also, parsing errors are now used: if an incorrect DOT string/file is used, an error will be displayed. This is simply using errors from the dot-parser lib and hiding them in ad-hoc opaque DotParsingError.

@Bromind Bromind marked this pull request as ready for review March 29, 2025 23:50
@Bromind Bromind changed the base branch from master to release-0.8.0 March 29, 2025 23:56
@starovoid
Copy link
Collaborator

Hi, is it possible to add more tests with graph isomorphism checks? This will make it possible to more strictly check the correctness of parsing in order to avoid possible regressions in the future.

@starovoid starovoid mentioned this pull request Mar 30, 2025
8 tasks
@starovoid starovoid added this to the 0.8 milestone Mar 30, 2025
@Bromind Bromind changed the base branch from release-0.8.0 to master March 31, 2025 20:11
@Bromind
Copy link
Contributor Author

Bromind commented Mar 31, 2025

Hi, is it possible to add more tests with graph isomorphism checks? This will make it possible to more strictly check the correctness of parsing in order to avoid possible regressions in the future.

I added a few more tests in 8ff3d6e . Only 3 are related to isomorphism (checking isomorphism, isomorphism of subgraph, and not isomorphism), but I also included checks with cyclic graphs.

@starovoid starovoid modified the milestones: 0.8, 0.8.1 Apr 1, 2025
@Bromind
Copy link
Contributor Author

Bromind commented Apr 7, 2025

I just tested the semver-checks failure, and it definitively seems to be a false positive. In a new and separate project, I wrote a dummy graph to implement Create and Build, and both work like a charm. So I think we could ignore this warning.

(For reference: obi1kenobi/cargo-semver-checks#1200)

use petgraph::data::{Build, Create};
use petgraph::visit::{Data, GraphBase, NodeCount};
use petgraph::dot::dot_parser::{ParseFromDot, DotNodeWeight, DotAttrList};
use std::marker::PhantomData;

#[derive(Default)]
struct MyDummyGraph<'a> {
    a: PhantomData<&'a ()>
}

impl<'a> GraphBase for MyDummyGraph<'a> {
    type EdgeId = ();
    type NodeId = ();
}

impl<'a> Data for MyDummyGraph<'a> {
    type NodeWeight = DotNodeWeight<'a>;
    type EdgeWeight = DotAttrList<'a>;
}

impl<'a> NodeCount for MyDummyGraph<'a> {
    fn node_count(&self) -> usize {
        0
    }
}

impl<'a> Build for MyDummyGraph<'a> {
    fn add_node(&mut self, _data: <Self as Data>::NodeWeight) -> <Self as GraphBase>::NodeId {
        return ();
    }

    fn update_edge(
        &mut self,
        _from: <MyDummyGraph as GraphBase>::NodeId,
        _to: <MyDummyGraph as GraphBase>::NodeId,
        _weight: <MyDummyGraph as Data>::EdgeWeight,
    ) -> <Self as GraphBase>::EdgeId {
        return ();
    }
}

impl<'a> Create for MyDummyGraph<'a> {
    fn with_capacity(_n: usize, _e: usize) -> Self {
        Self::default()
    }
}

impl<'a> ParseFromDot<'a> for MyDummyGraph<'a> {}

fn main() {
    println!("Hello, world!");
}

@starovoid
Copy link
Collaborator

Please apply cargo fmt to satisfy the formatting lint

@starovoid starovoid dismissed their stale review April 8, 2025 08:03

Resolved

@starovoid starovoid requested a review from ABorgna April 8, 2025 08:08
Copy link
Member

@ABorgna ABorgna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@ABorgna ABorgna added this pull request to the merge queue Apr 8, 2025
Merged via the queue into petgraph:master with commit 8dac216 Apr 8, 2025
10 checks passed
@github-actions github-actions bot mentioned this pull request Apr 8, 2025
github-merge-queue bot pushed a commit that referenced this pull request Jun 6, 2025
## 🤖 New release

* `petgraph`: 0.8.1 -> 0.8.2 (✓ API compatible changes)

<details><summary><i><b>Changelog</b></i></summary><p>

<blockquote>

##
[0.8.2](https://github.com/petgraph/petgraph/compare/petgraph@v0.8.1...petgraph@v0.8.2)
- 2025-06-06

### Bug Fixes

- Ford Fulkerson sometimes Panics on StableGraphs
([#793](#793))
- Run Maximal Cliques Quickcheck only on Digraphs which are symmetrical
([#800](#800))
- Run Steiner Tree Quickcheck on the connected components to properly
support disconnected graphs
([#801](#801))
- Quickcheck random01 function only outputs 0
([#798](#798))

### Documentation

- Specify that Acyclic::try_udpate_edge may add an edge
([#770](#770))
- Update remove_node doc comment in graphmap.rs
([#663](#663))
- Add examples to minimum spanning tree functions
([#808](#808))
- Minimal typo fix in comments
([#803](#803))
- Update docs.rs ([#807](#807))
- Add note about `StableGraph::edge_indices` behaviour
([#812](#812))
- Clarification of references to nodes and V (refresh #358)
([#814](#814))
- Fix link and mention Dfs and Bfs as special case in examples
([#816](#816))
- Unify algo docs
([#815](#815))

### New Features

- *(parser)* allow parsing graphs from Dot/Graphviz files
([#653](#653))
- Implement `DataMap` for `GraphMap` graphs
([#776](#776))
- Add Johnson's algorithm
([#741](#741))
- Add algorithm to find bridge edges
([#590](#590))

### Performance

- Reuse queue allocation in `maximum_matching` main loop
([#817](#817))

### Refactor

- Fix new clippy warnings
([#791](#791))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: starovoid <prototyperailgun@gmail.com>
RaoulLuque pushed a commit to RaoulLuque/petgraph that referenced this pull request Jun 18, 2025
## 🤖 New release

* `petgraph`: 0.8.1 -> 0.8.2 (✓ API compatible changes)

<details><summary><i><b>Changelog</b></i></summary><p>

<blockquote>

##
[0.8.2](https://github.com/petgraph/petgraph/compare/petgraph@v0.8.1...petgraph@v0.8.2)
- 2025-06-06

### Bug Fixes

- Ford Fulkerson sometimes Panics on StableGraphs
([petgraph#793](petgraph#793))
- Run Maximal Cliques Quickcheck only on Digraphs which are symmetrical
([petgraph#800](petgraph#800))
- Run Steiner Tree Quickcheck on the connected components to properly
support disconnected graphs
([petgraph#801](petgraph#801))
- Quickcheck random01 function only outputs 0
([petgraph#798](petgraph#798))

### Documentation

- Specify that Acyclic::try_udpate_edge may add an edge
([petgraph#770](petgraph#770))
- Update remove_node doc comment in graphmap.rs
([petgraph#663](petgraph#663))
- Add examples to minimum spanning tree functions
([petgraph#808](petgraph#808))
- Minimal typo fix in comments
([petgraph#803](petgraph#803))
- Update docs.rs ([petgraph#807](petgraph#807))
- Add note about `StableGraph::edge_indices` behaviour
([petgraph#812](petgraph#812))
- Clarification of references to nodes and V (refresh petgraph#358)
([petgraph#814](petgraph#814))
- Fix link and mention Dfs and Bfs as special case in examples
([petgraph#816](petgraph#816))
- Unify algo docs
([petgraph#815](petgraph#815))

### New Features

- *(parser)* allow parsing graphs from Dot/Graphviz files
([petgraph#653](petgraph#653))
- Implement `DataMap` for `GraphMap` graphs
([petgraph#776](petgraph#776))
- Add Johnson's algorithm
([petgraph#741](petgraph#741))
- Add algorithm to find bridge edges
([petgraph#590](petgraph#590))

### Performance

- Reuse queue allocation in `maximum_matching` main loop
([petgraph#817](petgraph#817))

### Refactor

- Fix new clippy warnings
([petgraph#791](petgraph#791))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: starovoid <prototyperailgun@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parse Graphviz .dot file to Graph?

4 participants