Skip to content

RRD - Add many new invariants/ predicates#25

Merged
RandyRDavila merged 4 commits into
mainfrom
rrd-add-many-new-invariants
Feb 3, 2026
Merged

RRD - Add many new invariants/ predicates#25
RandyRDavila merged 4 commits into
mainfrom
rrd-add-many-new-invariants

Conversation

@RandyRDavila
Copy link
Copy Markdown
Owner

No description provided.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a comprehensive set of new graph invariants and predicates to the graphcalc library, organized into three new modules and several additions to existing modules.

Changes:

  • Adds local invariants module with functions for computing graph parameters on neighborhood-induced subgraphs
  • Adds critical invariants module with vertex/edge deletion sensitivity analysis functions
  • Adds core invariants module with functions for computing the intersection of optimal solution sets
  • Extends degree.py with 5 new degree-based invariants (irregularity, degree counts)
  • Extends classics.py with 6 new classic graph invariants (arboricity, linear arboricity, bipartite number, average distance, path cover number)
  • Extends basics.py with 2 new C4-related predicates

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 20 comments.

Show a summary per file
File Description
local_invariants.py New module providing local parameter evaluation on neighborhoods (703 lines) with 9 exported functions
critical_invariants.py New module for vertex/edge deletion criticality analysis (853 lines) with helper functions for sensitivity testing
core_invariants.py New module for computing core sets (698 lines) with functions for finding forced vertices in optimal solutions
degree.py Added irregularity, n1_degree_count, distinct_degree_count, count_of_maximum_degree_vertices, count_of_minimum_degree_vertices
classics.py Added bipartite_number, average_distance, path_cover_number, arboricity, linear_arboricity with supporting helpers
basics.py Added is_C4_free and is_induced_C4_free predicates for detecting 4-cycles
init.py Added imports for the three new modules

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/graphcalc/invariants/degree.py Outdated
--------
>>> import networkx as nx
>>> G = nx.path_graph(5) # degrees: 1,2,2,2,1
>>> n1_degree_count(G)
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The function call in this example is missing the module prefix. It should be gc.n1_degree_count(G) to be consistent with other examples in this file.

Suggested change
>>> n1_degree_count(G)
>>> gc.n1_degree_count(G)

Copilot uses AI. Check for mistakes.
Comment thread src/graphcalc/invariants/degree.py Outdated
Comment on lines +974 to +977
>>> count_of_minimum_degree_vertices(G)
2
>>> H = nx.empty_graph(4) # all degrees 0
>>> count_of_minimum_degree_vertices(H)
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The function calls in these examples are missing the module prefix. They should be gc.count_of_minimum_degree_vertices(G) and gc.count_of_minimum_degree_vertices(H) to be consistent with other examples in this file.

Suggested change
>>> count_of_minimum_degree_vertices(G)
2
>>> H = nx.empty_graph(4) # all degrees 0
>>> count_of_minimum_degree_vertices(H)
>>> gc.count_of_minimum_degree_vertices(G)
2
>>> H = nx.empty_graph(4) # all degrees 0
>>> gc.count_of_minimum_degree_vertices(H)

Copilot uses AI. Check for mistakes.
Comment thread src/graphcalc/invariants/classics.py Outdated
Comment on lines +1033 to +1045
>>> # A path is coverable by a single path
>>> G = nx.path_graph(6)
>>> path_cover_number(G)
1

>>> # An edgeless graph on n vertices needs n singleton paths
>>> H = nx.empty_graph(5)
>>> path_cover_number(H)
5

>>> # Two disjoint paths need two paths in the cover
>>> J = nx.disjoint_union(nx.path_graph(3), nx.path_graph(4))
>>> path_cover_number(J)
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The function calls in these examples are missing the module prefix. They should be gc.path_cover_number(G), gc.path_cover_number(H), and gc.path_cover_number(J) to be consistent with the established pattern in this codebase.

Suggested change
>>> # A path is coverable by a single path
>>> G = nx.path_graph(6)
>>> path_cover_number(G)
1
>>> # An edgeless graph on n vertices needs n singleton paths
>>> H = nx.empty_graph(5)
>>> path_cover_number(H)
5
>>> # Two disjoint paths need two paths in the cover
>>> J = nx.disjoint_union(nx.path_graph(3), nx.path_graph(4))
>>> path_cover_number(J)
>>> import graphcalc as gc
>>> # A path is coverable by a single path
>>> G = nx.path_graph(6)
>>> gc.path_cover_number(G)
1
>>> # An edgeless graph on n vertices needs n singleton paths
>>> H = nx.empty_graph(5)
>>> gc.path_cover_number(H)
5
>>> # Two disjoint paths need two paths in the cover
>>> J = nx.disjoint_union(nx.path_graph(3), nx.path_graph(4))
>>> gc.path_cover_number(J)

Copilot uses AI. Check for mistakes.
Comment thread src/graphcalc/invariants/degree.py Outdated
Comment thread src/graphcalc/invariants/classics.py
Comment thread src/graphcalc/invariants/degree.py Outdated
Comment thread src/graphcalc/invariants/critical_invariants.py
Comment thread src/graphcalc/invariants/degree.py Outdated
Comment thread src/graphcalc/invariants/__init__.py
Comment thread src/graphcalc/invariants/__init__.py
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 33 out of 33 changed files in this pull request and generated 9 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/graphcalc/invariants/graph_indices.py Outdated
Comment thread docs/source/modules/viz.rst Outdated
Comment thread src/graphcalc/invariants/cycle_invariants.py
Comment thread src/graphcalc/invariants/classics.py Outdated
Comment thread src/graphcalc/invariants/graph_indices.py
Comment thread src/graphcalc/invariants/__init__.py
Comment thread src/graphcalc/invariants/cycle_invariants.py Outdated
Comment thread src/graphcalc/invariants/graph_indices.py Outdated
Comment thread src/graphcalc/invariants/graph_indices.py Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 34 out of 35 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -1,6 +1,6 @@

from typing import Hashable, List
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

Duplicate import: List is imported twice from the typing module on consecutive lines. The second import on line 3 also imports Sequence, making the first import redundant. Remove line 2.

Copilot uses AI. Check for mistakes.
index and the Wiener index. *Journal of Chemical Information and Computer Sciences*,
33(6), 1006-1009 (1993).
"""
return 2*sum((1/(gc.degree(G, v) + gc.degree(G, u)) for u, v in G.edges()))
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

Inefficiency: gc.degree(G, v) and gc.degree(G, u) are called for every edge. This makes O(m) degree lookups where m is the number of edges, which could be expensive. Consider pre-computing degrees once:

deg = dict(G.degree())
return 2*sum(1/(deg[u] + deg[v]) for u, v in G.edges())

This pattern is used correctly in other index functions in this same file (e.g., randic_index line 94-95).

Suggested change
return 2*sum((1/(gc.degree(G, v) + gc.degree(G, u)) for u, v in G.edges()))
deg = dict(G.degree())
return 2 * sum(1 / (deg[u] + deg[v]) for u, v in G.edges())

Copilot uses AI. Check for mistakes.

import math
import networkx as nx
import graphcalc as gc
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

Module 'graphcalc' is imported with both 'import' and 'import from'.

Suggested change
import graphcalc as gc

Copilot uses AI. Check for mistakes.
@RandyRDavila RandyRDavila merged commit 99ad473 into main Feb 3, 2026
7 checks passed
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