The LevAWC Project
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Pages
demo13.c
1 /*
2  * _____
3  * ANSI / ___/
4  * / /__
5  * \___/
6  *
7  * Filename: tst1.c
8  * Author : Dan Levin
9  * Date : Fri Feb 20 13:23:46 2015
10  * Version : 0.51
11  * ---
12  * Description: A demo program testing/showing some Graph Algorithms
13  *
14  * Revision history: (this is where you document the diffs between versions...)
15  * Date Revision
16  * 150331 This code ready for ver. 0.51
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <time.h>
22 #include "graph.h"
23 #include "algo.h"
24 #include "utils.h"
25 
26 /* --- MACROS --- */
27 #ifndef OK
28 #define OK 0
29 #endif
30 
31 #ifndef TRUE
32 #define TRUE 1
33 #endif
34 
35 #ifndef FALSE
36 #define FALSE 0
37 #endif
38 
39 /* MACRO DEFINITIONS */
40 #define NR_OF_MST_VERTICES 9
41 #define NR_OF_DSP_VERTICES 6
42 #define NR_OF_TSP_VERTICES 7
43 #define NR_OF_TSP_COORDS 2
44 
45 #define INITIAL_INFO "--- INITIAL DEMO INFORMATION ---\n\nThis demo contains code from the book - \"K Loudon: Mastering Algoritms with C\".\n\nFor further details - check the following:\n\n - \"Chapter 16: Graph Algorithms\"\n - The \"graphalg\" subfolder - in downloadable example zipfile\n\nTip: Use paper/pencil to draw initial graphs - and their calculated results.\nCould be useful here :-)..\n\n"
46 
47 #define MAIN_MENU_ROW "--- GRAPH ALGORITHMS DEMO ---\nMENU: 0=Exit 1=MST 2=DSP 3=TSP\nSelection "
48 /* --- END-MACRO-DEFINITIONS --- */
49 
50 /* --- GLOBAL-VARIABLES --- */
51 char mst_vtx_data[NR_OF_MST_VERTICES]={'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'};
52 
53 double mst_edge_data[NR_OF_MST_VERTICES][NR_OF_MST_VERTICES] =
54  {{0,4.0,0,0,0,0,0,8.0,0}, {4.0,0,8.0,0,0,0,0,11.0,0}, {0,8.0,0,7.0,0,4.0,0,0,2.0},
55  {0,0,7.0,0,9.0,14.0,0,0,0}, {0,0,0,9.0,0,10.0,0,0,0}, {0,0,4.0,14.0,10.0,0,2.0,0,0},
56  {0,0,0,0,0,2.0,0,1.0,6.0}, {8.0,11.0,0,0,0,0,1.0,0,7.0}, {0,0,2.0,0,0,0,6.0,7.0,0}};
57 
58 char dsp_vtx_data[NR_OF_DSP_VERTICES]={'a', 'b', 'c', 'd', 'e', 'f'};
59 double dsp_edge_data[NR_OF_DSP_VERTICES][NR_OF_DSP_VERTICES] =
60  {{0,8.0,4.0,0,0,0}, {0,0,6.0,2.0,0,4.0}, {0,0,0,0,4.0,1.0},
61  {0,0,0,0,0,0}, {0,0,0,0,0,5.0}, {0,2.0,0,7.0,4.0,0}};
62 
63 double tsp_data[NR_OF_TSP_VERTICES][NR_OF_TSP_COORDS] = {{2.0,1.0},{1.0,3.0},{2.0,4.0},{4.0,3.0},
64  {5.0,2.0},{5.0,5.0},{6.0,3.0}};
65 /* --- END-GLOBAL-VARIABLES --- */
66 
67 /* FUNCTION-DECLARATIONS */
68 /* Call-back functions */
69 void mst_destroy(void *data);
70 void dsp_destroy(void *data);
71 void tsp_destroy(void *data);
72 int mst_match(const void *k1, const void *k2);
73 int dsp_match(const void *k1, const void *k2);
74 int tsp_match(const void *k1, const void *k2);
75 void print_mst_vtx(const void *data);
76 void print_mst_edge(const void *data);
77 void print_mst(const void *data);
78 void print_dsp_vtx(const void *data);
79 void print_dsp_edge(const void *data);
80 void print_dsp(const void *data);
81 void print_tsp_vtx(const void *data);
82 /* void print_tsp_edge(const void *data); */
83 
84 /* Menu selections */
85 int mst(void);
86 int tsp(void);
87 int dsp(void);
88 
89 /* Misc. application functions.. */
90 int read_mst_vtx(Graph gr, char *vertices, int nr_of_vertices);
91 int read_mst_edge(Graph gr, double mst_edges[][NR_OF_MST_VERTICES], int nr_of_vertices);
92 int read_dsp_vtx(Graph gr, char *vertices, int nr_of_vertices);
93 int read_dsp_edge(Graph gr, double (*dsp_edges)[NR_OF_DSP_VERTICES], int nr_of_vertices);
94 int read_tsp_vtx(Slist lst, double (*vertices)[NR_OF_TSP_COORDS], int nr_of_vertices);
95 
96 /* END-OF-FUNCTION-DECLARATIONS */
97 
98 /* FUNCTION DEFINITIONS - the rest of the program */
99 /* --- Function: void mst_destroy(void *data) --- */
100 void mst_destroy(void *data)
101 {
102  free(((MstVertexdata)data)->data);
103  free(data);
104 }
105 
106 /* --- Function: void dsp_destroy(void *data) --- */
107 void dsp_destroy(void *data)
108 {
109  free(((DspVertexdata)data)->data);
110  free(data);
111 }
112 
113 /* --- Function: void tsp_destroy(void *data) --- */
114 void tsp_destroy(void *data)
115 {
116  free(((TspVertexdata)data)->data);
117  free(data);
118 }
119 
120 /* --- Function: void print_mst_vtx(const void *data) --- */
121 void print_mst_vtx(const void *data)
122 {
123  printf("%c ", *(char *)((MstVertexdata)data)->data);
124 }
125 
126 /* --- Function: void print_mst_edge(const void *data) --- */
127 void print_mst_edge(const void *data)
128 {
129  printf("%c %4.1lf ", *(char *)((MstVertexdata)data)->data,
130  ((MstVertexdata)data)->weight);
131 }
132 
133 /* --- Function: void print_mst(const void *data) --- */
134 void print_mst(const void *data)
135 {
136  MstVertexdata mst = (MstVertexdata)data;
137 
138  printf("\nVertex = %c, parent = %c", *(char *)mst->data,
139  mst->parent != NULL ? *(char *)mst->parent->data : '-');
140 }
141 
142 /* --- Function: void print_dsp_vtx(const void *data) --- */
143 void print_dsp_vtx(const void *data)
144 {
145  printf("%c ", *(char *)((DspVertexdata)data)->data);
146 }
147 
148 /* --- Function: void print_dsp_edge(const void *data) --- */
149 void print_dsp_edge(const void *data)
150 {
151  printf("%c %4.1lf ", *(char *)((DspVertexdata)data)->data,
152  ((DspVertexdata)data)->weight);
153 }
154 
155 /* --- Function: void print_dsp(const void *data) --- */
156 void print_dsp(const void *data)
157 {
158  DspVertexdata dsp = (DspVertexdata)data;
159 
160  printf("\nVertex = %c, parent = %c, distance=%.1lf", *(char *)dsp->data,
161  dsp->parent != NULL ? *(char *)dsp->parent->data : '-', dsp->distance);
162 }
163 
164 /* --- Function: void print_tsp_vtx(const void *data) --- */
165 void print_tsp_vtx(const void *data)
166 {
167  TspVertexdata tsp = (TspVertexdata)data;
168 
169  printf("\nVertex: %c, x: %.1lf, y: %.1lf", *(char *)tsp->data, tsp->x, tsp->y);
170 }
171 
172 /* --- Function: int mst_match(const void *k1, const void *k2) --- */
173 int mst_match(const void *k1, const void *k2)
174 {
175  return *(char *)((MstVertexdata)k1)->data == *(char *)((MstVertexdata)k2)->data;
176 }
177 
178 /* --- Function: int dsp_match(const void *k1, const void *k2) --- */
179 int dsp_match(const void *k1, const void *k2)
180 {
181  return *(char *)((DspVertexdata)k1)->data == *(char *)((DspVertexdata)k2)->data;
182 }
183 
184 /* --- Function: int tsp_match(const void *k1, const void *k2) --- */
185 int tsp_match(const void *k1, const void *k2)
186 {
187  return *(char *)((DspVertexdata)k1)->data == *(char *)((DspVertexdata)k2)->data;
188 }
189 
190 /* --- Function: int mst(void) --- */
191 int mst(void)
192 {
193  Graph gr;
194  Slist scan;
195  struct MstVertexdata_ mst_tmp;
196  char start;
197 
198  my_clearscrn();
199  printf("--- MINIMAL SPANNING TREE ---");
200 
201  gr = GRAPHinit(mst_match, mst_destroy);
202 
203  if ((read_mst_vtx(gr, mst_vtx_data, NR_OF_MST_VERTICES)) != OK)
204  {
205  GRAPHdestroy(gr);
206  return -2;
207  }
208 
209  if ((read_mst_edge(gr, mst_edge_data, NR_OF_MST_VERTICES)) != OK)
210  {
211  GRAPHdestroy(gr);
212  return -3;
213  }
214 
215  prompt_and_pause("\n\nGraph initialized and graph data read..");
216  printf("\nGRAPH:");
217 
218  /* Display graph.. */
219  GRAPHprint(gr, print_mst_vtx, print_mst_edge);
220  printf("\n--------------------------------------\nNr of vertices/edges: %d/%d",
221  GRAPHvcount(gr), GRAPHecount(gr));
222 
223  start = read_char("\nStart node ", 'a', 'i', isalpha);
224  mst_tmp.data = &start;
225 
226  /* Now - call appropriate algorithm to compute Minimal Spanning Tree.. */
227  if (ALGOmst(gr, &mst_tmp, &scan, mst_match) != OK)
228  {
229  GRAPHdestroy(gr);
230  return -4;
231  }
232 
233  /* Display Minimal Spanning Tree.. */
234  printf("\nMinimal spanning tree:\n");
235  SLISTtraverse(scan, print_mst, SLIST_FWD);
236  prompt_and_pause("\n\n");
237 
238  /* Tidy up.. */
239  SLISTdestroy(scan);
240  GRAPHdestroy(gr);
241 
242  /* Everything is OK */
243  return OK;
244 }
245 
246 /* --- Function: int read_mst_vtx(Graph gr, char *vertices, int nr_of_vertices) --- */
247 int read_mst_vtx(Graph gr, char *vertices, int nr_of_vertices)
248 {
249  int i, retval;
250  MstVertexdata mst;
251 
252  for (i = 0; i < nr_of_vertices; ++i)
253  {
254  mst = (MstVertexdata)malloc(sizeof(struct MstVertexdata_));
255  MALCHK(mst);
256 
257  mst->data = (char *)malloc(sizeof(char));
258  MALCHK(mst->data);
259 
260  /* Copy data to vertex - by pointer arithmetic.. */
261  *((char *)mst->data) = *(vertices+i);
262 
263  /* Insert vertex data into graph.. */
264  if ((retval = GRAPHinsvertex(gr, mst)) != OK)
265  {
266  mst_destroy(mst);
267  return retval;
268  }
269  }
270 
271  /* Everything OK */
272  return OK;
273 }
274 
275 /* --- Function: int read_mst_edge(Graph gr, double mst_edges[][NR_OF_MST_VERTICES], int nr_of vertices) --- */
276 int read_mst_edge(Graph gr, double mst_edges[][NR_OF_MST_VERTICES], int nr_of_vertices)
277 {
278  int i, j, retval;
279  char tmp;
280  struct MstVertexdata_ mst_tmp;
281  MstVertexdata mst;
282 
283  for (i = 0; i < nr_of_vertices; ++i)
284  {
285  for (j = 0; j < nr_of_vertices; ++j)
286  {
287  if (mst_edges[i][j] != 0)
288  {
289  mst = (MstVertexdata)malloc(sizeof(struct MstVertexdata_));
290  MALCHK(mst);
291 
292  mst->data = (char *)malloc(sizeof(char));
293  MALCHK(mst->data);
294 
295  *(char *)mst->data = 'a'+j;
296  /* Distribute data - via indexing into 2-dim. array.. */
297  mst->weight = mst_edges[i][j];
298 
299  /* Temporary vertex (search) data.. */
300  tmp = 'a'+i;
301  mst_tmp.data = &tmp;
302 
303  if ((retval = GRAPHinsedge(gr, &mst_tmp, mst)) != OK)
304  {
305  mst_destroy(mst);
306  return retval;
307  }
308  }
309  }
310  }
311  /* Everything OK */
312  return OK;
313 }
314 
315 /* --- Function: int dsp(void) --- */
316 int dsp(void)
317 {
318  Graph gr;
319  Slist spaths;
320  struct DspVertexdata_ dsp_tmp;
321  char start;
322 
323  my_clearscrn();
324  printf("--- DIJKSTRA'S SHORTEST PATH ---");
325 
326  gr = GRAPHinit(dsp_match, dsp_destroy);
327 
328  if ((read_dsp_vtx(gr, dsp_vtx_data, NR_OF_DSP_VERTICES)) != OK)
329  {
330  GRAPHdestroy(gr);
331  return -2;
332  }
333 
334  if ((read_dsp_edge(gr, dsp_edge_data, NR_OF_DSP_VERTICES)) != OK)
335  {
336  GRAPHdestroy(gr);
337  return -3;
338  }
339 
340  prompt_and_pause("\n\nGraph initialized and graph data read..");
341  printf("\nGRAPH:");
342 
343  /* Display graph.. */
344  GRAPHprint(gr, print_dsp_vtx, print_dsp_edge);
345  printf("\n-------------------------------\nNr of vertices/edges: %d/%d", GRAPHvcount(gr), GRAPHecount(gr));
346 
347  start = read_char("\nStart node ", 'a', 'f', isalpha);
348  dsp_tmp.data = &start;
349 
350  /* Now - call appropriate algorithm to compute Shortest Paths.. */
351  if (ALGOdsp(gr, &dsp_tmp, &spaths, dsp_match) != OK)
352  {
353  GRAPHdestroy(gr);
354  return -4;
355  }
356 
357  /* Display Dijkstra's Shortest Path.. */
358  printf("\nDijkstra's Shortest Paths:\n");
359  SLISTtraverse(spaths, print_dsp, SLIST_FWD);
360  prompt_and_pause("\n\n");
361 
362  /* Tidy up.. */
363  SLISTdestroy(spaths);
364  GRAPHdestroy(gr);
365 
366  /* Everything is OK */
367  return OK;
368 }
369 
370 /* --- Function: int read_dsp_vtx(Graph gr, char *vertices, int nr_of_vertices) --- */
371 int read_dsp_vtx(Graph gr, char *vertices, int nr_of_vertices)
372 {
373  int i, retval;
374  DspVertexdata dsp;
375 
376  for (i = 0; i < nr_of_vertices; ++i)
377  {
378  dsp = (DspVertexdata)malloc(sizeof(struct DspVertexdata_));
379  MALCHK(dsp);
380 
381  dsp->data = (char *)malloc(sizeof(char));
382  MALCHK(dsp->data);
383 
384  /* Copy data to vertex - by pointer arithmetic.. */
385  *((char *)dsp->data) = *(vertices+i);
386 
387  /* Insert vertex data into graph.. */
388  if ((retval = GRAPHinsvertex(gr, dsp)) != OK)
389  {
390  dsp_destroy(dsp);
391  return retval;
392  }
393  }
394 
395  /* Everything OK */
396  return OK;
397 }
398 
399 /* --- Function: int read_dsp_edge(Graph gr, double (*dsp_edges)[NR_OF_DSP_VERTICES], int nr_of_vertices) --- */
400 int read_dsp_edge(Graph gr, double (*dsp_edges)[NR_OF_DSP_VERTICES], int nr_of_vertices)
401 {
402  int i, j, retval;
403  char tmp;
404  struct DspVertexdata_ dsp_tmp;
405  DspVertexdata dsp;
406  double *pdbl;
407 
408  for (i = 0; i < nr_of_vertices; ++i)
409  {
410  for (j = 0; j < nr_of_vertices; ++j)
411  {
412 
413  /* Using pointer arithmetic here - just as an (uglier) alternative to indexing... */
414  /* Get the adress of double numbers in 2-dim array - using pointer arithmetic */
415  pdbl = *(dsp_edges+i)+j;
416 
417  if ( *pdbl != 0) /* If current dbl nr not equal to 0.. */
418  {
419  dsp = (DspVertexdata)malloc(sizeof(struct DspVertexdata_));
420  MALCHK(dsp);
421 
422  dsp->data = (char *)malloc(sizeof(char));
423  MALCHK(dsp->data);
424 
425  *(char *)dsp->data = 'a'+j;
426 
427  /* Copy read nr into relevant variable.. */
428  dsp->weight = *pdbl;
429  /* Temporary vertex (search) data.. */
430  tmp = 'a'+i;
431  dsp_tmp.data = &tmp;
432  /* Now - insert current edge into graph.. */
433  if ((retval = GRAPHinsedge(gr, &dsp_tmp, dsp)) != OK)
434  {
435  dsp_destroy(dsp);
436  return retval;
437  }
438  }
439  }
440  }
441  /* Everything OK */
442  return OK;
443 }
444 
445 /* --- Function: int tsp(void) --- */
446 int tsp(void)
447 {
448  Slist tsp_list, tour;
449  SlistNode node;
450  struct TspVertexdata_ tsp_start;
451  TspVertexdata tsp_rcd;
452  char id;
453  double x, y, total=0, distance;
454 
455  my_clearscrn();
456  printf("--- TRAVELING SALESMAN'S PATH ---");
457 
458  tsp_list = SLISTinit(tsp_destroy);
459 
460  /* Read tsp data.. */
461  if ((read_tsp_vtx(tsp_list, tsp_data, NR_OF_TSP_VERTICES)) != OK)
462  {
463  SLISTdestroy(tsp_list);
464  return -2;
465  }
466 
467  prompt_and_pause("\n\nTour list created - and data read..");
468 
469  /* Display tsp data read.. */
470  printf("\nTour Vertex Data:");
471  SLISTtraverse(tsp_list, print_tsp_vtx, SLIST_FWD);
472 
473  /* Set up start vertex.. */
474  id = read_char("\nStart node ", 'a', 'g', isalpha);
475  tsp_start.data = &id;
476 
477  /* Now - call appropriate algorithm to compute Traveling Salesman Path.. */
478  if (ALGOtsp(tsp_list, &tsp_start, &tour, tsp_match) != OK)
479  {
480  SLISTdestroy(tsp_list);
481  return -4;
482  }
483 
484  /* Print the optimized tour.. */
485  printf("\nTraveling Salesman Path:");
486  for (node = SLISThead(tour); node != NULL; node = SLISTnext(node))
487  {
488  tsp_rcd = SLISTdata(node);
489 
490  if (!SLISTishead(tour, node))
491  {
492  distance = sqrt(pow(tsp_rcd->x-x, 2.0) + pow(tsp_rcd->y-y, 2.0));
493  total = total + distance;
494  }
495 
496  x = tsp_rcd->x;
497  y = tsp_rcd->y;
498 
499  if (!SLISTishead(tour, node))
500  printf("\nVertex=%c, distance=%.2lf", *(char *)tsp_rcd->data, distance);
501  else
502  printf("\nVertex=%c", *(char *)tsp_rcd->data);
503  }
504 
505  printf("\n------------------------\nTotal = %.2lf", total);
506 
507  prompt_and_pause("\n\n");
508 
509  /* Tidy up.. */
510  SLISTdestroy(tsp_list);
511 
512  /* Everything OK */
513  return OK;
514 }
515 
516 /* --- Function: int read_tsp_vtx(Slist lst, double (*vertices)[NR_OF_TSP_COORDS], int nr_of_vertices) --- */
517 int read_tsp_vtx(Slist lst, double (*vertices)[NR_OF_TSP_COORDS], int nr_of_vertices)
518 {
519  int i, j, retval;
520  TspVertexdata tsp;
521  double *pdbl;
522 
523  for (i = 0; i < nr_of_vertices; ++i)
524  {
525  /* Allocate dyn. memory for a tsp record.. */
526  tsp = (TspVertexdata)malloc(sizeof(struct TspVertexdata_));
527  MALCHK(tsp);
528 
529  tsp->data = (char *)malloc(sizeof(char));
530  MALCHK(tsp->data);
531 
532  /* Copy current vertex id into record.. */
533  *(char *)tsp->data = 'a'+i;
534 
535  for (j = 0; j < NR_OF_TSP_COORDS; ++j)
536  {
537  /* Get the adress of double numbers in 2-dim array - using pointer arithmetic */
538  pdbl = *(vertices+i)+j;
539 
540  /* Copy current nr read - into relevant variable.. */
541  (j == 0) ? (tsp->x = *pdbl) : (tsp->y = *pdbl);
542  }
543 
544  /* Now - insert current tsp data record into list.. */
545  if ((retval = SLISTinsnext(lst, SLISTtail(lst), tsp)) != OK)
546  {
547  tsp_destroy(tsp);
548  return retval;
549  }
550  }
551 
552  /* Everything OK */
553  return OK;
554 }
555 
556 int main(void)
557 {
558  /* Declare YOUR variables here ! */
559  int menu_choice, retval;
560 
561  my_clearscrn();
562  prompt_and_pause(INITIAL_INFO);
563 
564  /* Enter menu loop.. */
565  do
566  {
567  menu_choice = menu(MAIN_MENU_ROW, 0, 3);
568 
569  switch (menu_choice)
570  {
571  case 1:
572  if ((retval = mst()) != OK)
573  {
574  if (retval == -2)
575  fprintf(stderr, "Error reading vertex data (errcode=%d).. - bailing out!", retval);
576  else if (retval == -3)
577  fprintf(stderr, "Error reading edge data (errcode=%d).. - bailing out!", retval);
578  else
579  fprintf(stderr, "Error: Fatal error (errcode=%d).. - bailing out!", retval);
580  exit(-1);
581  }
582  break;
583  case 2:
584  if ((retval = dsp()) != OK)
585  {
586  if (retval == -2)
587  fprintf(stderr, "Error reading vertex data (errcode=%d).. - bailing out!", retval);
588  else if (retval == -3)
589  fprintf(stderr, "Error reading edge data (errcode=%d).. - bailing out!", retval);
590  else
591  fprintf(stderr, "Error: Fatal error (errcode=%d).. - bailing out!", retval);
592  exit(-1);
593  }
594  break;
595  case 3:
596  if ((retval = tsp()) != OK)
597  {
598  if (retval == -2)
599  fprintf(stderr, "Error reading vertex data (errcode=%d).. - bailing out!", retval);
600  else if (retval == -3)
601  fprintf(stderr, "Error reading edge data (errcode=%d).. - bailing out!", retval);
602  else
603  fprintf(stderr, "Error: Fatal error (errcode=%d).. - bailing out!", retval);
604  exit(-1);
605  }
606  break;
607  default:
608  prompt_and_pause("\nThat's all folks - Bye..!");
609  break;
610  }
611  }
612  while (menu_choice);
613 
614  return 0;
615 }