Random Graphs inconsistencies and usability issues
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- cpp
- Domain
- data, developer-experience
Research direction
Start with erdos_renyi_generator.hpp and the linked Compiler Explorer examples for the ambiguous constructor and directed small-world behavior. Read the implementations and existing documentation for the named generators and random_vertex/random_edge entry points. Done means the API inconsistencies and empty-graph behavior are addressed or specified, while the directed small-world design is resolved separately with the cited literature.
Written by the indexing model from the issue text.
Description
While documenting the random graph generators and utilities and drafting examples, I bumped into some issues. It happens that several generator APIs seem to have inconsistencies and silent failures. I will drop my findings here for future reference.
Most of them seem easy fixes, but the ER directed case looks like a full feature that would need some math guy backup and a more in-depth dive in the existing literature.
A) erdos_renyi_iterator has ambiguous constructors
The class has two constructors:
erdos_renyi_iterator(gen, n, double fraction = 0.0, bool allow_self_loops = false);
erdos_renyi_iterator(gen, n, edges_size_type m, bool allow_self_loops = false);
Passing an integer literal is ambiguous (int converts equally to both double and edges_size_type):
erdos_renyi_iterator(gen, 100, 50); // compile error: ambiguous
Both gcc and clang reject this with "call is ambiguous". The fix is an explicit cast, but the error message does not explain this:
using EdgeCount = graph_traits<Graph>::edges_size_type;
erdos_renyi_iterator(gen, 100, EdgeCount(50)); // OK
B) small_world_iterator silently assumes undirected graphs
The original Watts-Strogatz model is strictly undirected. The algorithm starts from an undirected ring lattice and rewires undirected edges with probability p. There is no canonical directed version in the original paper.
Directed variants have been proposed in the literature, but they require explicit decisions and there is no consensus formulation:
- Algebraic approach to small-world network models
- Simple, distance-dependent formulation of the Watts-Strogatz model for directed and undirected small-world networks
However, in BGL when instantiated with a directed graph watts_strogatz_iterator, the iterator emits n * (k/2) directed edges (each source connects to its k/2 clockwise neighbors).
- For undirected graphs, each edge implicitly exists in both directions, giving every vertex degree k.
- For directed graphs, each edge exists in one direction only, giving every vertex out_degree = k/2.
- The Graph template parameter is only used for
vertices_size_type:directed_categoryis never checked.
Because generating a directed small-world graph requires explicit design choices, silently producing a broken/arbitrary result that does not check against any theory is probably worse than refusing to compile.
C) Default probability parameters mean different things across generators
| Generator | Default | Meaning |
|---|---|---|
erdos_renyi_iterator |
fraction = 0.0 |
Empty graph |
sorted_erdos_renyi_iterator |
prob = 0.5 |
50% density |
small_world_iterator |
prob = 0.0 |
No rewiring (ring lattice) |
A user familiar with one generator will be surprised by the others.
D) Parameter naming inconsistency in the same header
In erdos_renyi_generator.hpp:
erdos_renyi_iterator: parameter namedallow_self_loopssorted_erdos_renyi_iterator: parameter namedloops
Same concept, same header but different names is not very consistent.
E) Precondition violation behavior unspecified
random_vertex(g, gen)requiresnum_vertices(g) > 0random_edge(g, gen)requiresnum_edges(g) > 0
But neither the code nor the documentation specifies what happens on violation (undefined behavior, assertion, exception). Consequently:
random_vertexon empty graphs returns a boggus descriptorrandom_edgeon empty graph triggers assertion deep inside boost optional
output.s: /app/boost/include/boost/optional/optional.hpp:908: pointer_const_type boost::optional<std::pair<boost::detail::out_edge_iter<__gnu_cxx::__normal_iterator<boost::detail::stored_edge_property<unsigned long, boost::no_property> *, std::vector<boost::detail::stored_edge_property<unsigned long, boost::no_property>>>, unsigned long, boost::detail::edge_desc_impl<boost::directed_tag, unsigned long>, long>, boost::detail::out_edge_iter<__gnu_cxx::__normal_iterator<boost::detail::stored_edge_property<unsigned long, boost::no_property> *, std::vector<boost::detail::stored_edge_property<unsigned long, boost::no_property>>>, unsigned long, boost::detail::edge_desc_impl<boost::directed_tag, unsigned long>, long>>>::operator->() const [T = std::pair<boost::detail::out_edge_iter<__gnu_cxx::__normal_iterator<boost::detail::stored_edge_property<unsigned long, boost::no_property> *, std::vector<boost::detail::stored_edge_property<unsigned long, boost::no_property>>>, unsigned long, boost::detail::edge_desc_impl<boost::directed_tag, unsigned long>, long>, boost::detail::out_edge_iter<__gnu_cxx::__normal_iterator<boost::detail::stored_edge_property<unsigned long, boost::no_property> *, std::vector<boost::detail::stored_edge_property<unsigned long, boost::no_property>>>, unsigned long, boost::detail::edge_desc_impl<boost::directed_tag, unsigned long>, long>>]: Assertion `this->is_initialized()' failed.
- Dominant language
- C++
- Stars
- 395
- Forks
- 239
- Avg merge
- 18h 50m
- Merged PRs (30d)
- 20
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from boostorg/graph
-
beginner friendly
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
algorithm beginner friendly priority: high
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 5/5 Over a week Newbie friendliness 30/100
-
priority: high warning
-
algorithm
boostorg/graph#493 · 22 comments · 1 reaction · 2 assignees ·
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
AXERA-TECH/ax-llm#77 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
games-on-whales/wolf#509 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
bug-unconfirmed
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
NVIDIA/cuda-samples#453 ·