Skip to content

test: self-loops and parallel edges across degree, matrices, cycles and planning (+ fixes) - #26

Merged
petercorke merged 6 commits into
mainfrom
test/self-loops-parallel-edges
Oct 11, 2026
Merged

petercorke merged 6 commits into
mainfrom
test/self-loops-parallel-edges

Conversation

@petercorke

Copy link
Copy Markdown
Owner

Summary

Self-loops and parallel edges are permitted by connect()/add_edge(), but several things derived from the edge set gave wrong answers or hung. This adds tests that pin down the behavior for UGraph and DGraph, fixes what they found, and documents the conventions.

The narrative per graph type: simple acyclic network → add a self-loop on the route → remove it (must restore the baseline exactly) → add parallel edges (planning must take the cheapest) → add the loop back.

Bugs fixed

Area Before After
path_UCS / path_Astar with a self-loop on the route hung forever (the expanded vertex was re-added to the frontier as its own parent) loop skipped
Path length with parallel edges first edge found, not the cheapest (reported 2.0, correct 1.5) cheapest; edgeto() returns the cheapest
DGraph.path_BFS ValueError: dest is not a neighbour on every directed graph (child→parent edgeto) parent→child, as UCS/A*
adjacency() 0/1, so parallel edges collapsed edge counts; rows sum to the degree
Laplacian() degree - (adjacency > 0), row sums non-zero with multi-edges degree - adjacency, rows sum to zero
distance() last-written parallel edge wins (order dependent) cheapest
incidence() undirected loop column summed to 1 2, matching degree

Output is identical for simple graphs.

Conventions (documented in the docstrings under "For graphs with parallel edges or loops")

  • a self-loop adds 2 to a UGraph vertex's degree, 1 to a DGraph vertex's out-degree
  • adjacency()[i, j] is the number of edges from i to j
  • iscyclic(): a self-loop is a cycle; two parallel edges are a cycle in a UGraph but not in a DGraph

Notes for review

  • adjacency() and Laplacian() change for multigraphs, so this is worth a CHANGELOG line. I left CHANGELOG.md alone to avoid a conflict with Release 1.0.0 #14.
  • New tests are in tests/test_multigraph.py (15 tests); they fail on main and pass here. They use a SIGALRM guard so a regression fails rather than hanging the suite.
  • A follow-up stacked on this branch only clarifies the planners' :return: text.

🤖 Generated with Claude Code

petercorke and others added 4 commits October 11, 2026 09:52
…nd planning

Narrative per graph type: baseline, add self-loop on the route, remove it,
add parallel edges (planning must take the cheapest), add the loop back.
Fails on current code; fixes follow in separate commits.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ions

- path_UCS/path_Astar hung forever when a self-loop lay on the route
  (the expanded vertex was re-added to the frontier as its own parent)
- path lengths used the first edge found, not the cheapest of parallel
  edges; edgeto() now returns the cheapest
- path_BFS rebuilt the length with child->parent edgeto(), which raised
  ValueError on every DGraph; it now goes parent->child like UCS/A*
- adjacency() counts edges (was 0/1), so rows sum to the degree and
  Laplacian() = degree() - adjacency() has zero row sums again
- distance() takes the cheapest parallel edge rather than the last written
- incidence() column for an undirected self-loop is 2, matching degree

Identical results for simple graphs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Adds a 'For graphs with parallel edges or loops' rubric to degree(),
adjacency(), incidence(), Laplacian() and distance(); notes on edgeto()
and the three planners.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…anner exceptions

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@codacy-production

codacy-production Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 35 complexity · 4 duplication

Metric Results
Complexity 35
Duplication 4

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@codecov

codecov Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.45455% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 87.37%. Comparing base (e368024) to head (a238e71).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
src/pgraph/PGraph.py 95.45% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #26      +/-   ##
==========================================
+ Coverage   86.14%   87.37%   +1.22%     
==========================================
  Files           2        2              
  Lines         787      800      +13     
==========================================
+ Hits          678      699      +21     
+ Misses        109      101       -8     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@petercorke
petercorke merged commit 5beab4e into main Oct 11, 2026
12 checks passed
@petercorke
petercorke deleted the test/self-loops-parallel-edges branch October 11, 2026 03:59
@petercorke petercorke mentioned this pull request Oct 12, 2026
2 tasks done
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.

1 participant