int legacyCommandLine(int argc, char *argv[]) { graphP theGraph = gp_New(); int Result; Result = gp_Read(theGraph, argv[1]); if (Result != OK) { if (Result != NONEMBEDDABLE) { if (strlen(argv[1]) > MAXLINE - 100) sprintf(Line, "Failed to read graph\n"); else sprintf(Line, "Failed to read graph %s\n", argv[1]); ErrorMessage(Line); return -2; } } Result = gp_Embed(theGraph, EMBEDFLAGS_PLANAR); if (Result == OK) { gp_SortVertices(theGraph); gp_Write(theGraph, argv[2], WRITE_ADJLIST); } else if (Result == NONEMBEDDABLE) { if (argc >= 5 && strcmp(argv[3], "-n")==0) { gp_SortVertices(theGraph); gp_Write(theGraph, argv[4], WRITE_ADJLIST); } } else Result = NOTOK; gp_Free(&theGraph); // In the legacy 1.x versions, OK/NONEMBEDDABLE was 0 and NOTOK was -2 return Result==OK || Result==NONEMBEDDABLE ? 0 : -2; }
int RandomGraph(char command, int extraEdges, int numVertices, char *outfileName, char *outfile2Name) { int Result; platform_time start, end; graphP theGraph=NULL, origGraph; int embedFlags = GetEmbedFlags(command); char saveEdgeListFormat; GetNumberIfZero(&numVertices, "Enter number of vertices:", 1, 1000000); if ((theGraph = MakeGraph(numVertices, command)) == NULL) return NOTOK; srand(time(NULL)); Message("Creating the random graph...\n"); platform_GetTime(start); if (gp_CreateRandomGraphEx(theGraph, 3*numVertices-6+extraEdges) != OK) { ErrorMessage("gp_CreateRandomGraphEx() failed\n"); return NOTOK; } platform_GetTime(end); sprintf(Line, "Created random graph with %d edges in %.3lf seconds. ", theGraph->M, platform_GetDuration(start,end)); Message(Line); FlushConsole(stdout); // The user may have requested a copy of the random graph before processing if (outfile2Name != NULL) { gp_Write(theGraph, outfile2Name, WRITE_ADJLIST); } origGraph = gp_DupGraph(theGraph); // Do the requested algorithm on the randomly generated graph Message("Now processing\n"); FlushConsole(stdout); if (strchr("pdo234", command)) { platform_GetTime(start); Result = gp_Embed(theGraph, embedFlags); platform_GetTime(end); gp_SortVertices(theGraph); if (gp_TestEmbedResultIntegrity(theGraph, origGraph, Result) != Result) Result = NOTOK; } else if (command == 'c') { platform_GetTime(start); Result = gp_ColorVertices(theGraph); platform_GetTime(end); } else Result = NOTOK; // Write what the algorithm determined and how long it took WriteAlgorithmResults(theGraph, Result, command, start, end, NULL); // On successful algorithm result, write the output file and see if the // user wants the edge list formatted file. if (Result == OK || Result == NONEMBEDDABLE) { if (outfileName != NULL) gp_Write(theGraph, outfileName, WRITE_ADJLIST); Prompt("Do you want to save the generated graph in edge list format (y/n)? "); fflush(stdin); scanf(" %c", &saveEdgeListFormat); if (tolower(saveEdgeListFormat) == 'y') { char *fileName = "maxPlanarEdgeList.txt"; if (extraEdges > 0) fileName = "nonPlanarEdgeList.txt"; SaveAsciiGraph(theGraph, fileName); sprintf(Line, "Edge list format saved to '%s'\n", fileName); Message(Line); } } else ErrorMessage("Failure occurred"); gp_Free(&theGraph); gp_Free(&origGraph); FlushConsole(stdout); return Result; }
Obj boyers_planarity_check(Obj digraph, int flags, bool krtwsk) { DIGRAPHS_ASSERT(flags == EMBEDFLAGS_PLANAR || flags == EMBEDFLAGS_OUTERPLANAR || flags == EMBEDFLAGS_SEARCHFORK23 || flags == EMBEDFLAGS_SEARCHFORK4 || flags == EMBEDFLAGS_SEARCHFORK33); if (CALL_1ARGS(IsDigraph, digraph) != True) { ErrorQuit("Digraphs: boyers_planarity_check (C): the 1st argument must be " "a digraph, not %s", (Int) TNAM_OBJ(digraph), 0L); } Obj const out = FuncOutNeighbours(0L, digraph); if (FuncIS_ANTISYMMETRIC_DIGRAPH(0L, out) != True) { ErrorQuit("Digraphs: boyers_planarity_check (C): the 1st argument must be " "an antisymmetric digraph", 0L, 0L); } Int V = DigraphNrVertices(digraph); Int E = DigraphNrEdges(digraph); if (V > INT_MAX) { // Cannot currently test this, it might always be true, depending on the // definition of Int. ErrorQuit("Digraphs: boyers_planarity_check (C): the maximum number of " "nodes is %d, found %d", INT_MAX, V); return 0L; } else if (2 * E > INT_MAX) { // Cannot currently test this ErrorQuit("Digraphs: boyers_planarity_check (C): the maximum number of " "edges is %d, found %d", INT_MAX / 2, E); return 0L; } graphP theGraph = gp_New(); switch (flags) { case EMBEDFLAGS_SEARCHFORK33: gp_AttachK33Search(theGraph); break; case EMBEDFLAGS_SEARCHFORK23: gp_AttachK23Search(theGraph); break; case EMBEDFLAGS_SEARCHFORK4: gp_AttachK4Search(theGraph); break; } if (gp_InitGraph(theGraph, V) != OK) { gp_Free(&theGraph); ErrorQuit("Digraphs: boyers_planarity_check (C): invalid number of nodes!", 0L, 0L); return 0L; } else if (gp_EnsureArcCapacity(theGraph, 2 * E) != OK) { gp_Free(&theGraph); ErrorQuit("Digraphs: boyers_planarity_check (C): invalid number of edges!", 0L, 0L); return 0L; } int status; for (Int v = 1; v <= LEN_LIST(out); ++v) { DIGRAPHS_ASSERT(gp_VertexInRange(theGraph, v)); gp_SetVertexIndex(theGraph, v, v); Obj const out_v = ELM_LIST(out, v); for (Int w = 1; w <= LEN_LIST(out_v); ++w) { DIGRAPHS_ASSERT(gp_VertexInRange(theGraph, w)); int u = INT_INTOBJ(ELM_LIST(out_v, w)); if (v != u) { status = gp_AddEdge(theGraph, v, 0, u, 0); if (status != OK) { // Cannot currently test this, i.e. it shouldn't happen (and // currently there is no example where it does happen) gp_Free(&theGraph); ErrorQuit("Digraphs: boyers_planarity_check (C): internal error, " "can't add edge from %d to %d", (Int) v, (Int) u); return 0L; } } } } status = gp_Embed(theGraph, flags); if (status == NOTOK) { // Cannot currently test this, i.e. it shouldn't happen (and // currently there is no example where it does happen) gp_Free(&theGraph); ErrorQuit("Digraphs: boyers_planarity_check (C): status is not ok", 0L, 0L); } Obj res; if (krtwsk) { // Kuratowski subgraph isolator gp_SortVertices(theGraph); Obj subgraph = NEW_PLIST_IMM(T_PLIST, theGraph->N); SET_LEN_PLIST(subgraph, theGraph->N); for (int i = 1; i <= theGraph->N; ++i) { int nr = 0; Obj list = NEW_PLIST_IMM(T_PLIST, 0); int j = theGraph->V[i].link[1]; while (j) { if (CALL_3ARGS(IsDigraphEdge, digraph, INTOBJ_INT((Int) i), INTOBJ_INT((Int) theGraph->E[j].neighbor)) == True) { AssPlist(list, ++nr, INTOBJ_INT(theGraph->E[j].neighbor)); } j = theGraph->E[j].link[1]; } if (nr == 0) { RetypeBag(list, T_PLIST_EMPTY); } SET_ELM_PLIST(subgraph, i, list); CHANGED_BAG(subgraph); } res = NEW_PLIST_IMM(T_PLIST, 2); SET_LEN_PLIST(res, 2); SET_ELM_PLIST(res, 1, (status == NONEMBEDDABLE ? False : True)); SET_ELM_PLIST(res, 2, subgraph); CHANGED_BAG(res); } else if (status == NONEMBEDDABLE) { res = False; } else { res = True; } gp_Free(&theGraph); return res; }
int SpecificGraph(char command, char *infileName, char *outfileName, char *outfile2Name) { graphP theGraph, origGraph; platform_time start, end; int Result; // Get the filename of the graph to test if ((infileName = ConstructInputFilename(infileName)) == NULL) return NOTOK; // Create the graph and, if needed, attach the correct algorithm to it theGraph = gp_New(); switch (command) { case 'd' : gp_AttachDrawPlanar(theGraph); break; case '2' : gp_AttachK23Search(theGraph); break; case '3' : gp_AttachK33Search(theGraph); break; case '4' : gp_AttachK4Search(theGraph); break; case 'c' : gp_AttachColorVertices(theGraph); break; } // Read the graph into memory Result = gp_Read(theGraph, infileName); if (Result == NONEMBEDDABLE) { Message("The graph contains too many edges.\n"); // Some of the algorithms will still run correctly with some edges removed. if (strchr("pdo234", command)) { Message("Some edges were removed, but the algorithm will still run correctly.\n"); Result = OK; } } // If there was an unrecoverable error, report it if (Result != OK) ErrorMessage("Failed to read graph\n"); // Otherwise, call the correct algorithm on it else { // Copy the graph for integrity checking origGraph = gp_DupGraph(theGraph); // Run the algorithm if (strchr("pdo234", command)) { int embedFlags = GetEmbedFlags(command); platform_GetTime(start); // gp_CreateDFSTree(theGraph); // gp_SortVertices(theGraph); // gp_Write(theGraph, "debug.before.txt", WRITE_DEBUGINFO); // gp_SortVertices(theGraph); Result = gp_Embed(theGraph, embedFlags); platform_GetTime(end); Result = gp_TestEmbedResultIntegrity(theGraph, origGraph, Result); } else { platform_GetTime(start); if (command == 'c') { if ((Result = gp_ColorVertices(theGraph)) == OK) Result = gp_ColorVerticesIntegrityCheck(theGraph, origGraph); } else Result = NOTOK; platform_GetTime(end); } // Write what the algorithm determined and how long it took WriteAlgorithmResults(theGraph, Result, command, start, end, infileName); // Free the graph obtained for integrity checking. gp_Free(&origGraph); } // Report an error, if there was one, free the graph, and return if (Result != OK && Result != NONEMBEDDABLE) { ErrorMessage("AN ERROR HAS BEEN DETECTED\n"); Result = NOTOK; // gp_Write(theGraph, "debug.after.txt", WRITE_DEBUGINFO); } // Provide the output file(s) else { // Restore the vertex ordering of the original graph (undo DFS numbering) if (strchr("pdo234", command)) gp_SortVertices(theGraph); // Determine the name of the primary output file outfileName = ConstructPrimaryOutputFilename(infileName, outfileName, command); // For some algorithms, the primary output file is not always written if ((strchr("pdo", command) && Result == NONEMBEDDABLE) || (strchr("234", command) && Result == OK)) { // Do not write the file } // Write the primary output file, if appropriate to do so else { gp_Write(theGraph, outfileName, WRITE_ADJLIST); } // NOW WE WANT TO WRITE THE SECONDARY OUTPUT FILE // When called from the menu system, we want to write the planar or outerplanar // obstruction, if one exists. For planar graph drawing, we want the character // art rendition. An empty but non-NULL string is passed to indicate the necessity // of selecting a default name for the second output file. if (outfile2Name != NULL) { if ((command == 'p' || command == 'o') && Result == NONEMBEDDABLE) { // By default, use the same name as the primary output filename if (strlen(outfile2Name) == 0) outfile2Name = outfileName; gp_Write(theGraph, outfile2Name, WRITE_ADJLIST); } else if (command == 'd' && Result == OK) { // By default, add ".render.txt" to the primary output filename if (strlen(outfile2Name) == 0) strcat((outfile2Name = outfileName), ".render.txt"); gp_DrawPlanar_RenderToFile(theGraph, outfile2Name); } } } // Free the graph gp_Free(&theGraph); // Flush any remaining message content to the user, and return the result FlushConsole(stdout); return Result; }
int _TestSubgraph(graphP theSubgraph, graphP theGraph) { int v, e, degreeCount; int Result = TRUE; int invokeSortOnGraph = FALSE; int invokeSortOnSubgraph = FALSE; // If the graph is not sorted by DFI, but the alleged subgraph is, // then "unsort" the alleged subgraph so both have the same vertex order if (!(theGraph->internalFlags & FLAGS_SORTEDBYDFI) && (theSubgraph->internalFlags & FLAGS_SORTEDBYDFI)) { invokeSortOnSubgraph = TRUE; gp_SortVertices(theSubgraph); } // If the graph is not sorted by DFI, but the alleged subgraph is, // then "unsort" the alleged subgraph so both have the same vertex order if (!(theSubgraph->internalFlags & FLAGS_SORTEDBYDFI) && (theGraph->internalFlags & FLAGS_SORTEDBYDFI)) { invokeSortOnGraph = TRUE; gp_SortVertices(theGraph); } /* We clear all visitation flags */ _ClearVertexVisitedFlags(theGraph, FALSE); /* For each vertex... */ for (v = gp_GetFirstVertex(theSubgraph), degreeCount = 0; gp_VertexInRange(theSubgraph, v); v++) { /* For each neighbor w in the adjacency list of vertex v in the subgraph, set the visited flag in w in the graph */ e = gp_GetFirstArc(theSubgraph, v); while (gp_IsArc(e)) { if (gp_IsNotVertex(gp_GetNeighbor(theSubgraph, e))) { Result = FALSE; break; } degreeCount++; gp_SetVertexVisited(theGraph, gp_GetNeighbor(theSubgraph, e)); e = gp_GetNextArc(theSubgraph, e); } if (Result != TRUE) break; /* For each neighbor w in the adjacency list of vertex v in the graph, clear the visited flag in w in the graph */ e = gp_GetFirstArc(theGraph, v); while (gp_IsArc(e)) { if (gp_IsNotVertex(gp_GetNeighbor(theGraph, e))) { Result = FALSE; break; } gp_ClearVertexVisited(theGraph, gp_GetNeighbor(theGraph, e)); e = gp_GetNextArc(theGraph, e); } if (Result != TRUE) break; /* For each neighbor w in the adjacency list of vertex v in the subgraph, ensure that the visited flag in w was cleared (otherwise, the "subgraph" would incorrectly contain an adjacency not contained in the ("super") graph) */ e = gp_GetFirstArc(theSubgraph, v); while (gp_IsArc(e)) { if (gp_GetVertexVisited(theGraph, gp_GetNeighbor(theSubgraph, e))) { Result = FALSE; break; } e = gp_GetNextArc(theSubgraph, e); } if (Result != TRUE) break; } // Restore the DFI sort order of either graph if it had to be reordered at the start if (invokeSortOnSubgraph) gp_SortVertices(theSubgraph); if (invokeSortOnGraph) gp_SortVertices(theGraph); // Assuming theSubgraph is a subgraph, we also do an extra integrity check to ensure // proper edge array utilization if (Result == TRUE) { // If the edge count is wrong, we fail the subgraph test in a way that invokes // the name NOTOK so that in debug mode there is more trace on the failure. if (degreeCount != 2*theSubgraph->M) Result = NOTOK == FALSE ? NOTOK : FALSE; } return Result; }