Skip to content
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

Hydrofabric network cycle detection #718

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

hellkite500
Copy link
Member

@hellkite500 hellkite500 commented Jan 25, 2024

Cycles in the hydrofabric topology can cause a boost::not_a_dag exception to occur (when performing topological sort of the graph, for example.)

This exception, however, doesn't provide any useful context to determine what part of the hydrofabric creates/contributes to the cycle to be investigated.

This PR provides a custom cycle detection visitor which records the vertices of all back edges in the graph. This visitor is then used in the init_indicies function of all network creation to run an undirected depth first search and record the cycles. All cycles are identified and the vertices are mapped back to the hydrofabric ID and reported in a std::domain_error exception message that looks like

Cycle(s) detected in hydrofabric
The following features form a cycle:
        nex-1 --> cat-0

Additions

  • detect_cycles visitor

Removals

  • None

Changes

  • std::domain_error thrown in network creation when cycles are detected

Testing

  1. New test added which attempts to create a Network using a topology which has a cycle

Notes

Some additional code is left in the visitor implementation commented out. If additional information about hydrofabric features involved in the cycle are needed, it can be used to provide all vertices related to a reported cycle.

Checklist

  • PR has an informative and human-readable title
  • Changes are limited to a single goal (no scope creep)
  • Code can be automatically merged (no conflicts)
  • Code follows project standards (link if applicable)
  • Passes all existing automated tests
  • Any change in functionality is tested
  • New functions are documented (with a description, list of inputs, and expected output)
  • Placeholder code is flagged / future todos are captured in comments
  • Project documentation has been updated (including the "Unreleased" section of the CHANGELOG)
  • Reviewers requested with the Reviewers tool ➡️

Target Environment support

  • Linux
  • MacOS

Comment on lines +108 to +112
std::string msg = "The following features form a cycle:\n";
for(auto p : cycles){
msg += "\t"+get_id(p.first)+" --> "+get_id(p.second)+"\n";
}
throw std::domain_error("Cycle(s) detected in hydrofabric\n"+msg);
Copy link
Contributor

Choose a reason for hiding this comment

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

As phrased, this message might confusingly suggest that the identifying elements of distinct cycles are actually the set of elements in a single cycle

Copy link
Member Author

Choose a reason for hiding this comment

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

Would something like

Cycle(s) detected in hydrofabric
The following features form the connecting edge of a cycle:
        nex-1 --> cat-0

be more clear?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that's an improvement. Maybe "The following features each form the connecting edge of a cycle" (added 'each')?

I realize we probably don't need to word-smith this much more, since anyone encountering this is pretty likely to make their way back to us to help with getting it resolved.

Copy link
Member Author

Choose a reason for hiding this comment

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

I like added "each" to be clear when multiple cycles are found. I'll touch it up and rebase.

Comment on lines +103 to +106
detect_cycles vis(&cycles);
//Run an undirected, depth first search applying the loop detector visitor
//cycles added as vertex pairs for the closing edge of the cycle
boost::undirected_dfs(this->graph, vis, make_assoc_property_map(vis.vertex_coloring), make_assoc_property_map(vis.edge_coloring));
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
detect_cycles vis(&cycles);
//Run an undirected, depth first search applying the loop detector visitor
//cycles added as vertex pairs for the closing edge of the cycle
boost::undirected_dfs(this->graph, vis, make_assoc_property_map(vis.vertex_coloring), make_assoc_property_map(vis.edge_coloring));
detect_cycles cycles_visitor(&cycles);
//Run an undirected, depth first search applying the loop detector visitor
//cycles added as vertex pairs for the closing edge of the cycle
boost::undirected_dfs(this->graph, cycles_visitor, make_assoc_property_map(vis.vertex_coloring), make_assoc_property_map(vis.edge_coloring));

Just making the name a bit more verbose for clarity. Alternately,

Suggested change
detect_cycles vis(&cycles);
//Run an undirected, depth first search applying the loop detector visitor
//cycles added as vertex pairs for the closing edge of the cycle
boost::undirected_dfs(this->graph, vis, make_assoc_property_map(vis.vertex_coloring), make_assoc_property_map(vis.edge_coloring));
//Run an undirected, depth first search applying the loop detector visitor
//cycles added as vertex pairs for the closing edge of the cycle
boost::undirected_dfs(this->graph, detect_cycles(&cycles), make_assoc_property_map(vis.vertex_coloring), make_assoc_property_map(vis.edge_coloring));

Just don't name the temporary visitor object at all

Copy link
Contributor

Choose a reason for hiding this comment

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

I think I like the latter a bit better

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.

2 participants