Repository navigation
feat: directed vertices record incoming edges; degree is in plus out; validate(); BaseGraph - #40
Merged
Merged
Conversation
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The class was named _BaseGraph when PGraph was split into a base class and UGraph/DGraph, but it is in the signature of every graph method, is shown in the documentation, and is what a user writes in a type hint, while its counterpart BaseVertex has no underscore. _BaseGraph was never released, so there is no alias. BaseGraph and BaseVertex are exported from pgraph, with an __all__. Mechanical: with the rename reversed, PGraph.py and exporters.py are byte-identical to the previous commit. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…s out A directed vertex now holds the edges that end at it as well as the ones that leave it, kept in step by _attach/_detach. That gives: - predecessors(), successors() (which is adjacent()), in_edges(), out_edges() - in_degree and out_degree - remove_vertex finding a vertex's edges from its own lists rather than scanning every edge in the graph (O(degree), was O(E)) - iscyclic taking in-degrees from the vertices (O(V), was O(E)) BREAKING, for a DGraph: degree is now the graph-theory degree, in plus out, so a self-loop counts 2 and the degrees of a graph sum to twice its edges. It counted only the edges leaving the vertex. This changes: vertex.degree (use out_degree for the old value) graph.degree() (np.diag([v.out_degree for v in g])) graph.connectivity() ([v.out_degree for v in g]) graph.average_degree() 2E/N, was E/N (g.ne / g.n) Laplacian() is unchanged: it is D_out - A, and now takes the out-degree explicitly instead of relying on degree(). For an undirected graph every quantity is as before. Each is documented with a versionchanged note, and a survey of RTB, MVTB and RVC3 found no caller of any of them on a DGraph. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A graph keeps the same facts in several places: its set of edges, each vertex's outgoing (and, if directed, incoming) edge lists, each edge's two vertices, each vertex's pointer back to its graph, and the name table. validate() returns a list of the ways they disagree, empty when consistent. It does not change the graph, costs O(V+E), reports every problem rather than the first, and does not raise on corruption, including stray objects in the containers. For tests, debugging, and code that reaches into the internals; a graph built and edited through the public methods is always valid. 27 deliberate corruptions, one per kind of record, are each detected and named; random edit sequences stay valid. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… a graph
label read-only. It is the component number, computed by the graph.
name assigning to the name of a vertex that is in a graph updates the
graph's name table, refuses a name already in use (ValueError) and
refuses to clear it. It left the table stale before, so g[new]
failed.
exporters use the public API: out_edges() instead of a vertex's private
_edgelist, and get_exporter(name) instead of the private table.
docs BaseVertex no longer lists _edgelist as an attribute.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…name Names are how g[name] finds a vertex, so they must be unique in a graph. - adding a vertex whose name is already used raised nothing and replaced the earlier vertex in the name table, leaving it in the graph but unreachable by name; it now raises ValueError and changes nothing - the default name #N used the number of vertices, so after a removal it could equal an existing name (remove #0 from #0 #1 #2, add one: #2 twice); it now takes the first #N that is free - a vertex that already belongs to a graph, this one or another, could be added: it was then listed by both. It now raises ValueError; a removed vertex can be added again, or elsewhere - every check precedes any change, so a refused add leaves the graph and the vertex exactly as they were Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 166 |
| Duplication | 2 |
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 Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #40 +/- ##
==========================================
+ Coverage 93.86% 94.60% +0.73%
==========================================
Files 3 3
Lines 1076 1205 +129
==========================================
+ Hits 1010 1140 +130
+ Misses 66 65 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Directed vertices now record the edges that end at them as well as the ones that leave them, and the rest of the in-edge / degree / hygiene work that follows from it. Six commits, each verified green on exactly its own contents:
BaseGraphis the public name of the common base class (_BaseGraphwas never released, so no alias);BaseGraphandBaseVertexare exported with an__all__.predecessors(),successors()(=adjacent()),in_edges(),out_edges(),in_degree,out_degree.remove_vertexfinds a vertex's edges from its own lists (O(degree), was O(E));iscyclicuses in-degrees (O(V), was O(E)).graph.validate()returns a list of the ways the graph's records disagree (empty when consistent). It does not change the graph, costs O(V+E) and never raises on corruption.Vertex.labelis read-only; assigningVertex.nameupdates the graph's name table, refuses a duplicate orNone; exporters use only the public API.add_vertexnames. A duplicate name raisesValueErrorand changes nothing; the default#Nname is the first free one (it could collide after a removal); a vertex that already belongs to a graph is refused.Breaking change for
DGraph(1.0)degreeis now the graph-theory degree, in plus out, so a self-loop counts 2 and the degrees of a graph sum to twice its edges. It counted only the edges leaving the vertex.vertex.degreevertex.out_degreegraph.degree()np.diag([v.out_degree for v in g])graph.connectivity()[v.out_degree for v in g]graph.average_degree()is2E/Ng.ne / g.nLaplacian()is unchanged (it isD_out - A, and now takes the out-degree explicitly). For an undirected graph every quantity is as before. Each is documented with aversionchangednote. A survey of RTB, MVTB and RVC3 found no caller of any of them on aDGraph.Tests
New:
test_in_edges,test_validate(27 deliberate corruptions each detected and named; random edit sequences stay valid),test_attribute_hygiene,test_add_vertex_names.🤖 Generated with Claude Code