eg_pdp.c

Go to the documentation of this file.
00001 #include "eg_pdp.h"
00002 /* offsets for EGmengerEdgeData_t */
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 /* this macro return the 'edge' ponter asociated to the dual arc 'dedge' */
00020 #define EGd2dGetEdge(dedge) ((graphNodeP)(\
00021     ((EGmengerEdgeData_t*)(((EGdGraphEdge_t*)(dedge))->data))->data ))
00022 
00023 /* this macro return the dijksra cost of a dual edge */
00024 #define EGd2dGetEdgeCost(dedge) (\
00025     ((EGmengerEdgeData_t*)(((EGdGraphEdge_t*)(dedge))->data))->cost)
00026 /* this macro return the 'edge' ponter asociated to the 'b'-th arc in path 'a'
00027  * of the domino 'dom'. It takes care of different types of dominos in an easy
00028  * form */
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 /* given a ddom->path[i] array, a domino, and an index, return the edge pointer
00034  * asociated with that arc (taking care of the type of the domino ) */
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 /* return the first edge in the embeding list of a boyer's graph for node
00040  * 'curroot' */
00041 #define GETROOTEDGE(curroot, Graph) (Graph->G + Graph->G[curroot].link[1])
00042 
00043 /* return the next edge (cyclic) after 'curedge' in the embeding of a boyer's
00044  * graph for node 'nroot' */
00045 #define GETNEXTEDGE(curedge,curroot, Graph) ((curedge->link[1] < Graph->N) ? GETROOTEDGE(curroot,Graph) : (Graph->G + curedge->link[1]))
00046 
00047 /* return the other end-pint of an edge (in boyer's graph format */
00048 #define GETOTHEREND(cedge,G) (G->G[gp_GetTwinArc(G,cedge - G->G)].v)
00049 
00050 /* static functions and types */
00051 static inline int getNextA (unsigned int *nextA,
00052                             unsigned int curA,
00053                             unsigned int frontier,
00054                             unsigned int bounds[3][2])
00055 {
00056   /* if the borders haven't yet been set, we set them */
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 /* fix the value of the dual dominos */
00087 int EGfixDualDominos (EGlist_t * domino_list, /* dual dominos to be fixed */
00088 
00089                       int nnodes, /* number of nodes in primal graph */
00090 
00091                       int nedges, /* number of edges in primal graph */
00092 
00093                       double *weight, /* weight of all non small edges */
00094 
00095                       int *edges, /* non small edges in cook's format */
00096 
00097                       int *elim_edges,  /* index of eliminated edges */
00098 
00099                       int nelim_edges,  /* size of the array elim_edges */
00100 
00101                       graphP G, /* pointer to the dual graph in 
00102                                  * boyer's format */
00103 
00104                       EGmemPool_t * mem)  /* memory pool */
00105 {
00106   /* local variables */
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   /* looking for memory */
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   /* loop through all dominos */
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     /* mark all edges in the paths to powers of two */
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       }                         /* end for edges in path[pth] */
00150     }                           /* end loop through paths */
00151 
00152     /* up to this point all edges in the paths are marked 1,2 and 4
00153      * respectivelly, all other edges are zero */
00154     /* compute A_1, A_2, A_3 */
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       /* loop through the neighbours of the node */
00176       do
00177       {
00178         /* if edgemarks >=8 then is a traversed edge in the DFS and thus we can
00179          * discard it and keep going. */
00180         if (edgeMarks[curEdge->id] < 8)
00181         {
00182           /* the edge has no marks, then the node go to the current DFSlist, if
00183            * the edge has values 1,2 or 4, this implies that we are doing a
00184            * change of set */
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           /* acording to the end we put the other end in the corespondig DFS
00200            * list */
00201           EGlistPushHead (Adfs[nextA], (void *) curEdge->v);
00202           MESSAGE (EGFDOM_LVL, "Puting Node %d in Set %u", curEdge->v, nextA);
00203           /* set the edge as traversed */
00204           edgeMarks[curEdge->id] = 8;
00205         }
00206         curEdge = GETNEXTEDGE (curEdge, curNode, G);
00207       } while (curEdge != GETROOTEDGE (curNode, G));
00208     }                           /* end DFS */
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     /* now we start computing the corrected value of the domino */
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     }                           /* end for i */
00229     /* now we check that the price of the 2-Pie is not bellow the threshold, if
00230      * so we set it to the reset value. This is to avoid problems solving the
00231      * master problem */
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   }                             /* end for ddominos */
00260 
00261   /* ending */
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 /* given a list of dominos of type DOM_DUAL_NORM and the dual (planar) graph we
00279  * untangle all domino-paths and set path[1] as the longest one. mem is the
00280  * memory pool from where the dominos where allocated. cook-format edges of the
00281  * primal graph. */
00282 int EGuntangleAllDomino (EGlist_t * ddom_list,
00283                          EGdGraph_t * dgraph,
00284                          EGlist_t ** embed,
00285                          EGmemPool_t * mem)
00286 {
00287   /* local variables */
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   /* first we check if there is any intersection */
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     /* count edges used in all nodes */
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     /* find a node with more than 2 edges in the domino touching it that is not
00343      * the ending points of the domino */
00344     is_tangled = 0;
00345 
00346     for (j = dgraph->node_id_max; j--;)
00347     {
00348       /* we skip the two endpoints of the domino */
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     /* if the dual domino is not tangled we continue */
00362     if (!is_tangled)
00363       goto SET_MIDDLE;
00364     MESSAGE (EGPDP_DBGLVL, "domino %p is tangled, untanglin it", ddom_it->this);
00365 
00366     /* now we have a tangled domino in our hands and we need to untangle it,
00367      * we do so by constructing a new path structure */
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     /* we populate the list and create the beginning of the edges */
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     /* now we just find the next balanced node in the list of tangled node,
00406      * compute the local maping, and continue filling out the new paths */
00407     while ((curpos[0] != cur_ddom->npath[0]) ||
00408            (curpos[1] != cur_ddom->npath[1]) ||
00409            (curpos[2] != cur_ddom->npath[2]))
00410     {
00411       /* here we find the next map for the next node in the tangled_node 
00412        * list */
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       /* now we check that half the active edges have been already setted up */
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       /* if the node is not balanced, we discard it and go to the next node */
00435       if (ecount << 1 != node_marks[nroot])
00436         goto NEXT_NODE;
00437       /* check if ecount is <= 3 */
00438       TESTG (ecount > 3, CLEANUP, "more than three paths touch this node!");
00439       /* find eroot such that all next ecount edges (in the domino) are in the 
00440        * new path (I think that this is true.... but don't have an actual proof
00441        * for it) */
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       /* reset the maping */
00476       map[0] = map[1] = map[2] = 3;
00477       map2[0] = map2[1] = map2[2] = 3;
00478       /* now we just need to fill the map2 and map */
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       /* now, given the map we keep filling-up the new path */
00510       for (i = 3; i--;)
00511       {
00512         /* the local maping may have only two branches to follow, and we must
00513          * skip the other, we know wich map to skip because the value is bigger
00514          * than 2 */
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     }                           /* end computing the new untangled paths */
00537 
00538     /* now we save the untangled paths */
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     /* here we select wich path is going to be the middle path */
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   }                             /* end loop through all dual dominos */
00693 
00694   /* ending and cleaning-up */
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, /* dual DP constraint */
00708 
00709                    int nnodes,  /* number of nodes in primal graph */
00710 
00711                    int nedges,  /* number of edges in primal graph */
00712 
00713                    int *const edges,  /* non small edges in cook's format */
00714 
00715                    int *const elim_edges, /* index of eliminated edges */
00716 
00717                    int nelim_edges, /* size of the array elim_edges */
00718 
00719                    double *const weight,  /* weight of all non small edges */
00720 
00721                    int *const ndom, /* store number of dominos */
00722 
00723                    int **const nAset, /* store the size of A each sets */
00724 
00725                    int **const nBset, /* store the size of B each sets */
00726 
00727                    int *const nHandle,  /* store the size of the handle */
00728 
00729                    int ***const Aset, /* store each A set */
00730 
00731                    int ***const Bset, /* store each B set */
00732 
00733                    int **const Handle,  /* store the handle */
00734 
00735                    double *const violation, /* primal violation of the cut */
00736 
00737                    graphP G,    /* pointer to the dual graph in 
00738                                  * boyer's format */
00739 
00740                    EGmemPool_t * const mem) /* memory pool */
00741 {
00742 
00743   /* local variables */
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   /* some non-null test */
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   /* looking for memory */
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   /* alloc memory for the arrays */
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   /* reset violation to zero */
00832   *violation = 0;
00833 
00834   /* we use the field 'old' in graph to maintain the parity information to
00835    * build H */
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   /* now we update the parity of the edges in F */
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   /* here we compute the primal dominoes, and loop through all of them */
00856   for (j = ddp->ndom; j--;)
00857   {
00858     ddom = ddp->ddom[j];
00859     *violation += EGdijkstraCostToLf (ddom->primalValue);
00860 
00861     /* reset all marks to zero */
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     /* mark all paths with 2**i */
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         //EGmengerGetEdgeCost(EGddGetEdge(ddom,pth,k),os));
00878       }                         /* end for k (edges in path) */
00879     }                           /* end for pth */
00880 
00881     /* compute A_1, A_2, A_3 */
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       /* loop through the neighbours of the node */
00905       do
00906       {
00907         /* if edgemarks >=8 then is a traversed edge in the DFS and thus we can
00908          * discard it and keep going. */
00909         if (edgeMarks[curEdge->id] < 8)
00910         {
00911           /* the edge has no marks, then the node go to the current DFSlist, if
00912            * the edge has values 1,2 or 4, this implies that we are doing a
00913            * change of set */
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           /* acording to the end we put the other end in the corespondig DFS
00929            * list */
00930           EGlistPushHead (Adfs[nextA], (void *) curEdge->v);
00931           MESSAGE (EGFDOM_LVL, "Puting Node %d in Set %u", curEdge->v, nextA);
00932           /* set the edge as traversed */
00933           edgeMarks[curEdge->id] = 8;
00934         }
00935         curEdge = GETNEXTEDGE (curEdge, curNode, G);
00936       } while (curEdge != GETROOTEDGE (curNode, G));
00937     }                           /* end DFS */
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     /* compute the first edge of Pi */
00946     ep1 = EGddGetEdge (ddom, 0, 0);
00947     ep2 = EGddGetEdge (ddom, 1, 0);
00948     ep3 = EGddGetEdge (ddom, 2, 0);
00949 
00950     /* this sets the first try to find a 'good' domino path */
00951     /* up to now we have A, B and C, but we have to choose a domino path that
00952      * does not eliminate all 'odd' edges (i.e. that leaves a cut for H) */
00953     /* now we compute fA and fB as the two smallest sets */
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     /* now we update the 'odd' status of the eliminated edges */
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     }                           /* end for k (elimEdges) */
00992 
00993     /* now we set-up nAset, nBset, Aset, Bset */
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     /* copy set A */
01001     for (lIt = fA->begin, k = 0; lIt; lIt = lIt->next, k++)
01002       (*Aset)[j][k] = (int) (lIt->this);
01003     /* copy set B */
01004     for (lIt = fB->begin, k = 0; lIt; lIt = lIt->next, k++)
01005       (*Bset)[j][k] = (int) (lIt->this);
01006 
01007     /* update parity of the ABedges */
01008     for (k = nABedges; k--;)
01009     {
01010       edgeOld[EGddPathGetEdge (ddom, ABedges, k)->id] += 1;
01011     }
01012 
01013     /* clear all A, B, C, DFSlist is already empty */
01014     EGlistClear (Alist[0], nullFree);
01015     EGlistClear (Alist[1], nullFree);
01016     EGlistClear (Alist[2], nullFree);
01017   }                             /* end for j (ddominos) */
01018 
01019   /* now we compute the handle, to do that we compute handle and co-handle,
01020    * note that those sets might be non-contiguous */
01021   npt = 0;
01022   EGlistPushHead (HdfsList[npt & 1], (void *) 0);
01023   while (HdfsList[0]->size || HdfsList[1]->size)
01024   {
01025     /* this allow to change current partition */
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       /* if the edge is odd or it has an odd mark, we don't look at it */
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       }                         /* end current partition */
01048       /* if it is odd, (but not topMarked) we add the other end to the other
01049        * HdfsList */
01050       else if (edgeOld[curEdge->id] < topMark)
01051       {
01052         EGlistPushHead (HdfsList[(npt + 1) & 1], (void *) curEdge->v);
01053       }                         /* end complement */
01054       curEdge = GETNEXTEDGE (curEdge, curNode, G);
01055     } while (curEdge != GETROOTEDGE (curNode, G));
01056   }                             /* end computing H and H^c */
01057   EXIT (Hlist[0]->size + Hlist[1]->size != (unsigned) nnodes,
01058         "The primal graph is not connected.");
01059 
01060   /* now we update the 'odd' status of the eliminated edges */
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   }                             /* end for k (elimEdges) */
01073 
01074   /* final update of the violation */
01075   *violation -= 1;
01076   //*violation /= 2;
01077 
01078   /* now we define H as the smallest Hlist */
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   /* ending */
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 }

Generated on Thu Oct 20 14:58:41 2005 for DominoParitySeparator by  doxygen 1.4.5