Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/graphs/planarity/planarityUtils.c
4108 views
1
/*
2
Planarity-Related Graph Algorithms Project
3
Copyright (c) 1997-2010, John M. Boyer
4
All rights reserved. Includes a reference implementation of the following:
5
6
* John M. Boyer. "Simplified O(n) Algorithms for Planar Graph Embedding,
7
Kuratowski Subgraph Isolation, and Related Problems". Ph.D. Dissertation,
8
University of Victoria, 2001.
9
10
* John M. Boyer and Wendy J. Myrvold. "On the Cutting Edge: Simplified O(n)
11
Planarity by Edge Addition". Journal of Graph Algorithms and Applications,
12
Vol. 8, No. 3, pp. 241-273, 2004.
13
14
* John M. Boyer. "A New Method for Efficiently Generating Planar Graph
15
Visibility Representations". In P. Eades and P. Healy, editors,
16
Proceedings of the 13th International Conference on Graph Drawing 2005,
17
Lecture Notes Comput. Sci., Volume 3843, pp. 508-511, Springer-Verlag, 2006.
18
19
Redistribution and use in source and binary forms, with or without modification,
20
are permitted provided that the following conditions are met:
21
22
* Redistributions of source code must retain the above copyright notice, this
23
list of conditions and the following disclaimer.
24
25
* Redistributions in binary form must reproduce the above copyright notice, this
26
list of conditions and the following disclaimer in the documentation and/or
27
other materials provided with the distribution.
28
29
* Neither the name of the Planarity-Related Graph Algorithms Project nor the names
30
of its contributors may be used to endorse or promote products derived from this
31
software without specific prior written permission.
32
33
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
34
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
37
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
40
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
*/
44
45
#include "planarity.h"
46
47
/****************************************************************************
48
Configuration
49
****************************************************************************/
50
51
char Mode='r',
52
OrigOut='n',
53
EmbeddableOut='n',
54
ObstructedOut='n',
55
AdjListsForEmbeddingsOut='n',
56
quietMode='n';
57
58
void Reconfigure()
59
{
60
fflush(stdin);
61
62
Prompt("\nDo you want to \n"
63
" Randomly generate graphs (r),\n"
64
" Specify a graph (s),\n"
65
" Randomly generate a maximal planar graph (m), or\n"
66
" Randomly generate a non-planar graph (n)?");
67
scanf(" %c", &Mode);
68
69
Mode = tolower(Mode);
70
if (!strchr("rsmn", Mode))
71
Mode = 's';
72
73
if (Mode == 'r')
74
{
75
Message("\nNOTE: The directories for the graphs you want must exist.\n\n");
76
77
Prompt("Do you want original graphs in directory 'random' (last 10 max)?");
78
scanf(" %c", &OrigOut);
79
80
Prompt("Do you want adj. matrix of embeddable graphs in directory 'embedded' (last 10 max))?");
81
scanf(" %c", &EmbeddableOut);
82
83
Prompt("Do you want adj. matrix of obstructed graphs in directory 'obstructed' (last 10 max)?");
84
scanf(" %c", &ObstructedOut);
85
86
Prompt("Do you want adjacency list format of embeddings in directory 'adjlist' (last 10 max)?");
87
scanf(" %c", &AdjListsForEmbeddingsOut);
88
}
89
90
FlushConsole(stdout);
91
}
92
93
/****************************************************************************
94
MESSAGE - prints a string, but when debugging adds \n and flushes stdout
95
****************************************************************************/
96
97
#define MAXLINE 1024
98
char Line[MAXLINE];
99
100
void Message(char *message)
101
{
102
if (quietMode == 'n')
103
{
104
fprintf(stdout, "%s", message);
105
106
#ifdef DEBUG
107
// fprintf(stdout, "\n");
108
fflush(stdout);
109
#endif
110
}
111
}
112
113
void ErrorMessage(char *message)
114
{
115
if (quietMode == 'n')
116
{
117
fprintf(stderr, "%s", message);
118
119
#ifdef DEBUG
120
fprintf(stderr, "\n");
121
fflush(stderr);
122
#endif
123
}
124
}
125
126
void FlushConsole(FILE *f)
127
{
128
#ifdef DEBUG
129
// Certain debuggers only flush completed lines of output to the console
130
fprintf(f, "\n");
131
#endif
132
fflush(f);
133
}
134
135
void Prompt(char *message)
136
{
137
Message(message);
138
FlushConsole(stdout);
139
}
140
141
/****************************************************************************
142
****************************************************************************/
143
144
void SaveAsciiGraph(graphP theGraph, char *filename)
145
{
146
int e, limit;
147
FILE *outfile = fopen(filename, "wt");
148
fprintf(outfile, "%s\n", filename);
149
150
limit = theGraph->edgeOffset + 2*(theGraph->M + sp_GetCurrentSize(theGraph->edgeHoles));
151
152
for (e = theGraph->edgeOffset; e < limit; e+=2)
153
{
154
if (theGraph->G[e].v != NIL)
155
fprintf(outfile, "%d %d\n", theGraph->G[e].v+1, theGraph->G[e+1].v+1);
156
}
157
158
fprintf(outfile, "0 0\n");
159
160
fclose(outfile);
161
}
162
163
/****************************************************************************
164
****************************************************************************/
165
166
int FilesEqual(char *file1Name, char *file2Name)
167
{
168
FILE *infile1 = NULL, *infile2 = NULL;
169
int Result = TRUE;
170
171
infile1 = fopen(file1Name, "r");
172
infile2 = fopen(file2Name, "r");
173
174
if (infile1 == NULL || infile2 == NULL)
175
Result = FALSE;
176
else
177
{
178
int c1=0, c2=0;
179
180
// Read the first file to the end
181
while ((c1 = fgetc(infile1)) != EOF)
182
{
183
// If we got a char from the first file, but not from the second
184
// then the second file is shorter, so files are not equal
185
if ((c2 = fgetc(infile2)) == EOF)
186
{
187
Result = FALSE;
188
break;
189
}
190
191
// If we got a char from second file, but not equal to char from
192
// first file, then files are not equal
193
if (c1 != c2)
194
{
195
Result = FALSE;
196
break;
197
}
198
}
199
200
// If we got to the end of the first file without breaking the loop...
201
if (c1 == EOF)
202
{
203
// Then attempt to read from the second file to ensure it also ends.
204
if (fgetc(infile2) != EOF)
205
Result = FALSE;
206
}
207
}
208
209
if (infile1 != NULL) fclose(infile1);
210
if (infile2 != NULL) fclose(infile2);
211
return Result;
212
}
213
214
/****************************************************************************
215
****************************************************************************/
216
217
int GetEmbedFlags(char command)
218
{
219
int embedFlags = 0;
220
221
switch (command)
222
{
223
case 'o' : embedFlags = EMBEDFLAGS_OUTERPLANAR; break;
224
case 'p' : embedFlags = EMBEDFLAGS_PLANAR; break;
225
case 'd' : embedFlags = EMBEDFLAGS_DRAWPLANAR; break;
226
case '2' : embedFlags = EMBEDFLAGS_SEARCHFORK23; break;
227
case '3' : embedFlags = EMBEDFLAGS_SEARCHFORK33; break;
228
case '4' : embedFlags = EMBEDFLAGS_SEARCHFORK4; break;
229
}
230
231
return embedFlags;
232
}
233
234
/****************************************************************************
235
****************************************************************************/
236
237
char *GetAlgorithmName(char command)
238
{
239
char *algorithmName = "UnsupportedAlgorithm";
240
241
switch (command)
242
{
243
case 'p' : algorithmName = "PlanarEmbed"; break;
244
case 'd' : algorithmName = DRAWPLANAR_NAME; break;
245
case 'o' : algorithmName = "OuterplanarEmbed"; break;
246
case '2' : algorithmName = K23SEARCH_NAME; break;
247
case '3' : algorithmName = K33SEARCH_NAME; break;
248
case '4' : algorithmName = K4SEARCH_NAME; break;
249
case 'c' : algorithmName = COLORVERTICES_NAME; break;
250
}
251
252
return algorithmName;
253
}
254
255
/****************************************************************************
256
****************************************************************************/
257
258
void AttachAlgorithm(graphP theGraph, char command)
259
{
260
switch (command)
261
{
262
case 'd' : gp_AttachDrawPlanar(theGraph); break;
263
case '2' : gp_AttachK23Search(theGraph); break;
264
case '3' : gp_AttachK33Search(theGraph); break;
265
case '4' : gp_AttachK4Search(theGraph); break;
266
case 'c' : gp_AttachColorVertices(theGraph); break;
267
}
268
}
269
270
/****************************************************************************
271
A string used to construct input and output filenames.
272
273
The SUFFIXMAXLENGTH is 32 to accommodate ".out.txt" + ".render.txt" + ".test.txt"
274
****************************************************************************/
275
276
#define FILENAMEMAXLENGTH 128
277
#define ALGORITHMNAMEMAXLENGTH 32
278
#define SUFFIXMAXLENGTH 32
279
280
char theFileName[FILENAMEMAXLENGTH+1+ALGORITHMNAMEMAXLENGTH+1+SUFFIXMAXLENGTH+1];
281
282
/****************************************************************************
283
ConstructInputFilename()
284
Returns a string not owned by the caller (do not free string).
285
String contains infileName content if infileName is non-NULL.
286
If infileName is NULL, then the user is asked to supply a name.
287
Returns NULL on error, or a non-NULL string on success.
288
****************************************************************************/
289
290
char *ConstructInputFilename(char *infileName)
291
{
292
if (infileName == NULL)
293
{
294
Prompt("Enter graph file name: ");
295
fflush(stdin);
296
scanf(" %s", theFileName);
297
298
if (!strchr(theFileName, '.'))
299
strcat(theFileName, ".txt");
300
}
301
else
302
{
303
if (strlen(infileName) > FILENAMEMAXLENGTH)
304
{
305
ErrorMessage("Filename is too long");
306
return NULL;
307
}
308
strcpy(theFileName, infileName);
309
}
310
311
return theFileName;
312
}
313
314
/****************************************************************************
315
ConstructPrimaryOutputFilename()
316
Returns a string not owned by the caller (do not free string).
317
Reuses the same memory space as ConstructinputFilename().
318
If outfileName is non-NULL, then the result string contains its content.
319
If outfileName is NULL, then the infileName and the command's algorithm name
320
are used to construct a string.
321
Returns non-NULL string
322
****************************************************************************/
323
324
char *ConstructPrimaryOutputFilename(char *infileName, char *outfileName, char command)
325
{
326
char *algorithmName = GetAlgorithmName(command);
327
328
if (outfileName == NULL)
329
{
330
// The output filename is based on the input filename
331
if (theFileName != infileName)
332
strcpy(theFileName, infileName);
333
334
// If the primary output filename has not been given, then we use
335
// the input filename + the algorithm name + a simple suffix
336
if (strlen(algorithmName) <= ALGORITHMNAMEMAXLENGTH)
337
{
338
strcat(theFileName, ".");
339
strcat(theFileName, algorithmName);
340
}
341
else
342
ErrorMessage("Algorithm Name is too long, so it will not be used in output filename.");
343
344
strcat(theFileName, ".out.txt");
345
}
346
else
347
{
348
if (strlen(outfileName) > FILENAMEMAXLENGTH)
349
{
350
// The output filename is based on the input filename
351
if (theFileName != infileName)
352
strcpy(theFileName, infileName);
353
354
if (strlen(algorithmName) <= ALGORITHMNAMEMAXLENGTH)
355
{
356
strcat(theFileName, ".");
357
strcat(theFileName, algorithmName);
358
}
359
strcat(theFileName, ".out.txt");
360
sprintf(Line, "Outfile filename is too long. Result placed in %s", theFileName);
361
ErrorMessage(Line);
362
}
363
else
364
{
365
if (theFileName != outfileName)
366
strcpy(theFileName, outfileName);
367
}
368
}
369
370
return theFileName;
371
}
372
373