eg_greedykp.c

Go to the documentation of this file.
00001 #include "eg_greedykp.h"
00002 #define EG_PRIMALIZATION_ERROR 0.001
00003 
00004 EGgreedyData_t* EGnewGreedyData(EGmemPool_t *mem)
00005 {
00006    EGgreedyData_t *data;
00007 
00008    data = EGmemPoolSMalloc(mem, EGgreedyData_t, 1);
00009 
00010    data->bdG = 0;
00011    data->cycleG = 0;
00012    data->bdGnodeMap = 0;
00013    data->cycleEdgeMap = 0;
00014    data->ddom_list = 0;
00015    data->ee_dist = 0;
00016    data->ee_prec = 0;
00017    data->eo_prec = 0;
00018 
00019    return data;
00020 }
00021 
00022 void EGfreeGreedyData(void *vdata)
00023 {
00024 
00025    unsigned int i;
00026    EGgreedyData_t *data = (EGgreedyData_t*)(vdata);
00027 
00028    EGmemPool_t *mem = data->cycleG->mem;
00029    if(data->randa) EGfree(data->randa);
00030    if(data->randb) EGfree(data->randb);
00031 
00032    if (data->pndummy)
00033       free(data->pndummy);
00034    if (data->pedummy)
00035       free(data->pedummy);
00036 
00037    if (data->bdnodes)
00038       free(data->bdnodes);
00039    if (data->pedges)
00040       free(data->pedges);
00041    if (data->pedgevals)
00042       free(data->pedgevals);
00043 
00044    if (data->bdGnodeMap)
00045       EGmemPoolSFree(data->bdGnodeMap, EGdGraphNode_t*, data->bdG->nodes->size, mem);
00046    if (data->cycleEdgeMap)
00047       EGmemPoolSFree(data->cycleEdgeMap, EGdGraphEdge_t*, data->cycleG->nedges, mem);
00048 
00049    for(i=0; i < data->bdG->nodes->size; i++)
00050    {
00051       if (data->ee_dist)
00052          EGmemPoolSFree(data->ee_dist[i], EGdijkstraCost_t, i+1, mem);
00053       #if EG_KP_HEURISTIC
00054       if (data->eo_dist)
00055          EGmemPoolSFree(data->eo_dist[i], EGdijkstraCost_t, i+1, mem);
00056       #endif
00057       if (data->ee_prec)
00058          EGmemPoolSFree(data->ee_prec[i], int, i+1, mem);
00059       if (data->eo_prec)
00060          EGmemPoolSFree(data->eo_prec[i], int, i+1, mem);
00061    }
00062 
00063    if (data->ee_dist)
00064       EGmemPoolSFree(data->ee_dist, EGdijkstraCost_t*, data->bdG->nodes->size, mem);
00065    #if EG_KP_HEURISTIC
00066    if (data->eo_dist)
00067       EGmemPoolSFree(data->eo_dist, EGdijkstraCost_t*, data->bdG->nodes->size, mem);
00068    #endif
00069    if (data->ee_prec)
00070       EGmemPoolSFree(data->ee_prec, int*, data->bdG->nodes->size, mem);
00071    if (data->eo_prec)
00072       EGmemPoolSFree(data->eo_prec, int*, data->bdG->nodes->size, mem);
00073 
00074    #if EG_KP_HEURISTIC
00075    EGmemPoolSFree(data->bdGtoCycleGmap, EGdGraphNode_t*, data->bdG->nodes->size, mem);
00076    #endif
00077 
00078    if (data->cycleG)
00079    {
00080       EGdGraphClearMP(data->cycleG, EGfreeCycleDataMP, EGfreeDijkstraNodeDataMP, 0, mem, mem, 0);
00081       EGfreeDGraph(data->cycleG);
00082    }
00083 
00084    EGmemPoolSFree(data, EGgreedyData_t, 1, mem);
00085 
00086    return;
00087 
00088 }
00089 
00090 int EGfillGreedyData (EGgreedyData_t * data,
00091                       EGdGraph_t * bdG,
00092                       EGlist_t * ddom_list,
00093                       EGlist_t** dembed,
00094                       graphP G,
00095                       int norig_nodes,
00096                       int norig_edges,
00097                       int nplanar_edges,
00098                       int *orig_edges,
00099                       int *planar_edges,
00100                       double *orig_weight,
00101                       double *planar_weight)
00102 {
00103 
00104   int rval=0;
00105   register unsigned int i;
00106   EGmemPool_t *mem = bdG->mem;
00107   memset(data,0,sizeof(EGgreedyData_t));
00108   static size_t  dij_os[6] = { 
00109     [EG_DIJ_DIST] = offsetof (EGdijkstraNodeData_t, dist),
00110     [EG_DIJ_NDIST] = offsetof (EGdijkstraNodeData_t, ndist),
00111     [EG_DIJ_FATHER] = offsetof (EGdijkstraNodeData_t, father),
00112     [EG_DIJ_MARKER] = offsetof (EGdijkstraNodeData_t, marker),
00113     [EG_DIJ_HCONNECTOR] = offsetof (EGdijkstraNodeData_t, hc),
00114     [EG_DIJ_ELENGTH] = offsetof (EGcycleData_t, weight)
00115     };
00116 
00117   EGdijkstraCost_t max_cycle_edge = EGdijkstraToCost(1.0),
00118                    max_even_path = EGdijkstraToCost(1.0);
00119 
00120   data->norig_nodes = norig_nodes;
00121   data->norig_edges = norig_edges;
00122   data->nplanar_edges = nplanar_edges;
00123   data->randa = EGsMalloc(unsigned int,norig_edges);
00124   data->randb = EGsMalloc(unsigned int,norig_edges);
00125   data->pndummy = EGsMalloc(unsigned char, data->norig_nodes);
00126   data->pedummy = EGsMalloc(unsigned char, data->norig_edges);
00127   data->pedges = EGsMalloc(EGdGraphEdge_t*,data->norig_edges);
00128   data->bdnodes = EGsMalloc(EGdGraphNode_t*,bdG->nodes->size);
00129   data->pedgevals = EGsMalloc(double,data->norig_edges);
00130 
00131   data->nviolated = 0;
00132   data->min_violated =  10000.0;
00133   data->max_violated = -10000.0;
00134   
00135   for( i = norig_edges ; i-- ; )
00136   {
00137     data->randa[i] = random()>>12;
00138     data->randb[i] = random()>>12;
00139   }
00140   data->orig_edges = orig_edges;
00141   data->planar_edges = planar_edges;
00142 
00143   data->orig_weight = orig_weight;
00144   data->planar_weight = planar_weight;
00145  
00146   data->bdG = bdG;
00147   data->ddom_list = ddom_list;
00148   data->G = G;
00149   data->cycleG = EGnewCycleGraph (mem, ddom_list, bdG, max_cycle_edge);
00150   TEST(!data->cycleG, "error generating cycle graph");
00151 
00152 #if DISPLAY_MODE
00153   fprintf (stdout, "KP greedy data: Cycle graph has %u nodes and %d arcs.\n",
00154                     data->cycleG->nodes->size, data->cycleG->nedges);
00155   fflush (stdout);
00156 #endif
00157 
00158   data->dembed = dembed;
00159   data->ee_dist = EGmemPoolSMalloc (mem, EGdijkstraCost_t *, bdG->nodes->size);
00160   #if EG_KP_HEURISTIC
00161   data->eo_dist = EGmemPoolSMalloc (mem, EGdijkstraCost_t *, bdG->nodes->size);
00162   #endif
00163   data->ee_prec = EGmemPoolSMalloc (mem, int *, bdG->nodes->size);
00164   data->eo_prec = EGmemPoolSMalloc (mem, int *, bdG->nodes->size);
00165 
00166   for (i = 0; i < bdG->nodes->size; i++)
00167   {
00168     data->ee_dist[i] = EGmemPoolSMalloc (mem, EGdijkstraCost_t, i+1);
00169     #if EG_KP_HEURISTIC
00170     data->eo_dist[i] = EGmemPoolSMalloc (mem, EGdijkstraCost_t, i+1);
00171     #endif
00172     data->ee_prec[i] = EGmemPoolSMalloc (mem, int, i+1); 
00173     data->eo_prec[i] = EGmemPoolSMalloc (mem, int, i+1);
00174   }
00175 
00176   data->cycleEdgeMap = EGmemPoolSMalloc(mem, EGdGraphEdge_t*, data->cycleG->nedges);
00177   {
00178      EGlistNode_t *vit, *eit;
00179      EGdGraphNode_t *v;
00180      EGdGraphEdge_t *e;
00181      for( vit = data->cycleG->nodes->begin; vit; vit=vit->next )
00182      {
00183         v = (EGdGraphNode_t*)(vit->this);
00184         for(eit=v->out_edges->begin; eit; eit=eit->next)
00185         {
00186            e = (EGdGraphEdge_t*)(eit->this);
00187            data->cycleEdgeMap[e->id] = e;
00188         }
00189      }
00190   }
00191 
00192   /* Remember that the nodes in bdG may not be sorted according to their id.  *
00193    * Hence, it is necessary to use a map to establish which id is which.      */
00194 
00195   data->bdGnodeMap = EGmemPoolSMalloc(mem, EGdGraphNode_t*, bdG->nodes->size);
00196   {
00197      EGlistNode_t *it;
00198 
00199      for(i=0, it=bdG->nodes->begin; it; it=it->next, i++)
00200      {
00201         data->bdGnodeMap[i] = (EGdGraphNode_t*)(it->this);
00202      }
00203   }
00204 
00205 
00206 #if EG_KP_HEURISTIC
00207   {
00208     EGdGraphNode_t *cycle_v, *bdg_v;
00209     EGlistNode_t *it;
00210 
00211     data->bdGtoCycleGmap = EGmemPoolSMalloc(mem, EGdGraphNode_t*, data->bdG->nodes->size);
00212     for( it = data->cycleG->nodes->begin; it; it=it->next->next )
00213     {
00214       cycle_v = (EGdGraphNode_t*)(it->this);
00215       bdg_v = data->bdGnodeMap[cycle_v->id / 2];
00216       data->bdGtoCycleGmap[ bdg_v->id ] = cycle_v;
00217     }
00218   }
00219 #endif
00220 
00221   /* fill the data in the table */ 
00222 #if EG_GREEDYKP_FILLTABLE
00223   {
00224      EGlistNode_t *u_it, *v_it;
00225      EGdGraphNode_t *s, *t;
00226 
00227      EGdijkstraCost_t dist;
00228      int prec;
00229      int s_id, t_id;
00230 
00231      EGheap_t *my_heap = EGnewHeap (mem, 2, data->cycleG->nodes->size);
00232 
00233      /* u_it will iterate through even nodes in cycleG */
00234      for(u_it=data->cycleG->nodes->begin; u_it; u_it=((u_it->next)->next))
00235      {
00236 
00237         TEST (!(u_it->next), "cycle graph badly defined");
00238 
00239         s = (EGdGraphNode_t*)(u_it->this);
00240 
00241         rval = EGpartialDijkstra (s,0,max_even_path,dij_os,my_heap,data->cycleG);
00242         TEST(rval, "error running dijkstra");
00243 
00244         /* v_it will iterate through nodes smaller than u_it in cycleG */
00245         for(v_it=data->cycleG->nodes->begin; v_it != u_it->next->next; v_it=v_it->next)
00246         {
00247            t = (EGdGraphNode_t*)(v_it->this);
00248           
00249            s_id = data->bdGnodeMap[s->id/2]->id;
00250            t_id = data->bdGnodeMap[t->id/2]->id;
00251 
00252            /* we should never request the even distance between a node and
00253             * itself! might as well make the software crash */
00254 
00255            if (v_it == u_it)
00256            {
00257               data->ee_dist[s_id][t_id] = 0;
00258               data->ee_prec[s_id][t_id] = -1;
00259               continue;
00260            }
00261 
00262            /* determine distance(s,t) and father(t) */ 
00263            if (EGdijkstraGetMarker(t, dij_os) == UINT_MAX)
00264            {
00265               dist = EG_DIJKSTRA_COST_MAX;
00266               prec = 0;
00267            }
00268            else
00269            {
00270               dist = EGdijkstraGetDist(t, dij_os);
00271               prec = EGdijkstraGetFather(t, dij_os)->id;
00272            }
00273 
00274            /* store distance(s,t) and father(t) in tables */
00275            if (t->id & 1)
00276            {
00277               if (t_id < s_id)
00278               {
00279                  #if EG_KP_HEURISTIC
00280                  data->eo_dist[s_id][t_id] = dist;
00281                  #endif
00282                  data->eo_prec[s_id][t_id] = prec;
00283               }
00284               else
00285               {
00286                  #if EG_KP_HEURISTIC
00287                  data->eo_dist[t_id][s_id] = dist;
00288                  #endif
00289                  data->eo_prec[t_id][s_id] = prec;
00290               }
00291            }
00292            else
00293            {
00294               if (t_id < s_id)
00295               {
00296                 data->ee_dist[s_id][t_id] = dist;
00297                 data->ee_prec[s_id][t_id] = prec;
00298               }
00299               else
00300               {
00301                 data->ee_dist[t_id][s_id] = dist;
00302                 data->ee_prec[t_id][s_id] = prec;
00303               }
00304            }
00305            
00306         }
00307      }
00308 
00309      EGfreeHeap (my_heap, mem);
00310 
00311   }
00312   /* done filling the data in the table */
00313 #endif
00314 
00315   return rval;
00316 
00317 }
00318 
00319 
00320 EGdualCut_t* EGnewDualCut(EGmemPool_t *mem, unsigned int sz)
00321 {
00322 
00323    EGdualCut_t *dc;
00324 
00325    dc = EGmemPoolSMalloc(mem, EGdualCut_t, 1);
00326 
00327    dc->sz = sz;
00328    dc->value = EGdijkstraToCost(0.0);
00329 
00330    if(sz) 
00331       dc->edges = EGmemPoolSMalloc(mem, EGdGraphEdge_t*, sz);
00332    else 
00333       dc->edges = 0;
00334 
00335    return dc;
00336 
00337 }
00338 
00339 void EGfreeDualCut(void *v, EGmemPool_t *mem)
00340 {
00341 
00342    EGdualCut_t *dc = (EGdualCut_t*)(v);
00343 
00344    if (dc->sz)
00345       EGmemPoolSFree(dc->edges, EGdGraphEdge_t*, dc->sz, mem);
00346    EGmemPoolSFree(dc, EGdualCut_t, 1, mem);
00347 
00348    return;
00349 
00350 }
00351 
00352 EGdcutIter_t* EGnewDcutIter(EGgreedyData_t *gdata)
00353 {
00354 
00355    EGdcutIter_t *zit;
00356 
00357    if (!gdata || !gdata->cycleG || !gdata->ddom_list)
00358       return 0;
00359 
00360    zit = EGmemPoolSMalloc(gdata->cycleG->mem, EGdcutIter_t, 1);
00361 
00362    zit->num_it = 0;
00363    zit->ddit = gdata->ddom_list->begin;
00364    zit->current_side = 0;
00365    zit->current_middle = 0;
00366    zit->gdata = gdata;
00367 
00368    return zit;
00369 
00370 }
00371 
00372 void EGfreeDcutIter(void *v)
00373 {
00374  
00375    EGdcutIter_t *zit = (EGdcutIter_t*)(v);
00376 
00377    if (!v)
00378       return;
00379 
00380    EXIT(!zit->gdata || !zit->gdata->cycleG, "cycleG is null");
00381 
00382    EGmemPoolSFree(v, EGdcutIter_t, 1, zit->gdata->cycleG->mem);
00383 
00384    return;
00385 
00386 }
00387 
00388 int EGincrementDcutIter(EGdcutIter_t *zit)
00389 {
00390 
00391    TEST(!zit || !zit->ddit, "error with zit");
00392 
00393    zit->num_it += 1;
00394    zit->ddit = zit->ddit->next;
00395 
00396    if (!zit->ddit)
00397    {
00398    
00399       if (!zit->current_side)
00400          zit->current_side = 1;
00401       else if (zit->current_middle < 2)
00402       {
00403          zit->current_middle += 1;
00404          zit->current_side = 0;
00405       }
00406       else 
00407          return 0;
00408 
00409       zit->ddit = zit->gdata->ddom_list->begin;
00410 
00411    }
00412 
00413    return 0;
00414 
00415 }
00416 
00417 EGdualCut_t* EGgetDcut(EGdcutIter_t *zit)
00418 {
00419 
00420    unsigned int i, j, p1, p2;
00421    EGdualCut_t *dc;
00422    EGddomino_t *ddom;
00423    EGmemPool_t *mem = zit->gdata->cycleG->mem;
00424 
00425    size_t mos[6];
00426    mos[EG_DIJ_ELENGTH] = offsetof(EGmengerEdgeData_t, cost);
00427 
00428    EGdijkstraCost_t val=EGdijkstraToCost(0.0);
00429 
00430    EXIT(!zit || !zit->ddit, "bad zit");
00431 
00432    ddom = zit->ddit->this;
00433 
00434    switch(zit->current_middle)
00435    {
00436       case 0:
00437          p1=1; p2=2;
00438          break;
00439       case 1:
00440          p1=0; p2=2;
00441          break;
00442       case 2:
00443          p1=0; p2=1;
00444          break;
00445       default:
00446          return 0; 
00447          break;
00448    }
00449 
00450    dc = EGnewDualCut(mem, ddom->npath[p1]+ddom->npath[p2]);
00451 
00452    for(i=0, j=0; i < ddom->npath[p1]; i++, j++)
00453    {
00454       dc->edges[j] = (EGdGraphEdge_t*)(ddom->path[p1][i]);
00455       val = EGdijkstraCostAdd(val, EGdijkstraGetEdgeLength(dc->edges[j], mos));
00456    }
00457    for(i=ddom->npath[p2]; i; i--, j++)
00458    {
00459       dc->edges[j] = (EGdGraphEdge_t*)(ddom->path[p2][i-1]);
00460       val = EGdijkstraCostAdd(val, EGdijkstraGetEdgeLength(dc->edges[j], mos));
00461    }
00462 
00463    dc->value = val;
00464 
00465    return dc;
00466 
00467 }
00468 
00469 int EGgetOddPrec (unsigned int s, unsigned int t, EGgreedyData_t*data)
00470 {
00471 
00472    if (t < s)
00473       return ( data->eo_prec[s][t] ); 
00474    else
00475       return ( data->eo_prec[t][s] ); 
00476 
00477 }
00478 
00479 int EGgetEvenPrec (unsigned int s, unsigned int t, EGgreedyData_t*data)
00480 {
00481    #if DEBUG > 3 
00482    if (s >= data->bdG->nodes->size)
00483       MESSAGE(1, "out of range s %u / %u", s, data->bdG->nodes->size);
00484    if (t >= data->bdG->nodes->size)
00485       MESSAGE(1, "out of range t %u / %u", t, data->bdG->nodes->size);
00486    #endif
00487    
00488    if (t < s)
00489       return ( data->ee_prec[s][t] ); 
00490    else
00491       return ( data->ee_prec[t][s] ); 
00492 }
00493 
00494 EGdijkstraCost_t EGgetEvenDistance (unsigned s, unsigned t, EGgreedyData_t*data)
00495 {
00496 
00497    #if DEBUG > 3
00498    if (s >= data->bdG->nodes->size)
00499       MESSAGE(1, "out of range s %u / %u", s, data->bdG->nodes->size);
00500    if (t >= data->bdG->nodes->size)
00501       MESSAGE(1, "out of range t %u / %u", t, data->bdG->nodes->size);
00502    #endif
00503 
00504    if(t < s)
00505       return ( data->ee_dist[s][t] ); 
00506    else
00507       return ( data->ee_dist[t][s] ); 
00508 
00509 }
00510 
00511 #if EG_KP_HEURISTIC
00512 EGdijkstraCost_t EGgetOddDistance (unsigned s, unsigned t, EGgreedyData_t*data)
00513 {
00514 
00515    if(t < s)
00516       return ( data->eo_dist[s][t] ); 
00517    else
00518       return ( data->eo_dist[t][s] ); 
00519 
00520 }
00521 #endif
00522 
00523 int EGextractEEpath(unsigned int s, 
00524                     unsigned int t, 
00525                     EGgreedyData_t *data, 
00526                     EGlist_t *path)
00527 {
00528 
00529    unsigned int curr_s = s, curr_t = t;
00530    int tot_even = 1, e_even = 1, rval=1;
00531    EGdGraphEdge_t *e;
00532    EGcycleData_t *e_data;
00533 
00534    EGdijkstraCost_t dist;
00535    dist = EGdijkstraToCost(0.0);
00536 
00537    EGlistClear(path, nullFree);
00538 
00539    int ncycle = 0;
00540    while ( curr_t != curr_s )
00541    {
00542     
00543       if (ncycle++ > 1000000)
00544          goto CLEANUP;
00545     
00546       if (tot_even)
00547          e = data->cycleEdgeMap[EGgetEvenPrec(curr_s,curr_t,data)];
00548       else
00549          e = data->cycleEdgeMap[EGgetOddPrec(curr_s,curr_t,data)];
00550 
00551       EGlistPushBack(path, e);
00552 
00553       e_data = (EGcycleData_t*)(e->data);
00554 
00555       dist = EGdijkstraCostAdd(dist, e_data->weight);
00556 
00557       if ( e_data->e )
00558          e_even = 1;
00559       else
00560          e_even = 0;
00561 
00562       if ( data->bdGnodeMap[e->head->id / 2]->id == curr_s )
00563          curr_s = data->bdGnodeMap[e->tail->id / 2]->id;
00564       else if ( data->bdGnodeMap[e->tail->id / 2]->id == curr_s )
00565          curr_s = data->bdGnodeMap[e->head->id / 2]->id;
00566       else if ( data->bdGnodeMap[e->head->id / 2]->id == curr_t )
00567          curr_t = data->bdGnodeMap[e->tail->id / 2]->id;
00568       else if ( data->bdGnodeMap[e->tail->id / 2]->id == curr_t )
00569          curr_t = data->bdGnodeMap[e->head->id / 2]->id;
00570       else 
00571       {
00572          fprintf(stderr, "missing case\n");
00573          fprintf(stderr, "curr_s = %u\n", curr_s);
00574          fprintf(stderr, "curr_t = %u\n", curr_t);
00575          fprintf(stderr, "e_head = %u\n", data->bdGnodeMap[e->head->id / 2]->id);
00576          fprintf(stderr, "e_tail = %u\n", data->bdGnodeMap[e->tail->id / 2]->id);
00577          goto CLEANUP;
00578       }
00579 
00580       if ( e_even == tot_even )
00581          tot_even = 1;
00582       else
00583          tot_even = 0;
00584 
00585    }
00586 
00587    if (!tot_even)
00588    {
00589       //fprintf(stderr, "need to add odd-cycle to compute actual path. IGNORING.\n");
00590       EGlistClear(path, nullFree);
00591    }
00592    else
00593    {
00594      EGdijkstraCost_t const evendist = EGgetEvenDistance(s,t,data);
00595      if ( fabs(EGdijkstraCostToLf(dist) - EGdijkstraCostToLf( evendist)) > 0.0001  )
00596      {
00597         fprintf(stderr, "computed distance  = %lf.\n", EGdijkstraCostToLf(dist));
00598         fprintf(stderr, "distance should be = %lf.\n", EGdijkstraCostToLf(evendist));
00599         fprintf(stderr, "distances do not match\n");
00600         rval = 1;
00601         goto CLEANUP;
00602      }
00603    }
00604 
00605    rval = 0;
00606    CLEANUP:
00607 
00608    return rval;
00609 
00610 }
00611 
00612 EGdkpc_t* EGdkdomToDKPC(EGdkdomino_t *dkdom,
00613                         EGmemPool_t *mem)
00614 {
00615 
00616    EGdkpc_t *dkpc;
00617    unsigned int i;
00618 
00619    dkpc = EGmemPoolSMalloc(mem, EGdkpc_t, 1);
00620 
00621    dkpc->nhandles = 0;
00622 
00623    dkpc->dkdom = EGnewList(mem);
00624    for(i=0; i<EG_KPC_MAX_HANDLES; i++)
00625       dkpc->FH[i] = EGnewList(mem);
00626 
00627    EGlistPushBack(dkpc->dkdom, dkdom);
00628 
00629    dkpc->slack = EGdijkstraCostSub( dkdom->cut->value, EGdijkstraToCost(2.0) );
00630 
00631    return dkpc;
00632 
00633 }
00634 
00635 EGdkpc_t* EGdcutToDKPC(EGdualCut_t *dc, 
00636                        unsigned int orientation, 
00637                        EGmemPool_t *mem)
00638 {
00639 
00640    EGdkdomino_t *dkdom;
00641    dkdom = EGdcutToDKdom( EG_KPC_MAX_HANDLES, dc, orientation, mem);
00642    return (EGdkdomToDKPC(dkdom, mem));
00643 
00644 }
00645 
00646 void EGfreeDKPC(void *v, EGmemPool_t *mem)
00647 {
00648 
00649    EGdkpc_t *dkpc;
00650    unsigned int i;
00651 
00652    dkpc = (EGdkpc_t*)(v);
00653 
00654    for(i=0; i < EG_KPC_MAX_HANDLES; i++)
00655       EGfreeList(dkpc->FH[i]);
00656 
00657    EGlistClearMP(dkpc->dkdom, EGfreeDKdomino, mem);
00658    EGfreeList(dkpc->dkdom);
00659   
00660    EGmemPoolSFree(dkpc, EGdkpc_t, 1, mem);
00661 
00662    return;
00663 
00664 }
00665 
00666 EGdkdomino_t* EGdcutToDKdom(unsigned int max_k, 
00667                             EGdualCut_t *dc, 
00668                             unsigned int orientation, 
00669                             EGmemPool_t *mem)
00670 {
00671 
00672    EGdkdomino_t *dkd=0;
00673 
00674    dkd = EGmemPoolSMalloc(mem, EGdkdomino_t, 1);
00675    dkd->k = 0;
00676    dkd->max_k = max_k;
00677 
00678    dkd->orientation=orientation;
00679    dkd->pairs = EGmemPoolSMalloc(mem, EGinternalPairs_t, max_k);
00680    dkd->handleid = EGmemPoolSMalloc(mem, unsigned int, max_k);
00681    dkd->cut = EGcopyDualCut(mem, dc);
00682 
00683    return dkd;
00684 
00685 }
00686 
00687 void EGfreeDKdomino(void *v, EGmemPool_t *mem)
00688 {
00689 
00690    unsigned int i;
00691    EGdkdomino_t *dkd;
00692 
00693    dkd = (EGdkdomino_t*)(v);
00694 
00695    for(i=0; i<dkd->max_k; i++)
00696       EGinternalPairsClear(&(dkd->pairs[i]),mem);
00697    EGmemPoolSFree(dkd->pairs, EGinternalPairs_t, dkd->max_k, mem);
00698    EGmemPoolSFree(dkd->handleid, unsigned int, dkd->max_k, mem); 
00699 
00700    EGfreeDualCut(dkd->cut, mem);
00701 
00702    EGmemPoolSFree(dkd, EGdkdomino_t, 1, mem);
00703    
00704    return;
00705 
00706 }
00707 
00708 EGdijkstraCost_t EGweightDKdomino(EGdkdomino_t *dkd)
00709 {
00710 
00711    unsigned int i,j;
00712    EGdijkstraCost_t weight;
00713    size_t mos[EG_MENGER_NUMOS];
00714 
00715    mos[EG_MENGER_ECOST]  = offsetof (EGmengerEdgeData_t, cost);
00716    mos[EG_MENGER_EDATA] = offsetof (EGmengerEdgeData_t, data);
00717 
00718    EGcomputeDualCutValue(dkd->cut);
00719    weight = dkd->cut->value;
00720 
00721    for(i=0; i < dkd->k; i++)
00722      for(j=0; j < dkd->pairs[i].npath; j++)
00723        weight = EGdijkstraCostAdd(weight, 
00724                 EGmengerGetEdgeCost(dkd->pairs[i].stpath[j],mos));
00725 
00726    weight = EGdijkstraCostSub(weight, EGdijkstraToCost( (double)(dkd->k+2) ));
00727 
00728    return weight;
00729 
00730 }
00731 
00732 EGdijkstraCost_t EGcomputeDKPCslack(EGdkpc_t *dkpc)
00733 {
00734 
00735    unsigned int i; 
00736    EGlistNode_t *it;
00737    size_t mos[EG_MENGER_NUMOS];
00738 
00739    // SLACK = 0.0
00740 
00741    EGdijkstraCost_t slack = EGdijkstraToCost(0.0);
00742    EGdijkstraCost_t weight;
00743 
00744    mos[EG_MENGER_ECOST]  = offsetof (EGmengerEdgeData_t, cost);
00745    mos[EG_MENGER_EDATA] = offsetof (EGmengerEdgeData_t, data);
00746 
00747    // SLACK += SUM_T w(T)
00748 
00749    for(it=dkpc->dkdom->begin; it; it=it->next)
00750    {
00751       weight = EGweightDKdomino( (EGdkdomino_t*)(it->this) );
00752       slack = EGdijkstraCostAdd(slack, weight); 
00753    }
00754 
00755    // SLACK += SUM_H x(F_H)
00756 
00757    for(i=0; i < dkpc->nhandles; i++)
00758       for(it=dkpc->FH[i]->begin; it; it=it->next)
00759          slack = EGdijkstraCostAdd(slack, EGmengerGetEdgeCost(it->this,mos) );
00760 
00761    // SLACK -= |H|
00762    
00763    slack = EGdijkstraCostSub(slack, EGdijkstraToCost( (double)(dkpc->nhandles) ) );
00764 
00765    return slack;
00766 
00767 }
00768 
00769 int EGgrowHandle(EGdkpc_t *dkpc, 
00770                  EGdkdomino_t *link_dkdom,
00771                  EGinternalPairs_t *p, 
00772                  EGgreedyData_t *data,
00773                  EGmemPool_t *mem,
00774                  unsigned char *const pndummy,
00775                  unsigned char *const pedummy)
00776 {
00777 
00778    int rval, h;
00779    EGlist_t *extpath;
00780    EGlistNode_t *it;
00781    EGdGraphEdge_t *e;
00782    EGcycleData_t *edata;
00783    EGdkdomino_t *dkdom = 0;
00784 
00785    /* handle id of new handle */
00786    h = dkpc->nhandles;
00787 
00788    /* make sure we don't exceed max # of handles */
00789    TEST( h >= EG_KPC_MAX_HANDLES, "# of handles exceeded");
00790 
00791    /* extract external path */  
00792    extpath = p->extpath; 
00793 
00794    if (!extpath->size)
00795       goto CLEANUP;
00796 
00797    /* grow the dual k-domino by using the internal path */
00798 
00799    rval = EGgrowDKdomino(link_dkdom, p, h, mem); 
00800    CHECKRVAL(rval);
00801 
00802    /* add the handle by going through the external path */
00803 
00804    for(it=extpath->begin; it; it=it->next)
00805    {
00806       e = (EGdGraphEdge_t*)(it->this);
00807       edata = (EGcycleData_t*)(e->data);
00808       if (edata->e)
00809          EGlistPushBack(dkpc->FH[h],edata->e);
00810       if (edata->ddom)
00811       {
00812          dkdom = EGddominoToDKdom(edata->ddom, h, EG_KPC_MAX_HANDLES, data, mem, pndummy, pedummy);
00813          EGlistPushBack(dkpc->dkdom,dkdom);
00814       }
00815    }
00816 
00817    dkpc->nhandles += 1;
00818    dkpc->slack = EGdijkstraCostAdd(dkpc->slack, p->value);
00819    dkpc->slack = EGdijkstraCostSub(dkpc->slack, EGdijkstraToCost(2.0));
00820 
00821    CLEANUP:
00822 
00823    return 0;
00824 
00825 }
00826 
00827 int EGgrowDKdomino(EGdkdomino_t *dkd, 
00828                    EGinternalPairs_t *p,
00829                    int handle_num,
00830                    EGmemPool_t *mem)
00831 {
00832 
00833    TEST( dkd->k >= dkd->max_k, "invalid dkd k size (k = %d | max = %d)", dkd->k, dkd->max_k);
00834 
00835    dkd->handleid[dkd->k] = handle_num;
00836    dkd->pairs[dkd->k].s = p->s;
00837    dkd->pairs[dkd->k].t = p->t;
00838 
00839    /* actually, the next line is misleading... 
00840       p->value also considers external path    */
00841    dkd->pairs[dkd->k].value = p->value;
00842 
00843    /* copy the path! */
00844    dkd->pairs[dkd->k].npath  = p->npath;
00845    dkd->pairs[dkd->k].stpath = EGmemPoolSMalloc(mem,EGdGraphEdge_t*,p->npath);
00846    memcpy(dkd->pairs[dkd->k].stpath,p->stpath,sizeof(EGdGraphEdge_t*)*p->npath);
00847 
00848    dkd->k++;
00849 
00850    return 0;
00851 
00852 }
00853 
00854 EGdkdomino_t *EGddominoToDKdom(EGddomino_t *ddom, 
00855                                int h, 
00856                                int max_nh, 
00857                                EGgreedyData_t *gdata,
00858                                EGmemPool_t *mem,
00859                                unsigned char *const pndummy,
00860                                unsigned char *const pedummy)
00861 {
00862    unsigned int i;
00863    EGdkdomino_t *dkdom;
00864 
00865    dkdom = EGmemPoolSMalloc(mem, EGdkdomino_t, 1);
00866 
00867    dkdom->k = 1;
00868    dkdom->max_k = max_nh;
00869 
00870    dkdom->handleid = EGmemPoolSMalloc(mem,unsigned int,max_nh); 
00871    dkdom->handleid[0] = h;
00872 
00873    /* prepare internal pairs */
00874    dkdom->pairs = EGmemPoolSMalloc(mem,EGinternalPairs_t,max_nh); 
00875    dkdom->pairs[0].s      = ddom->s;
00876    dkdom->pairs[0].t      = ddom->t;
00877    dkdom->pairs[0].value  = 0;
00878    //dkdom->pairs[0].kdom   = dkdom;
00879   
00880    dkdom->pairs[0].npath  = ddom->npath[1];
00881    dkdom->pairs[0].stpath = EGmemPoolSMalloc(mem, EGdGraphEdge_t*, ddom->npath[1]);
00882    for(i=0; i < ddom->npath[1]; i++)
00883       dkdom->pairs[0].stpath[i] = ddom->path[1][i];
00884   
00885    /* dual cut */ 
00886    dkdom->cut = EGnewDualCut(mem, ddom->npath[0]+ddom->npath[2]);
00887    for(i=0; i < ddom->npath[0]; i++)
00888       dkdom->cut->edges[i] = ddom->path[0][i];
00889    for(i=0; i < ddom->npath[2]; i++)
00890       dkdom->cut->edges[i+ddom->npath[0]] = ddom->path[2][i];
00891 
00892    /* orientation */
00893    int rval = EGgetOrientation(gdata, 
00894                            dkdom->cut, 
00895                            dkdom->pairs[0].npath,
00896                            dkdom->pairs[0].stpath,
00897                            &(dkdom->orientation),
00898                            pndummy,
00899                            pedummy);
00900    if (rval)
00901    {
00902       EGfreeDKdomino(dkdom, mem);
00903       dkdom = 0;
00904    }
00905 
00906    return dkdom;
00907 }
00908 
00909 EGdualCut_t* EGextractHandleCut(EGdkpc_t *dkpc, unsigned int h)
00910 {
00911 
00912    unsigned int i,j;
00913    EGlist_t *hcut;
00914    EGlistNode_t *it;
00915    EGdkdomino_t *dkd;
00916    EGinternalPairs_t *p;
00917    EGdualCut_t *dc;
00918    
00919    hcut = EGnewList(dkpc->dkdom->mempool); 
00920 
00921    for(it = dkpc->FH[h]->begin; it; it=it->next)
00922      EGlistPushBack(hcut, it->this);
00923 
00924    for(it = dkpc->dkdom->begin; it; it=it->next)
00925    {
00926       dkd = (EGdkdomino_t*)(it->this);
00927       for(i=0; i < dkd->k; i++)
00928          if ( dkd->handleid[i] == h )
00929          {
00930             p = &(dkd->pairs[i]);
00931             for(j=0; j<p->npath; j++)
00932                EGlistPushBack(hcut, p->stpath[j]); 
00933          }
00934    }
00935 
00936    dc = EGnewDualCut(dkpc->dkdom->mempool, hcut->size);
00937    for(i=0, it = hcut->begin; it; it=it->next, i++)
00938       dc->edges[i] = (EGdGraphEdge_t*)(it->this);
00939    dc->value = EGdijkstraToCost(0.0);
00940 
00941    EGfreeList(hcut);
00942 
00943    return dc;
00944 
00945 }
00946 
00947 void EGdisplayDualCut(FILE *fout, EGdualCut_t* dc)
00948 {
00949 
00950    unsigned int i;
00951    size_t mos[EG_MENGER_NUMOS];
00952 
00953    mos[EG_MENGER_ECOST]  = offsetof (EGmengerEdgeData_t, cost);
00954    mos[EG_MENGER_EDATA] = offsetof (EGmengerEdgeData_t, data);
00955 
00956    fprintf(fout, "cut: (%d) ", dc->sz);
00957 
00958    for(i=0; i < dc->sz; i++)
00959       fprintf(fout, "(%d,%d)[%4.3lf] ", dc->edges[i]->head->id, 
00960               dc->edges[i]->tail->id, 
00961               EGdijkstraCostToLf(EGmengerGetEdgeCost(dc->edges[i],mos))); 
00962    fprintf(fout, "\n");
00963 
00964    return;
00965 
00966 }
00967 
00968 void EGdisplayInternalPair(FILE *fout, EGinternalPairs_t *p)
00969 {
00970 
00971    unsigned int i;
00972    size_t mos[EG_MENGER_NUMOS];
00973 
00974    mos[EG_MENGER_ECOST]  = offsetof (EGmengerEdgeData_t, cost);
00975    mos[EG_MENGER_EDATA] = offsetof (EGmengerEdgeData_t, data);
00976 
00977    fprintf(fout, "(s=%d,t=%d) [sz=%d] ", p->s->id, p->t->id, p->npath);
00978 
00979    for(i=0; i < p->npath; i++)
00980       fprintf(fout, "(%d %d)[%lf] ", 
00981                     p->stpath[i]->tail->id, p->stpath[i]->head->id,
00982                     EGdijkstraCostToLf(EGmengerGetEdgeCost(p->stpath[i],mos)));
00983 
00984    fprintf(fout, "\n");
00985 
00986    return;
00987 
00988 }
00989 
00990 void EGdisplayDKdomino(FILE *fout, EGdkdomino_t *dkdom)
00991 {
00992 
00993    unsigned int i;
00994    EGdijkstraCost_t weight;
00995 
00996    fprintf(fout, "k=%d max_k = %d [orientation=%d]\n\n", 
00997                  dkdom->k, dkdom->max_k, dkdom->orientation);
00998 
00999    fprintf(fout, "delta(T) = ");
01000    EGdisplayDualCut(fout, dkdom->cut);
01001    fprintf(fout, "\n");
01002 
01003    for(i=0; i<dkdom->k; i++)
01004    {
01005       fprintf(fout, "path of handle %d: ", dkdom->handleid[i]);
01006       EGdisplayInternalPair(fout, &(dkdom->pairs[i]));
01007       fprintf(fout, "\n");
01008    }
01009 
01010    weight = EGweightDKdomino(dkdom);
01011    fprintf(stderr, "*weight = %lf\n\n", EGdijkstraCostToLf(weight));
01012 
01013    return;
01014 
01015 }
01016 
01017 
01018 void EGdisplayDKPC(FILE *fout, EGdkpc_t *dkpc)
01019 {
01020 
01021    unsigned int i,j;
01022    EGlistNode_t *it;
01023    EGdkdomino_t *dkd;
01024    EGdGraphEdge_t *e;
01025 
01026    fprintf(fout, "----------- DKPC ----------- \n\n");
01027    fprintf(fout, "DKPC slack    = %lf\n", EGdijkstraCostToLf(dkpc->slack));
01028    fprintf(fout, "nhandles = %d\n\n", dkpc->nhandles);
01029 
01030    for(i=0; i < dkpc->nhandles; i++)
01031    {
01032       fprintf(fout, "FH[%1u] (%3u elements): ", i, dkpc->FH[i]->size );
01033       for(it=dkpc->FH[i]->begin; it; it=it->next)
01034       {
01035          e = (EGdGraphEdge_t*)(it->this);
01036          fprintf(fout, "(%d,%d)", e->tail->id, e->head->id);
01037       }
01038       fprintf(fout, "\n");
01039    }
01040 
01041    fprintf(fout, "\n");
01042    fprintf(fout, "--- TEETH ---\n\n");
01043 
01044    for(it = dkpc->dkdom->begin; it; it=it->next)
01045    {
01046       dkd = (EGdkdomino_t *)(it->this);
01047       EGdisplayDKdomino(fout, dkd);
01048    }
01049 
01050    fprintf(fout, "--- HANDLES ---\n\n"); 
01051    
01052    EGdualCut_t *dc;
01053 
01054    for(i=0; i < dkpc->nhandles; i++)
01055    { 
01056       dc = EGextractHandleCut(dkpc, i);
01057       fprintf(fout, "delta(H_%d): ", i); 
01058       for(j=0; j < dc->sz; j++)
01059       {
01060          e = dc->edges[j];
01061          fprintf(fout, "(%d,%d)", e->tail->id, e->head->id);
01062       }
01063       fprintf(fout, "\n\n");
01064       EGfreeDualCut(dc, dkpc->dkdom->mempool);
01065    }
01066    
01067 
01068    return;
01069 
01070 }
01071 
01072 int EGprimalizeDKPC( EGdkpc_t *dkpc,
01073                      EGgreedyData_t *gdata,
01074                      EGpkpc_t *pkpc,
01075                      unsigned char *const pndummy,
01076                      unsigned char *const pedummy)
01077 {
01078 
01079    int rval;
01080    double internal_slack,
01081           external_slack,
01082           orig_slack,
01083           planar_slack;
01084    EGdijkstraCost_t dij_external_slack;
01085    pkpc->randa = pkpc->randb = 0;
01086 
01087    rval = EGprimalizeDKPCB( dkpc,
01088                             gdata,
01089                             &pkpc->nhandles,
01090                             &pkpc->handle_size,
01091                             &pkpc->handles,
01092                             &pkpc->nteeth,
01093                             &pkpc->teeth_size,
01094                             &pkpc->teeth,
01095                             &pkpc->teeth_k,
01096                             &pkpc->teeth_handle,
01097                             &pkpc->teeth_nhalf,
01098                             &pkpc->teeth_halves,
01099                             pndummy,
01100                             pedummy);
01101    if (rval == EG_KP_NOST)
01102      return rval;
01103    CHECKRVAL(rval);
01104 
01105    internal_slack = (double)EGdijkstraCostToLf(dkpc->slack);
01106    dij_external_slack = EGcomputeDKPCslack(dkpc);
01107    external_slack = (double)EGdijkstraCostToLf(dij_external_slack);
01108 
01109    orig_slack = EGcomputePKPCslack(gdata,
01110                                    pkpc,
01111                                    gdata->norig_nodes,
01112                                    gdata->norig_edges,
01113                                    gdata->orig_edges,
01114                                    gdata->orig_weight);
01115 
01116    planar_slack = EGcomputePKPCslack(gdata,
01117                                      pkpc,
01118                                      gdata->norig_nodes,
01119                                      gdata->nplanar_edges,
01120                                      gdata->planar_edges,
01121                                      gdata->planar_weight);
01122 
01123    pkpc->slack = orig_slack;
01124 
01125    /* TEST FOR CONSISTENCY! */
01126    #if 0
01127    WARNING( (fabs(internal_slack - external_slack) > EG_PRIMALIZATION_ERROR) ,
01128          "internal slack (%lf) and external slack (%lf) are inconsistent",
01129           internal_slack, external_slack);
01130    WARNING( (fabs(internal_slack - planar_slack) > EG_PRIMALIZATION_ERROR),
01131          "dual slack (%lf) and primal slack (%lf) are inconsistent",
01132           internal_slack, planar_slack);
01133    #endif
01134    #warning A check could be added here to doubly ensure that the primal-dual conversion is correct.
01135 
01136    return 0;
01137 
01138 }
01139 
01140 int EGprimalizeDKPCB( EGdkpc_t *dkpc,
01141                       EGgreedyData_t *gdata,
01142                       int *nhandles,
01143                       int **handle_size,
01144                       int ***handles,
01145                       int *nteeth,
01146                       int **teeth_size,
01147                       int ***teeth,
01148                       int **teeth_k,
01149                       int ***teeth_handle,
01150                       int ***teeth_nhalf,
01151                       int ****teeth_halves,
01152                       unsigned char *const pndummy,
01153                       unsigned char *const pedummy)
01154 {
01155 
01156    int rval;
01157    unsigned int i,j;
01158    EGdualCut_t *dc;
01159    EGlistNode_t *it;
01160    EGdkdomino_t *dkd;
01161    int kill_this_pkpc = 0;
01162 
01163    /* HANDLES */
01164    *nhandles = dkpc->nhandles;
01165 
01166    *handle_size = EGsMalloc(int,dkpc->nhandles);
01167    *handles     = EGsMalloc(int*,dkpc->nhandles);
01168 
01169    for(i=0; i<dkpc->nhandles; i++)
01170    {
01171       dc = EGextractHandleCut(dkpc, i);
01172       rval = EGgetCutNodes(gdata, 
01173                            dc,
01174                            0,
01175                            &((*handle_size)[i]),
01176                            &((*handles)[i]),
01177                            pndummy,
01178                            pedummy);
01179       CHECKRVAL(rval);
01180       EGfreeDualCut(dc, dkpc->dkdom->mempool);
01181       #warning Handles are not complemented before being added. 
01182    }
01183 
01184    /* TEETH */
01185    *nteeth = (int)(dkpc->dkdom->size); 
01186 
01187    *teeth_size     = EGsMalloc(int,*nteeth);
01188    *teeth          = EGsMalloc(int*,*nteeth);
01189    *teeth_k        = EGsMalloc(int,*nteeth);
01190    *teeth_handle   = EGsMalloc(int*,*nteeth);
01191    *teeth_nhalf    = EGsMalloc(int*,*nteeth);
01192    *teeth_halves   = EGsMalloc(int**,*nteeth);
01193 
01194 
01195    for(i=0, it=dkpc->dkdom->begin; it; it=it->next, i++)
01196    {
01197       dkd = (EGdkdomino_t*)(it->this);
01198 
01199       EGcomputeDualCutValue(dkd->cut);
01200      
01201       rval = EGgetCutNodes(gdata,
01202                            dkd->cut,
01203                            dkd->orientation,
01204                            &((*teeth_size)[i]),
01205                            &((*teeth)[i]),
01206                            pndummy,
01207                            pedummy);
01208       CHECKRVAL(rval);
01209 
01210       (*teeth_k)[i] = dkd->k;
01211 
01212       (*teeth_handle)[i] = EGsMalloc(int,dkd->k);
01213       (*teeth_nhalf)[i]  = EGsMalloc(int,dkd->k);
01214       (*teeth_halves)[i] = EGsMalloc(int*,dkd->k);
01215 
01216       for(j=0; j<dkd->k;j++)
01217       {
01218          (*teeth_handle)[i][j] = (int)dkd->handleid[j];
01219          rval = EGgetANodes( gdata,
01220                              dkd,
01221                              j,
01222                              &((*teeth_nhalf)[i][j]),
01223                              &((*teeth_halves)[i][j]),
01224                              pndummy,
01225                              pedummy,
01226                              gdata->pedges);
01227          if (rval == EG_KP_NOST)
01228             kill_this_pkpc = 1;
01229          else
01230             CHECKRVAL(rval);
01231       }
01232    }
01233 
01234    if (kill_this_pkpc)
01235       return EG_KP_NOST;
01236 
01237    return 0;
01238 
01239 }
01240 
01241 void EGfreePKPC( void *v )
01242 {
01243 
01244    EGpkpc_t *pkpc = (EGpkpc_t*)(v);
01245 
01246    EGfreePKPCB( pkpc->nhandles,
01247                 pkpc->handle_size,
01248                 pkpc->handles,
01249                 pkpc->nteeth,
01250                 pkpc->teeth_size,
01251                 pkpc->teeth,
01252                 pkpc->teeth_k,
01253                 pkpc->teeth_handle,
01254                 pkpc->teeth_nhalf,
01255                 pkpc->teeth_halves );
01256 
01257    free(pkpc);
01258 
01259    return;
01260 
01261 }
01262                     
01263 int EGfreePKPCB( int nhandles,
01264                  int *handle_size,
01265                  int **handles,
01266                  int nteeth,
01267                  int *teeth_size,
01268                  int **teeth,
01269                  int *teeth_k,
01270                  int **teeth_handle,
01271                  int **teeth_nhalf,
01272                  int ***teeth_halves )
01273 {
01274 
01275    int i,j;
01276 
01277    for(i=0; i < nhandles; i++)
01278       free(handles[i]);
01279    
01280    free(handles);
01281    free(handle_size);
01282 
01283    for(i=0; i < nteeth; i++)
01284    {
01285       free(teeth[i]);    
01286       free(teeth_handle[i]);
01287       free(teeth_nhalf[i]);
01288       for(j=0; j < teeth_k[i]; j++)
01289          free(teeth_halves[i][j]);
01290       free(teeth_halves[i]);
01291    }
01292 
01293    free(teeth_k);
01294    free(teeth_size);
01295 
01296    free(teeth);
01297    free(teeth_handle);
01298    free(teeth_nhalf);
01299    free(teeth_halves);
01300    
01301    return 0;
01302 
01303 }
01304 
01305 int EGnewPKPCset(int nineq,
01306                  int **nhandles,
01307                  int ***handle_size,
01308                  int ****handles,
01309                  int **nteeth,
01310                  int ***teeth_size,
01311                  int ****teeth,
01312                  int ***teeth_k,
01313                  int ****teeth_handle,
01314                  int ****teeth_nhalf,
01315                  int *****teeth_halves)
01316 {
01317 
01318    /* do the mallocs for nineq equations */
01319 
01320    *nhandles     = EGsMalloc(int,nineq);
01321    *handle_size  = EGsMalloc(int*,nineq);
01322    *handles      = EGsMalloc(int**,nineq);
01323    *nteeth       = EGsMalloc(int,nineq);
01324    *teeth_size   = EGsMalloc(int*,nineq);
01325    *teeth        = EGsMalloc(int**,nineq);
01326    *teeth_k      = EGsMalloc(int*,nineq);
01327    *teeth_handle = EGsMalloc(int**,nineq);
01328    *teeth_nhalf  = EGsMalloc(int**,nineq);
01329    *teeth_halves = EGsMalloc(int***,nineq);
01330 
01331    return 0;
01332 
01333 }
01334 
01335 void EGcomputeDualCutValue( EGdualCut_t *dc )
01336 {
01337 
01338   unsigned int i;
01339   size_t mos[EG_MENGER_NUMOS];
01340 
01341   mos[EG_MENGER_ECOST]  = offsetof (EGmengerEdgeData_t, cost);
01342   mos[EG_MENGER_EDATA] = offsetof (EGmengerEdgeData_t, data);
01343 
01344   dc->value = EGdijkstraToCost(0.0);
01345   for(i=0; i < dc->sz; i++)
01346     dc->value = EGdijkstraCostAdd(dc->value,EGmengerGetEdgeCost(dc->edges[i],mos));
01347 
01348   return;
01349 
01350 }
01351 
01352 // dummy should be an array of size at least nnodes
01353 double EGcomputePrimalCutValue(EGgreedyData_t*data,
01354                                EGpkpc_t*pkpc,
01355                                int set_size, 
01356                                int *set_nodes, 
01357                                int nnodes, 
01358                                int nedges, 
01359                                int *edges,
01360                                double *weight,
01361                                unsigned char *dummy)
01362 {
01363    int i;
01364    double val = 0.0;
01365    memset(dummy, 0, sizeof(unsigned char)*nnodes);
01366    for(i=0; i < set_size; i++)
01367    {
01368       dummy[set_nodes[i]] = 1;
01369    }
01370    for(i=0; i < nedges; i++)
01371       if ( (dummy[edges[2*i]] + dummy[edges[2*i+1]]) == 1 )
01372       {
01373          val += weight[i];
01374          pkpc->randa += data->randa[i];
01375          pkpc->randb += data->randb[i];
01376       }
01377    return val;
01378 }
01379 
01380 /* dummy should be an array of size at least nnodes */
01381 
01382 double EGcomputeInterfaceValue(int T_size, 
01383                                int *T_nodes, 
01384                                int A_size,
01385                                int *A_nodes,
01386                                int nnodes, 
01387                                int nedges, 
01388                                int *edges,
01389                                double *weight,
01390                                unsigned char *dummy)
01391 {
01392    int i;
01393    double val = 0.0;
01394 
01395    memset(dummy, 0, sizeof(unsigned char)*nnodes);
01396   
01397    for(i=0; i < T_size; i++)
01398       dummy[T_nodes[i]] = 1;
01399 
01400    for(i=0; i < A_size; i++)
01401       if ( dummy[A_nodes[i]] )
01402          dummy[A_nodes[i]] = 2;
01403       else 
01404       {
01405          EXIT(1, "A not a subset of T");
01406       }
01407 
01408    for(i=0; i < nedges; i++)
01409       if ( dummy[edges[2*i]] + dummy[edges[2*i+1]] == 3 )
01410          val += weight[i];
01411 
01412    return val;
01413 }
01414 
01415 int EGincrementInterface( int T_size,
01416                           int *T,
01417                           int A_size,
01418                           int *A,
01419                           int nnodes,
01420                           int nedges,
01421                           int *edges,
01422                           unsigned char *ndummy,
01423                           unsigned char *emarkers )
01424 {
01425 
01426    int i;
01427    memset(ndummy, 0, sizeof(unsigned char)*nnodes);
01428    for(i=0; i < T_size; i++) ndummy[ T[i] ] = 1;
01429    for(i=0; i < A_size; i++) ndummy[ A[i] ] = 2;
01430    for(i=0; i<nedges; i++)
01431       if ( ndummy[edges[2*i]] + ndummy[edges[2*i+1]] == 3 ) emarkers[i] += 1;
01432    return 0;
01433 }
01434 
01435 double EGcomputePKPCslack( EGgreedyData_t*data,
01436                            EGpkpc_t *pkpc, 
01437                            int nnodes,
01438                            int nedges,
01439                            int *edges,
01440                            double *weight )
01441 {
01442   return ( EGcomputePKPCBslack( data,
01443                                 pkpc,
01444                                 pkpc->nhandles,
01445                                 pkpc->handle_size,
01446                                 pkpc->handles,
01447                                 pkpc->nteeth,
01448                                 pkpc->teeth_size,
01449                                 pkpc->teeth,
01450                                 pkpc->teeth_k,
01451                                 pkpc->teeth_handle,
01452                                 pkpc->teeth_nhalf,
01453                                 pkpc->teeth_halves,
01454                                 nnodes,
01455                                 nedges,
01456                                 edges,
01457                                 weight ) );
01458 }
01459 
01460 double EGcomputePKPCBslack( EGgreedyData_t*data,
01461                             EGpkpc_t*pkpc,
01462                             int nhandles,
01463                             int *handle_size,
01464                             int **handles,
01465                             int nteeth,
01466                             int *teeth_size,
01467                             int **teeth,
01468                             int *teeth_k,
01469                             int **teeth_handle,
01470                             int **teeth_nhalf,
01471                             int ***teeth_halves,
01472                             int nnodes,
01473                             int nedges,
01474                             int *edges,
01475                             double *weight)
01476                            
01477 {
01478 
01479    int i,j,k; 
01480    unsigned char *ndummy = data->pndummy, *edummy = data->pedummy;
01481    double slack = 0;
01482 
01483    /* initialize */
01484 
01485    /* add SUM x( delta(T) ) */
01486    for(i=0; i<nteeth; i++) 
01487       slack += EGcomputePrimalCutValue(data,
01488                                        pkpc,
01489                                        teeth_size[i],
01490                                        teeth[i],
01491                                        nnodes,
01492                                        nedges,
01493                                        edges,
01494                                        weight,
01495                                        ndummy);
01496 
01497    /* add SUM x(mu(H)) */
01498    for(i=0; i < nhandles; i++)
01499    {
01500       /* first, compute how many times each edge is in an interface */  
01501       memset(edummy, 0, sizeof(unsigned char)*nedges);
01502       for(j=0; j<nteeth;j++)
01503          for(k=0; k<teeth_k[j]; k++)
01504             if ( teeth_handle[j][k] == i )
01505                EGincrementInterface( teeth_size[j],
01506                                      teeth[j],
01507                                      teeth_nhalf[j][k],
01508                                      teeth_halves[j][k],
01509                                      nnodes,
01510                                      nedges,
01511                                      edges,
01512                                      ndummy,
01513                                      edummy);
01514 
01515       /* mark the nodes in H */
01516       memset(ndummy, 0, sizeof(unsigned char)*nnodes);
01517       for(j=0; j<handle_size[i]; j++)
01518          ndummy[ handles[i][j] ] = 1;
01519 
01520       /* add the corresponding value for each edge */
01521       for(j=0; j<nedges; j++)
01522       {
01523          /* if an edge is in an even number of interfaces and in delta(H) */
01524          if ( !(edummy[j]&1) && ( ndummy[edges[2*j]] + ndummy[edges[2*j+1]] == 1 ) )
01525           {
01526             slack += (edummy[j]+1)*weight[j];
01527             pkpc->randa += (edummy[j]+1)*data->randa[j];
01528             pkpc->randb += (edummy[j]+1)*data->randb[j];
01529           }
01530 
01531          /* if an edge is in an odd  number of interfaces and in delta(H) */
01532          if ( (edummy[j]&1) && ( ndummy[edges[2*j]] + ndummy[edges[2*j+1]] == 1 ) )
01533           {
01534             slack += (edummy[j])*weight[j];
01535             pkpc->randa += (edummy[j])*data->randa[j];
01536             pkpc->randb += (edummy[j])*data->randb[j];
01537           }
01538 
01539          /* if an edge 1s in an even number of interfaces and not in delta(H) */
01540          if ( !(edummy[j]&1) && ( ndummy[edges[2*j]] + ndummy[edges[2*j+1]] != 1 ) )
01541           {
01542             slack += (edummy[j])*weight[j];
01543             pkpc->randa += (edummy[j])*data->randa[j];
01544             pkpc->randb += (edummy[j])*data->randb[j];
01545           }
01546 
01547          /* if an edge is in an odd  number of interfaces and not in delta(H) */
01548          if ( (edummy[j]&1) && ( ndummy[edges[2*j]] + ndummy[edges[2*j+1]] != 1 ) )
01549           {
01550             slack += (edummy[j]+1)*weight[j];
01551             pkpc->randa += (edummy[j]+1)*data->randa[j];
01552             pkpc->randb += (edummy[j]+1)*data->randb[j];
01553           }
01554       }
01555 
01556    }
01557 
01558    /* subtract |H| */
01559    slack -= (double)nhandles;
01560 
01561    /* subtract |J| */
01562    for(i=0; i < nteeth; i++)
01563       slack -= (double)teeth_k[i];
01564 
01565    /* subtract 2|T| */
01566    slack -= (double)(2*nteeth);
01567 
01568    return slack;
01569 }
01570 
01571 int EGkpTo2pTooth( int kp_size,
01572                    int* kp_nodes,
01573                    int kp_k,
01574                    int* kp_handles,
01575                    int* kp_nhalf,
01576                    int** kp_halves,
01577                    int *tp_naset,
01578                    int *tp_nbset,
01579                    int *tp_nmset,
01580                    int **tp_aset,
01581                    int **tp_bset,
01582                    int **tp_mset,
01583                    int nnodes,
01584                    unsigned char *vdummy )
01585 {
01586 
01587   int k, i, m[2];
01588 
01589   TEST( kp_k > 2 || kp_k < 1, "can only convert k-dominoes with 1 <= k <= 2");
01590 
01591   memset( vdummy, 0, sizeof(unsigned char)*nnodes );
01592 
01593   /* bit 0 == 1 iff a node is in T
01594      bit 1 == 1 iff a node is in A
01595      bit 2 == 1 iff a node is in B */
01596 
01597   /* mark nodes in T */
01598   for(i=0; i< kp_size; i++)
01599     vdummy[ kp_nodes[i] ] |= 1;
01600 
01601   /* the idea is that 
01602      m[k] will match handle k to handle A if kp_handle[k] = 0
01603      m[k] will match handle k to handle B if kp_handle[k] = 1 */
01604 
01605   m[0] = 2*(kp_handles[0]+1);
01606   m[1] = 2*(2 - kp_handles[0]);
01607 
01608   /* mark nodes in each half */
01609   for(k=0; k < kp_k; k++)
01610     for(i=0; i< kp_nhalf[k]; i++)
01611       vdummy[ kp_halves[k][i] ] |= m[k];
01612     
01613   /* count members of each set */
01614   *tp_naset = 0;
01615   *tp_nbset = 0;
01616   *tp_nmset = 0;
01617   for(i=0; i<nnodes; i++)
01618   {
01619     if (vdummy[i])
01620        (*tp_nmset) += 1;
01621     if (vdummy[i]  & 2)
01622        (*tp_naset) += 1;
01623     if (vdummy[i]  & 4)
01624        (*tp_nbset) += 1;
01625   }
01626 
01627   /* allocate arrays */
01628   if (*tp_naset)
01629     (*tp_aset) = EGsMalloc(int,*tp_naset);
01630   if (*tp_nbset)
01631     (*tp_bset) = EGsMalloc(int,*tp_nbset);
01632   if (*tp_nmset)
01633     (*tp_mset) = EGsMalloc(int,*tp_nmset);
01634 
01635   /* add members to each set */
01636   *tp_naset = 0;
01637   *tp_nbset = 0;
01638   *tp_nmset = 0;
01639   for(i=0; i<nnodes; i++)
01640   {
01641     if (vdummy[i])
01642        (*tp_mset)[(*tp_nmset)++] = i;
01643     if (vdummy[i]  & 2)
01644        (*tp_aset)[(*tp_naset)++] = i;
01645     if (vdummy[i]  & 4)
01646        (*tp_bset)[(*tp_nbset)++] = i;
01647   }
01648 
01649   return 0;
01650 
01651 }
01652 
01653 /* removes handles, very carefully, leaving the internal pairs 
01654    paths floating in memory - USE CAREFULLY! Not for general use */
01655 
01656 int EGremoveHandles(EGdkpc_t *dkpc, EGmemPool_t *mem)
01657 {
01658 
01659    unsigned int i;
01660    EGdkdomino_t *dkd;
01661    EGlistNode_t *it;
01662 
01663    /* remove the handles */
01664    if (!dkpc->nhandles)
01665       return 0;
01666 
01667    for(i=0; i<dkpc->nhandles; i++)
01668       EGlistClear(dkpc->FH[i], nullFree); 
01669 
01670    dkpc->nhandles = 0;
01671 
01672    /* redirect the paths of dkd->pairs */
01673    for(it=dkpc->dkdom->begin; it; it=it->next)
01674    {
01675       dkd = (EGdkdomino_t*)(it->this);
01676       for(i=0; i<dkd->max_k; i++)
01677       {
01678         dkd->pairs[i].npath = 0;  
01679         dkd->pairs[i].stpath = 0;  
01680       }
01681    }
01682 
01683    /* remove all the dominoes except the first one */
01684    while(dkpc->dkdom->size > 1)
01685       EGlistEraseMP(dkpc->dkdom, dkpc->dkdom->end, EGfreeDKdomino, mem);
01686 
01687    /* re-size the first domino */
01688    dkd = (EGdkdomino_t*)(dkpc->dkdom->begin->this); 
01689    dkd->k = 0;
01690 
01691    /*
01692    for(i=0; i<dkd->max_k; i++)
01693       EGinternalPairsClear(&(dkd->pairs[i]),mem);
01694    */
01695 
01696    dkpc->slack = EGcomputeDKPCslack(dkpc);
01697 
01698    return 0;
01699 
01700 }
01701 
01702 EGdualCut_t* EGcopyDualCut(EGmemPool_t *mem, EGdualCut_t *dc_in)
01703 {
01704 
01705   unsigned int i;
01706   EGdualCut_t *dc_out;
01707 
01708   dc_out = EGnewDualCut(mem, dc_in->sz);
01709 
01710   for(i=0; i<dc_in->sz; i++)
01711     dc_out->edges[i] = dc_in->edges[i];
01712 
01713   dc_out->value = dc_in->value;
01714 
01715   return dc_out;
01716 
01717 }
01718 
01719 int KPseparateFromDualCut( EGdualCut_t *dcut,
01720                            unsigned int orientation,
01721                            EGgreedyData_t *gdata,
01722                            int *nadded,
01723                            double *best_val,
01724                            double sample_time )
01725 {
01726  
01727   int rval;
01728   int i;
01729   EGmemPool_t *mem = gdata->bdG->mem;
01730   int add_cut_to_heap = 1;     
01731   double slack;
01732 
01733   EGdkdomino_t *zdom;
01734   EGdkpc_t *dkpc;
01735   EGpkpc_t *pkpc, *hpkpc;
01736   EGlist_t *pairs_list;
01737   EGinternalPairs_t *p, *q;
01738   EGlistNode_t *it, *jt;
01739 
01740   /* initialize */
01741 
01742   for( i = 0 ; i < 7 ; i++)
01743     if(EGdijkstraCostIsLess(dcut->value,EGdijkstraToCost(i+1.000001)))
01744     {
01745       gdata->delta_distr[i]++;
01746       break;
01747     }
01748 
01749   pairs_list = EGnewList(mem);
01750 
01751   (*nadded) = 0;
01752   (*best_val) = EGdijkstraToCost(1.0);
01753  
01754   /* we generate zdom only to generate the internal pairs...
01755      we free it immediatly after. Yes... its a bit wasteful. */
01756   zdom = EGdcutToDKdom( EG_KPC_MAX_HANDLES, 
01757                         dcut, 
01758                         orientation, 
01759                         mem);
01760 
01761   rval = EGgenerateInternalPairs( gdata, 
01762                                   zdom, 
01763                                   zdom->orientation, 
01764                                   pairs_list, 
01765                                   (unsigned int)gdata->max_handles*15, 
01766                                   gdata->percentage,
01767                                   gdata->pndummy,
01768                                   gdata->pedummy,
01769                                   gdata->bdnodes);
01770   CHECKRVAL(rval);
01771 
01772   EGfreeDKdomino(zdom, mem);
01773   zdom = 0;
01774 
01775   if (sample_time > 0.1)
01776   {
01777     //fprintf(stdout, "before: %u  ", pairs_list->size);
01778     EGlist_t *new_pairs;
01779     // generate the new list
01780     new_pairs = EGnewList(gdata->bdG->mem);
01781     rval = EGgenerateRandomInternalPairs( gdata,
01782                                           new_pairs,
01783                                           pairs_list,
01784                                           (unsigned int)gdata->max_handles*35, 
01785                                           sample_time );
01786     CHECKRVAL(rval);
01787     // merge the lists
01788     pairs_list = EGmergeIPlists(pairs_list, new_pairs);
01789     //fprintf(stdout, "after: %u      ", pairs_list->size);
01790   }
01791 
01792   /* now we loop through all possible combinations of internal
01793      paths so as to generate as many constraints as possible   */
01794   for(it=pairs_list->begin; it; it=it->next)
01795   for(jt=it->next; jt; jt=jt->next)
01796   {
01797         
01798     p = (EGinternalPairs_t*)(it->this);
01799     q = (EGinternalPairs_t*)(jt->this);
01800 
01801     if (p->s == q->s && p->t == q->t)
01802       continue;
01803 
01804     zdom = EGdcutToDKdom( EG_KPC_MAX_HANDLES, 
01805                           dcut, 
01806                           orientation, 
01807                           mem);
01808 
01809     dkpc = EGdkdomToDKPC(zdom, mem);
01810 
01811     slack = EGdijkstraCostToLf(dkpc->slack);
01812 
01813 
01814     rval = EGgrowHandle(dkpc, 
01815                         zdom,
01816                         p, 
01817                         gdata, 
01818                         mem,
01819                         gdata->pndummy,
01820                         gdata->pedummy);
01821     CHECKRVAL(rval); 
01822 
01823     rval = EGgrowHandle(dkpc, 
01824                         zdom,
01825                         q, 
01826                         gdata, 
01827                         mem,
01828                         gdata->pndummy,
01829                         gdata->pedummy);
01830     CHECKRVAL(rval);
01831 
01832     /* if the current constraint is no good, then, because
01833     the pairs are sorted, the next ones might not be as well */
01834     if (EGdijkstraCostToLf(dkpc->slack) > -0.01)
01835     {
01836       EGfreeDKPC(dkpc, mem);
01837       dkpc = 0;
01838       if (jt == pairs_list->begin->next)
01839         it = pairs_list->end;
01840       break;
01841     }
01842 
01843     /* primalize the constraint */
01844     pkpc = EGsMalloc(EGpkpc_t,1);
01845 
01846     add_cut_to_heap = 1;
01847 
01848     rval = EGprimalizeDKPC( dkpc,
01849                             gdata,
01850                             pkpc,
01851                             gdata->pndummy,
01852                             gdata->pedummy);
01853     if (rval == EG_KP_NOST)
01854     {
01855        rval = 0;
01856        add_cut_to_heap = 0;
01857     }
01858     else if (rval)
01859     {
01860       fprintf(stdout, "WARNING! graphs are inconsistent. Saving to 'inconsistent_graph.b.x'\n");
01861       saveBgraph ("inconsistent_graph.b.x", gdata->norig_nodes, 
01862                                             gdata->norig_edges, 
01863                                             gdata->orig_edges, 
01864                                             gdata->orig_weight);
01865     }
01866     CHECKRVAL(rval);
01867 
01868     /* check if the cut is violated */
01869    if (pkpc->slack > 0.0001)
01870      add_cut_to_heap = 0;
01871 
01872     /* check if handle is empty */
01873     for(i=0; i<pkpc->nhandles; i++)
01874       if ( !pkpc->handle_size[i] || (pkpc->handle_size[i] == gdata->norig_nodes) )
01875       {
01876         #warning Erasing constraints with empty handles.
01877         //MESSAGE(0, "Warning! Removing a constraint with empty handle!");
01878         add_cut_to_heap = 0;
01879         break;
01880       }
01881     
01882     /* if the heap is full, check if the cut has fabs(slack) 
01883     lower than all the elements of the heap               */
01884     if (gdata->cut_heap->size == gdata->cut_heap->max_size)
01885     {
01886       const EGheapCost_t mv = EGheapGetMinVal(gdata->cut_heap);
01887       const double mv_lf = (double)EGheapCostToLf(mv);
01888       if ( !(fabs(pkpc->slack) > mv_lf) )
01889         add_cut_to_heap = 0;
01890     }
01891  
01892     /* check if the cut is already in the constraint heap */
01893     if (add_cut_to_heap)
01894       for(i=0; i < (int)gdata->cut_heap->size; i++)
01895       {
01896         hpkpc = (EGpkpc_t*)(gdata->cut_heap->heap[i]->this);
01897         if (hpkpc->randa == pkpc->randa)
01898           if (hpkpc->randb == pkpc->randb) 
01899             if (hpkpc->nhandles == pkpc->nhandles)
01900               if (hpkpc->nteeth == pkpc->nteeth)
01901                 add_cut_to_heap = 0;   
01902       } 
01903 
01904     if (add_cut_to_heap)
01905     {
01906       /* if the cut heap is full, remove constraint with highest slack */
01907       if (gdata->cut_heap->size == gdata->cut_heap->max_size)
01908       {
01909         hpkpc = (EGpkpc_t*)(EGheapGetMin(gdata->cut_heap)->this);
01910         EGfreePKPC(hpkpc);
01911         EGheapDeleteMin(gdata->cut_heap, mem);
01912       }
01913 
01914       /* add the new constraint to the heap */
01915       EGheapInsert( gdata->cut_heap,
01916                     pkpc,
01917                     EGheapToCost( fabs(pkpc->slack) ),
01918                     mem );
01919       if ( !(*nadded) )
01920          (*best_val) = pkpc->slack;
01921       (*nadded) += 1;
01922     } 
01923 
01924 
01925     /* update global statistics */
01926     if (pkpc->slack < -0.01)
01927       gdata->nviolated += 1;
01928     if (pkpc->slack < gdata->min_violated)
01929         gdata->min_violated = pkpc->slack;
01930     if (pkpc->slack > gdata->max_violated)
01931         gdata->max_violated = pkpc->slack;
01932 
01933     #if DISPLAY_MODE
01934     if (add_cut_to_heap)
01935       EGdisplayStatus(stdout, gdata);
01936     #endif
01937 
01938     /* free dual form */
01939     EGfreeDKPC(dkpc, mem);
01940     dkpc = 0;
01941 
01942     /* if we do not keep the primal cut, we free it */
01943     if (!add_cut_to_heap && pkpc)
01944       EGfreePKPC(pkpc);
01945     pkpc = 0;
01946 
01947   }
01948 
01949   /* free objects used to derive this round of cuts */
01950   EGlistClearMP(pairs_list,EGfreeInternalPairs,mem);
01951   EGfreeList(pairs_list);
01952 
01953   return 0;
01954 
01955 }
01956                            
01957 void EGdisplayStatus(FILE *fout, EGgreedyData_t *gdata)
01958 {
01959 
01960   double hmax;
01961   EGheapCost_t hhmax;
01962 
01963   if (gdata->cut_heap->size)
01964   {
01965     hhmax = EGheapGetMinVal(gdata->cut_heap);
01966     hmax = EGheapCostToLf(hhmax);
01967   }
01968   else
01969     hmax = 0.0;
01970 
01971   //if(!(gdata->nviolated&0x1f))
01972   if(!(gdata->nviolated&0xf))
01973   fprintf(fout, "\rnviolated = %4u   min = %10lf   max = %10lf   hsz = %3u   hmax = %10lf", 
01974           gdata->nviolated, gdata->min_violated, gdata->max_violated, 
01975           gdata->cut_heap->size, -1*hmax);
01976 
01977   return;
01978 
01979 }
01980 
01981 
01982 int KPprocess_cut(int*cutset,
01983                   int cutsize,
01984                   double cutweight,
01985                   void*process_indo,
01986                   setlist**sets)
01987 {
01988   int rval = 0, nadded = 0;
01989   EGgreedyData_t*const data = (EGgreedyData_t*) process_indo;
01990   EGdualCut_t*dualcut = 0;
01991   double minslack;
01992   EGmemPool_t *mem = data->bdG->mem;
01993   
01994   /* to eliminate warnings from the compiler */
01995   sets = 0;
01996   cutweight = 0;
01997   
01998   /* get the dual cut */
01999   rval = EGgetDualCut(data, &dualcut, cutsize, cutset, data->pndummy,
02000                       data->pedummy, data->pedges);
02001   CHECKRVALG(rval,CLEANUP);
02002 
02003   /* separate: orientation = 0 */
02004   rval = KPseparateFromDualCut(dualcut, 0, data, &nadded, &minslack, 0.0);
02005   CHECKRVALG(rval,CLEANUP);
02006 
02007   if (nadded)
02008   {
02009     EGdualCut_t *dc_copy = EGcopyDualCut(mem, dualcut);
02010     EGaddDualCutToHeap(data->dc_heap,
02011                        dc_copy,
02012                        0, 
02013                        minslack,
02014                        mem);
02015   }
02016 
02017   /* separate: orientation = 1 */
02018   rval = KPseparateFromDualCut(dualcut, 1, data, &nadded, &minslack, 0.0);
02019   CHECKRVALG(rval,CLEANUP);
02020 
02021   if (nadded)
02022   {
02023     EGdualCut_t *dc_copy = EGcopyDualCut(mem, dualcut);
02024     EGaddDualCutToHeap(data->dc_heap,
02025                        dc_copy,
02026                        1, 
02027                        minslack,
02028                        mem);
02029   }
02030 
02031   EGfreeDualCut(dualcut,data->bdG->mem);
02032 
02033   /* ending */
02034   CLEANUP:
02035   return rval ? PROCESS_ERROR:PROCESS_INCOMPLETE;
02036 }
02037 
02038 int EGaddDualCutToHeap(EGheap_t *h, 
02039                        EGdualCut_t *dc, 
02040                        int orientation,
02041                        double lfval, 
02042                        EGmemPool_t *mem)
02043 {
02044 
02045   unsigned int i;
02046   EGheapCost_t hval = EGheapToCost(fabs(lfval));
02047   EGdualCut_t *hdc;
02048   EGcutSeed_t *hcs;
02049   int add_dc_to_heap = 0;
02050 
02051   /* sort dual cut data */
02052   qsort (dc->edges, dc->sz, sizeof (EGdGraphEdge_t *), EGedgeCompare);
02053 
02054   /* check first if the dual cut is already in the heap */
02055   for(i=0; i<h->size; i++)
02056   {
02057     hcs = (EGcutSeed_t*) h->heap[i]->this;
02058     hdc = hcs->dc;
02059     if ( hcs->orientation == orientation && EGareDualCutsEqual(hdc,dc) )
02060       goto DONE; 
02061   }
02062 
02063   /* if the heap is not full, in goes the cut */
02064   if ( h->size != h->max_size )
02065     add_dc_to_heap = 1;
02066   /* else, we compare it to the worst value in the heap */
02067   else if (EGheapCostIsLess(EGheapGetMinVal(h),hval))
02068   {
02069     /* if its better, we remove this 'bad' heap entry */
02070     hcs = (EGcutSeed_t*)EGheapGetMinThis(h);
02071     EGfreeDualCut(hcs->dc,mem);
02072     EGmemPoolSFree(hcs, EGcutSeed_t, 1, mem);
02073     EGheapDeleteMin(h,mem);
02074     add_dc_to_heap = 1;
02075   }
02076 
02077   DONE:
02078 
02079   /* add to the heap if we have decided to do so */
02080   if (add_dc_to_heap)
02081   {
02082     EGcutSeed_t *cs;
02083     cs = EGmemPoolSMalloc(mem, EGcutSeed_t, 1);
02084     cs->dc = dc;
02085     cs->orientation = orientation;
02086     EGheapInsert(h,cs,hval,mem);
02087   }
02088   else
02089     EGfreeDualCut(dc,mem);
02090   
02091   return 0; 
02092 
02093 }
02094 
02095 int EGareDualCutsEqual(EGdualCut_t *a, EGdualCut_t *b)
02096 {
02097   unsigned int i, are_equal = 0;
02098 
02099   if (a->sz != b->sz)
02100     goto DONE;
02101 
02102   for (i = 0; i < a->sz; i++)
02103     if (EGboyerEdgeNumber (a->edges[i]) != EGboyerEdgeNumber (b->edges[i]))
02104       goto DONE;
02105 
02106   are_equal = 1;
02107 
02108   DONE:
02109 
02110   return are_equal;
02111 }

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