eg_kppairs.c

Go to the documentation of this file.
00001 #include "eg_kppairs.h"
00002 
00003 #define GETOTHEREND(_cedge) (G->G[gp_GetTwinArc(G,_cedge - G->G)].v)
00004 #define GETROOTEDGE(curroot) (G->G + G->G[curroot].link[1])
00005 #define GETNEXTEDGE(curedge,curroot) ((curedge->link[1] < G->N) ? GETROOTEDGE(curroot) : (G->G + curedge->link[1]))
00006 
00007 /* ========================================================================= */
00008 #define EG_KPPAIRS_VERBOSE 100
00009 #define EG_KPPAIRS_DEBUG 0
00010 
00011 static size_t os[EG_MENGER_NUMOS] = {
00012     [EG_MENGER_PI] = offsetof (EGmengerNodeData_t, pi),
00013     [EG_MENGER_DIST] = offsetof (EGmengerNodeData_t, dist),
00014     [EG_MENGER_ORIG_DIST] = offsetof (EGmengerNodeData_t, orig_dist),
00015     [EG_MENGER_NDIST] = offsetof (EGmengerNodeData_t, ndist),
00016     [EG_MENGER_ORIG_NDIST] = offsetof (EGmengerNodeData_t, orig_ndist),
00017     [EG_MENGER_MARK] = offsetof (EGmengerNodeData_t, marker),
00018     [EG_MENGER_ORIG_MARK] = offsetof (EGmengerNodeData_t, orig_marker),
00019     [EG_MENGER_FATHER] = offsetof (EGmengerNodeData_t, father),
00020     [EG_MENGER_ORIG_FATHER] = offsetof (EGmengerNodeData_t, orig_father),
00021     [EG_MENGER_HEAP_CONNECTOR] = offsetof (EGmengerNodeData_t, hc),
00022     [EG_MENGER_ECOST] = offsetof (EGmengerEdgeData_t, cost),
00023     [EG_MENGER_REDUCED_ECOST] = offsetof (EGmengerEdgeData_t, reduced_cost),
00024     [EG_MENGER_IS_IN_SOL] = offsetof (EGmengerEdgeData_t, is_in_solution),
00025     [EG_MENGER_EDATA] = offsetof (EGmengerEdgeData_t, data)
00026   };
00027 static size_t  dij_os[6] = { 
00028     [EG_DIJ_DIST] = offsetof (EGmengerNodeData_t, orig_dist),
00029     [EG_DIJ_NDIST] = offsetof (EGmengerNodeData_t, orig_ndist),
00030     [EG_DIJ_FATHER] = offsetof (EGmengerNodeData_t, orig_father),
00031     [EG_DIJ_MARKER] = offsetof (EGmengerNodeData_t, orig_marker),
00032     [EG_DIJ_HCONNECTOR] = offsetof (EGmengerNodeData_t, hc),
00033     [EG_DIJ_ELENGTH] = offsetof (EGmengerEdgeData_t, cost)
00034   };
00035 
00036 #define KP_CHECK_SUM_IS_LESS(a,b,c) \
00037   WARNINGL(EG_KPPAIRS_DEBUG, EGdijkstraCostIsLess( EGdijkstraCostAdd((a),(b)), EGdijkstraToCost(c)), "Inequality not satisfied %lf < %lf", EGdijkstraCostToLf(EGdijkstraCostAdd((a), (b))), c)
00038 /* ========================================================================= */
00058 int static EGdoPrimalDfs( const unsigned n_marks,
00059                           size_t*const set_sz,
00060                           EGlist_t** CUT, 
00061                           unsigned char*const node_mark, 
00062                           unsigned char*const edge_mark, 
00063                           EGgreedyData_t*const data)
00064 {
00065   int rval = 0;
00066   const size_t nedges = data->bdG->edge_id_max/2;
00067   const size_t nnodes = nedges + 2 - data->bdG->node_id_max;
00068   size_t node_id = 0, other_id;
00069   const graphP G = data->G;
00070   register unsigned i;
00071   unsigned char cur_mark = 0, oth_mark;
00072   graphNodeP pedge;
00073   for( i = n_marks ; i-- ; )
00074   {
00075     set_sz[i] = 0;
00076     EGlistClear(CUT[i],0);
00077   }
00078   memset(node_mark,0,sizeof(unsigned char)*nnodes);
00079   node_mark[node_id] = cur_mark+1;
00080   set_sz[cur_mark] += 1;
00081   EGlistPushHead(CUT[cur_mark],(void*)node_id);
00082   do
00083   {
00084     node_id = (size_t)(CUT[cur_mark]->begin->this);
00085     EGlistErase(CUT[cur_mark],CUT[cur_mark]->begin,0);
00086     pedge = GETROOTEDGE(node_id);
00087     do
00088     {
00089       if(edge_mark[pedge->id]&128U) goto NEXT_EDGE;
00090       edge_mark[pedge->id] |= 128U;
00091       other_id = pedge->v;
00092       oth_mark = cur_mark ^ ((edge_mark[pedge->id])&127U);
00093       if(node_mark[other_id])
00094       {
00095         TESTG((rval=(oth_mark+1!=node_mark[other_id])), CLEANUP, "Imposible");
00096         goto NEXT_EDGE;
00097       }
00098       node_mark[other_id] = oth_mark + 1;
00099       set_sz[oth_mark] += 1;
00100       EGlistPushHead(CUT[oth_mark],(void*)other_id);
00101       NEXT_EDGE:
00102       pedge = GETNEXTEDGE(pedge, node_id);
00103     } while(pedge != GETROOTEDGE(node_id));
00104     cur_mark = 0;
00105     while( cur_mark < n_marks && !(CUT[cur_mark]->size)) cur_mark++;
00106   } while( cur_mark < n_marks);
00107   node_id = 0;
00108   #if KPPAIRS_VERBOSE <= DEBUG
00109   fprintf(stderr,"Number of Sets found %u\n",n_marks);
00110   #endif
00111   for( i = n_marks ; i-- ; )
00112   {
00113     node_id += set_sz[i];
00114     #if KPPAIRS_VERBOSE <= DEBUG
00115     fprintf(stderr,"\tset[%u]=%zd\n",i,set_sz[i]);
00116     #endif
00117   }
00118   TESTG((rval=(node_id != nnodes)), CLEANUP, "Imposible, nnodes %zd, marked nodes %zd",nnodes,node_id);
00119   CLEANUP:
00120   return rval;
00121 }
00122 
00123 
00124 /* ========================================================================= */
00125 int EGgenerateInternalPairs (EGgreedyData_t*const data,
00126                              EGdkdomino_t*const zerodom,
00127                              const unsigned int orientation,
00128                              EGlist_t*const pairs,
00129                              const unsigned max_pairs,
00130                              double const percentage,
00131                              unsigned char*const node_mark,
00132                              unsigned char*const edge_mark,
00133                              EGdGraphNode_t**const dc_nodes)
00134 {
00135   unsigned register int i = 0, j = 0, k = 0;
00136   int node_id, other_id;
00137   //EGlist_t**dembed = data->dembed;
00138   EGdGraph_t*const bdG = data->bdG;
00139   EGmemPool_t* mem = bdG->mem;
00140   EGlist_t*CUT[2]={EGnewList(mem),EGnewList(mem)};
00141   size_t set_sz[2] = {0,0};
00142   EGinternalPairs_t *worst_pair = 0, *cur_pair = 0;
00143   unsigned char const cur_mark = orientation ? 2U : 1U;
00144   unsigned int tot_pairs = 0;
00145   EGlist_t* unattach_edges = EGnewList(mem);
00146   EGdGraphNode_t *cur_node;
00147   EGdGraphEdge_t *tmp_edge = 0;
00148   EGheap_t* dij_heap = EGnewHeap(mem, 2, bdG->nodes->size);
00149   EGlistNode_t* It1;
00150   const graphP G = data->G;
00151   graphNodeP pedge;
00152   unsigned int cycle_sz = zerodom->cut->sz;
00153   int rval = 0;
00154   EGlist_t *extpath;
00155   MESSAGE(KPPAIRS_VERBOSE,"Entering for cut %p orientation %u", 
00156           (void*)zerodom->cut, orientation);
00157   
00158   EGdijkstraCost_t dist, path_dist;
00159   EGdijkstraCost_t const slack = EGdijkstraCostMul(EGdijkstraToCost(2.0),
00160                                                 EGdijkstraToCost(percentage));
00161   /* test that the graph max id is equal to the number of nodes in it */
00162   TESTG((rval=(bdG->node_id_max!=bdG->nodes->size)),CLEANUP,"Imposible!");
00163 
00164   /* now we define the cut as the edges with mark 1. and identify all nodes 
00165    * in the (dual) cycle */
00166   memset(dc_nodes,0,sizeof(EGdGraphNode_t*)*bdG->nodes->size);
00167   memset(edge_mark,0,sizeof(unsigned char)*bdG->edge_id_max/2);
00168   for( i = cycle_sz ; i-- ; )
00169   {
00170     WARNINGL(KPPAIRS_VERBOSE, edge_mark[ EGmengerGetEdgeData( 
00171              zerodom->cut->edges[i],os)->id], "repeated edge %p in cut", 
00172              (void*)zerodom->cut->edges[i]);
00173     edge_mark[EGmengerGetEdgeData(zerodom->cut->edges[i],os)->id] ^= 1U;
00174     dc_nodes[zerodom->cut->edges[i]->head->id] = zerodom->cut->edges[i]->head;
00175     dc_nodes[zerodom->cut->edges[i]->tail->id] = zerodom->cut->edges[i]->tail;
00176   }
00177 
00178   /* identify the primal partition */
00179   rval = EGdoPrimalDfs(2,set_sz,CUT,node_mark,edge_mark,data);
00180   CHECKRVALG(rval,CLEANUP);
00181   TESTG((rval=!set_sz[cur_mark-1]),CLEANUP,"Empty set! imposible!");
00182 
00183   /* put all nodes in the delta of the cycle at the beginning of the array */
00184   for( i = 0, tot_pairs = 0 ; i < bdG->nodes->size ; i++ )
00185     if(dc_nodes[i]) dc_nodes[tot_pairs++] = dc_nodes[i];
00186   TESTG((rval=(cycle_sz < tot_pairs)),CLEANUP,"Imposible!, cycle_sz %u "
00187         "cycle_nodes %u",cycle_sz, tot_pairs);
00188   cycle_sz = tot_pairs;
00189 
00190   /* depending in the orientation, we unnatach the edges with at least one
00191    * primal end in the wrong side for all nodes in the boundary of the cycle. 
00192    * */
00193   for( i = cycle_sz ; i-- ; )
00194   {
00195     cur_node = dc_nodes[i];
00196     MESSAGE(KPPAIRS_VERBOSE,"Checking node %u", cur_node->id);
00197     for( It1 = cur_node->out_edges->begin ; It1 ; It1 = It1->next)
00198     {
00199       pedge = EGmengerGetEdgeData(It1->this,os);
00200       node_id = pedge->v;
00201       other_id = GETOTHEREND(pedge);
00202       if(node_mark[node_id] != cur_mark || node_mark[other_id] != cur_mark)
00203       {
00204         MESSAGE(KPPAIRS_VERBOSE,"Unnattaching edge %p: %u (%u,%u)", 
00205                 It1->this, ((EGdGraphEdge_t*)It1->this)->id, 
00206                 ((EGdGraphEdge_t*)It1->this)->tail->id, 
00207                 ((EGdGraphEdge_t*)It1->this)->head->id);
00208         EGlistPushBack(unattach_edges,It1->this);
00209         //EGdGraphUnattachEdge(bdG,((EGdGraphEdge_t*)It1->this));
00210       }
00211     }
00212   }
00213   for(It1 = unattach_edges->begin ; It1; It1 = It1->next)
00214     EGdGraphUnattachEdge(bdG,((EGdGraphEdge_t*)It1->this));
00215   /* display the reduced graph */
00216   #if KPPAIRS_VERBOSE <= DEBUG
00217   MESSAGE(KPPAIRS_VERBOSE,"Unattach %u edges from G", unattach_edges->size);
00218   EGdGraphDisplay(bdG,0,0,0,stderr);
00219   #endif
00220 
00221   /* now we are ready to call dijkstra in the reduced graph */
00222   tot_pairs = 0;
00223   for( i = cycle_sz ; i-- ; )
00224   {
00225     rval = EGpartialDijkstra( dc_nodes[i], 0, slack , dij_os, dij_heap, bdG);
00226     CHECKRVALG(rval,CLEANUP);
00227     for( j = i ; j-- ; )
00228     {
00229       /* discard pairs that are unreachable */
00230       if(EGmengerGetOrigMark(dc_nodes[j],os) > UINT_MAX - 2) continue;
00231       /* discard pairs with cost over the bound */
00232       path_dist = EGdijkstraGetDist(dc_nodes[j],dij_os);
00233       dist = EGdijkstraCostAdd( path_dist, EGgetEvenDistance(dc_nodes[i]->id, 
00234                                 dc_nodes[j]->id, data));
00235       /* note that cut->val + dist < 4 for the inequality to have a chance to
00236        * be violated, se we ask that dist < 4 - cut->val <==> dist < slack,
00237        * thus we discard all pairs such that slack < dist */
00238       if(EGdijkstraCostIsLess(slack,dist)) continue;
00239       /* discard pairs that are already in the kdomino */
00240       for(k = zerodom->k ; k-- ; )
00241       {
00242         if(dc_nodes[i] == zerodom->pairs[k].s && 
00243            dc_nodes[j] == zerodom->pairs[k].t) 
00244           continue;
00245         if(dc_nodes[i] == zerodom->pairs[k].t && 
00246            dc_nodes[j] == zerodom->pairs[k].s) 
00247           continue;
00248       }
00249       MESSAGE(KPPAIRS_VERBOSE,"Path (%u,%u) with value %lf", dc_nodes[i]->id,
00250               dc_nodes[j]->id, EGdijkstraCostToLf(dist));
00251       /* compare against worst pair */
00252       if(pairs->size >= max_pairs)
00253       {
00254         worst_pair = (EGinternalPairs_t*)pairs->end->this;
00255         if(EGdijkstraCostIsLess(worst_pair->value,dist)) continue;
00256       }
00257 
00258       /* ensure we can extract the even path */
00259       extpath = EGnewList(mem);
00260       EGextractEEpath(dc_nodes[i]->id, dc_nodes[j]->id, data, extpath);
00261       if (!extpath->size)
00262       {
00263         #warning WARNING: This happens a lot!! Look.
00264         EGlistClear(extpath, nullFree);
00265         EGfreeList(extpath);
00266         continue;
00267       }
00268 
00269       /* define the current pair */
00270       tot_pairs++;
00271       cur_pair = EGmemPoolSMalloc(mem,EGinternalPairs_t,1);
00272       cur_pair->s = dc_nodes[i];
00273       cur_pair->t = dc_nodes[j];
00274       cur_pair->ivalue = path_dist;
00275       cur_pair->value = dist;
00276       cur_pair->stpath = EGmemPoolSMalloc(mem, EGdGraphEdge_t*, EGdijkstraGetNdist(dc_nodes[j], dij_os));
00277       EGdijkstraExtractSolution( cur_pair->stpath, &cur_pair->npath, dc_nodes[i], dc_nodes[j], dij_os );
00278       cur_pair->extpath = extpath;
00279 
00280       /* otherwise, we add the pair to the external heap of pairs */
00281       for(It1 = pairs->end ; It1 ; It1 = It1->prev)
00282       {
00283         worst_pair = (EGinternalPairs_t*)It1->this;
00284         if(EGdijkstraCostIsLess(worst_pair->value,dist)) 
00285           break;
00286       }
00287       if(It1) EGlistInsertAfter(pairs,It1,cur_pair);
00288       else EGlistPushHead(pairs,cur_pair);
00289       while(pairs->size > max_pairs)
00290       {
00291         EGlistEraseMP(pairs,pairs->end,EGfreeInternalPairs,mem);
00292       }
00293     }
00294   }
00295   
00296   /* ending */
00297   CLEANUP:
00298   if(tot_pairs)
00299   MESSAGE(KPPAIRS_VERBOSE, "for kdom %p generate %u pairs,  value range"
00300           " [%lf,%lf], eliminated edges %u",
00301           (void*)zerodom, tot_pairs, pairs->size ? 
00302           EGdijkstraCostToLf(((EGinternalPairs_t*)pairs->begin->this)->value):
00303           2.0, pairs->size ? 
00304           EGdijkstraCostToLf(((EGinternalPairs_t*)pairs->end->this)->value):
00305           2.0, unattach_edges->size);
00306   for(It1 = unattach_edges->begin ; It1; It1 = It1->next)
00307   {
00308     tmp_edge = (EGdGraphEdge_t*)It1->this;
00309     EGdGraphAttachEdge(bdG,tmp_edge);
00310   }
00311   EGfreeList(unattach_edges);
00312   EGfreeHeap(dij_heap,mem);
00313   EGfreeList(CUT[0]);
00314   EGfreeList(CUT[1]);
00315   return rval;
00316 }
00317 
00318 /* ========================================================================= */
00319 void EGinternalPairsClear(void*pair,EGmemPool_t*mem)
00320 {
00321  
00322   EGinternalPairs_t*const p = (EGinternalPairs_t*)pair;
00323   if(p->stpath) EGmemPoolSFree(p->stpath, EGdGraphEdge_t*, p->npath, mem); 
00324   p->stpath = 0;
00325   p->npath = 0;
00326   if(p->extpath)
00327   {
00328     EGlistClear(p->extpath, nullFree);
00329     EGfreeList(p->extpath);
00330     p->extpath = 0;
00331   }
00332   return;
00333 }
00334 
00335 /* ========================================================================= */
00336 void EGfreeInternalPairs(void*pair,EGmemPool_t*mem)
00337 {
00338   EGinternalPairsClear(pair,mem);
00339   EGmemPoolSFree(pair,EGinternalPairs_t,1,mem);
00340   return;
00341 }
00342 
00343 /* ========================================================================= */
00344 int EGgetCutNodes(EGgreedyData_t*const data,
00345                   EGdualCut_t*const dualcut,
00346                   const unsigned int orientation,
00347                   int*const cutsz,
00348                   int**const cutnodes,
00349                   unsigned char*const node_mark,
00350                   unsigned char*const edge_mark)
00351 {
00352   unsigned register int i = 0;
00353   int j = 0;
00354   EGmemPool_t* mem = data->bdG->mem;
00355   EGlist_t*CUT[2]={EGnewList(mem),EGnewList(mem)};
00356   size_t set_sz[2] = {0,0};
00357   unsigned char cur_mark = orientation ? 2U : 1U;
00358   unsigned const int cycle_sz = dualcut->sz;
00359   const size_t nedges = data->bdG->edge_id_max/2;
00360   const size_t nnodes = nedges + 2 - data->bdG->node_id_max;
00361   int rval = 0;
00362   
00363   /* test that the graph max id is equal to the number of nodes in it */
00364   TESTG((rval=(data->bdG->node_id_max!=data->bdG->nodes->size)), 
00365         CLEANUP,"Imposible!");
00366 
00367   /* now we define the cut as the edges with mark 1. and identify all nodes 
00368    * in the (dual) cycle */
00369   memset(edge_mark,0,sizeof(unsigned char)*nedges);
00370   for( i = cycle_sz ; i-- ; )
00371     edge_mark[EGmengerGetEdgeData(dualcut->edges[i],os)->id] ^= 1U;
00372 
00373   /* identify the partition */
00374   rval = EGdoPrimalDfs(2,set_sz,CUT,node_mark,edge_mark,data);
00375   CHECKRVALG(rval,CLEANUP);
00376   TESTG((rval=!set_sz[cur_mark-1]),CLEANUP,"Empty set! imposible!");
00377 
00378   /* depending on the orientation, we select the size of the set */
00379   *cutsz = set_sz[cur_mark-1];
00380   if(*cutsz) *cutnodes = EGsMalloc(int,*cutsz);
00381   j = 0;
00382   for( i = nnodes ; i-- ; )
00383     if(node_mark[i] == cur_mark)
00384       (*cutnodes)[j++] = i;
00385   TESTG((rval=(j!=(*cutsz))), CLEANUP, "Imposible!");
00386 
00387   /* ending */
00388   CLEANUP:
00389   EGfreeList(CUT[0]);
00390   EGfreeList(CUT[1]);
00391   return rval;
00392 }
00393 
00394 /* ========================================================================= */
00395 int EGgetANodes(EGgreedyData_t*const data,
00396                 EGdkdomino_t*const kdom,
00397                 int unsigned const k,
00398                 int*const cutsz,
00399                 int**const cutnodes,
00400                 unsigned char*const node_mark,
00401                 unsigned char*const edge_mark,
00402                 EGdGraphEdge_t**const dc_nodes)
00403 {
00404   unsigned register int i = 0;
00405   int j = 0;
00406   EGmemPool_t* mem = data->bdG->mem;
00407   EGlist_t*CUT[4]={EGnewList(mem),EGnewList(mem),EGnewList(mem),EGnewList(mem)};
00408   size_t set_sz[4] = {0,0,0,0};
00409   unsigned char cur_mark = kdom->orientation ? 4U : 2U;
00410   unsigned const int cycle_sz = kdom->cut->sz;
00411   const size_t nedges = data->bdG->edge_id_max/2;
00412   const size_t nnodes = nedges + 2 - data->bdG->node_id_max;
00413   EGdGraphNode_t*s = kdom->pairs[k].s;
00414   EGdGraphNode_t*const t = kdom->pairs[k].t;
00415   EGdGraphEdge_t*e=0;
00416   int rval = 0;
00417   EGlistNode_t* It = 0;
00418   *cutsz = 0;
00419   *cutnodes = 0;
00420   EGlist_t* DFS = EGnewList(mem);
00421   memset(dc_nodes,0,sizeof(EGdGraphEdge_t*)*data->bdG->nodes->size);
00422   
00423   /* test that the graph max id is equal to the number of nodes in it */
00424   TESTG((rval=(data->bdG->node_id_max!=data->bdG->nodes->size)), 
00425         CLEANUP,"Imposible!");
00426 
00427   /* now we define the cut as the edges with mark 2. and identify all nodes 
00428    * in the (dual) cycle */
00429   memset(edge_mark,0,sizeof(unsigned char)*nedges);
00430   for( i = cycle_sz ; i-- ; )
00431     edge_mark[EGmengerGetEdgeData(kdom->cut->edges[i],os)->id] ^= 2U;
00432 
00433   /* now we must find another s-t path with mark 2 and set the mark ^= 1U */
00434   EGlistPushBack(DFS,s);
00435   while(DFS->size && s!= t)
00436   {
00437     s = (EGdGraphNode_t*)DFS->begin->this;
00438     EGlistErase(DFS,DFS->begin,0);
00439     for( It = s->out_edges->begin ; It ; It = It->next)
00440     {
00441       e = (EGdGraphEdge_t*)It->this;
00442       if(edge_mark[EGmengerGetEdgeData(e,os)->id]== 2 && !dc_nodes[e->head->id])
00443       {
00444         dc_nodes[e->head->id] = e;
00445         EGlistPushHead(DFS,e->head);
00446         edge_mark[EGmengerGetEdgeData(e,os)->id] = 3;
00447       }
00448     }
00449   }
00450   if(s!=t)
00451   {
00452     rval = EG_KP_NOST;
00453     //MESSAGE(0, "Imposible, can't reach T from S");
00454     goto CLEANUP;
00455   }
00456 
00457   /* now we define the cut as the edges with mark 2. and identify all nodes 
00458    * in the (dual) cycle */
00459   memset(edge_mark,0,sizeof(unsigned char)*nedges);
00460   for( i = cycle_sz ; i-- ; )
00461     edge_mark[EGmengerGetEdgeData(kdom->cut->edges[i],os)->id] ^= 2U;
00462 
00463   /* now we mark all edges in the path with mark 1 */
00464   for( i = kdom->pairs[k].npath ; i-- ; )
00465     edge_mark[EGmengerGetEdgeData(kdom->pairs[k].stpath[i],os)->id] ^= 1U;
00466   
00467   /* now we mark the other path from s to t */
00468   for( e = dc_nodes[t->id] ; e && e->head != kdom->pairs[k].s ; e = dc_nodes[e->tail->id])
00469     edge_mark[EGmengerGetEdgeData(e,os)->id] ^= 1U;
00470 
00471   /* identify the partition */
00472   rval = EGdoPrimalDfs(4,set_sz,CUT,node_mark,edge_mark,data);
00473   CHECKRVALG(rval,CLEANUP);
00474   TESTG((rval=!set_sz[cur_mark-1]),CLEANUP,"Empty set! imposible!");
00475 
00476   /* depending on the orientation, we select the size of the set */
00477   *cutsz = set_sz[cur_mark-1];
00478   if(*cutsz) *cutnodes = EGsMalloc(int,*cutsz);
00479   j = 0;
00480   for( i = nnodes ; i-- ; )
00481     if(node_mark[i] == cur_mark)
00482       (*cutnodes)[j++] = i;
00483   TESTG((rval=(j!=(*cutsz))), CLEANUP, "Imposible!");
00484 
00485   /* ending */
00486   CLEANUP:
00487   EGfreeList(DFS);
00488   EGfreeList(CUT[0]);
00489   EGfreeList(CUT[1]);
00490   EGfreeList(CUT[2]);
00491   EGfreeList(CUT[3]);
00492   return rval;
00493 }
00494 
00495 /* ========================================================================= */
00496 int EGgetOrientation( EGgreedyData_t*const data,
00497                       EGdualCut_t*const dualcut,
00498                       int unsigned const pathsz,
00499                       EGdGraphEdge_t**const path,
00500                       unsigned int*const orientation,
00501                       unsigned char*const node_mark,
00502                       unsigned char*const edge_mark)
00503 {
00504   unsigned register int i = 0;
00505   EGmemPool_t* mem = data->bdG->mem;
00506   EGlist_t*CUT[2]={EGnewList(mem),EGnewList(mem)};
00507   size_t set_sz[2] = {0,0};
00508   unsigned char cur_mark = 0;
00509   unsigned const int cycle_sz = dualcut->sz;
00510   const size_t nedges = data->bdG->edge_id_max/2;
00511   const graphP G = data->G;
00512   graphNodeP pedge;
00513   int rval = 0;
00514   
00515   /* test that the graph max id is equal to the number of nodes in it */
00516   TESTG((rval=(data->bdG->node_id_max!=data->bdG->nodes->size)), 
00517         CLEANUP,"Imposible!");
00518 
00519   /* now we define the cut as the edges with mark 1. and identify all nodes 
00520    * in the (dual) cycle */
00521   memset(edge_mark,0,sizeof(unsigned char)*nedges);
00522   for( i = cycle_sz ; i-- ; )
00523     edge_mark[EGmengerGetEdgeData(dualcut->edges[i],os)->id] ^= 1U;
00524 
00525   /* identify the partition */
00526   rval = EGdoPrimalDfs(2,set_sz,CUT,node_mark,edge_mark,data);
00527   CHECKRVALG(rval,CLEANUP);
00528 
00529   /* test that the path is only within one orientation */
00530   cur_mark = node_mark[EGmengerGetEdgeData(path[0],os)->v];
00531   *orientation = cur_mark - 1;
00532   for( i = pathsz ; i-- ; )
00533   {
00534     pedge = EGmengerGetEdgeData(path[i],os);
00535     TESTG((rval=((node_mark[pedge->v]!=cur_mark) || 
00536                  (node_mark[GETOTHEREND(pedge)]!=cur_mark))), 
00537           CLEANUP, "Imposible!");
00538   }
00539 
00540   /* ending */
00541   CLEANUP:
00542   EGfreeList(CUT[0]);
00543   EGfreeList(CUT[1]);
00544   return rval;
00545 }
00546 
00547 /* ========================================================================= */
00548 int EGgetDualCut( EGgreedyData_t*const data,
00549                   EGdualCut_t**const dualcut,
00550                   const int pset_sz,
00551                   const int*const pset,
00552                   unsigned char*const node_mark,
00553                   unsigned char*const edge_mark,
00554                   EGdGraphEdge_t**const dc_nodes)
00555 {
00556   int rval = 0;
00557   register unsigned int i;
00558   unsigned cycle_sz = 0;
00559   EGlistNode_t *nit,*eit;
00560   EGdGraphNode_t*c_node;
00561   EGdGraphEdge_t*c_edge;
00562   const graphP G = data->G;
00563   EGdijkstraCost_t cutval = EGdijkstraToCost(0.0);
00564   graphNodeP pedge;
00565   /* reset marks */
00566   memset(dc_nodes,0,sizeof(EGdGraphEdge_t*)*data->norig_edges);
00567   memset(node_mark,0,sizeof(unsigned char)*data->norig_nodes);
00568   memset(edge_mark,0,sizeof(unsigned char)*data->norig_edges);
00569   /* mark all nodes in the cut */
00570   for( i = pset_sz ; i-- ; ) node_mark[pset[i]] = 1;
00571   /* loop through all edges in the bi-dual graph */
00572   for( nit = data->bdG->nodes->begin ; nit ;  nit = nit->next)
00573   {
00574     c_node = (EGdGraphNode_t*)nit->this;
00575     for(eit = c_node->out_edges->begin ; eit ; eit = eit->next)
00576     {
00577       c_edge = (EGdGraphEdge_t*)eit->this;
00578       pedge = EGmengerGetEdgeData(c_edge,os);
00579       if(edge_mark[pedge->id]) continue;
00580       if(node_mark[pedge->v] != node_mark[GETOTHEREND(pedge)])
00581       {
00582         edge_mark[pedge->id] = 1;
00583         cutval = EGdijkstraCostAdd( cutval, 
00584                                     EGdijkstraGetEdgeLength( c_edge, dij_os) );
00585         dc_nodes[cycle_sz++] = c_edge;
00586       }
00587     }
00588   }
00589   /* save the cut */
00590   *dualcut = EGnewDualCut(data->bdG->mem, cycle_sz);
00591   memcpy((*dualcut)->edges,dc_nodes,cycle_sz*sizeof(EGdGraphEdge_t*));
00592   (*dualcut)->value = cutval;
00593   return rval;
00594 }

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