graphP MakeGraph(int Size, char command) { graphP theGraph; if ((theGraph = gp_New()) == NULL || gp_InitGraph(theGraph, Size) != OK) { ErrorMessage("Error creating space for a graph of the given size.\n"); gp_Free(&theGraph); return NULL; } // Enable the appropriate feature. Although the same code appears in SpecificGraph, // it is deliberately not separated to a common utility because SpecificGraph is // used as a self-contained tutorial. It is not that hard to update both locations // when new algorithms are added. 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; } return theGraph; }
void AttachAlgorithm(graphP theGraph, char command) { 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; } }
int gp_ColorVertices(graphP theGraph) { ColorVerticesContext *context = NULL; int v, deg; int u=0, w=0, contractible; // Attach the algorithm if it is not already attached if (gp_AttachColorVertices(theGraph) != OK) return NOTOK; // Ensure there is enough stack to perform this operation. // At a maximum, the graph reduction will push 7N+M integers. // One integer is pushed per edge that is hidden. Plus, whether // a vertex is hidden or identified with another vertex, 7 integers // are used to store enough information to restore it. if (sp_NonEmpty(theGraph->theStack)) return NOTOK; if (sp_GetCapacity(theGraph->theStack) < 7*theGraph->N + theGraph->M) { stackP newStack = sp_New(7*theGraph->N + theGraph->M); if (newStack == NULL) return NOTOK; sp_Free(&theGraph->theStack); theGraph->theStack = newStack; } // Get the extension context and reinitialize it if necessary gp_FindExtension(theGraph, COLORVERTICES_ID, (void *)&context); if (context->color[0] > -1) _ColorVertices_Reinitialize(context); // Initialize the degree lists, and provide a color for any trivial vertices for (v = 0; v < theGraph->N; v++) { deg = gp_GetVertexDegree(theGraph, v); _AddVertexToDegList(context, theGraph, v, deg); if (deg == 0) context->color[v] = 0; } // Initialize the visited flags so they can be used during reductions _FillVisitedFlags(theGraph, 0); // Reduce the graph using minimum degree selection while (context->numVerticesToReduce > 0) { v = _GetVertexToReduce(context, theGraph); // Find out if v is contractible and the neighbors to contract contractible = _GetContractibleNeighbors(context, v, &u, &w); // Remove the vertex from the graph. This calls the fpHideEdge // overload, which performs the correct _RemoveVertexFromDegList() // and _AddVertexToDegList() operations on v and its neighbors. if (gp_HideVertex(theGraph, v) != OK) return NOTOK; // If v was contractibile, then identify u and w if (contractible) { if (gp_IdentifyVertices(theGraph, u, w, NIL) != OK) return NOTOK; } } // Restore the graph one vertex at a time, coloring each vertex distinctly // from its neighbors as it is restored. context->colorDetector = (int *) calloc(theGraph->N, sizeof(int)); if (context->colorDetector == NULL) return NOTOK; if (gp_RestoreVertices(theGraph) != OK) return NOTOK; free(context->colorDetector); context->colorDetector = NULL; return OK; }
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; }