Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/express/write_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@
planarity.write(edgelist, "stdout", planarity.WRITE_G6)
print("\n")

print("GraphML: ")
planarity.write(edgelist, "stdout", planarity.WRITE_GRAPHML)
print("\n")
18 changes: 10 additions & 8 deletions examples/full/demo_specific_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def specific_graph(
WRITE_ADJLIST,
WRITE_ADJMATRIX,
WRITE_G6,
WRITE_GRAPHML,
Graph,
)

Expand Down Expand Up @@ -65,7 +66,7 @@ def specific_graph(
outdir: parent directory under which to make output directory
command: algorithm command specifier
output_mode: the desired output format, i.e., WRITE_ADJLIST,
WRITE_ADJMATRIX, or WRITE_G6
WRITE_ADJMATRIX, WRITE_G6, or WRITE_GRAPHML

Returns:
OK, NONEMBEDDABLE, or NOTOK based on the embed_result
Expand All @@ -78,7 +79,7 @@ def specific_graph(
"""
gp_SetQuietMode(QUIETMODE_NONE)

if output_mode not in (WRITE_ADJLIST, WRITE_ADJMATRIX, WRITE_G6):
if output_mode not in (WRITE_ADJLIST, WRITE_ADJMATRIX, WRITE_G6, WRITE_GRAPHML):
raise ValueError(
f"Invalid output_mode = {output_mode}"
)
Expand Down Expand Up @@ -232,8 +233,8 @@ def print_embed_result(command: str, embed_result: int) -> None:
type=str,
required=False,
default="a",
help="Desired graph output format: .g6 (g), Adjacency List (a), or "
"Adjacency Matrix (m). Defaults to 'a'\n",
help="Desired graph output format: .g6 (g), .graphml (x), "
"Adjacency List (a), or Adjacency Matrix (m). Defaults to 'a'\n",
)

args = parser.parse_args()
Expand All @@ -245,14 +246,15 @@ def print_embed_result(command: str, embed_result: int) -> None:
] if args.commands else PLANARITY_ALGORITHM_SPECIFIERS()

output_mode = (WRITE_ADJLIST if args.mode == "a"
else (WRITE_ADJMATRIX if args.mode == "m"
else (WRITE_ADJMATRIX if args.mode == "m"
else (WRITE_G6 if args.mode == "g"
else None)))
else (WRITE_GRAPHML if args.mode == "x"
else None))))

if not output_mode:
raise ValueError(
f"Invalid argument for mode = {args.mode}; only accepted values "
"are g (.g6), a (Adjacency List), or m (Adjacency Matrix)"
f"Invalid argument for mode = {args.mode}; only accepted values are "
"g (.g6), x (.graphml), a (Adjacency List), or m (Adjacency Matrix)"
)

for command in commands:
Expand Down
14 changes: 14 additions & 0 deletions examples/full/sample_files/one_edge.graphml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<graph id="G1" edgedefault="undirected"
parse.nodes="2" parse.edges="1"
parse.nodeids="canonical" parse.edgeids="canonical"
parse.order="nodesfirst">
<node id="n0"/>
<node id="n1"/>
<edge id="e0" source="n0" target="n1"/>
</graph>
</graphml>
3 changes: 3 additions & 0 deletions examples/full/sample_files/one_edge.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
N=2
1: 2 0
2: 1 0
1 change: 1 addition & 0 deletions planarity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
WRITE_ADJLIST,
WRITE_ADJMATRIX,
WRITE_G6,
WRITE_GRAPHML,
GRAPHFLAGS_ZEROBASEDIO,
)
# Surfaced from planarity/c/graphLib/planarityRelated/graphPlanarity.h
Expand Down
22 changes: 0 additions & 22 deletions planarity/c/LICENSE.TXT
Original file line number Diff line number Diff line change
@@ -1,26 +1,4 @@
The Edge Addition Planarity Suite
Copyright (c) 1997-2026, John M. Boyer
All rights reserved. Includes a reference implementation of the following:

* John M. Boyer. "Subgraph Homeomorphism via the Edge Addition Planarity Algorithm".
Journal of Graph Algorithms and Applications, Vol. 16, no. 2, pp. 381-410, 2012.
http://dx.doi.org/10.7155/jgaa.00268

* John M. Boyer. "A New Method for Efficiently Generating Planar Graph
Visibility Representations". In P. Eades and P. Healy, editors,
Proceedings of the 13th International Conference on Graph Drawing 2005,
Lecture Notes Comput. Sci., Volume 3843, pp. 508-511, Springer-Verlag, 2006.
http://dx.doi.org/10.1007/11618058_47

* John M. Boyer and Wendy J. Myrvold. "On the Cutting Edge: Simplified O(n)
Planarity by Edge Addition". Journal of Graph Algorithms and Applications,
Vol. 8, No. 3, pp. 241-273, 2004.
http://dx.doi.org/10.7155/jgaa.00091

* John M. Boyer. "Simplified O(n) Algorithms for Planar Graph Embedding,
Kuratowski Subgraph Isolation, and Related Problems". Ph.D. Dissertation,
University of Victoria, 2001.
https://dspace.library.uvic.ca/handle/1828/9918

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Expand Down
101 changes: 53 additions & 48 deletions planarity/c/graphLib/extensionSystem/graphExtensions.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ See the LICENSE.TXT file for licensing information.
#include <string.h>

#include "../lowLevelUtils/appconst.h"
#include "../graph.private.h"

#include "graphExtensions.private.h"
#include "graphExtensions.h"
Expand Down Expand Up @@ -95,15 +96,11 @@ static int moduleIDGenerator = 0;
if your feature is attached but not active or if your feature
augments the base behavior rather than replacing it.

a) If extra data must be maintained at the graph, vertex or edge
levels, then fpEnsureVertexCapacity(), fpEnsureEdgeCapacity(),
and fpResetGraphStorage() must be overloaded.
a) If extra data must be maintained at the graph, vertex or edge
levels, then fpEnsureVertexCapacity(), fpEnsureEdgeCapacity(),
fpDeleteEdge(), and fpResetGraphStorage() must be overloaded.

b) For a parallel array of edge data, the extension must currently
provides its own _Feature_DeleteEdge() that initializes its edge
extension data along with calling gp_DeleteEdge().

c) If any data must be persisted in the file format, then overloads
b) If any data must be persisted in the file format, then overloads
of fpReadPostprocess() and fpWritePostprocess() are needed.

7) Define internal functions for _Feature_ClearStructures(),
Expand Down Expand Up @@ -182,7 +179,12 @@ int gp_AddExtension(graphP theGraph,

if (theGraph == NULL || pModuleID == NULL ||
context == NULL || copyData == NULL || freeContext == NULL ||
functions == NULL)
functions == NULL || theGraph->extensionLookupTable == NULL)
{
return NOTOK;
}

if (*pModuleID < 0 || *pModuleID > MAXNUMSUPPORTEDEXTENSIONS)
{
return NOTOK;
}
Expand All @@ -196,6 +198,10 @@ int gp_AddExtension(graphP theGraph,
// Assign a unique ID to the extension if it does not already have one
if (*pModuleID == 0)
{
if (moduleIDGenerator >= MAXNUMSUPPORTEDEXTENSIONS)
{
return NOTOK;
}
*pModuleID = ++moduleIDGenerator;
}

Expand All @@ -218,6 +224,7 @@ int gp_AddExtension(graphP theGraph,
// Make the new linkages
newExtension->next = (struct graphExtensionStruct *)theGraph->extensions;
theGraph->extensions = newExtension;
theGraph->extensionLookupTable[newExtension->moduleID] = newExtension;

// The new extension was successfully added
return OK;
Expand Down Expand Up @@ -273,32 +280,28 @@ void _OverloadFunctions(graphP theGraph, graphFunctionTableP functions)

int gp_FindExtension(graphP theGraph, int moduleID, void **pContext)
{
graphExtensionP first = NULL, next = NULL;
graphExtensionP extension = NULL;

if (pContext != NULL)
{
*pContext = NULL;
}

if (theGraph == NULL || moduleID == 0)
if (theGraph == NULL || moduleID <= 0 ||
moduleID > MAXNUMSUPPORTEDEXTENSIONS ||
theGraph->extensionLookupTable == NULL)
{
return FALSE;
}

first = theGraph->extensions;

while (first != NULL)
extension = theGraph->extensionLookupTable[moduleID];
if (extension != NULL)
{
next = (graphExtensionP)first->next;
if (first->moduleID == moduleID)
if (pContext != NULL)
{
if (pContext != NULL)
{
*pContext = first->context;
}
return TRUE;
*pContext = extension->context;
}
first = next;
return TRUE;
}

return FALSE;
Expand Down Expand Up @@ -342,7 +345,9 @@ int gp_RemoveExtension(graphP theGraph, int moduleID)
{
graphExtensionP prev = NULL, curr = NULL, next = NULL;

if (theGraph == NULL || moduleID == 0)
if (theGraph == NULL || moduleID <= 0 ||
moduleID > MAXNUMSUPPORTEDEXTENSIONS ||
theGraph->extensionLookupTable == NULL)
return NOTOK;

curr = theGraph->extensions;
Expand Down Expand Up @@ -372,6 +377,7 @@ int gp_RemoveExtension(graphP theGraph, int moduleID)
theGraph->extensions = next;

// Free the curr extension
theGraph->extensionLookupTable[curr->moduleID] = NULL;
_FreeExtension(curr);
}

Expand Down Expand Up @@ -448,7 +454,8 @@ int gp_DupExtensions(graphP dstGraph, graphP srcGraph)
{
graphExtensionP next = NULL, newNext = NULL, newLast = NULL;

if (srcGraph == NULL || dstGraph == NULL)
if (srcGraph == NULL || dstGraph == NULL ||
dstGraph->extensionLookupTable == NULL)
return NOTOK;

gp_FreeExtensions(dstGraph);
Expand All @@ -457,6 +464,12 @@ int gp_DupExtensions(graphP dstGraph, graphP srcGraph)

while (next != NULL)
{
if (next->moduleID <= 0 || next->moduleID > MAXNUMSUPPORTEDEXTENSIONS)
{
gp_FreeExtensions(dstGraph);
return NOTOK;
}

if ((newNext = (graphExtensionP)malloc(sizeof(graphExtensionStruct))) == NULL)
{
gp_FreeExtensions(dstGraph);
Expand All @@ -471,6 +484,10 @@ int gp_DupExtensions(graphP dstGraph, graphP srcGraph)
newNext->functions = next->functions;
newNext->next = NULL;

// Add the new extension to the dstGraph extension lookup table
dstGraph->extensionLookupTable[newNext->moduleID] = newNext;

// Add the new extension to the dstGraph extensions linked list
if (newLast != NULL)
newLast->next = (struct graphExtensionStruct *)newNext;
else
Expand All @@ -488,38 +505,18 @@ int gp_DupExtensions(graphP dstGraph, graphP srcGraph)
gp_CopyExtensions()
********************************************************************/

// This number can just be made bigger if ever needed
#define MAXNUMSUPPORTEDEXTENSIONS 32

int gp_CopyExtensions(graphP dstGraph, graphP srcGraph)
{
graphExtensionP dstExtension = NULL, srcExtension = NULL;
graphExtensionP srcExtensionIDMap[MAXNUMSUPPORTEDEXTENSIONS+1];

if (srcGraph == NULL || dstGraph == NULL)
if (srcGraph == NULL || dstGraph == NULL ||
srcGraph->extensionLookupTable == NULL ||
dstGraph->extensionLookupTable == NULL)
return NOTOK;

if (gp_GetN(dstGraph) != gp_GetN(srcGraph) || gp_GetN(dstGraph) == 0)
return NOTOK;

// NULL out the pointers in the srcExtensionIDMap
memset(srcExtensionIDMap, 0, (MAXNUMSUPPORTEDEXTENSIONS+1)*sizeof(graphExtensionP));

// Run through the srcGraph extensions linked list and put the pointer to
// each extension in the srcExtensionIDMap at the index location indicated
// by the extension module ID. This mapping is needed because the srcGraph
// may have been extended with the extensions in a different order than the
// dstGraph, but the moduleID for each extension is the same across graphs.
srcExtension = srcGraph->extensions;
while (srcExtension != NULL)
{
if (srcExtension->moduleID < 0 || srcExtension->moduleID > MAXNUMSUPPORTEDEXTENSIONS)
return NOTOK;

srcExtensionIDMap[srcExtension->moduleID] = srcExtension;
srcExtension = (graphExtensionP)srcExtension->next;
}

// For each extension in the dstGraph, if the srcGraph has the same extension,
// then we invoke the extension's copyData to copy from srcGraph to dstGraph.
// If the dstGraph has an extension that the srcGraph does not have, then
Expand All @@ -528,7 +525,11 @@ int gp_CopyExtensions(graphP dstGraph, graphP srcGraph)
dstExtension = dstGraph->extensions;
while (dstExtension != NULL)
{
srcExtension = srcExtensionIDMap[dstExtension->moduleID];
if (dstExtension->moduleID <= 0 ||
dstExtension->moduleID > MAXNUMSUPPORTEDEXTENSIONS)
return NOTOK;

srcExtension = srcGraph->extensionLookupTable[dstExtension->moduleID];
if (dstExtension->copyData(dstExtension->context, srcExtension ? srcExtension->context : NULL) != OK)
return NOTOK;

Expand Down Expand Up @@ -562,6 +563,10 @@ void gp_FreeExtensions(graphP theGraph)
}

theGraph->extensions = NULL;
if (theGraph->extensionLookupTable != NULL)
{
memset(theGraph->extensionLookupTable, 0, (MAXNUMSUPPORTEDEXTENSIONS+1)*sizeof(graphExtensionP));
}
_InitFunctionTable(theGraph);
}
}
Expand Down
6 changes: 3 additions & 3 deletions planarity/c/graphLib/extensionSystem/graphExtensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ extern "C"
int gp_AddExtension(graphP theGraph,
int *pModuleID,
void *context,
void *(*dupContext)(void *, void *),
int (*copyData)(void *, void *),
void (*freeContext)(void *),
void *(*dupContext)(void *pContext, void *theGraph),
int (*copyData)(void *dstContext, void *srcContext),
void (*freeContext)(void *pContext),
graphFunctionTableP overloadTable);

int gp_FindExtension(graphP theGraph, int moduleID, void **pContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ extern "C"
{
int moduleID;
void *context;
void *(*dupContext)(void *, void *);
int (*copyData)(void *, void *);
void (*freeContext)(void *);
void *(*dupContext)(void *pContext, void *theGraph);
int (*copyData)(void *dstContext, void *srcContext);
void (*freeContext)(void *pContext);

graphFunctionTableP functions;

Expand Down
Loading
Loading