Path: blob/master/sage/graphs/planarity/planarityUtils.c
4108 views
/*1Planarity-Related Graph Algorithms Project2Copyright (c) 1997-2010, John M. Boyer3All rights reserved. Includes a reference implementation of the following:45* John M. Boyer. "Simplified O(n) Algorithms for Planar Graph Embedding,6Kuratowski Subgraph Isolation, and Related Problems". Ph.D. Dissertation,7University of Victoria, 2001.89* John M. Boyer and Wendy J. Myrvold. "On the Cutting Edge: Simplified O(n)10Planarity by Edge Addition". Journal of Graph Algorithms and Applications,11Vol. 8, No. 3, pp. 241-273, 2004.1213* John M. Boyer. "A New Method for Efficiently Generating Planar Graph14Visibility Representations". In P. Eades and P. Healy, editors,15Proceedings of the 13th International Conference on Graph Drawing 2005,16Lecture Notes Comput. Sci., Volume 3843, pp. 508-511, Springer-Verlag, 2006.1718Redistribution and use in source and binary forms, with or without modification,19are permitted provided that the following conditions are met:2021* Redistributions of source code must retain the above copyright notice, this22list of conditions and the following disclaimer.2324* Redistributions in binary form must reproduce the above copyright notice, this25list of conditions and the following disclaimer in the documentation and/or26other materials provided with the distribution.2728* Neither the name of the Planarity-Related Graph Algorithms Project nor the names29of its contributors may be used to endorse or promote products derived from this30software without specific prior written permission.3132THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"33AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE34IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE35DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR36ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES37(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;38LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON39ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT40(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS41SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.42*/4344#include "planarity.h"4546/****************************************************************************47Configuration48****************************************************************************/4950char Mode='r',51OrigOut='n',52EmbeddableOut='n',53ObstructedOut='n',54AdjListsForEmbeddingsOut='n',55quietMode='n';5657void Reconfigure()58{59fflush(stdin);6061Prompt("\nDo you want to \n"62" Randomly generate graphs (r),\n"63" Specify a graph (s),\n"64" Randomly generate a maximal planar graph (m), or\n"65" Randomly generate a non-planar graph (n)?");66scanf(" %c", &Mode);6768Mode = tolower(Mode);69if (!strchr("rsmn", Mode))70Mode = 's';7172if (Mode == 'r')73{74Message("\nNOTE: The directories for the graphs you want must exist.\n\n");7576Prompt("Do you want original graphs in directory 'random' (last 10 max)?");77scanf(" %c", &OrigOut);7879Prompt("Do you want adj. matrix of embeddable graphs in directory 'embedded' (last 10 max))?");80scanf(" %c", &EmbeddableOut);8182Prompt("Do you want adj. matrix of obstructed graphs in directory 'obstructed' (last 10 max)?");83scanf(" %c", &ObstructedOut);8485Prompt("Do you want adjacency list format of embeddings in directory 'adjlist' (last 10 max)?");86scanf(" %c", &AdjListsForEmbeddingsOut);87}8889FlushConsole(stdout);90}9192/****************************************************************************93MESSAGE - prints a string, but when debugging adds \n and flushes stdout94****************************************************************************/9596#define MAXLINE 102497char Line[MAXLINE];9899void Message(char *message)100{101if (quietMode == 'n')102{103fprintf(stdout, "%s", message);104105#ifdef DEBUG106// fprintf(stdout, "\n");107fflush(stdout);108#endif109}110}111112void ErrorMessage(char *message)113{114if (quietMode == 'n')115{116fprintf(stderr, "%s", message);117118#ifdef DEBUG119fprintf(stderr, "\n");120fflush(stderr);121#endif122}123}124125void FlushConsole(FILE *f)126{127#ifdef DEBUG128// Certain debuggers only flush completed lines of output to the console129fprintf(f, "\n");130#endif131fflush(f);132}133134void Prompt(char *message)135{136Message(message);137FlushConsole(stdout);138}139140/****************************************************************************141****************************************************************************/142143void SaveAsciiGraph(graphP theGraph, char *filename)144{145int e, limit;146FILE *outfile = fopen(filename, "wt");147fprintf(outfile, "%s\n", filename);148149limit = theGraph->edgeOffset + 2*(theGraph->M + sp_GetCurrentSize(theGraph->edgeHoles));150151for (e = theGraph->edgeOffset; e < limit; e+=2)152{153if (theGraph->G[e].v != NIL)154fprintf(outfile, "%d %d\n", theGraph->G[e].v+1, theGraph->G[e+1].v+1);155}156157fprintf(outfile, "0 0\n");158159fclose(outfile);160}161162/****************************************************************************163****************************************************************************/164165int FilesEqual(char *file1Name, char *file2Name)166{167FILE *infile1 = NULL, *infile2 = NULL;168int Result = TRUE;169170infile1 = fopen(file1Name, "r");171infile2 = fopen(file2Name, "r");172173if (infile1 == NULL || infile2 == NULL)174Result = FALSE;175else176{177int c1=0, c2=0;178179// Read the first file to the end180while ((c1 = fgetc(infile1)) != EOF)181{182// If we got a char from the first file, but not from the second183// then the second file is shorter, so files are not equal184if ((c2 = fgetc(infile2)) == EOF)185{186Result = FALSE;187break;188}189190// If we got a char from second file, but not equal to char from191// first file, then files are not equal192if (c1 != c2)193{194Result = FALSE;195break;196}197}198199// If we got to the end of the first file without breaking the loop...200if (c1 == EOF)201{202// Then attempt to read from the second file to ensure it also ends.203if (fgetc(infile2) != EOF)204Result = FALSE;205}206}207208if (infile1 != NULL) fclose(infile1);209if (infile2 != NULL) fclose(infile2);210return Result;211}212213/****************************************************************************214****************************************************************************/215216int GetEmbedFlags(char command)217{218int embedFlags = 0;219220switch (command)221{222case 'o' : embedFlags = EMBEDFLAGS_OUTERPLANAR; break;223case 'p' : embedFlags = EMBEDFLAGS_PLANAR; break;224case 'd' : embedFlags = EMBEDFLAGS_DRAWPLANAR; break;225case '2' : embedFlags = EMBEDFLAGS_SEARCHFORK23; break;226case '3' : embedFlags = EMBEDFLAGS_SEARCHFORK33; break;227case '4' : embedFlags = EMBEDFLAGS_SEARCHFORK4; break;228}229230return embedFlags;231}232233/****************************************************************************234****************************************************************************/235236char *GetAlgorithmName(char command)237{238char *algorithmName = "UnsupportedAlgorithm";239240switch (command)241{242case 'p' : algorithmName = "PlanarEmbed"; break;243case 'd' : algorithmName = DRAWPLANAR_NAME; break;244case 'o' : algorithmName = "OuterplanarEmbed"; break;245case '2' : algorithmName = K23SEARCH_NAME; break;246case '3' : algorithmName = K33SEARCH_NAME; break;247case '4' : algorithmName = K4SEARCH_NAME; break;248case 'c' : algorithmName = COLORVERTICES_NAME; break;249}250251return algorithmName;252}253254/****************************************************************************255****************************************************************************/256257void AttachAlgorithm(graphP theGraph, char command)258{259switch (command)260{261case 'd' : gp_AttachDrawPlanar(theGraph); break;262case '2' : gp_AttachK23Search(theGraph); break;263case '3' : gp_AttachK33Search(theGraph); break;264case '4' : gp_AttachK4Search(theGraph); break;265case 'c' : gp_AttachColorVertices(theGraph); break;266}267}268269/****************************************************************************270A string used to construct input and output filenames.271272The SUFFIXMAXLENGTH is 32 to accommodate ".out.txt" + ".render.txt" + ".test.txt"273****************************************************************************/274275#define FILENAMEMAXLENGTH 128276#define ALGORITHMNAMEMAXLENGTH 32277#define SUFFIXMAXLENGTH 32278279char theFileName[FILENAMEMAXLENGTH+1+ALGORITHMNAMEMAXLENGTH+1+SUFFIXMAXLENGTH+1];280281/****************************************************************************282ConstructInputFilename()283Returns a string not owned by the caller (do not free string).284String contains infileName content if infileName is non-NULL.285If infileName is NULL, then the user is asked to supply a name.286Returns NULL on error, or a non-NULL string on success.287****************************************************************************/288289char *ConstructInputFilename(char *infileName)290{291if (infileName == NULL)292{293Prompt("Enter graph file name: ");294fflush(stdin);295scanf(" %s", theFileName);296297if (!strchr(theFileName, '.'))298strcat(theFileName, ".txt");299}300else301{302if (strlen(infileName) > FILENAMEMAXLENGTH)303{304ErrorMessage("Filename is too long");305return NULL;306}307strcpy(theFileName, infileName);308}309310return theFileName;311}312313/****************************************************************************314ConstructPrimaryOutputFilename()315Returns a string not owned by the caller (do not free string).316Reuses the same memory space as ConstructinputFilename().317If outfileName is non-NULL, then the result string contains its content.318If outfileName is NULL, then the infileName and the command's algorithm name319are used to construct a string.320Returns non-NULL string321****************************************************************************/322323char *ConstructPrimaryOutputFilename(char *infileName, char *outfileName, char command)324{325char *algorithmName = GetAlgorithmName(command);326327if (outfileName == NULL)328{329// The output filename is based on the input filename330if (theFileName != infileName)331strcpy(theFileName, infileName);332333// If the primary output filename has not been given, then we use334// the input filename + the algorithm name + a simple suffix335if (strlen(algorithmName) <= ALGORITHMNAMEMAXLENGTH)336{337strcat(theFileName, ".");338strcat(theFileName, algorithmName);339}340else341ErrorMessage("Algorithm Name is too long, so it will not be used in output filename.");342343strcat(theFileName, ".out.txt");344}345else346{347if (strlen(outfileName) > FILENAMEMAXLENGTH)348{349// The output filename is based on the input filename350if (theFileName != infileName)351strcpy(theFileName, infileName);352353if (strlen(algorithmName) <= ALGORITHMNAMEMAXLENGTH)354{355strcat(theFileName, ".");356strcat(theFileName, algorithmName);357}358strcat(theFileName, ".out.txt");359sprintf(Line, "Outfile filename is too long. Result placed in %s", theFileName);360ErrorMessage(Line);361}362else363{364if (theFileName != outfileName)365strcpy(theFileName, outfileName);366}367}368369return theFileName;370}371372373