Skip to content

Issue #33 - Move existing planarity module and associated files into classic subpackage, and add full subpackage with extended API for EAPS graphLib#35

Merged
john-boyer-phd merged 5 commits intomasterfrom
Issue33-AddFullGraphLibAPI
Mar 15, 2026
Merged

Issue #33 - Move existing planarity module and associated files into classic subpackage, and add full subpackage with extended API for EAPS graphLib#35
john-boyer-phd merged 5 commits intomasterfrom
Issue33-AddFullGraphLibAPI

Conversation

@wbkboyer
Copy link
Copy Markdown
Member

@wbkboyer wbkboyer commented Mar 6, 2026

Resolves #33

Added

  • planarity/__init__.pxd, planarity/classic/__init__.pxd - Needed for Cython package discovery
    • NOTE: Might require further discussion as to whether we should explicitly promote subpackage contents to the package namespace using cimport statements, as is done in __init__.py; see Cython Docs - pxd files: __init__.pxd
  • planarity/classic/__init__.py - supports imports from classic subpackage
  • planarity/full
    • cappconst.pxd - definition file for constants defined in planarity/c/graphLib/lowLevelUtils/appconst.h

    • cgraphLib.pxd - definition file for constants and functions pertaining to Graph class (currently used by planarity/full/graph.pyx and planarity/full/g6IterationUtils.pyx modules)

    • cg6IterationDefs.pxd - definitions from planarity/c/graphLib/io/g6-read-iterator.h and planarity/c/graphLib/io/g6-write-iterator.h required by planarity/full/g6IterationUtils.pyx

    • g6IterationUtils.pyx - introduces the G6ReadIterator and G6WriteIterator classes, which wrap the functions implemented in planarity/c/graphLib/io/g6-read-iterator.c and planarity/c/graphLib/io/g6-write-iterator.c that operate over G6ReadIteratorP and G6WriteIteratorP respectively (see EAPS Epic #10 for full context of this pattern)

    • graph.pxd - Cython definition file that ensures we can cimport the Graph from other Cython modules (e.g. the g6IterationUtils module); from the Cython docs on pxd files:

      When accompanying an equally named .pyx / .py file, they provide a Cython interface to the Cython module so that other Cython modules can communicate with it using a more efficient protocol than the Python one.

      And from Sharing Extension types:

      An extension type can be made available via cimport by splitting its definition into two parts, one in a definition file and the other in the corresponding implementation file.

    • graph.pyx - introduces the Graph class, which wraps a graphP and handles initialization and freeing in the __cinit__() and __dealloc__() methods, and wraps various gp_ functions and macros that operate on graphPs

    • g6IterationUtils.c and graph.c - extension source files produced when we Cythonize the planarity.full.g6IterationUtils and planarity.full.graph Extensions for use when installing on platforms without cython installed

    • planarity_app_utils.py - Pure python module containing constants and helper functions for working with Graphs, many of which have equivalents in the EAPS planarityApp layer

Updated

  • MANIFEST.in - changed include statements to reflect new classic subpackage contents, and added include statements for full subpackage
  • pyproject.toml - added the planarity.classic and planarity.full subpackages to the explicit list of packages`
  • setup.py - updated the Extension definition for the planarity.classic.planarity, and added Extensions for planarity.full.g6ReadIterationUtils and planarity.full.graph modules
  • planarity/__init__.py - Updated pathing for planarity package's planarity Cython module, since it is now contained in the classic subpackage. Performed similar promotion of full API contents to the planarity package namespace
  • planarity/classic/
    • cplanarity.pxd - updated pathing to reflect new project structure
    • planarity.pyx - updated cimport statement to reflect new project structure
    • cplanarity.c - rebuilt Cython extension source file to be used when installing on platforms without cython installed
    • planarity_functions.py and planarity_networkx.py - updated __all__ lists of exposed functions for readability

wbkboyer added 3 commits March 3, 2026 16:21
Note that this Cython sub-package has successfully been leveraged by refactored versions of the Test All Graphs Orchestrator and Edge Deletion Analyzer.
…g up the bounds-checking in the Graph methods

- Removed EDGEFLAG_DIRECTION constants from cgraphLib.pxd because they aren't currently used in Graph class
- Exposed gp_GetFirstEdge() and gp_EdgeInUseIndexBound(), then updated Graph.gp_IsArc() with additional bounds checks (also exposed gp_EdgeInUse())
- Added Graph.is_vertex() checks to Graph.gp_GetFirstArc()
- Added checks to ensure valid edge index in Graph.gp_GetNextArc(), Graph.gp_EdgeInUse(), Graph.gp_GetNeighbor(), and Graph.gp_DeleteEdge()
- Added checks to ensure valid link index in Graph.gp_AddEdge(), Graph.gp_DeleteEdge()
@wbkboyer wbkboyer requested a review from john-boyer-phd March 6, 2026 00:35
Copy link
Copy Markdown
Member

@john-boyer-phd john-boyer-phd left a comment

Choose a reason for hiding this comment

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

This is great progress. There are a few smaller edits to make on this PR.

Seeing how it has come out, esp. for read/write iterator, suggests pulling in an updated release of EAPS graphLib, but that should be done as a separate issue on this repo.

- confirmed EDA invalid OK results for N=6-10 (see https://github.com/graph-algorithms/edge-addition-planarity-suite/blob/fcded21925346e68876d5e50124caa1483bb01a6/TestSupport/tables/) by grafting pre-105 fix files (i.e. commit 89ca75fa4a2f35357e4aed64ec837860f77f1878 before graph-algorithms/edge-addition-planarity-suite@54ded4d) into C source and locally compiling package
- confirmed package published to TestPyPI produces 0 invalid OKs for N=6-10
@wbkboyer wbkboyer requested a review from john-boyer-phd March 11, 2026 02:06
Copy link
Copy Markdown
Member

@john-boyer-phd john-boyer-phd left a comment

Choose a reason for hiding this comment

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

Your work here has prompted a very important reconsideration of the names of a few functions in the C graphLib, because of an inconsistency in naming. So, I am over there working on the issue now, and in the meantime the additional requested changes here will make the functions use a new naming convention that is consistent and generally behave as they currently do in the C graphLib (except that the inconsistency was gp_IsVertex(), and your code here has the consistent behavior, and the C graphLib is being corrected accordingly).

def gp_IsVertex(self, int v):
return (
(v >= self.gp_GetFirstVertex()) and
self.gp_VertexInRange(v) and
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be better to use v<= self.gp_GetLastVertex() here, because of an upcoming change that appears to be necessary in the C API.

Copy link
Copy Markdown
Member Author

@wbkboyer wbkboyer Mar 13, 2026

Choose a reason for hiding this comment

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

Should I also remove the method gp_VertexInRange() from the Graph Cython class, as well as remove gp_VertexInRange() from the graph.pxd definition file?


def is_vertex(self, int v):
return v >= self.gp_GetFirstVertex() and self.gp_VertexInRange(v)
def gp_IsVertex(self, int v):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be helpful to define another function gp_IsAnyVertex() that returns true if and only if v >= first vertex and v <= last virtual vertex. This will be needed because some parameter guard invocations of gp_IsVertex() need to be gp_IsAnyVertex() because they should work whether the call is related to a vertex or a virtual vertex. It would also be best for it to have a commented-out call to cgraphlib.gp_IsAnyVertex(v) with a FIXME comment to make it a little easier to add the call once the new version of graphLib shows up that contains the function.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Should I be using the conjunct (v <= cgraphLib.gp_GetLastVirtualVertex(self._theGraph)) to test against the upper-bound for virtual vertices? So then the method would look something like:

    def gp_IsAnyVertex(self, int v):
        return (
            (v >= self.gp_GetFirstVertex()) and
            (v <= cgraphLib.gp_GetLastVirtualVertex(self._theGraph))
            # FIXME: Add conjunct to call upcoming macro cgraphLib.gp_IsAnyVertex()
        )

Should I go one step further and add a wrapper method for gp_GetLastVirtualVertex(theGraph)? If so, should I add a wrapper for gp_GetFirstVirtualVertex(theGraph) for symmetry? I don't want to clutter the API with wrappers that we don't yet use at the Python level, but the mixed syntax in the snippet above feels off D:

…ructures.h. Also updated second conjunct to explicitly test vertex index v against the index of the last vertex.
@wbkboyer wbkboyer requested a review from john-boyer-phd March 13, 2026 23:57
Copy link
Copy Markdown
Member

@john-boyer-phd john-boyer-phd left a comment

Choose a reason for hiding this comment

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

As we hashed out in our last meeting, I agree that the methods calling gp_IsVertex() should continue to do so because we are not yet exposing any reason much less any API way to access or use the virtual vertices.

@john-boyer-phd john-boyer-phd merged commit 528e64c into master Mar 15, 2026
5 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.

Integrate independent graphLib API for fine-grained access to gp_ functions.

2 participants