Issue #37 - Update planarity/c/graphLib/ contents + corresponding .pxd definition files + .pyx Cython source files in preparation for EAPS 4.0.2 release#38
Conversation
…D of master. Tested that classic scripts all still produce expected output, ran pytest, and updated (currently private) EAPS testing Python script repo to leverage the wrapper to ensure test_all_graphs.py and edge_deletion_analysis.py both produce the same OK/NONEMBEDDABLE results for N=6,10.
…D of master, updating .pxd definition files, and updating C library function calls in .pyx files.
… embed result integrity, then writes the result to file. Running the module as a script allows user to specify the input file, the parent of the output directory for that input file, and the graph algorithm extensions to run on that input file.
john-boyer-phd
left a comment
There was a problem hiding this comment.
This is great work, only two minor changes:
-
Can you please make the new "specific graph" script (full api 101 demo) also emit the core embedResult from
gp_Embed()? If multiple algorithms are executed, then a result for each would be great (the graph is planar/non-planar, the graph contains/doesn't contain a K3,3 homeomorph, etc.). -
Please can you expose two functions from graphLib.h:
gp_GetProjectVersionFullandgp_GetLibPlanarityVersionFull? These are useful so that a user of the planarity python package can always find out about the underlying EAPS version. Ideally, you could even have your specific graph start out by emitting the "The planarity package is based on the Edge Addition Planarity Suite version N.N.N.N, which contains the libPlanarity graph library version N:N:N" or similar.
…he chosen graph algorithm extension(s) on the input graph.
…didn't cause issues with local pytest nor running script locally, i.e. "worked on my box"
john-boyer-phd
left a comment
There was a problem hiding this comment.
This is really coming along. Just a few more requested changes:
- Moving most of
planarity_app_utils.pyto the bottom oftest_specific_graph.py - Removing the edge capacity specifiers method and logic.
- Tweak to return value of planarity package info method
- Fix up algo name versus name of what algo returns
- Comment fix in max num edges method
Discuss necessity and name of two non-EAPS methods in graph.pyx (and any non-EAPS methods anywhere else, e.g., G6).
Separated classic and full example scripts into their own namespace packages under examples/ directory. Verified that pip install planarity of sdist published to TestPyPI was able to be used with examples/full/test_specific_graph.py
john-boyer-phd
left a comment
There was a problem hiding this comment.
Excellent addressing of all requests.
Contributes to #37
Type of change
Please check only relevant options:
Changes
Added
examples/full/test_specific_graph.py- reads in a graph, callsgp_Embed()and tests embed result integrity, then writes the result to file. Running the module as a script allows user to specify the input file, the parent of the output directory for that input file, and the graph algorithm extensions to run on that input file.Updated
examples/- Moved existing Python scripts leveraging theplanaritypackage into theclassic/package, then created thefull/namespace package to contain the newtest_specific_graph.pymodule and the (moved)planarity_app_utils.pyfull/planarity_app_utils.py- moved__all__variable to reside under docstring (see Module Level Dunder Names).examples/full/test_specific_graph.pyneeds neithermax_num_edges_for_order()norENSURE_EDGE_CAPACITY_SPECIFIERS()functions, since we are reading a single graph usinggp_Read()(which will always callgp_DynamicAddEdge()behind the scenes, which itself callsgp_EnsureEdgeCapacity()ifgp_AddEdge()failed due to lack of space in the edge array) before we extend the graph with the structures associated with the desired the graph algorithm extension (see this comment).N.B. Due to the move, the
planarity_app_utilsmodule contents are no longer in theplanaritypackage namespaceplanarity/c/graphLib/- Updated to reflectc/graphLib/of current EAPSHEADofmasterplanarity/__init__.py- exposed new Cython functions togp_GetProjectVersionFull()andgp_GetLibPlanarityVersionFull()(which directly call into thecgraphLibplanarity/classic/cplanarity.pxd-gp_IsArc()renamed togp_IsEdge()and now takes thegraphPas well as the vertex index.gp_Get(First|Last|Prev|Next)Arc()renamed togp_Get(First|Last|Prev|Next)Edge()with no change to parameter list.cdefbefore declarations withincdef externblocks (see Cython docs - Interfacing with External C Code: Referencing C Header Files, where they say "Thecdef externfrom clause does three things:... 3) It treats all declarations within the block as though they started withcdef extern.")gp_AttachDrawPlanar()togp_ExtendWith_DrawPlanar()planarity.pyx-PGraph.embed_planar(), early-out if embedding has already been performed; then, callcplanarity.gp_ExtendWith_Planarity(self.theGraph)(even though this currently is a macro that returnsOK, this will eventually become a function in a separate header file according to @john-boyer-phd , i.e. will need to extend thegraphPwith structures associated with core planarity)PGraph.embed_drawplanar(), now callcgraphLib.gp_ExtendWith_DrawPlanar()and updatedRuntimeErrormessagingPGraph.edges(), updated calls togp_IsArc()togp_IsEdge()with the first parameter being thegraphPassociated with the CythonPGraphobject. Also usegp_GetFirstEdge()rather thanArcplanarity.c- rebuilt on MacOS Tahoe 26.3.1 using Cython 3.2.4 withclang22.1.1planarity/full/cg6IterationDefs.pxd- updated function names to reflect changes to thegraphLibcgraphLib.pxd- updated function and macro names and parameterization to reflect changes to thegraphLib, e.g.gp_IsArc()-->gp_IsEdge()(Which now hasgraphPas first param),gp_EdgeIndexBound()-->gp_EdgeArraySize(),gp_EdgeInUseIndexBound()-->gp_EdgeInUseArraySize(),gp_Get(First|Next)Arc()-->gp_Get(First|Next)Edge(),gp_VertexInRange()-->gp_VertexInRangeAscending(). Also,gp_IsVertex()takes agraphPas first param (as mentioned above). Finally, added declarations forgp_ExtendWith_Planarity()andgp_ExtendWith_Outerplanarity()(although these macros will become functions whose declarations will be in their own respective header files in the future according to @john-boyer-phd ; see above) Finally, exposes definitions forgp_DrawPlanar_RenderTo(File|String)()g6IterationUtils.pyx- updatedG6(Read|Write)IteratorCython classes so that method names match the CgraphLibfunction names. Note also that we no longer end iteration before freeing (i.e. removed redundant behaviour in thegraphLib).graph.pyx- UpdatedGraphCython class so that method names match the CgraphLibfunction/macro names (taking care to ensure the right macros are being used due to the distinction of Principal Vertices vs. Virtual Vertices vs. Any Type Vertices), and updated the arguments passed down to the C layer. Removedis_graph_NULL(), since this method was only used as a check ingp_CopyGraph()(which I've updated to work around this removal from the public API). Finally, adds wrappers forgp_DrawPlanar_RenderTo(File|String)(), where the string functionality makes sure to clean up therenditionStringreturned from thegraphLibafter copying the contents to a Python string.g6IterationUtils.candgraph.c- rebuilt on MacOS Tahoe 26.3.1 using Cython 3.2.4 withclang22.1.1Removed
Testing
pytest tests/test_all_graphs.pyandedge_deletion_analysis.pyboth produce the sameOK/NONEMBEDDABLEresults forN=6,10.numInvalidOKscounts forgraphK33Search.c:extern int _MarkLowestXYPath()declaration toextern int _MarkHighestXYPath()_TestForLowXYPath(), and restore definition of this function_RunExtraK33Tests(), remove call to_ClearVisitedFlagsInBicomp()and restore call to_TestForLowXYPath(), and remove call to re-mark lowest x-y path_TestForLowXYPath(), need to add checks forIC->py != NILany time we look at the result of_MarkHighestXYPath(), because if we are in the E4 case and no path is found, we must be in an error state. This is because the original implementation of_MarkHighestXYPath()used to returnTRUE(highest x-y path marked successfully) orFALSE(no x-y path exists OR an error was encountered when attempting to mark the path) but NOW returnsOK(highest x-y path marked successfully) orNOTOK(failed to mark path between x and y), so in order to verify that a path exists, you need to also check thatIC->py != NIL(i.e. if no path exists between x and y, no error would be emitted by_MarkHighestXYPath(), and the low connection points would beNIL).Testing examples/full/test_specific_graph.py and all examples/classic examples, plus pytest
Installing dependencies (note especially
setuptoolsto install from TestPyPI using--no-build-isolationflag forpip; see this comment for details):Installing
planaritypackage from TestPyPI:Running
examples/classic/scripts:Running
pytest:Zip files of tables vs. prior version of
graphLib:tables.zip
tables-old.zip