00001 #include "eg_pdp.h"
00002
00003 static const size_t os[EG_MENGER_NUMOS] = {
00004 [EG_MENGER_PI] = offsetof (EGmengerNodeData_t, pi),
00005 [EG_MENGER_DIST] = offsetof (EGmengerNodeData_t, dist),
00006 [EG_MENGER_ORIG_DIST] = offsetof (EGmengerNodeData_t, orig_dist),
00007 [EG_MENGER_NDIST] = offsetof (EGmengerNodeData_t, ndist),
00008 [EG_MENGER_ORIG_NDIST] = offsetof (EGmengerNodeData_t, orig_ndist),
00009 [EG_MENGER_MARK] = offsetof (EGmengerNodeData_t, marker),
00010 [EG_MENGER_ORIG_MARK] = offsetof (EGmengerNodeData_t, orig_marker),
00011 [EG_MENGER_FATHER] = offsetof (EGmengerNodeData_t, father),
00012 [EG_MENGER_ORIG_FATHER] = offsetof (EGmengerNodeData_t, orig_father),
00013 [EG_MENGER_HEAP_CONNECTOR] = offsetof (EGmengerNodeData_t, hc),
00014 [EG_MENGER_ECOST] = offsetof (EGmengerEdgeData_t, cost),
00015 [EG_MENGER_REDUCED_ECOST] = offsetof (EGmengerEdgeData_t, reduced_cost),
00016 [EG_MENGER_IS_IN_SOL] = offsetof (EGmengerEdgeData_t, is_in_solution),
00017 [EG_MENGER_EDATA] = offsetof (EGmengerEdgeData_t, data)
00018 };
00019
00020 #define EGd2dGetEdge(dedge) ((graphNodeP)(\
00021 ((EGmengerEdgeData_t*)(((EGdGraphEdge_t*)(dedge))->data))->data ))
00022
00023
00024 #define EGd2dGetEdgeCost(dedge) (\
00025 ((EGmengerEdgeData_t*)(((EGdGraphEdge_t*)(dedge))->data))->cost)
00026
00027
00028
00029 #define EGddGetEdge(DOM,a,b) ((graphNodeP)(((DOM)->DDtype == DOM_CC_ONE) ? \
00030 (DOM)->path[a][b]:((EGmengerEdgeData_t*)(((EGdGraphEdge_t*)\
00031 ((DOM)->path[a][b]))->data))->data))
00032
00033
00034
00035 #define EGddPathGetEdge(dom,path,b) ((graphNodeP)((dom->DDtype == \
00036 DOM_DUAL_NORM) ? ((EGmengerEdgeData_t*)(((EGdGraphEdge_t*)\
00037 (path[b]))->data))->data : path[b]))
00038
00039
00040
00041 #define GETROOTEDGE(curroot, Graph) (Graph->G + Graph->G[curroot].link[1])
00042
00043
00044
00045 #define GETNEXTEDGE(curedge,curroot, Graph) ((curedge->link[1] < Graph->N) ? GETROOTEDGE(curroot,Graph) : (Graph->G + curedge->link[1]))
00046
00047
00048 #define GETOTHEREND(cedge,G) (G->G[gp_GetTwinArc(G,cedge - G->G)].v)
00049
00050
00051 static inline int getNextA (unsigned int *nextA,
00052 unsigned int curA,
00053 unsigned int frontier,
00054 unsigned int bounds[3][2])
00055 {
00056
00057 if (bounds[curA][0] == frontier)
00058 {
00059 *nextA = curA ? curA - 1 : 2;
00060 return 0;
00061 }
00062 if (bounds[curA][1] == frontier)
00063 {
00064 *nextA = curA == 2 ? 0 : curA + 1;
00065 return 0;
00066 }
00067 if (!bounds[curA][0])
00068 {
00069 bounds[curA][0] = frontier;
00070 bounds[curA ? curA - 1 : 2][1] = frontier;
00071 *nextA = curA ? curA - 1 : 2;
00072 return 0;
00073 }
00074 if (!bounds[curA][1])
00075 {
00076 bounds[curA][1] = frontier;
00077 bounds[curA == 2 ? 0 : curA + 1][0] = frontier;
00078 *nextA = curA == 2 ? 0 : curA + 1;
00079 return 0;
00080 }
00081 MESSAGE (0, "Found crossed paths");
00082 return 1;
00083
00084 }
00085
00086
00087 int EGfixDualDominos (EGlist_t * domino_list,
00088
00089 int nnodes,
00090
00091 int nedges,
00092
00093 double *weight,
00094
00095 int *edges,
00096
00097 int *elim_edges,
00098
00099 int nelim_edges,
00100
00101 graphP G,
00102
00103
00104 EGmemPool_t * mem)
00105 {
00106
00107 EGlistNode_t *dIt;
00108 unsigned char *primalMarks,
00109 *nodeMarks,
00110 *edgeMarks,
00111 pth;
00112 EGlist_t *Adfs[3];
00113 graphNodeP curEdge;
00114 int curNode;
00115 EGddomino_t *ddom;
00116 register unsigned int i,
00117 j;
00118 unsigned int curA = 0,
00119 bounds[3][2],
00120 nextA = 0;
00121 int rval;
00122
00123
00124 nodeMarks = EGmemPoolSMalloc (mem, unsigned char,
00125 nnodes);
00126 edgeMarks = EGmemPoolSMalloc (mem, unsigned char,
00127 nedges);
00128 primalMarks = EGmemPoolSMalloc (mem, unsigned char,
00129 nnodes);
00130 Adfs[0] = EGnewList (mem);
00131 Adfs[1] = EGnewList (mem);
00132 Adfs[2] = EGnewList (mem);
00133
00134
00135 for (dIt = domino_list->begin; dIt; dIt = dIt->next)
00136 {
00137 ddom = (EGddomino_t *) dIt->this;
00138 memset (edgeMarks, 0, sizeof (unsigned char) * nedges);
00139 memset (nodeMarks, 0, sizeof (unsigned char) * nnodes);
00140 memset (primalMarks, 0, sizeof (unsigned char) * nnodes);
00141 memset (bounds, 0, sizeof (bounds));
00142
00143
00144 for (pth = 0; pth < 3; pth++)
00145 {
00146 for (i = ddom->npath[pth]; i--;)
00147 {
00148 edgeMarks[(EGddGetEdge (ddom, pth, i)->id)] = 1 << pth;
00149 }
00150 }
00151
00152
00153
00154
00155 curNode = EGddGetEdge (ddom, 0, 0)->v;
00156 EGlistPushHead (Adfs[curA], (void *) curNode);
00157 MESSAGE (EGFDOM_LVL, "\nProcessing Domino %u", j);
00158 MESSAGE (EGFDOM_LVL, "Puting Node %d in Set %u", curNode, curA);
00159 while (Adfs[0]->size || Adfs[1]->size || Adfs[2]->size)
00160 {
00161 if (Adfs[0]->size)
00162 curA = 0;
00163 else if (Adfs[1]->size)
00164 curA = 1;
00165 else
00166 curA = 2;
00167 curNode = (int) (Adfs[curA]->begin->this);
00168 EGlistErase (Adfs[curA], Adfs[curA]->begin, nullFree);
00169 if (nodeMarks[curNode])
00170 continue;
00171 MESSAGE (EGFDOM_LVL, "Checking Node %d in Set %u", curNode, curA);
00172 nodeMarks[curNode] = 1 << (curA);
00173 primalMarks[curNode] = 1 << (curA);
00174 curEdge = GETROOTEDGE (curNode, G);
00175
00176 do
00177 {
00178
00179
00180 if (edgeMarks[curEdge->id] < 8)
00181 {
00182
00183
00184
00185 switch (edgeMarks[curEdge->id])
00186 {
00187 case 0:
00188 nextA = curA;
00189 break;
00190 case 1:
00191 case 2:
00192 case 4:
00193 rval = getNextA (&nextA, curA, edgeMarks[curEdge->id], bounds);
00194 CHECKRVAL (rval);
00195 break;
00196 default:
00197 EXIT (1, "This should not happen");
00198 }
00199
00200
00201 EGlistPushHead (Adfs[nextA], (void *) curEdge->v);
00202 MESSAGE (EGFDOM_LVL, "Puting Node %d in Set %u", curEdge->v, nextA);
00203
00204 edgeMarks[curEdge->id] = 8;
00205 }
00206 curEdge = GETNEXTEDGE (curEdge, curNode, G);
00207 } while (curEdge != GETROOTEDGE (curNode, G));
00208 }
00209 TEST (Adfs[0]->size, "Adfs[0] is not empty");
00210 TEST (Adfs[1]->size, "Adfs[1] is not empty");
00211 TEST (Adfs[2]->size, "Adfs[2] is not empty");
00212
00213
00214 ddom->primalValue = ddom->value;
00215 for (i = nelim_edges; i--;)
00216 {
00217 TESTL (1, edges[elim_edges[i] << 1] >= nnodes,
00218 "Accessing memory outside bounds");
00219 TESTL (1, edges[(elim_edges[i] << 1) | 1] >= nnodes,
00220 "Accessing memory outside bounds");
00221 if ((primalMarks[edges[elim_edges[i] << 1]] !=
00222 primalMarks[edges[(elim_edges[i] << 1) | 1]]))
00223 {
00224 ddom->primalValue =
00225 EGdijkstraCostAdd (ddom->primalValue,
00226 EGdijkstraToCost (weight[elim_edges[i]]));
00227 }
00228 }
00229
00230
00231
00232 if (EGdijkstraCostIsLess (ddom->primalValue, EGdijkstraToCost (1e-9)))
00233 {
00234 if (EGdijkstraCostIsLess
00235 (ddom->primalValue, EGdijkstraToCost (DP_RESET_VALUE)))
00236 {
00237 fprintf (stderr, "FIX_DDOM: WARNING! SEC constraints not satisfied.\n");
00238 fprintf (stderr, "FIX_DDOM: Found a 1-domino with value %lf.\n",
00239 EGdijkstraCostToLf (ddom->primalValue));
00240 fprintf (stderr,
00241 "FIX_DDOM: This means there exists at least one SEC violated by at least %lf.\n",
00242 (-2.0 * EGdijkstraCostToLf (ddom->primalValue)) / 3.0);
00243 fprintf (stderr,
00244 "FIX_DDOM: Setting this ddom to 0 (will introduce some errors).\n");
00245 fprintf (stderr,
00246 "FIX_DDOM: Error written to file \"ERROR_SEC.txt\".\n");
00247 FILE *efile;
00248 efile = fopen ("ERROR_SEC.txt", "a");
00249 fprintf (efile, "FIX_DDOM: WARNING! SEC constraints not satisfied.\n");
00250 fprintf (efile, "FIX_DDOM: Found a 1-domino with value %lf.\n",
00251 EGdijkstraCostToLf (ddom->primalValue));
00252 fprintf (efile,
00253 "FIX_DDOM: This means there exists at least one SEC violated by at least %lf.\n",
00254 (-2.0 * EGdijkstraCostToLf (ddom->primalValue)) / 3.0);
00255 fclose (efile);
00256 }
00257 ddom->primalValue = EGdijkstraToCost (1e-9);
00258 }
00259 }
00260
00261
00262 EGfreeList (Adfs[0]);
00263 EGfreeList (Adfs[1]);
00264 EGfreeList (Adfs[2]);
00265 EGmemPoolSFree (primalMarks, unsigned char,
00266 nnodes,
00267 mem);
00268 EGmemPoolSFree (nodeMarks, unsigned char,
00269 nnodes,
00270 mem);
00271 EGmemPoolSFree (edgeMarks, unsigned char,
00272 nedges,
00273 mem);
00274 return 0;
00275 }
00276
00277 #define DPU_GETID(edge,os) (EGmengerGetEdgeData(edge,os)->id)
00278
00279
00280
00281
00282 int EGuntangleAllDomino (EGlist_t * ddom_list,
00283 EGdGraph_t * dgraph,
00284 EGlist_t ** embed,
00285 EGmemPool_t * mem)
00286 {
00287
00288 int rval = 0;
00289 unsigned int i;
00290 unsigned int register j;
00291 EGlistNode_t *ddom_it;
00292 EGdGraphEdge_t *cur_edge;
00293 EGddomino_t *cur_ddom;
00294 unsigned char *node_marks = 0;
00295 unsigned char *edge_marks = 0;
00296 unsigned char is_tangled;
00297 void **path[3] = { 0, 0, 0 };
00298 unsigned int npath[4];
00299 unsigned int curpos[3];
00300 int nroot;
00301 unsigned int ecount;
00302 EGlistNode_t *eroot,
00303 *enexti,
00304 *enextii;
00305 EGlist_t *tangled_node = EGnewList (mem);
00306 int map[3],
00307 map2[3];
00308
00309 #warning ASSUMING DOMINO PATH ARE DIRECTED PATHS FROM S->T
00310 MESSAGE (0, "Untangle: untangling %u dual dominos", ddom_list->size);
00311 edge_marks = EGsMalloc (unsigned char,
00312 (dgraph->edge_id_max) >> 1);
00313 node_marks = EGsMalloc (unsigned char,
00314 dgraph->node_id_max);
00315
00316 for (ddom_it = ddom_list->begin; ddom_it; ddom_it = ddom_it->next)
00317 {
00318 MESSAGE (EGPDP_DBGLVL, "Checking domino %p", ddom_it->this);
00319 memset (node_marks, 0, sizeof (unsigned char) * dgraph->node_id_max);
00320 memset (edge_marks, 0,
00321 sizeof (unsigned char) * ((dgraph->edge_id_max) >> 1));
00322 cur_ddom = (EGddomino_t *) ddom_it->this;
00323 if ((cur_ddom->DDtype) != (DOM_DUAL_NORM))
00324 continue;
00325
00326 MESSAGE (EGPDP_DBGLVL, "domino %p s=%u t=%u", ddom_it->this,
00327 cur_ddom->s->id, cur_ddom->t->id);
00328 for (i = 3; i--;)
00329 {
00330 for (j = 0; j < cur_ddom->npath[i]; j++)
00331 {
00332 cur_edge = (EGdGraphEdge_t *) cur_ddom->path[i][j];
00333 node_marks[cur_edge->head->id]++;
00334 node_marks[cur_edge->tail->id]++;
00335 edge_marks[DPU_GETID (cur_edge, os)] |= 1U << i;
00336 MESSAGE (EGPDP_DBGLVL, "path %u edge %u(%u,%u) id %u(%u) mark %03o",
00337 i, j, cur_edge->tail->id, cur_edge->head->id,
00338 DPU_GETID (cur_edge, os), cur_edge->id,
00339 edge_marks[DPU_GETID (cur_edge, os)]);
00340 }
00341 }
00342
00343
00344 is_tangled = 0;
00345
00346 for (j = dgraph->node_id_max; j--;)
00347 {
00348
00349 if (j == cur_ddom->s->id)
00350 continue;
00351 if (j == cur_ddom->t->id)
00352 continue;
00353 if (node_marks[j] > 2)
00354 {
00355 TESTG ((rval = (node_marks[j] & 1U)), CLEANUP, "found an node with"
00356 " odd number of path touching it, this can't be");
00357 is_tangled = 1;
00358 break;
00359 }
00360 }
00361
00362 if (!is_tangled)
00363 goto SET_MIDDLE;
00364 MESSAGE (EGPDP_DBGLVL, "domino %p is tangled, untanglin it", ddom_it->this);
00365
00366
00367
00368 npath[3] = cur_ddom->npath[0] + cur_ddom->npath[1] + cur_ddom->npath[2];
00369 path[0] = EGmemPoolSMalloc (mem, void *,
00370 npath[3]);
00371 path[1] = EGmemPoolSMalloc (mem, void *,
00372 npath[3]);
00373 path[2] = EGmemPoolSMalloc (mem, void *,
00374 npath[3]);
00375 npath[0] = npath[1] = npath[2] = curpos[0] = curpos[1] = curpos[2] = 0;
00376
00377
00378 EGlistClear (tangled_node, nullFree);
00379 for (i = 3; i--;)
00380 {
00381 for (j = 0; j < cur_ddom->npath[i]; j++)
00382 {
00383 cur_edge = (EGdGraphEdge_t *) cur_ddom->path[i][curpos[i]];
00384 MESSAGE (EGPDP_DBGLVL, "id %3u original mark %03o",
00385 DPU_GETID (cur_edge, os),
00386 edge_marks[DPU_GETID (cur_edge, os)]);
00387 edge_marks[DPU_GETID (cur_edge, os)] |= 1 << (3 + i);
00388 edge_marks[DPU_GETID (cur_edge, os)] &= ~(1U << i);
00389 MESSAGE (EGPDP_DBGLVL, "id %3u final mark %03o",
00390 DPU_GETID (cur_edge, os),
00391 edge_marks[DPU_GETID (cur_edge, os)]);
00392 path[i][npath[i]++] = cur_edge;
00393 curpos[i]++;
00394 if (node_marks[cur_edge->head->id] > 2 && cur_edge->head != cur_ddom->t)
00395 {
00396 TESTG ((rval = (node_marks[cur_edge->head->id] & 1U)), CLEANUP,
00397 "found an node with odd number of path touching it, this "
00398 "can't be");
00399 EGlistPushBack (tangled_node, (void *) (cur_edge->head->id));
00400 break;
00401 }
00402 }
00403 }
00404
00405
00406
00407 while ((curpos[0] != cur_ddom->npath[0]) ||
00408 (curpos[1] != cur_ddom->npath[1]) ||
00409 (curpos[2] != cur_ddom->npath[2]))
00410 {
00411
00412
00413 NEXT_NODE:
00414 MESSAGE (EGPDP_DBGLVL, "tangled nodes remaining: %u", tangled_node->size);
00415 TESTG ((rval = !(tangled_node->size)), CLEANUP, "no more tangled nodes "
00416 "in list but haven't finish covering the paths of the domino");
00417 nroot = (size_t) tangled_node->begin->this;
00418 EGlistErase (tangled_node, tangled_node->begin, nullFree);
00419
00420 ecount = node_marks[nroot];
00421 eroot = EGclistRoot (embed[nroot]);
00422 enexti = eroot;
00423 MESSAGE (EGPDP_DBGLVL, "checking if tangled node %d is balanced", nroot);
00424 do
00425 {
00426 if (edge_marks[(size_t) enexti->this] > 7)
00427 ecount--;
00428 enexti = EGclistGetNextIt (embed[nroot], enexti);
00429 MESSAGE (EGPDP_DBGLVL, "checking edge: %u mark %03o",
00430 (unsigned) enexti->this, edge_marks[(size_t) enexti->this]);
00431 } while (enexti != eroot);
00432 MESSAGE (EGPDP_DBGLVL, "paths:%u edges:%u", node_marks[nroot] - ecount,
00433 node_marks[nroot]);
00434
00435 if (ecount << 1 != node_marks[nroot])
00436 goto NEXT_NODE;
00437
00438 TESTG (ecount > 3, CLEANUP, "more than three paths touch this node!");
00439
00440
00441
00442 MESSAGE (EGPDP_DBGLVL, "Looking for eroot");
00443 eroot = EGclistRoot (embed[nroot]);
00444 enexti = eroot;
00445 do
00446 {
00447 ecount = (node_marks[nroot] >> 1);
00448 enextii = enexti;
00449 if (edge_marks[(size_t) enexti->this])
00450 {
00451 do
00452 {
00453 MESSAGE (EGPDP_DBGLVL, "looking edges %u %u %u edge_marks %u",
00454 (unsigned) eroot->this, (unsigned) enexti->this,
00455 (unsigned) enextii->this,
00456 edge_marks[(size_t) enextii->this]);
00457 if (edge_marks[(size_t) enextii->this])
00458 {
00459 if (edge_marks[(size_t) enextii->this] < 8)
00460 break;
00461 ecount--;
00462 }
00463 if (!ecount)
00464 break;
00465 enextii = EGclistGetNextIt (embed[nroot], enextii);
00466 } while (enextii != enexti);
00467 if (!ecount)
00468 break;
00469 }
00470 enexti = EGclistGetNextIt (embed[nroot], enexti);
00471 } while (enexti != eroot);
00472 TESTG (ecount, CLEANUP, "this should not happen (or may?)");
00473 eroot = enexti;
00474 MESSAGE (EGPDP_DBGLVL, "eroot is edge %u", (unsigned) eroot->this);
00475
00476 map[0] = map[1] = map[2] = 3;
00477 map2[0] = map2[1] = map2[2] = 3;
00478
00479 MESSAGE (EGPDP_DBGLVL, "looking for local map");
00480 ecount = node_marks[nroot] >> 1;
00481 for (enexti = eroot, i = 0;
00482 i < ecount; enexti = EGclistGetNextIt (embed[nroot], enexti))
00483 {
00484 MESSAGE (EGPDP_DBGLVL, "edge %3u mark %03o", (unsigned) enexti->this,
00485 edge_marks[(size_t) enexti->this]);
00486 if (edge_marks[(size_t) enexti->this])
00487 {
00488 TESTG ((rval = edge_marks[(size_t) enexti->this] < 8), CLEANUP,
00489 "this should not happen");
00490 map2[i++] = edge_marks[(size_t) enexti->this] >> 4;
00491 }
00492 }
00493 MESSAGE (EGPDP_DBGLVL, "map2[0]=%d map2[1]=%d map2[2]=%d i=%u", map2[0],
00494 map2[1], map2[2], i);
00495 for (; i; enexti = EGclistGetNextIt (embed[nroot], enexti))
00496 {
00497 MESSAGE (EGPDP_DBGLVL, "edge %3u mark %03o", (unsigned) enexti->this,
00498 edge_marks[(size_t) enexti->this]);
00499 if (edge_marks[(size_t) enexti->this])
00500 {
00501 TESTG ((rval = edge_marks[(size_t) enexti->this] > 7), CLEANUP,
00502 "this should not happen");
00503 map[map2[--i]] = edge_marks[(size_t) enexti->this] >> 1;
00504 }
00505 }
00506 MESSAGE (EGPDP_DBGLVL, "map[0]=%d map[1]=%d map[2]=%d i=%u", map[0],
00507 map[1], map[2], i);
00508
00509
00510 for (i = 3; i--;)
00511 {
00512
00513
00514
00515 if (map[i] > 2)
00516 continue;
00517 for (j = curpos[map[i]]; j < cur_ddom->npath[map[i]]; j++)
00518 {
00519 cur_edge = (EGdGraphEdge_t *) cur_ddom->path[map[i]][curpos[map[i]]];
00520 edge_marks[DPU_GETID (cur_edge, os)] |= 1 << (3 + i);
00521 edge_marks[DPU_GETID (cur_edge, os)] &= ~(1U << map[i]);
00522 path[i][npath[i]++] = cur_edge;
00523 curpos[map[i]]++;
00524 if (node_marks[cur_edge->head->id] > 2
00525 && cur_edge->head != cur_ddom->t)
00526 {
00527 TESTG ((rval = (node_marks[cur_edge->head->id] & 1U) &&
00528 (cur_edge->head != cur_ddom->t)), CLEANUP,
00529 "found an node with odd number of path touching it, this"
00530 " can't be");
00531 EGlistPushBack (tangled_node, (void *) (cur_edge->head->id));
00532 break;
00533 }
00534 }
00535 }
00536 }
00537
00538
00539 MESSAGE (EGPDP_DBGLVL, "saving new paths");
00540 EGmemPoolSFree (cur_ddom->path[0], void *,
00541 cur_ddom->npath[0],
00542 mem);
00543 EGmemPoolSFree (cur_ddom->path[1], void *,
00544 cur_ddom->npath[1],
00545 mem);
00546 EGmemPoolSFree (cur_ddom->path[2], void *,
00547 cur_ddom->npath[2],
00548 mem);
00549 cur_ddom->path[0] = EGmemPoolSMalloc (mem, void *,
00550 npath[0]);
00551 cur_ddom->path[1] = EGmemPoolSMalloc (mem, void *,
00552 npath[1]);
00553 cur_ddom->path[2] = EGmemPoolSMalloc (mem, void *,
00554 npath[2]);
00555 memcpy (cur_ddom->path[0], path[0], sizeof (void *) * npath[0]);
00556 memcpy (cur_ddom->path[1], path[1], sizeof (void *) * npath[1]);
00557 memcpy (cur_ddom->path[2], path[2], sizeof (void *) * npath[2]);
00558 EGmemPoolSFree (path[0], void *,
00559 npath[3],
00560 mem);
00561 EGmemPoolSFree (path[1], void *,
00562 npath[3],
00563 mem);
00564 EGmemPoolSFree (path[2], void *,
00565 npath[3],
00566 mem);
00567 cur_ddom->npath[0] = npath[0];
00568 cur_ddom->npath[1] = npath[1];
00569 cur_ddom->npath[2] = npath[2];
00570
00571 SET_MIDDLE:
00572
00573 map[0] = 0;
00574 map[1] = 1;
00575 map[2] = 2;
00576 MESSAGE (EGPDP_DBGLVL, "setting middle path");
00577 #if DP_CHOOSE_MIDDLE == DP_LONGEST
00578 if (cur_ddom->npath[0] > cur_ddom->npath[1])
00579 {
00580 npath[1] = cur_ddom->npath[1];
00581 cur_ddom->npath[1] = cur_ddom->npath[0];
00582 cur_ddom->npath[0] = npath[1];
00583 path[1] = cur_ddom->path[1];
00584 cur_ddom->path[1] = cur_ddom->path[0];
00585 cur_ddom->path[0] = path[1];
00586 }
00587 if (cur_ddom->npath[2] > cur_ddom->npath[1])
00588 {
00589 npath[1] = cur_ddom->npath[1];
00590 cur_ddom->npath[1] = cur_ddom->npath[2];
00591 cur_ddom->npath[2] = npath[1];
00592 path[1] = cur_ddom->path[1];
00593 cur_ddom->path[1] = cur_ddom->path[2];
00594 cur_ddom->path[2] = path[1];
00595 }
00596 #elif DP_CHOOSE_MIDDLE == DP_SHORTEST
00597 if (cur_ddom->npath[0] < cur_ddom->npath[1])
00598 {
00599 npath[1] = cur_ddom->npath[1];
00600 cur_ddom->npath[1] = cur_ddom->npath[0];
00601 cur_ddom->npath[0] = npath[1];
00602 path[1] = cur_ddom->path[1];
00603 cur_ddom->path[1] = cur_ddom->path[0];
00604 cur_ddom->path[0] = path[1];
00605 }
00606 if (cur_ddom->npath[2] < cur_ddom->npath[1])
00607 {
00608 npath[1] = cur_ddom->npath[1];
00609 cur_ddom->npath[1] = cur_ddom->npath[2];
00610 cur_ddom->npath[2] = npath[1];
00611 path[1] = cur_ddom->path[1];
00612 cur_ddom->path[1] = cur_ddom->path[2];
00613 cur_ddom->path[2] = path[1];
00614 }
00615 #elif DP_CHOOSE_MIDDLE == DP_LIGHTEST
00616 {
00617 EGdijkstraCost_t vpath[3];
00618 vpath[0] = EGdijkstraToCost (0.0);
00619 vpath[1] = EGdijkstraToCost (0.0);
00620 vpath[2] = EGdijkstraToCost (0.0);
00621 for (j = cur_ddom->npath[0]; j--;)
00622 vpath[0] =
00623 EGdijkstraCostAdd (vpath[0],
00624 EGmengerGetEdgeCost (cur_ddom->path[0][j]));
00625 for (j = cur_ddom->npath[1]; j--;)
00626 vpath[1] =
00627 EGdijkstraCostAdd (vpath[1],
00628 EGmengerGetEdgeCost (cur_ddom->path[1][j]));
00629 for (j = cur_ddom->npath[2]; j--;)
00630 vpath[2] =
00631 EGdijkstraCostAdd (vpath[2],
00632 EGmengerGetEdgeCost (cur_ddom->path[2][j]));
00633 if (vpath[0] < vpath[1])
00634 {
00635 npath[1] = cur_ddom->npath[1];
00636 cur_ddom->npath[1] = cur_ddom->npath[0];
00637 cur_ddom->npath[0] = npath[1];
00638 path[1] = cur_ddom->path[1];
00639 cur_ddom->path[1] = cur_ddom->path[0];
00640 cur_ddom->path[0] = path[1];
00641 }
00642 if (vpath[2] < vpath[1])
00643 {
00644 npath[1] = cur_ddom->npath[1];
00645 cur_ddom->npath[1] = cur_ddom->npath[2];
00646 cur_ddom->npath[2] = npath[1];
00647 path[1] = cur_ddom->path[1];
00648 cur_ddom->path[1] = cur_ddom->path[2];
00649 cur_ddom->path[2] = path[1];
00650 }
00651 }
00652 #elif DP_CHOOSE_MIDDLE == DP_HEVIEST
00653 {
00654 EGdijkstraCost_t vpath[3];
00655 vpath[0] = EGdijkstraToCost (0.0);
00656 vpath[1] = EGdijkstraToCost (0.0);
00657 vpath[2] = EGdijkstraToCost (0.0);
00658 for (j = cur_ddom->npath[0]; j--;)
00659 vpath[0] =
00660 EGdijkstraCostAdd (vpath[0],
00661 EGmengerGetEdgeCost (cur_ddom->path[0][j]));
00662 for (j = cur_ddom->npath[1]; j--;)
00663 vpath[1] =
00664 EGdijkstraCostAdd (vpath[1],
00665 EGmengerGetEdgeCost (cur_ddom->path[1][j]));
00666 for (j = cur_ddom->npath[2]; j--;)
00667 vpath[2] =
00668 EGdijkstraCostAdd (vpath[2],
00669 EGmengerGetEdgeCost (cur_ddom->path[2][j]));
00670 if (vpath[0] > vpath[1])
00671 {
00672 npath[1] = cur_ddom->npath[1];
00673 cur_ddom->npath[1] = cur_ddom->npath[0];
00674 cur_ddom->npath[0] = npath[1];
00675 path[1] = cur_ddom->path[1];
00676 cur_ddom->path[1] = cur_ddom->path[0];
00677 cur_ddom->path[0] = path[1];
00678 }
00679 if (vpath[2] > vpath[1])
00680 {
00681 npath[1] = cur_ddom->npath[1];
00682 cur_ddom->npath[1] = cur_ddom->npath[2];
00683 cur_ddom->npath[2] = npath[1];
00684 path[1] = cur_ddom->path[1];
00685 cur_ddom->path[1] = cur_ddom->path[2];
00686 cur_ddom->path[2] = path[1];
00687 }
00688 }
00689 #else
00690 #error DP_CHOOSE_MIDDLE Mmust be either DP_LONGEST DP_SHORTEST DP_LIGHTEST or DP_HEVIEST
00691 #endif
00692 }
00693
00694
00695 CLEANUP:
00696 if (edge_marks)
00697 EGfree (edge_marks);
00698 if (node_marks)
00699 EGfree (node_marks);
00700 if (tangled_node)
00701 EGfreeList (tangled_node);
00702 MESSAGE (0, "Untangle: done");
00703 return rval;
00704
00705 }
00706
00707 int EGgetPrimalDP (EGddpConstraint_t * ddp,
00708
00709 int nnodes,
00710
00711 int nedges,
00712
00713 int *const edges,
00714
00715 int *const elim_edges,
00716
00717 int nelim_edges,
00718
00719 double *const weight,
00720
00721 int *const ndom,
00722
00723 int **const nAset,
00724
00725 int **const nBset,
00726
00727 int *const nHandle,
00728
00729 int ***const Aset,
00730
00731 int ***const Bset,
00732
00733 int **const Handle,
00734
00735 double *const violation,
00736
00737 graphP G,
00738
00739
00740 EGmemPool_t * const mem)
00741 {
00742
00743
00744 unsigned char *primalMarks,
00745 *nodeMarks,
00746 *edgeMarks,
00747 *nodeOld,
00748 *edgeOld,
00749 mA,
00750 mB,
00751 pth;
00752 const int topMark = INT_MAX | 1;
00753 int rval,
00754 curNode;
00755 register int j,
00756 k;
00757 unsigned int *elimMarks = 0,
00758 bounds[3][2],
00759 curA = 0,
00760 nextA = 0,
00761 nABedges,
00762 npt;
00763 void **ABedges = 0;
00764 graphNodeP curEdge,
00765 ep1,
00766 ep2,
00767 ep3;
00768 EGddomino_t *ddom;
00769 EGlistNode_t *lIt;
00770 EGlist_t *Hlist[2],
00771 *H,
00772 *Alist[3],
00773 *Adfs[3],
00774 *HdfsList[2],
00775 *fA,
00776 *fB;
00777 EGdijkstraCost_t p_cost[3] = { EGdijkstraToCost (0), EGdijkstraToCost (0),
00778 EGdijkstraToCost (0)
00779 };
00780
00781
00782 TEST (!ddp, "This shouldn't happen");
00783 TEST (!edges, "This shouldn't happen");
00784 TEST (!weight, "This shouldn't happen");
00785 TEST (!ndom, "This shouldn't happen");
00786 TEST (!nAset, "This shouldn't happen");
00787 TEST (!nBset, "This shouldn't happen");
00788 TEST (!nHandle, "This shouldn't happen");
00789 TEST (!violation, "This shouldn't happen");
00790 TEST (!Aset, "This shouldn't happen");
00791 TEST (!Bset, "This shouldn't happen");
00792 TEST (!Handle, "This shouldn't happen");
00793
00794
00795 HdfsList[1] = EGnewList (mem);
00796 HdfsList[0] = EGnewList (mem);
00797 Hlist[1] = EGnewList (mem);
00798 Hlist[0] = EGnewList (mem);
00799 Alist[0] = EGnewList (mem);
00800 Alist[1] = EGnewList (mem);
00801 Alist[2] = EGnewList (mem);
00802 Adfs[0] = EGnewList (mem);
00803 Adfs[1] = EGnewList (mem);
00804 Adfs[2] = EGnewList (mem);
00805 nodeMarks = EGmemPoolSMalloc (mem, unsigned char,
00806 nnodes);
00807 edgeMarks = EGmemPoolSMalloc (mem, unsigned char,
00808 nedges);
00809 primalMarks = EGmemPoolSMalloc (mem, unsigned char,
00810 nnodes);
00811 memset (primalMarks, 0, sizeof (unsigned char) * nnodes);
00812 if (nelim_edges)
00813 {
00814 elimMarks = EGmemPoolSMalloc (mem, unsigned,
00815 nelim_edges);
00816 memset (elimMarks, 0, sizeof (unsigned int) * nelim_edges);
00817 }
00818
00819
00820 TEST (ddp->ndom < 1, "no dominos");
00821 *ndom = ddp->ndom;
00822 *Bset = EGsMalloc (int *,
00823 ddp->ndom);
00824 *Aset = EGsMalloc (int *,
00825 ddp->ndom);
00826 *nAset = EGsMalloc (int,
00827 ddp->ndom);
00828 *nBset = EGsMalloc (int,
00829 ddp->ndom);
00830
00831
00832 *violation = 0;
00833
00834
00835
00836 nodeOld = EGmemPoolSMalloc (mem, unsigned char,
00837 nnodes);
00838 edgeOld = EGmemPoolSMalloc (mem, unsigned char,
00839 nedges);
00840 memset (nodeOld, 0, sizeof (unsigned char) * nnodes);
00841 memset (edgeOld, 0, sizeof (unsigned char) * nedges);
00842
00843
00844 for (k = ddp->nF; k--;)
00845 {
00846 TESTL (1, ((graphNodeP) (((EGmengerEdgeData_t *)
00847 (ddp->F[k]->data))->data))->id >= nedges,
00848 "Accessing memory outside bounds");
00849 edgeOld[((graphNodeP) (((EGmengerEdgeData_t *)
00850 (ddp->F[k]->data))->data))->id] += 1;
00851 *violation +=
00852 EGdijkstraCostToLf (((EGmengerEdgeData_t *) (ddp->F[k]->data))->cost);
00853 }
00854
00855
00856 for (j = ddp->ndom; j--;)
00857 {
00858 ddom = ddp->ddom[j];
00859 *violation += EGdijkstraCostToLf (ddom->primalValue);
00860
00861
00862 memset (nodeMarks, 0, sizeof (unsigned char) * nnodes);
00863 memset (edgeMarks, 0, sizeof (unsigned char) * nedges);
00864 memset (bounds, 0, sizeof (bounds));
00865 p_cost[0] = EGdijkstraToCost (0);
00866 p_cost[1] = EGdijkstraToCost (0);
00867 p_cost[2] = EGdijkstraToCost (0);
00868
00869
00870 for (pth = 3; pth--;)
00871 {
00872 for (k = ddom->npath[pth]; k--;)
00873 {
00874 edgeMarks[EGddGetEdge (ddom, pth, k)->id] = 1 << pth;
00875 p_cost[pth] = EGdijkstraCostAdd (p_cost[pth],
00876 EGd2dGetEdgeCost (ddom->path[pth][k]));
00877
00878 }
00879 }
00880
00881
00882 curNode = EGddGetEdge (ddom, 0, 0)->v;
00883 curA = 0;
00884 EGlistPushHead (Adfs[curA], (void *) curNode);
00885 MESSAGE (EGFDOM_LVL, "\nProcessing Domino %u", j);
00886 MESSAGE (EGFDOM_LVL, "Puting Node %d in Set %u", curNode, curA);
00887 while (Adfs[0]->size || Adfs[1]->size || Adfs[2]->size)
00888 {
00889 if (Adfs[0]->size)
00890 curA = 0;
00891 else if (Adfs[1]->size)
00892 curA = 1;
00893 else
00894 curA = 2;
00895 curNode = (int) (Adfs[curA]->begin->this);
00896 EGlistErase (Adfs[curA], Adfs[curA]->begin, nullFree);
00897 if (nodeMarks[curNode])
00898 continue;
00899 MESSAGE (EGFDOM_LVL, "Checking Node %d in Set %u", curNode, curA);
00900 EGlistPushBack (Alist[curA], (void *) curNode);
00901 nodeMarks[curNode] = 1 << (curA);
00902 primalMarks[curNode] = 1 << (curA);
00903 curEdge = GETROOTEDGE (curNode, G);
00904
00905 do
00906 {
00907
00908
00909 if (edgeMarks[curEdge->id] < 8)
00910 {
00911
00912
00913
00914 switch (edgeMarks[curEdge->id])
00915 {
00916 case 0:
00917 nextA = curA;
00918 break;
00919 case 1:
00920 case 2:
00921 case 4:
00922 rval = getNextA (&nextA, curA, edgeMarks[curEdge->id], bounds);
00923 CHECKRVAL (rval);
00924 break;
00925 default:
00926 EXIT (1, "This should not happen");
00927 }
00928
00929
00930 EGlistPushHead (Adfs[nextA], (void *) curEdge->v);
00931 MESSAGE (EGFDOM_LVL, "Puting Node %d in Set %u", curEdge->v, nextA);
00932
00933 edgeMarks[curEdge->id] = 8;
00934 }
00935 curEdge = GETNEXTEDGE (curEdge, curNode, G);
00936 } while (curEdge != GETROOTEDGE (curNode, G));
00937 }
00938 TEST (Adfs[0]->size, "Adfs[0] is not empty");
00939 TEST (Adfs[1]->size, "Adfs[1] is not empty");
00940 TEST (Adfs[2]->size, "Adfs[2] is not empty");
00941 TEST (!Alist[0]->size, "Aset[0] is empty");
00942 TEST (!Alist[1]->size, "Aset[1] is empty");
00943 TEST (!Alist[2]->size, "Aset[2] is empty");
00944
00945
00946 ep1 = EGddGetEdge (ddom, 0, 0);
00947 ep2 = EGddGetEdge (ddom, 1, 0);
00948 ep3 = EGddGetEdge (ddom, 2, 0);
00949
00950
00951
00952
00953
00954 if (EGdijkstraCostIsLess (p_cost[0], p_cost[1]) &&
00955 EGdijkstraCostIsLess (p_cost[0], p_cost[2]))
00956 {
00957 mA = nodeMarks[ep1->v];
00958 mB = nodeMarks[GETOTHEREND (ep1, G)];
00959 ABedges = ddom->path[0];
00960 nABedges = ddom->npath[0];
00961 }
00962 else if (EGdijkstraCostIsLess (p_cost[1], p_cost[0]) &&
00963 EGdijkstraCostIsLess (p_cost[1], p_cost[2]))
00964 {
00965 mA = nodeMarks[ep2->v];
00966 mB = nodeMarks[GETOTHEREND (ep2, G)];
00967 ABedges = ddom->path[1];
00968 nABedges = ddom->npath[1];
00969 }
00970 else
00971 {
00972 mA = nodeMarks[ep3->v];
00973 mB = nodeMarks[GETOTHEREND (ep3, G)];
00974 ABedges = ddom->path[2];
00975 nABedges = ddom->npath[2];
00976 }
00977 fA = Alist[mA / 2];
00978 fB = Alist[mB / 2];
00979 TEST (nABedges == 0, "one domino path has zero length");
00980
00981
00982 for (k = nelim_edges; k--;)
00983 {
00984 TESTL (1, edges[elim_edges[k] << 1] >= nnodes,
00985 "Accessing memory outside bounds");
00986 TESTL (1, edges[(elim_edges[k] << 1) | 1] >= nnodes,
00987 "Accessing memory outside bounds");
00988 if (primalMarks[edges[elim_edges[k] << 1]] +
00989 primalMarks[edges[(elim_edges[k] << 1) | 1]] == mA + mB)
00990 elimMarks[k]++;
00991 }
00992
00993
00994 (*nAset)[j] = fA->size;
00995 (*nBset)[j] = fB->size;
00996 (*Aset)[j] = EGsMalloc (int,
00997 fA->size);
00998 (*Bset)[j] = EGsMalloc (int,
00999 fB->size);
01000
01001 for (lIt = fA->begin, k = 0; lIt; lIt = lIt->next, k++)
01002 (*Aset)[j][k] = (int) (lIt->this);
01003
01004 for (lIt = fB->begin, k = 0; lIt; lIt = lIt->next, k++)
01005 (*Bset)[j][k] = (int) (lIt->this);
01006
01007
01008 for (k = nABedges; k--;)
01009 {
01010 edgeOld[EGddPathGetEdge (ddom, ABedges, k)->id] += 1;
01011 }
01012
01013
01014 EGlistClear (Alist[0], nullFree);
01015 EGlistClear (Alist[1], nullFree);
01016 EGlistClear (Alist[2], nullFree);
01017 }
01018
01019
01020
01021 npt = 0;
01022 EGlistPushHead (HdfsList[npt & 1], (void *) 0);
01023 while (HdfsList[0]->size || HdfsList[1]->size)
01024 {
01025
01026 if (!(HdfsList[npt & 1]->size))
01027 npt++;
01028 curNode = ((int) (HdfsList[npt & 1]->begin->this));
01029 EGlistErase (HdfsList[npt & 1], HdfsList[npt & 1]->begin, nullFree);
01030 if (nodeOld[curNode])
01031 continue;
01032 EGlistPushBack (Hlist[npt & 1], (void *) curNode);
01033 nodeOld[curNode] = npt + 1;
01034 TESTL (1, curNode >= nnodes, "Accessing memory outside bounds");
01035 primalMarks[curNode] = npt + 1;
01036 curEdge = GETROOTEDGE (curNode, G);
01037 do
01038 {
01039
01040 TESTL (1, curEdge->id >= nedges, "Accessing memory outside bounds");
01041 if (!(edgeOld[curEdge->id] & 1))
01042 {
01043
01044 EGlistPushHead (HdfsList[npt & 1], (void *) curEdge->v);
01045 TESTL (1, curEdge->id >= nedges, "Accessing memory outside bounds");
01046 edgeOld[curEdge->id] = topMark;
01047 }
01048
01049
01050 else if (edgeOld[curEdge->id] < topMark)
01051 {
01052 EGlistPushHead (HdfsList[(npt + 1) & 1], (void *) curEdge->v);
01053 }
01054 curEdge = GETNEXTEDGE (curEdge, curNode, G);
01055 } while (curEdge != GETROOTEDGE (curNode, G));
01056 }
01057 EXIT (Hlist[0]->size + Hlist[1]->size != (unsigned) nnodes,
01058 "The primal graph is not connected.");
01059
01060
01061 for (k = nelim_edges; k--;)
01062 {
01063 TESTL (1, edges[elim_edges[k] << 1] >= nnodes,
01064 "Accessing memory outside bounds");
01065 TESTL (1, edges[(elim_edges[k] << 1) | 1] >= nnodes,
01066 "Accessing memory outside bounds");
01067 if (((primalMarks[edges[elim_edges[k] << 1]]) & 1) !=
01068 ((primalMarks[edges[(elim_edges[k] << 1) | 1]]) & 1))
01069 elimMarks[k]++;
01070 if (elimMarks[k] & 1)
01071 *violation += weight[elim_edges[k]];
01072 }
01073
01074
01075 *violation -= 1;
01076
01077
01078
01079 H = (Hlist[0]->size < Hlist[1]->size) ? Hlist[0] : Hlist[1];
01080 *nHandle = H->size;
01081 if (H->size)
01082 *Handle = EGsMalloc (int,
01083 H->size);
01084 for (lIt = H->begin, k = 0; lIt; lIt = lIt->next, k++)
01085 (*Handle)[k] = (int) (lIt->this);
01086
01087
01088 EGmemPoolSFree (primalMarks, unsigned char,
01089 nnodes,
01090 mem);
01091 EGmemPoolSFree (nodeOld, unsigned char,
01092 nnodes,
01093 mem);
01094 EGmemPoolSFree (nodeMarks, unsigned char,
01095 nnodes,
01096 mem);
01097 EGmemPoolSFree (edgeOld, unsigned char,
01098 nedges,
01099 mem);
01100 EGmemPoolSFree (edgeMarks, unsigned char,
01101 nedges,
01102 mem);
01103 if (nelim_edges)
01104 EGmemPoolSFree (elimMarks, unsigned int,
01105 nelim_edges,
01106 mem);
01107 EGfreeList (Alist[0]);
01108 EGfreeList (Alist[1]);
01109 EGfreeList (Alist[2]);
01110 EGfreeList (HdfsList[0]);
01111 EGfreeList (HdfsList[1]);
01112 EGfreeList (Hlist[0]);
01113 EGfreeList (Hlist[1]);
01114 EGfreeList (Adfs[0]);
01115 EGfreeList (Adfs[1]);
01116 EGfreeList (Adfs[2]);
01117 return 0;
01118 }