00001 #include "graphdual.h"
00002 #ifndef GRD_TEST
00003 #define GRD_TEST 1
00004 #endif
00005
00006
00007 typedef struct
00008 {
00009 double value;
00010 int tail;
00011 int head;
00012 int index;
00013 }
00014 localEdge_t;
00015
00016 typedef const localEdge_t *clep_t;
00017 typedef const clep_t *cclep_t;
00018
00019 static int localEdgeCompare (const void *p1,
00020 const void *p2)
00021 {
00022 return ((*((cclep_t) (p1)))->value < (*((cclep_t) (p2)))->value) ? 1 : -1;
00023 }
00024
00025
00026
00027
00028 static int sortEdgeIndices (int nedges,
00029 int *edges,
00030 int *indices,
00031 double *x)
00032 {
00033
00034 int n;
00035 localEdge_t **edgeArray;
00036
00037
00038 edgeArray = (localEdge_t **) malloc (sizeof (localEdge_t *) * nedges);
00039 for (n = 0; n < nedges; n++)
00040 {
00041 edgeArray[n] = (localEdge_t *) malloc (sizeof (localEdge_t));
00042 edgeArray[n]->value = x[n];
00043 edgeArray[n]->head = edges[2 * n];
00044 edgeArray[n]->tail = edges[2 * n + 1];
00045 edgeArray[n]->index = indices[n];
00046 }
00047
00048
00049 if (nedges > 1)
00050 qsort (edgeArray, (unsigned) nedges, sizeof (localEdge_t *),
00051 localEdgeCompare);
00052 EXIT (edgeArray[0]->value < edgeArray[nedges - 1]->value,
00053 "edgeArray is not well sorted");
00054
00055 for (n = 0; n < nedges; n++)
00056 {
00057 indices[n] = edgeArray[n]->index;
00058 free (edgeArray[n]);
00059 }
00060
00061 free (edgeArray);
00062
00063 return 0;
00064
00065 }
00066
00067
00068 static int sortEdges (int nedges,
00069 int *edges,
00070 double *x)
00071 {
00072
00073 int n;
00074 localEdge_t **edgeArray;
00075
00076
00077 edgeArray = (localEdge_t **) malloc (sizeof (localEdge_t *) * nedges);
00078 for (n = 0; n < nedges; n++)
00079 {
00080 edgeArray[n] = (localEdge_t *) malloc (sizeof (localEdge_t));
00081 edgeArray[n]->value = x[n];
00082 edgeArray[n]->head = edges[2 * n];
00083 edgeArray[n]->tail = edges[2 * n + 1];
00084 edgeArray[n]->index = n;
00085 }
00086
00087
00088 if (nedges > 1)
00089 qsort (edgeArray, (unsigned) nedges, sizeof (localEdge_t *),
00090 localEdgeCompare);
00091 EXIT (edgeArray[0]->value < edgeArray[nedges - 1]->value,
00092 "edgeArray is not well sorted");
00093
00094 for (n = 0; n < nedges; n++)
00095 {
00096 edges[2 * n] = edgeArray[n]->head;
00097 edges[2 * n + 1] = edgeArray[n]->tail;
00098 x[n] = edgeArray[n]->value;
00099 free (edgeArray[n]);
00100 }
00101
00102 free (edgeArray);
00103
00104 return 0;
00105
00106 }
00107
00108 #define GETROOTEDGE(curroot, G) (G->G + G->G[curroot].link[1])
00109 #define GETNEXTEDGE(curedge,curroot, G) ((curedge->link[1] < G->N) ? GETROOTEDGE(curroot,G) : (G->G + curedge->link[1]))
00110 #define ISNODEEMPTY(curroot, G) (G->G[curroot].link[1] < G->N ? 1 : 0 )
00111 #define GETOTHEREND(cedge,nroot,G) (G->G[gp_GetTwinArc(G,(cedge == GETROOTEDGE( nroot, G ) ? (G->G[nroot].link[1]) : (G->G[cedge->link[0]].link[1])))].v)
00112
00113
00114
00115 EGdGraph_t *getDualBoyer (graphP G,
00116 int nnodes,
00117 int nedges,
00118 double *weigh,
00119 EGlist_t *** dembed,
00120 EGmemPool_t * localmem,
00121 EGlist_t *** lembed)
00122 {
00123
00124
00125 size_t os[EG_MENGER_NUMOS] = {
00126 [EG_MENGER_PI] = offsetof (EGmengerNodeData_t, pi),
00127 [EG_MENGER_DIST] = offsetof (EGmengerNodeData_t, dist),
00128 [EG_MENGER_ORIG_DIST] = offsetof (EGmengerNodeData_t, orig_dist),
00129 [EG_MENGER_NDIST] = offsetof (EGmengerNodeData_t, ndist),
00130 [EG_MENGER_ORIG_NDIST] = offsetof (EGmengerNodeData_t, orig_ndist),
00131 [EG_MENGER_MARK] = offsetof (EGmengerNodeData_t, marker),
00132 [EG_MENGER_ORIG_MARK] = offsetof (EGmengerNodeData_t, orig_marker),
00133 [EG_MENGER_FATHER] = offsetof (EGmengerNodeData_t, father),
00134 [EG_MENGER_ORIG_FATHER] = offsetof (EGmengerNodeData_t, orig_father),
00135 [EG_MENGER_HEAP_CONNECTOR] = offsetof (EGmengerNodeData_t, hc),
00136 [EG_MENGER_ECOST] = offsetof (EGmengerEdgeData_t, cost),
00137 [EG_MENGER_REDUCED_ECOST] = offsetof (EGmengerEdgeData_t, reduced_cost),
00138 [EG_MENGER_IS_IN_SOL] = offsetof (EGmengerEdgeData_t, is_in_solution),
00139 [EG_MENGER_EDATA] = offsetof (EGmengerEdgeData_t, data)
00140 };
00141 EGdGraph_t *bdG = 0;
00142 EGdGraphEdge_t *e;
00143 EGdGraphNode_t **node_array;
00144 EGmengerNodeData_t *ndata;
00145 EGmengerEdgeData_t *edata;
00146 int nroot,
00147 nnexti,
00148 i,
00149 rval,
00150 curface,
00151 nnextii;
00152 graphNodeP eproot,
00153 eroot,
00154 epnexti,
00155 epnextii;
00156 unsigned short *e_old,
00157 *e_mark;
00158 const int nFaces = nedges - nnodes + 2;
00159 unsigned char *face_mark;
00160
00161
00162 ADVTESTL (GD_LEVEL, nnodes != G->N, 0, "number nodes in graph and "
00163 "indicated doesn't match %d != %d", nnodes, G->N);
00164 ADVTESTL (GD_LEVEL, nedges != G->M, 0, "number edges in graph and "
00165 "indicated doesn't match %d != %d", nedges, G->M);
00166 e_old = EGmemPoolSMalloc (localmem, unsigned short,
00167 G->M);
00168 e_mark = EGmemPoolSMalloc (localmem, unsigned short,
00169 G->M);
00170 face_mark = EGsMalloc (unsigned char,
00171 nFaces);
00172 memset (face_mark, 0, sizeof (unsigned char) * nFaces);
00173 node_array = EGmemPoolSMalloc (localmem, EGdGraphNode_t *, nFaces);
00174 *dembed = EGmemPoolSMalloc (localmem, EGlist_t *, nFaces);
00175 if(lembed) *lembed = EGmemPoolSMalloc (localmem, EGlist_t *, nFaces);
00176 bdG = EGnewDGraph (localmem);
00177
00178 i = gp_Embed (G, EMBEDFLAGS_PLANAR);
00179 rval = gp_SortVertices (G);
00180 EXITRVAL (rval);
00181 if (i != OK)
00182 return 0;
00183
00184
00185
00186
00187 for (nroot = 0; nroot < G->N; nroot++)
00188 {
00189 if (ISNODEEMPTY (nroot, G))
00190 continue;
00191 eproot = GETROOTEDGE (nroot, G);
00192 e_mark[eproot->id] = 0;
00193 e_old[eproot->id] = 0;
00194
00195 for (epnexti = GETNEXTEDGE (eproot, nroot, G); epnexti != eproot;
00196 epnexti = GETNEXTEDGE (epnexti, nroot, G))
00197 {
00198 e_mark[epnexti->id] = 0;
00199 e_old[epnexti->id] = 0;
00200 }
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210 curface = 1;
00211
00212 for (nroot = 0; nroot < G->N; nroot++)
00213 {
00214
00215 eproot = GETROOTEDGE (nroot, G);
00216 epnexti = eproot;
00217 do
00218 {
00219
00220 if (((unsigned) (epnexti - G->G)) & 1U)
00221 {
00222
00223 if (e_mark[epnexti->id])
00224 {
00225 epnexti = GETNEXTEDGE (epnexti, nroot, G);
00226 continue;
00227 }
00228 }
00229 else
00230 {
00231
00232 if (e_old[epnexti->id])
00233 {
00234 epnexti = GETNEXTEDGE (epnexti, nroot, G);
00235 continue;
00236 }
00237 }
00238
00239 nnextii = epnexti->v;
00240
00241
00242 epnextii = epnexti;
00243 nnexti = nroot;
00244 eroot = epnextii;
00245 do
00246 {
00247 if (((unsigned) (epnextii - G->G)) & 1U)
00248 {
00249 e_mark[epnextii->id] = curface;
00250 i = e_old[epnextii->id];
00251 }
00252 else
00253 {
00254 e_old[epnextii->id] = curface;
00255 i = e_mark[epnextii->id];
00256 }
00257
00258 epnextii = GETROOTEDGE (nnextii, G);
00259
00260 while (epnextii->v != nnexti)
00261 epnextii = GETNEXTEDGE (epnextii, nnextii, G);
00262
00263 epnextii = GETNEXTEDGE (epnextii, nnextii, G);
00264 eroot = epnextii;
00265 nnexti = nnextii;
00266 nnextii = eroot->v;
00267 } while ((epnextii != epnexti) || (nroot != nnexti));
00268
00269
00270 curface++;
00271 EXIT (curface - 1 > nFaces, "Number of faces is wrong nFaces %u "
00272 "curface %u", nFaces, curface - 1);
00273
00274 epnexti = GETNEXTEDGE (epnexti, nroot, G);
00275 } while (epnexti != eproot);
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 for (i = 0; i < nFaces; i++)
00287 {
00288 ndata = EGnewMengerNodeData (localmem);
00289 node_array[i] = EGdGraphAddNode (bdG, ndata);
00290 (*dembed)[i] = EGnewList (localmem);
00291 if(lembed) (*lembed)[i] = EGnewList (localmem);
00292 }
00293
00294 for (nroot = 0; nroot < G->N; nroot++)
00295 {
00296
00297 eproot = GETROOTEDGE (nroot, G);
00298 epnexti = eproot;
00299 do
00300 {
00301
00302 if (((unsigned) (epnexti - G->G)) & 1U)
00303 {
00304
00305 curface = e_mark[epnexti->id];
00306 if (face_mark[curface - 1])
00307 {
00308 epnexti = GETNEXTEDGE (epnexti, nroot, G);
00309 continue;
00310 }
00311 }
00312 else
00313 {
00314
00315 curface = e_old[epnexti->id];
00316 if (face_mark[curface - 1])
00317 {
00318 epnexti = GETNEXTEDGE (epnexti, nroot, G);
00319 continue;
00320 }
00321 }
00322 face_mark[curface - 1] = 1;
00323
00324 nnextii = epnexti->v;
00325
00326
00327 epnextii = epnexti;
00328 nnexti = nroot;
00329 eroot = epnextii;
00330 do
00331 {
00332 if (((unsigned) (epnextii - G->G)) & 1U)
00333 {
00334 i = e_old[epnextii->id];
00335 }
00336 else
00337 {
00338 i = e_mark[epnextii->id];
00339 }
00340
00341 EGlistPushBack ((*dembed)[curface - 1], (void *) (epnextii->id));
00342 edata = EGnewMengerEdgeData (localmem);
00343 e = EGdGraphAddEdge (bdG, edata,
00344 node_array[i - 1], node_array[curface - 1]);
00345 EGmengerSetEdgeCost (e, os, EGdijkstraToCost (weigh[epnextii->id]));
00346 EGmengerSetEdgeData (e, os, epnextii);
00347 EGmengerSetEdgeIsInSolution (e, os, 0);
00348 if(lembed) EGlistPushBack((*lembed)[curface - 1], e);
00349
00350 epnextii = GETROOTEDGE (nnextii, G);
00351
00352 while (epnextii->v != nnexti)
00353 epnextii = GETNEXTEDGE (epnextii, nnextii, G);
00354
00355 epnextii = GETNEXTEDGE (epnextii, nnextii, G);
00356 eroot = epnextii;
00357 nnexti = nnextii;
00358 nnextii = eroot->v;
00359 } while ((epnextii != epnexti) || (nroot != nnexti));
00360
00361 epnexti = GETNEXTEDGE (epnexti, nroot, G);
00362 } while (epnexti != eproot);
00363 }
00364
00365
00366 EGmemPoolSFree (node_array, EGdGraphNode_t *, nFaces, localmem);
00367 EGmemPoolSFree (e_old, unsigned short,
00368 G->M,
00369 localmem);
00370 EGmemPoolSFree (e_mark, unsigned short,
00371 G->M,
00372 localmem);
00373 EGfree (face_mark);
00374 return bdG;
00375 }
00376
00377
00378
00379 int DPedgeEliminationHeuristic (int nnodes,
00380 int nedges,
00381 int *edges,
00382 double *weight,
00383 int *nplanar_edges,
00384 int *planar_edges,
00385 double *planar_weight,
00386 int *nelim_indices,
00387 int *elim_indices)
00388 {
00389
00390 #if DISPLAY_MODE
00391 fprintf (stdout, "EEH: Initiating Edge Elimination Heuristic.\n");
00392 fflush (stdout);
00393 #endif
00394
00395 int rval;
00396
00397 rval = sortEdges (nedges, edges, weight);
00398 CHECKRVAL (rval);
00399
00400 #if DISPLAY_MODE
00401 fprintf (stdout, "EEH: Executing binary search.\n");
00402 fflush (stdout);
00403 #endif
00404
00405 rval =
00406 DPbinPlanarizeBoyer (nnodes, nedges, 0, edges, weight, nplanar_edges,
00407 planar_edges, planar_weight, elim_indices);
00408 CHECKRVAL (rval);
00409
00410 *nelim_indices = nedges - *nplanar_edges;
00411
00412 #if DISPLAY_MODE
00413 fprintf (stdout, "EEH: Finished.\n");
00414 fflush (stdout);
00415 #endif
00416
00417 return 0;
00418
00419 }
00420
00421 int isPlanarBoyer (int nnodes,
00422 int nedges,
00423 int *edges)
00424 {
00425
00426 int rval,
00427 is_G_planar_b;
00428 graphP G;
00429
00430 G = gp_New ();
00431 rval = cook2boyerGraph (G, nnodes, nedges, edges);
00432 EXITRVAL (rval);
00433 is_G_planar_b = gp_Embed (G, EMBEDFLAGS_PLANAR);
00434 gp_Free (&G);
00435
00436 if (is_G_planar_b == OK)
00437 return 1;
00438
00439 return 0;
00440
00441 }
00442
00443 int isPlanarOrMinorBoyer (int nnodes,
00444 int nedges,
00445 int *edges,
00446 int *nmedges,
00447 int *medges)
00448 {
00449
00450 int rval,
00451 is_G_planar_b,
00452 nmnodes;
00453 graphP G;
00454
00455 G = gp_New ();
00456 rval = cook2boyerGraph (G, nnodes, nedges, edges);
00457 EXITRVAL (rval);
00458 is_G_planar_b = gp_Embed (G, EMBEDFLAGS_PLANAR);
00459
00460 if (is_G_planar_b == OK)
00461 {
00462 gp_Free (&G);
00463 return 1;
00464 }
00465
00466 gp_SortVertices (G);
00467 extractCookEdgeIds (G, &nmnodes, nmedges, medges);
00468 gp_Free (&G);
00469
00470 return 0;
00471
00472 }
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 int DPbinPlanarizeBoyer (int nnodes,
00488 int nedges1,
00489 int nedges2,
00490 int *edges,
00491 double *weigh,
00492 int *nedges3,
00493 int *edges3,
00494 double *weigh3,
00495 int *elim_indices)
00496 {
00497
00498 int nelim = 0,
00499 i,
00500 rval,
00501 current_edge,
00502 is_G_planar_b,
00503 top,
00504 bottom,
00505 middle,
00506 ltop,
00507 lbottom,
00508 lmiddle;
00509 graphP G;
00510
00511 #if DISPLAY_MODE
00512 fprintf (stdout, "\rBIN: Binary Search Heuristic.\n");
00513 fflush (stdout);
00514 #endif
00515
00516
00517 G = gp_New ();
00518 rval = cook2boyerGraph (G, nnodes, nedges1, edges);
00519 EXITRVAL (rval);
00520 is_G_planar_b = gp_Embed (G, EMBEDFLAGS_PLANAR);
00521 gp_Free (&G);
00522
00523
00524 if (is_G_planar_b == OK)
00525 {
00526 #if DISPLAY_MODE
00527 fprintf (stdout, "\rBIN: Graph is planar.\n");
00528 fflush (stdout);
00529 #endif
00530 *nedges3 = 0;
00531 return 0;
00532 }
00533
00534
00535
00536 *nedges3 = nedges2;
00537
00538 for (i = 0; i < nedges2; i++)
00539 {
00540 edges3[2 * i] = edges[2 * i];
00541 edges3[2 * i + 1] = edges[2 * i + 1];
00542 weigh3[i] = weigh[i];
00543 }
00544 top = nedges2;
00545 bottom = nedges1;
00546 middle = top + (bottom - top) / 2;
00547
00548 while ((bottom - top) > 0)
00549 {
00550
00551 ltop = top;
00552 lbottom = bottom;
00553 lmiddle = ltop + (lbottom - ltop) / 2;
00554
00555 while (lmiddle != ltop)
00556 {
00557
00558
00559
00560 current_edge = (*nedges3);
00561 for (i = ltop; i < lmiddle; i++)
00562 {
00563 edges3[2 * (*nedges3)] = edges[2 * i];
00564 edges3[2 * (*nedges3) + 1] = edges[2 * i + 1];
00565 weigh3[*nedges3] = weigh[i];
00566 (*nedges3)++;
00567 }
00568
00569
00570 G = gp_New ();
00571 rval = cook2boyerGraph (G, nnodes, (*nedges3), edges3);
00572 EXITRVAL (rval);
00573 is_G_planar_b = gp_Embed (G, EMBEDFLAGS_PLANAR);
00574 gp_Free (&G);
00575
00576
00577 if (is_G_planar_b == OK)
00578 {
00579 ltop = lmiddle;
00580 lmiddle = ltop + (lbottom - ltop) / 2;
00581 continue;
00582 }
00583
00584
00585 else
00586 {
00587 (*nedges3) = current_edge;
00588 lbottom = lmiddle;
00589 lmiddle = ltop + (lbottom - ltop) / 2;
00590 continue;
00591 }
00592
00593 }
00594
00595
00596 top = lbottom;
00597 elim_indices[nelim++] = lmiddle;
00598
00599 #if DISPLAY_MODE
00600 fprintf (stdout, "\rBIN: Removing edge (%6d %6d) [%lf]\n",
00601 edges[2 * lmiddle], edges[2 * lmiddle + 1], weigh[lmiddle]);
00602 fflush (stdout);
00603 #endif
00604
00605
00606
00607 current_edge = (*nedges3);
00608 for (i = top; i < bottom; i++)
00609 {
00610 edges3[2 * (*nedges3)] = edges[2 * i];
00611 edges3[2 * (*nedges3) + 1] = edges[2 * i + 1];
00612 weigh3[(*nedges3)] = weigh[i];
00613 (*nedges3)++;
00614 }
00615
00616
00617 G = gp_New ();
00618 rval = cook2boyerGraph (G, nnodes, (*nedges3), edges3);
00619 EXITRVAL (rval);
00620 is_G_planar_b = gp_Embed (G, EMBEDFLAGS_PLANAR);
00621 gp_Free (&G);
00622
00623
00624 if (is_G_planar_b == OK)
00625 break;
00626
00627
00628
00629 else
00630 (*nedges3) = current_edge;
00631
00632 }
00633
00634 #if DISPLAY_MODE
00635 fprintf (stdout, "\rBIN: Eliminated %d edges.\n", nelim);
00636 fprintf (stdout, "BIN: Completed planar sub-graph search.\n");
00637 fflush (stdout);
00638 #endif
00639
00640 return 0;
00641
00642 }
00643
00644
00645
00646 int DPgetTrivialNodesToContract (int nnodes,
00647 int nedges,
00648 int *edges,
00649 double *weight,
00650 int *node_1,
00651 int *node_2)
00652 {
00653
00654 int i;
00655 int *degree;
00656
00657 *node_1 = -1;
00658 *node_2 = -1;
00659
00660 degree = (int *) calloc ((size_t) nnodes, sizeof (int));
00661
00662 for (i = 0; i < nedges; i++)
00663 if (weight[i] > 0.99)
00664 {
00665 degree[edges[2 * i]] += 1;
00666 degree[edges[2 * i + 1]] += 1;
00667 }
00668
00669 for (i = 0; i < nedges; i++)
00670 if (degree[edges[2 * i]] == 2 || degree[edges[2 * i + 1]] == 2)
00671 {
00672 *node_1 = edges[2 * i];
00673 *node_2 = edges[2 * i + 1];
00674 break;
00675 }
00676
00677
00678
00679 free (degree);
00680
00681 return 0;
00682
00683 }
00684
00685 int DPgetNonMinorNodesToContract (int nnodes,
00686 int nedges,
00687 int *edges,
00688 double *weight,
00689 int *node_1,
00690 int *node_2)
00691 {
00692
00693 *node_1 = -1;
00694 *node_2 = -1;
00695
00696 int rval;
00697 int i,
00698 nmedges = 0,
00699 *medges,
00700 *degree,
00701 nmnodes = 0,
00702 max_degree = -1;
00703
00704 medges = (int *) malloc (sizeof (int) * nedges);
00705 degree = (int *) malloc (sizeof (int) * nnodes);
00706
00707 memset (degree, 0, sizeof (int) * nnodes);
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 {
00719 rval = isPlanarBoyer (nnodes, nedges, edges);
00720 if (rval)
00721 goto CLEANUP;
00722
00723 rval = sortEdges (nedges, edges, weight);
00724 if (rval)
00725 goto CLEANUP;
00726
00727 rval = DPgetBinMinor (nnodes, nedges, edges, &nmedges, medges, nedges);
00728 if (rval)
00729 goto CLEANUP;
00730 }
00731
00732 max_degree = 0;
00733
00734 for (i = 0; i < nmedges; i++)
00735 {
00736 degree[edges[2 * medges[i]]] += 1;
00737 degree[edges[2 * medges[i] + 1]] += 1;
00738
00739 if (degree[edges[2 * medges[i]]] == 1)
00740 nmnodes++;
00741 if (degree[edges[2 * medges[i]]] > max_degree)
00742 max_degree = degree[edges[2 * medges[i]]];
00743 if (degree[edges[1 + 2 * medges[i]]] == 1)
00744 nmnodes++;
00745 if (degree[edges[1 + 2 * medges[i]]] > max_degree)
00746 max_degree = degree[edges[1 + 2 * medges[i]]];
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 #if 0 == 1
00770
00771 for (i = 0; i < nmedges; i++)
00772 if (degree[edges[2 * medges[i]]] == 2
00773 && degree[edges[2 * medges[i] + 1]] == 2)
00774 if (weight[medges[i]] > 0.999)
00775 {
00776 *node_1 = edges[2 * medges[i]];
00777 *node_2 = edges[2 * medges[i] + 1];
00778 fprintf (stdout, "contracted strong path edge of weight 1\n");
00779 goto DISPLAY;
00780 }
00781
00782
00783 for (i = 0; i < nmedges; i++)
00784 if (degree[edges[2 * medges[i]]] == 2
00785 || degree[edges[2 * medges[i] + 1]] == 2)
00786 if (weight[medges[i]] > 0.999)
00787 {
00788 *node_1 = edges[2 * medges[i]];
00789 *node_2 = edges[2 * medges[i] + 1];
00790 fprintf (stdout, "contracted path edge of weight 1\n");
00791 goto DISPLAY;
00792 }
00793 #endif
00794
00795
00796 for (i = 0; i < nedges; i++)
00797 if (weight[i] > 0.99)
00798 if (!degree[edges[2 * i]] || !degree[edges[2 * i + 1]])
00799 {
00800 *node_1 = edges[2 * i];
00801 *node_2 = edges[2 * i + 1];
00802 fprintf (stdout, "contracted unrelated edge of weight 1\n");
00803 goto DISPLAY;
00804 }
00805
00806 #if 0 == 1
00807
00808 for (i = 0; i < nmedges; i++)
00809 if (degree[edges[2 * medges[i]]] == 2
00810 || degree[edges[2 * medges[i] + 1]] == 2)
00811 {
00812 *node_1 = edges[2 * medges[i]];
00813 *node_2 = edges[2 * medges[i] + 1];
00814 fprintf (stdout, "contracted path edge\n");
00815 goto DISPLAY;
00816 }
00817 #endif
00818
00819 DISPLAY:
00820
00821 ADVTESTL (0, max_degree != 3
00822 && max_degree != 4, 1, "Error! unidentified minor");
00823
00824 if (*node_1 == -1)
00825 saveSubGraph ("contracted_to_minor.x", nnodes, nmedges, edges, medges,
00826 weight);
00827
00828 CLEANUP:
00829
00830 #if DISPLAY_MODE
00831 if (max_degree == 3)
00832 fprintf (stdout,
00833 "MINOR_CONTRACT: Found K3,3 minor (m=%d, n=%d). Nodes to contract: %d and %d.\n",
00834 nmedges, nmnodes, *node_1, *node_2);
00835 else if (max_degree == 4)
00836 fprintf (stdout,
00837 "MINOR_CONTRACT: Found K5 minor (m=%d, n=%d). Nodes to contract: %d and %d.\n",
00838 nmedges, nmnodes, *node_1, *node_2);
00839 else if (max_degree == -1)
00840 fprintf (stdout,
00841 "MINOR_CONTRACT: Graph is planar. No nodes to contract.\n");
00842 else
00843 fprintf (stdout, "MINOR_CONTRACT: Error! Error!\n");
00844 fflush (stdout);
00845 #endif
00846
00847 free (medges);
00848 free (degree);
00849
00850 return 0;
00851
00852 }
00853
00854 int DPgetMinorNodesToContract (int nnodes,
00855 int nedges,
00856 int *edges,
00857 int *node_1,
00858 int *node_2)
00859 {
00860
00861 *node_1 = -1;
00862 *node_2 = -1;
00863
00864 int rval,
00865 nfound = 0;
00866 int i,
00867 nmedges = 0,
00868 *medges,
00869 *degree,
00870 nmnodes = 0;
00871
00872 medges = (int *) malloc (sizeof (int) * nedges);
00873 degree = (int *) malloc (sizeof (int) * nnodes);
00874
00875 memset (degree, 0, sizeof (int) * nnodes);
00876
00877 rval = isPlanarOrMinorBoyer (nnodes, nedges, edges, &nmedges, medges);
00878
00879 if (rval)
00880 goto CLEANUP;
00881
00882 for (i = 0; i < nmedges; i++)
00883 {
00884 degree[edges[2 * medges[i]]] += 1;
00885 degree[edges[2 * medges[i] + 1]] += 1;
00886 if (degree[edges[2 * medges[i]]] == 1)
00887 nmnodes++;
00888 if (degree[edges[1 + 2 * medges[i]]] == 1)
00889 nmnodes++;
00890 }
00891
00892 for (i = 0; i < nnodes; i++)
00893 {
00894 if (degree[i] > 2 && !nfound)
00895 {
00896 *node_1 = i;
00897 nfound = 1;
00898 }
00899 else if (degree[i] > 2)
00900 {
00901 *node_2 = i;
00902 break;
00903 }
00904 }
00905
00906 {
00907
00908 int error = 0;
00909
00910 if (degree[*node_1] == 3 && degree[*node_2] != 3)
00911 error = 1;
00912 else if (degree[*node_1] == 4 && degree[*node_2] != 4)
00913 error = 1;
00914 else if (degree[*node_1] != 3 && degree[*node_1] != 4)
00915 error = 1;
00916
00917 if (error)
00918 for (i = 0; i < nnodes; i++)
00919 if (degree[i] != 0 && degree[i] != 2)
00920 fprintf (stderr, "degree[%d] = %d\n", i, degree[i]);
00921 }
00922
00923 ADVTESTL (0, *node_1 == -1
00924 || *node_2 == -1, 1, "Failed to find nodes to contract");
00925 ADVTESTL (2, degree[*node_1] == 3
00926 && degree[*node_2] != 3, 1, "Error! unidentified minor");
00927 ADVTESTL (2, degree[*node_1] == 4
00928 && degree[*node_2] != 4, 1, "Error! unidentified minor");
00929 ADVTESTL (2, degree[*node_1] != 3
00930 && degree[*node_1] != 4, 1, "Error! unidentified minor");
00931
00932 #if DISPLAY_MODE
00933 if (degree[*node_1] == 3)
00934 fprintf (stdout,
00935 "MINOR_CONTRACT: Found K3,3 minor (n=%d, m=%d). Nodes to contract: %d and %d.\n",
00936 nmedges, nmnodes, *node_1, *node_2);
00937 else if (degree[*node_1] == 4)
00938 fprintf (stdout,
00939 "MINOR_CONTRACT: Found K5 minor (n=%d, m=%d). Nodes to contract: %d and %d.\n",
00940 nmedges, nmnodes, *node_1, *node_2);
00941 #endif
00942
00943 CLEANUP:
00944
00945 free (medges);
00946 free (degree);
00947
00948 return 0;
00949
00950 }
00951
00952 int DPfindBadEdgeK (int nnodes,
00953 int nedges,
00954 int *edges,
00955 double *weight,
00956 int k)
00957 {
00958
00959 int rval,
00960 bad_edge = -1;
00961 int who,
00962 i,
00963 nmedges = 0,
00964 *medges,
00965 *kedges = 0,
00966 *kindices = 0;
00967 double *kweight = 0,
00968 rvalue;
00969
00970 if (k == 1)
00971 return (DPfindBadEdge (nnodes, nedges, edges, weight));
00972 else if (k < 1)
00973 return -1;
00974
00975 medges = (int *) malloc (sizeof (int) * nedges);
00976
00977 rval = isPlanarOrMinorBoyer (nnodes, nedges, edges, &nmedges, medges);
00978
00979
00980
00981 if (rval)
00982 goto CLEANUP;
00983
00984 if (k > nmedges)
00985 k = nmedges;
00986
00987 kedges = (int *) malloc (sizeof (int) * 2 * nmedges);
00988 kweight = (double *) malloc (sizeof (double) * nmedges);
00989 kindices = (int *) malloc (sizeof (int) * nmedges);
00990
00991 for (i = 0; i < nmedges; i++)
00992 {
00993 kedges[2 * i] = edges[2 * (medges[i])];
00994 kedges[2 * i + 1] = edges[2 * (medges[i]) + 1];
00995 kweight[i] = -1 * weight[medges[i]];
00996 kindices[i] = i;
00997 }
00998
00999 sortEdgeIndices (nmedges, kedges, kindices, kweight);
01000
01001 rvalue = random ();
01002 rvalue /= EGRAND_MAX;
01003
01004 who = (int) (k * rvalue);
01005
01006 if (who == k)
01007 who = k - 1;
01008
01009 bad_edge = medges[kindices[who]];
01010
01011 CLEANUP:
01012
01013 free (medges);
01014
01015 if (kedges)
01016 free (kedges);
01017 if (kweight)
01018 free (kweight);
01019 if (kindices)
01020 free (kindices);
01021
01022 return bad_edge;
01023
01024 }
01025
01026 int DPfindBadEdge (int nnodes,
01027 int nedges,
01028 int *edges,
01029 double *weight)
01030 {
01031
01032 int rval;
01033 int i,
01034 nmedges = 0,
01035 *medges,
01036 min_ind = -1;
01037 double min = 200000000.0;
01038
01039 medges = (int *) malloc (sizeof (int) * nedges);
01040
01041 rval = isPlanarOrMinorBoyer (nnodes, nedges, edges, &nmedges, medges);
01042
01043 if (rval)
01044 goto CLEANUP;
01045
01046 for (i = 0; i < nmedges; i++)
01047 if (weight[medges[i]] < min)
01048 {
01049 min = weight[medges[i]];
01050 min_ind = medges[i];
01051 }
01052
01053 CLEANUP:
01054
01055 free (medges);
01056
01057 return min_ind;
01058
01059 }
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070 int DPfastEdgeEliminationHeuristic (int nnodes,
01071 int nedges1,
01072 int *edges,
01073 double *weight,
01074 int *nedges2,
01075 int *edges2,
01076 double *weight2,
01077 int *nelim,
01078 int *elim_indices,
01079 int k_param)
01080 {
01081
01082 int i,
01083 iswap,
01084 bad_edge;
01085
01086 int *indices = 0;
01087
01088 double dswap;
01089
01090 #if DISPLAY_MODE
01091 fprintf (stdout, "\rSEE: Simple Edge Elimination Heuristic.\n");
01092 fflush (stdout);
01093 #endif
01094
01095 *nelim = 0;
01096
01097 indices = (int *) malloc (sizeof (int) * nedges1);
01098
01099
01100
01101 *nedges2 = nedges1;
01102 for (i = 0; i < nedges1; i++)
01103 {
01104 edges2[2 * i] = edges[2 * i];
01105 edges2[2 * i + 1] = edges[2 * i + 1];
01106 weight2[i] = weight[i];
01107 indices[i] = i;
01108 }
01109
01110
01111
01112 bad_edge = DPfindBadEdgeK (nnodes, *nedges2, edges2, weight2, k_param);
01113
01114 while (bad_edge != -1)
01115 {
01116
01117 fprintf (stdout, "SEE: Remove edge (%6d %6d) [w = %lf]\n",
01118 edges2[2 * bad_edge], edges2[2 * bad_edge + 1], weight2[bad_edge]);
01119 fflush (stdout);
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129 elim_indices[*nelim] = indices[bad_edge];
01130 (*nelim) += 1;
01131
01132 iswap = indices[bad_edge];
01133 indices[bad_edge] = indices[*nedges2 - 1];
01134 indices[*nedges2 - 1] = iswap;
01135
01136 iswap = edges2[2 * bad_edge];
01137 edges2[2 * bad_edge] = edges2[2 * (*nedges2 - 1)];
01138 edges2[2 * (*nedges2 - 1)] = iswap;
01139
01140 iswap = edges2[2 * bad_edge + 1];
01141 edges2[2 * bad_edge + 1] = edges2[2 * (*nedges2 - 1) + 1];
01142 edges2[2 * (*nedges2 - 1) + 1] = iswap;
01143
01144 dswap = weight2[bad_edge];
01145 weight2[bad_edge] = weight2[*nedges2 - 1];
01146 weight2[*nedges2 - 1] = dswap;
01147
01148 (*nedges2) -= 1;
01149
01150 bad_edge = DPfindBadEdgeK (nnodes, *nedges2, edges2, weight2, k_param);
01151
01152 }
01153
01154 free (indices);
01155
01156 #if DISPLAY_MODE
01157 fprintf (stdout, "\rBIN: Eliminated %d edges.\n", *nelim);
01158 fprintf (stdout, "BIN: Completed planar sub-graph search.\n");
01159 fflush (stdout);
01160 #endif
01161
01162 return 0;
01163
01164 }
01165
01166 int DPfindBadBinEdge (int nnodes,
01167 int nedges,
01168 int *edges)
01169 {
01170
01171
01172 EGmemPool_t *mem;
01173 int ltop,
01174 lbottom,
01175 lmiddle;
01176 int is_G_planar_b,
01177 res = INT_MAX;
01178
01179
01180 mem = EGnewMemPool (8192, EGmemPoolNewSize, 4096);
01181 is_G_planar_b = isPlanarBoyer (nnodes, nedges, edges);
01182 if (is_G_planar_b)
01183 goto CLEANUP;
01184
01185
01186 ltop = nedges - 1;
01187 lbottom = 0;
01188 lmiddle = lbottom + (ltop - lbottom) / 2;
01189
01190 while (ltop != lbottom)
01191 {
01192
01193
01194 is_G_planar_b = isPlanarBoyer (nnodes, lmiddle + 1, edges);
01195
01196
01197 if (is_G_planar_b)
01198 lbottom = lmiddle + 1;
01199
01200
01201 else
01202 ltop = lmiddle;
01203
01204 lmiddle = lbottom + (ltop - lbottom) / 2;
01205
01206 }
01207
01208 is_G_planar_b = isPlanarBoyer (nnodes, lmiddle + 1, edges);
01209
01210
01211 if (lbottom < nedges)
01212 res = lbottom;
01213
01214
01215 CLEANUP:
01216 EGfreeMemPool (mem);
01217 return res;
01218 }
01219
01220 int DPfindBadBinEdgeK (int nnodes,
01221 int nedges,
01222 int *edges,
01223 double *weight,
01224 int k)
01225 {
01226
01227 int rval,
01228 bad_edge = -1;
01229 int who,
01230 nmedges = 0,
01231 *medges;
01232 double rvalue;
01233
01234 if (k == 1)
01235 return (DPfindBadEdge (nnodes, nedges, edges, weight));
01236 else if (k < 1)
01237 return -1;
01238
01239 medges = (int *) malloc (sizeof (int) * nedges);
01240
01241 rval = isPlanarBoyer (nnodes, nedges, edges);
01242
01243 if (rval)
01244 goto CLEANUP;
01245
01246 if (k > nedges)
01247 k = nedges;
01248
01249
01250 rval = DPgetBinMinor (nnodes, nedges, edges, &nmedges, medges, k);
01251 CHECKRVAL (rval);
01252
01253
01254
01255 rvalue = random ();
01256 rvalue /= EGRAND_MAX;
01257
01258 who = (int) (k * rvalue);
01259
01260 if (who == k)
01261 who = k - 1;
01262
01263 bad_edge = medges[who];
01264
01265 CLEANUP:
01266
01267 free (medges);
01268
01269 return bad_edge;
01270
01271 }
01272
01273 int DPgetBinMinor (int nnodes,
01274 int nedges,
01275 int *edges,
01276 int *nmedges,
01277 int *medges,
01278 int k)
01279 {
01280
01281
01282
01283 EGmemPool_t *mem;
01284 mem = EGnewMemPool (512, EGmemPoolNewSize, 4096);
01285
01286 int badedge = 0,
01287 *ledges,
01288 *lind,
01289 lnedges = nedges,
01290 itmp;
01291 register int i;
01292
01293
01294 *nmedges = 0;
01295 ledges = (int *) malloc (sizeof (int) * nedges * 2);
01296 lind = (int *) malloc (sizeof (int) * nedges);
01297 memcpy (ledges, edges, sizeof (int) * nedges * 2);
01298 for (i = nedges; i--;)
01299 lind[i] = i;
01300
01301 while ((*nmedges < lnedges) && (*nmedges < k))
01302 {
01303
01304
01305 badedge = DPfindBadBinEdge (nnodes, lnedges, ledges);
01306 if (badedge >= lnedges || badedge < *nmedges)
01307 break;
01308
01309
01310 itmp = ledges[badedge * 2];
01311 ledges[badedge * 2] = ledges[(*nmedges) * 2];
01312 ledges[(*nmedges) * 2] = itmp;
01313
01314
01315 itmp = ledges[badedge * 2 + 1];
01316 ledges[badedge * 2 + 1] = ledges[(*nmedges) * 2 + 1];
01317 ledges[(*nmedges) * 2 + 1] = itmp;
01318
01319
01320 medges[(*nmedges)] = lind[badedge];
01321
01322
01323 itmp = lind[*nmedges];
01324 lind[*nmedges] = lind[badedge];
01325 lind[badedge] = itmp;
01326
01327
01328 (*nmedges) += 1;
01329 lnedges = badedge + 1;
01330
01331 }
01332
01333
01334 EGfreeMemPool (mem);
01335 free (ledges);
01336 free (lind);
01337 return 0;
01338 }