adding files from cvs
commit
5d3139a877
|
@ -0,0 +1,16 @@
|
|||
[Settings]
|
||||
Archive=0
|
||||
Pack=0
|
||||
Packed Variable=
|
||||
Project Name=VColor
|
||||
GCC Switches=-Os -O2 -Wall -W -Wwrite-strings
|
||||
GNU Assembler Switches=
|
||||
Assembler Switches=-g -t
|
||||
GNU Linker Switches=
|
||||
Linker Switches=
|
||||
Debug Info=0
|
||||
Standard Library=1
|
||||
Command Line=
|
||||
Post-Build Process=
|
||||
[Included Files]
|
||||
C File 1=vcolor.c
|
Binary file not shown.
After Width: | Height: | Size: 574 KiB |
|
@ -0,0 +1,502 @@
|
|||
/*
|
||||
VertexColoration
|
||||
Andrew Coleman
|
||||
Licensed under the GPL version 2 or later.
|
||||
Full license details are available at http://gnu.org/
|
||||
CSC-2400
|
||||
|
||||
This program is designed to create or read in a graph
|
||||
from a user and find a way to identify each vertex
|
||||
without touching another vertex of the same indentifier
|
||||
(color) and using as few colors as possible.
|
||||
*/
|
||||
|
||||
#define USE_TI92PLUS
|
||||
#define OPTIMIZE_ROM_CALLS
|
||||
#define MIN_AMS 208
|
||||
#define SAVE_SCREEN
|
||||
|
||||
#include <tigcclib.h>
|
||||
|
||||
#define MAX_VERTEX 100
|
||||
#define SLIDER_WIDTH 125
|
||||
#define START_COL 2
|
||||
#define START_ROW 10
|
||||
|
||||
int (*neighbor)[MAX_VERTEX];
|
||||
FILE *output;
|
||||
void RandomizeGraph ( int );
|
||||
void UserDefineGraph ( int );
|
||||
void DrawGraph ( int );
|
||||
void Greedy ( int );
|
||||
void BackTrack ( int );
|
||||
/* algorithmstr, numvertexes, numsteps, numcolors, colorarray */
|
||||
void ColorationResults ( const char *, int, unsigned long, int, int * );
|
||||
|
||||
void _main(void)
|
||||
{
|
||||
randomize();
|
||||
int numvert = 0;
|
||||
randomize();
|
||||
|
||||
output = NULL;
|
||||
|
||||
char *params = calloc ( 11, sizeof( char ) );
|
||||
short *opt = calloc ( 2, sizeof( short ) );
|
||||
opt[1] = 1;
|
||||
/* TIOS specific windowing */
|
||||
HANDLE sizewin = DialogNewSimple ( 120, 70 );
|
||||
HANDLE sourcepopup = PopupNew ( NULL, 0 );
|
||||
PopupAddText ( sourcepopup, -1, "Random", 0 );
|
||||
PopupAddText ( sourcepopup, -1, "User", 0 );
|
||||
DialogAddTitle ( sizewin, "Graph Source", BT_OK, BT_NONE );
|
||||
DialogAddRequest ( sizewin, 2, 16, "Size: ", 0, 3, 4 );
|
||||
DialogAddPulldown ( sizewin, 2, 29, "Source: ", sourcepopup, 1 );
|
||||
DialogAddRequest ( sizewin, 2, 42, "Output: ", 3, 8, 9 );
|
||||
|
||||
do {
|
||||
if ( DialogDo ( sizewin, CENTER, CENTER, params, opt ) == KEY_ESC )
|
||||
{
|
||||
HeapFree ( sizewin );
|
||||
HeapFree ( sourcepopup );
|
||||
free ( params );
|
||||
free ( opt );
|
||||
return;
|
||||
}
|
||||
/* convert the number of strings and filename to something i can use */
|
||||
char *tmp = calloc ( 8, sizeof( char ) );
|
||||
memcpy ( tmp, params, 3 * sizeof( char ) );
|
||||
numvert = atoi ( tmp );
|
||||
memcpy ( tmp, params + 3, 8 * sizeof( char ) );
|
||||
if ( strcmp ( tmp, "" ) != 0 )
|
||||
output = fopen ( tmp, "w" );
|
||||
free ( tmp );
|
||||
} while ( numvert <= 0 && numvert >= MAX_VERTEX );
|
||||
HeapFree ( sizewin );
|
||||
HeapFree ( sourcepopup );
|
||||
free ( params );
|
||||
|
||||
/* initialize the adjacency matrix */
|
||||
neighbor = calloc ( numvert, sizeof( *neighbor ) );
|
||||
|
||||
if ( opt[1] == 1 )
|
||||
RandomizeGraph ( numvert );
|
||||
else
|
||||
UserDefineGraph ( numvert );
|
||||
free ( opt );
|
||||
|
||||
/* display the neighborlist, size permitting */
|
||||
DrawGraph ( numvert );
|
||||
/* perform a greedy coloration */
|
||||
Greedy ( numvert );
|
||||
/* perform a backtrack coloration */
|
||||
BackTrack ( numvert );
|
||||
|
||||
if ( output != NULL )
|
||||
fclose ( output );
|
||||
free ( neighbor );
|
||||
}
|
||||
|
||||
/*
|
||||
This is the random graph algorithm handed out in class.
|
||||
*/
|
||||
void RandomizeGraph ( int numvert )
|
||||
{
|
||||
ClrScr();
|
||||
int row = 0, col = 0;
|
||||
DrawStr ( 1, 1, "Creating neighbors...", A_NORMAL );
|
||||
/* For the slider */
|
||||
DrawLine ( START_COL, START_ROW, START_COL + SLIDER_WIDTH, START_ROW, A_NORMAL );
|
||||
DrawLine ( START_COL, START_ROW + 2, START_COL + SLIDER_WIDTH, START_ROW + 2, A_NORMAL );
|
||||
DrawPix ( START_COL, START_ROW + 1, A_NORMAL );
|
||||
DrawPix ( START_COL + SLIDER_WIDTH, START_ROW + 1, A_NORMAL );
|
||||
int lastsize = 1;
|
||||
for ( row = 0; row < numvert - 2; row++ )
|
||||
{
|
||||
/* again for the slider */
|
||||
for ( col = lastsize; col < ceil ( row * SLIDER_WIDTH / numvert ); col++ )
|
||||
DrawPix ( col + START_COL, START_ROW + 1, A_NORMAL );
|
||||
lastsize = ceil ( row * SLIDER_WIDTH / numvert );
|
||||
|
||||
/* randomly pick edges for each vertex after this one to eliminate duplicates */
|
||||
for ( col = row + 1; col < numvert; col++ )
|
||||
{
|
||||
int tmp = random ( numvert ) + 1;
|
||||
if ( tmp > numvert / 2 )
|
||||
{
|
||||
neighbor[row][col] = 1;
|
||||
neighbor[col][row] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* finish drawing the slider */
|
||||
for ( col = lastsize; col < SLIDER_WIDTH; col++ )
|
||||
DrawPix ( col + START_COL, START_ROW + 1, A_NORMAL );
|
||||
}
|
||||
|
||||
/*
|
||||
This function will query the user for each vertex's neighbors
|
||||
*/
|
||||
void UserDefineGraph ( int numvert )
|
||||
{
|
||||
char *letters = calloc ( MAX_VERTEX * 2, sizeof( int ) );
|
||||
HANDLE neighbors = DialogNewSimple ( 145, 70 );
|
||||
DialogAddTitle ( neighbors, "Neighbors", BT_OK, BT_NONE );
|
||||
|
||||
int row = 0;
|
||||
char title[23];
|
||||
for ( row = 0; row < numvert; row++ )
|
||||
{
|
||||
/* repeat the same dialog pattern for each vertex */
|
||||
memset ( title, 0, 23 * sizeof( char ) );
|
||||
memset ( letters, 0, MAX_VERTEX * 2 * sizeof( char ) );
|
||||
sprintf ( title, "Enter neighbors for %d", row + 1 );
|
||||
DialogAddText ( neighbors, 2, 16, title );
|
||||
DialogAddText ( neighbors, 2, 29, "separated by commas" );
|
||||
DialogAddRequest ( neighbors, 2, 42, "", 0, MAX_VERTEX * 2, 20 );
|
||||
int error = 0;
|
||||
if ( DialogDo ( neighbors, CENTER, CENTER, letters, NULL ) == KEY_ESC )
|
||||
error = 1;
|
||||
if ( !error )
|
||||
{
|
||||
/* convert the string to neighbors */
|
||||
char *num = strtok ( letters, "," );
|
||||
while ( num != NULL )
|
||||
{
|
||||
int neighbornum = atoi ( num );
|
||||
/* if neighbornum is out of this range, there is nothing we can do with it */
|
||||
if ( neighbornum > 0 && neighbornum <= MAX_VERTEX && neighbornum != row )
|
||||
{
|
||||
/* otherwise, put in a neighbor */
|
||||
neighbor[row][neighbornum - 1] = 1;
|
||||
neighbor[neighbornum - 1][row] = 1;
|
||||
}
|
||||
num = strtok ( NULL, "," );
|
||||
}
|
||||
}
|
||||
/* the user pressed esc, so they want to leave */
|
||||
else
|
||||
break;
|
||||
}
|
||||
free ( letters );
|
||||
HeapFree ( neighbors );
|
||||
}
|
||||
|
||||
/*
|
||||
This function will display the neighbor list so long as there are < 15 vertecies (screen is too small...)
|
||||
*/
|
||||
void DrawGraph ( int numvert )
|
||||
{
|
||||
ClrScr();
|
||||
|
||||
int row = 0, col = 0;
|
||||
char *tmp = calloc ( 5, sizeof ( char ) );
|
||||
if ( numvert < 15 )
|
||||
DrawStr ( 1, 1, "Neighbor listing...", A_NORMAL );
|
||||
if ( output != NULL )
|
||||
fputs ( "Neighbor listing...\n", output );
|
||||
|
||||
/* go over each vertex, yes, we can go over this even if we have > 15 vertecies and we aren't printing to a file */
|
||||
for ( row = 0; row < numvert; row++ )
|
||||
{
|
||||
sprintf ( tmp, "%d: ", row + 1 );
|
||||
if ( numvert < 15 )
|
||||
DrawStr ( 1, (row + 1) * 8 + 1, tmp, A_NORMAL );
|
||||
if ( output != NULL )
|
||||
fputs ( tmp, output );
|
||||
|
||||
/* find all neighbors of current vertex */
|
||||
for ( col = 0; col < numvert; col++ )
|
||||
{
|
||||
/* if we have a neighbor, and the random/user graph functions make sure we don't have (row == col) being a neighbor */
|
||||
if ( neighbor[row][col] == 1 )
|
||||
{
|
||||
sprintf ( tmp, " %d", col + 1 );
|
||||
if ( numvert < 15 )
|
||||
DrawStr ( col * 14 + 20, (row + 1) * 8 + 2, tmp, A_NORMAL );
|
||||
if ( output != NULL )
|
||||
fputs ( tmp, output );
|
||||
}
|
||||
}
|
||||
if ( output != NULL )
|
||||
fputs ( "\n", output );
|
||||
}
|
||||
if ( output != NULL )
|
||||
fputc ( '\n', output );
|
||||
free ( tmp );
|
||||
|
||||
/* if we displayed something, wait for the user to get done before continuing */
|
||||
if ( numvert < 15 )
|
||||
{
|
||||
GKeyFlush();
|
||||
ngetchx();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This function will color the graph in a greedy fashion
|
||||
*/
|
||||
void Greedy ( int numvert )
|
||||
{
|
||||
ClrScr();
|
||||
int maxcolor = 1, row = 0, col = 0, curcolor = 0;
|
||||
unsigned long steps = 0;
|
||||
/* array of colors for each vertex */
|
||||
int *colors = calloc ( numvert, sizeof( int ) );
|
||||
/* display what we are doing and the box for the slider bar */
|
||||
DrawStr ( 1, 1, "Coloring by greed...", A_NORMAL );
|
||||
DrawLine ( START_COL, START_ROW, START_COL + SLIDER_WIDTH, START_ROW, A_NORMAL );
|
||||
DrawLine ( START_COL, START_ROW + 2, START_COL + SLIDER_WIDTH, START_ROW + 2, A_NORMAL );
|
||||
DrawPix ( START_COL, START_ROW + 1, A_NORMAL );
|
||||
DrawPix ( START_COL + SLIDER_WIDTH, START_ROW + 1, A_NORMAL );
|
||||
|
||||
/* used to keep the last position for the slider */
|
||||
int lastsize = 1;
|
||||
/* we want to color each vertex */
|
||||
for ( row = 0; row < numvert; row++ )
|
||||
{
|
||||
/* flag to know if a neighbor of the same current color was found */
|
||||
int found = 0;
|
||||
|
||||
/* update the slider bar for each vertex */
|
||||
for ( col = lastsize; col < ceil ( row * SLIDER_WIDTH / numvert ); col++ )
|
||||
DrawPix ( col + START_COL, START_ROW + 1, A_NORMAL );
|
||||
lastsize = ceil ( row * SLIDER_WIDTH / numvert );
|
||||
|
||||
/* we want to search all colors from 1 to maxcolor + 1 */
|
||||
for ( curcolor = 1; curcolor <= maxcolor + 1; curcolor++ )
|
||||
{
|
||||
/* we already have a color selected, move on */
|
||||
if ( colors[row] != 0 )
|
||||
continue;
|
||||
found = 0;
|
||||
/* now we search every other vertex for a neighbor */
|
||||
for ( col = 1; col <= numvert; col++ )
|
||||
{
|
||||
/* don't keep looking if we have already found a color */
|
||||
if ( found )
|
||||
break;
|
||||
/* do we have a neighbor of the same color */
|
||||
if ( neighbor[row][col - 1] == 1 && colors[col - 1] == curcolor )
|
||||
found = 1;
|
||||
/* that's another step towards the solution */
|
||||
steps++;
|
||||
}
|
||||
|
||||
/* if no neighbor of this color was found and no color has been assigned, use curcolor */
|
||||
if ( !found && colors[row] == 0 )
|
||||
colors[row] = curcolor;
|
||||
|
||||
/* if we have gone over our maximum color limit, increase it */
|
||||
if ( colors[row] > maxcolor )
|
||||
maxcolor = colors[row];
|
||||
}
|
||||
}
|
||||
|
||||
/* finish drawing the slider */
|
||||
for ( col = lastsize; col < SLIDER_WIDTH; col++ )
|
||||
DrawPix ( col + START_COL, START_ROW + 1, A_NORMAL );
|
||||
|
||||
/* display the results */
|
||||
ColorationResults ( "Greed Colors", numvert, steps, maxcolor, colors );
|
||||
free ( colors );
|
||||
}
|
||||
|
||||
void BackTrack ( int numvert )
|
||||
{
|
||||
ClrScr();
|
||||
/* if we output partial listings, we can break the 64KB file limit on the calculator, plus file writes are *slow* */
|
||||
int partiallistings = 0;
|
||||
if ( output != NULL && DlgMessage ( "Question", "Output partial listings of BackTrack?", BT_YES, BT_NO ) == KEY_ENTER )
|
||||
partiallistings = 1;
|
||||
int maxcolor = 1, curcolor = 1, row = 0, col = 0;
|
||||
unsigned long steps = 0;
|
||||
int *colors = calloc ( numvert, sizeof( int ) );
|
||||
char *tmp = calloc ( 20, sizeof( char ) );
|
||||
/* let the user know what's going on */
|
||||
DrawStr ( 1, 1, "BackTrack Color", A_NORMAL );
|
||||
ST_helpMsg ( "Hit [ESC] to quit..." );
|
||||
sprintf ( tmp, "MaxColor: %d", maxcolor );
|
||||
DrawStr ( 1, 9, tmp, A_NORMAL );
|
||||
|
||||
/* clear the keyboard queue to make sure any stray kepresses don't bother the results */
|
||||
GKeyFlush();
|
||||
|
||||
/* flag to find a neighbor of same color, if we are backtracking in the for loop, and if we have an error */
|
||||
int found = 0, back = 0, error = 0;
|
||||
if ( output != NULL && partiallistings )
|
||||
fputs ( "\nBacktrack Partial Colorings:\n", output );
|
||||
for ( row = 0; row < numvert; row++ )
|
||||
{
|
||||
/* if we are backtracking, start coloring above that vertex's current color */
|
||||
if ( back )
|
||||
{
|
||||
curcolor = colors[row] + 1;
|
||||
back = 0;
|
||||
}
|
||||
/* if we are not backtracking, and we do want to output partial listings, print */
|
||||
else if ( output != NULL && partiallistings )
|
||||
{
|
||||
int i = 0, zero = 0;
|
||||
for ( i = 0; i < numvert; i++ )
|
||||
{
|
||||
char outputltr[4];
|
||||
if ( colors[i] != 0 )
|
||||
{
|
||||
zero = 1;
|
||||
sprintf ( outputltr, "%d ", colors[i] );
|
||||
fputs ( outputltr, output );
|
||||
}
|
||||
}
|
||||
if ( zero )
|
||||
fputs ( "\n", output );
|
||||
}
|
||||
|
||||
found = 0;
|
||||
|
||||
/* if current color is bigger than maxcolor, we need to stop and back up */
|
||||
if ( curcolor > maxcolor )
|
||||
{
|
||||
/* if we are at the first vertex, then we can increase the current maximum color limit */
|
||||
if ( row == 0 )
|
||||
{
|
||||
/* increase maximum colors */
|
||||
maxcolor++;
|
||||
sprintf ( tmp, "MaxColor: %d ", maxcolor );
|
||||
DrawStr ( 1, 9, tmp, A_REPLACE );
|
||||
/* start coloring again */
|
||||
curcolor = 1;
|
||||
/* if maxcolor is greater than the number of vertecies, then we cannot use more than 1 color per vertex */
|
||||
if ( maxcolor > numvert )
|
||||
{
|
||||
ClrScr();
|
||||
DrawStr ( 1, 1, "Cannot be solved by\n tracking backwards.", A_NORMAL );
|
||||
if ( output != NULL )
|
||||
fputs ( "Cannot be solved by tracking backwards.\n", output );
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* since we aren't at the first vertex, reset the color, since it was wrong anyways, and backtrack */
|
||||
else
|
||||
{
|
||||
colors[row] = 0;
|
||||
row = row - 2;
|
||||
back = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* since we aren't backtracking, and we don't need to backtrack, do some work */
|
||||
for ( col = 0; col < numvert; col++ )
|
||||
{
|
||||
/* don't keep looking if we already have a neighbor of same color */
|
||||
if ( found )
|
||||
continue;
|
||||
/* if we have a neighbor of same color */
|
||||
if ( neighbor[row][col] == 1 && colors[col] == curcolor )
|
||||
found = 1;
|
||||
steps++;
|
||||
}
|
||||
|
||||
/* if a color is not found, increase color and try the same vertex */
|
||||
if ( found )
|
||||
{
|
||||
curcolor++;
|
||||
row--;
|
||||
continue;
|
||||
}
|
||||
/* found a color */
|
||||
else
|
||||
{
|
||||
colors[row] = curcolor;
|
||||
}
|
||||
|
||||
/* backtrack takes a long time, so if the user wants to quit prematurely, just hit esc */
|
||||
if ( kbhit() )
|
||||
{
|
||||
if ( ngetchx() == KEY_ESC )
|
||||
{
|
||||
ClrScr();
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( output != NULL && partiallistings )
|
||||
fputs ( "\n", output );
|
||||
|
||||
/* if the user didn't press esc, display the results */
|
||||
if ( !error )
|
||||
{
|
||||
ColorationResults ( "BackTrack Colors", numvert, steps, maxcolor, colors );
|
||||
}
|
||||
|
||||
free ( colors );
|
||||
free ( tmp );
|
||||
}
|
||||
|
||||
/*
|
||||
this function will display the results for each of the algorithms
|
||||
*/
|
||||
void ColorationResults ( const char *algorithm, int numvert, unsigned long steps, int maxcolor, int *colors )
|
||||
{
|
||||
/* the number of vertecies to put on one row */
|
||||
#define ROW_WIDTH 6
|
||||
ClrScr();
|
||||
char *tmp = calloc ( 20, sizeof( char ) );
|
||||
int row = 0, col = 0;
|
||||
|
||||
/* clear the keyboard queue to make sure we don't get a stray keypress */
|
||||
GKeyFlush();
|
||||
|
||||
DrawStr ( 1, 1, algorithm, A_NORMAL );
|
||||
/* print to a file if we need to */
|
||||
if ( output != NULL )
|
||||
{
|
||||
fputs ( algorithm, output );
|
||||
fputs ( "\n", output );
|
||||
}
|
||||
/* print each vertex */
|
||||
for ( row = 0; row <= numvert / ROW_WIDTH; row++ )
|
||||
{
|
||||
/* find each vertex's neighbors */
|
||||
for ( col = 1; col <= ROW_WIDTH; col++ )
|
||||
{
|
||||
/* make sure we don't try to display a vertex that doesn't exist */
|
||||
if ( row * ROW_WIDTH + col <= numvert )
|
||||
{
|
||||
int vert = row * ROW_WIDTH + col;
|
||||
sprintf ( tmp, "%d: %d", vert, colors[vert - 1] );
|
||||
DrawStr ( ( col - 1 ) * 40, ( row + 2 ) * 8, tmp, A_REPLACE );
|
||||
if ( output != NULL )
|
||||
{
|
||||
fputs ( tmp, output );
|
||||
fputs ( "\n", output );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* display and print out colors used */
|
||||
sprintf ( tmp, "Colors used: %d", maxcolor );
|
||||
DrawStr ( 1, ceil ( numvert / ROW_WIDTH + 4 ) * 8, tmp, A_NORMAL );
|
||||
if ( output != NULL )
|
||||
{
|
||||
fputs ( tmp, output );
|
||||
fputs ( "\n", output );
|
||||
}
|
||||
/* display and print out steps taken */
|
||||
sprintf ( tmp, "Steps taken: %lu", steps );
|
||||
DrawStr ( 1, ceil ( numvert / ROW_WIDTH + 5 ) * 8, tmp, A_NORMAL );
|
||||
if ( output != NULL )
|
||||
{
|
||||
fputs ( tmp, output );
|
||||
fputs ( "\n", output );
|
||||
fputs ( "\n", output );
|
||||
}
|
||||
/* let the user press a key when done */
|
||||
ngetchx();
|
||||
free ( tmp );
|
||||
#undef ROW_WIDTH
|
||||
}
|
Reference in New Issue