eg_greedysample.c

Go to the documentation of this file.
00001 #include "eg_greedysample.h"
00002 
00003 /* CHANGES TO EG_GREEDYKP:
00004 
00005    1. Add eo_dist to EGgreedyData_t
00006    2. Add an array: double *cand_weight, of size (cycleG->nedges).
00007    3. Add an array: EGdGraphEdge_t **cand_edge, of size (cycleG->nedges).
00008 
00009 */
00010 
00011 int EGgenerateRandomInternalPairs( EGgreedyData_t *const gdata,
00012                                    EGlist_t *const new_pairs,
00013                                    EGlist_t *const old_pairs,
00014                                    unsigned int max_new_pairs,
00015                                    double sample_time )
00016 {
00017 
00018   int rval;
00019   EGlistNode_t *it;
00020   EGinternalPairs_t *old_p, *new_p;
00021   EGdijkstraCost_t ext_ubound;
00022   EGlist_t *ext_path;
00023   EGdijkstraCost_t ext_path_val;
00024   EGmemPool_t *mem = gdata->bdG->mem;
00025   EGtimer_t timer;
00026 
00027   const int ext_parity = 0;
00028   const EGdijkstraCost_t dij_two = EGdijkstraToCost(2.0);
00029 
00030   for(it=old_pairs->end; it; it=it->prev)
00031   {
00032 
00033     old_p = (EGinternalPairs_t*)(it->this);
00034     ext_ubound = EGdijkstraCostSub(dij_two,old_p->ivalue);
00035     EGtimerReset(&timer);
00036 
00037     while(1)
00038     {
00039 
00040       EGtimerStart(&timer);
00041 
00042       ext_path = EGnewList(mem);  
00043  
00044       rval = EGgreedySample(old_p->s,
00045                             old_p->t,
00046                             ext_ubound,
00047                             ext_parity,
00048                             gdata,
00049                             &ext_path_val,
00050                             ext_path);
00051       CHECKRVAL(rval);
00052 
00053       if (!ext_path->size)
00054       {
00055         //fprintf(stderr, "ignoring.\n");
00056         EGfreeList(ext_path);
00057       }
00058       else
00059       {
00060         //fprintf(stderr, "opt = %lf  new = %lf\n", EGdijkstraCostToLf(old_p->evalue), EGdijkstraCostToLf(ext_path_val));
00061         new_p = EGnewRandomInternalPairs(old_p, ext_path, ext_path_val, mem);
00062         TEST(!new_p, "bad internal pair generated");
00063         EGaddIPtoList(new_p, new_pairs, max_new_pairs); 
00064       }
00065 
00066       EGtimerStop(&timer);
00067       //fprintf(stderr, "%lf / %lf\n", timer.time, (sample_time / old_pairs->size) );
00068       if (timer.time > (sample_time / old_pairs->size) )
00069          break;
00070     }
00071 
00072   }
00073 
00074   return 0;
00075 
00076 }
00077 
00078 EGinternalPairs_t* EGnewRandomInternalPairs( EGinternalPairs_t *old_pair,
00079                                              EGlist_t *ext_path,
00080                                              EGdijkstraCost_t ext_value,
00081                                              EGmemPool_t *mem )
00082 {
00083   EGinternalPairs_t *p;
00084 
00085   p = EGmemPoolSMalloc(mem, EGinternalPairs_t, 1);
00086 
00087   p->s = old_pair->s;
00088   p->t = old_pair->t;
00089 
00090   p->value  = old_pair->ivalue + ext_value;
00091   p->ivalue = old_pair->ivalue;
00092   p->evalue = ext_value;
00093 
00094   p->npath = old_pair->npath;
00095   p->stpath = EGmemPoolSMalloc(mem, EGdGraphEdge_t*, p->npath);
00096   memcpy(p->stpath, old_pair->stpath, sizeof(EGdGraphEdge_t*)*(p->npath));
00097 
00098   p->extpath = ext_path;
00099 
00100   return p;
00101 }
00102 
00103 /* NOTE: s,t are given from the graph bdG. 
00104          we are sampling in the graph cycleG. */
00105 
00106 int EGgreedySample( EGdGraphNode_t *bdg_s,
00107                     EGdGraphNode_t *bdg_t,
00108                     EGdijkstraCost_t st_ubound, 
00109                     int st_parity,
00110                     EGgreedyData_t *gdata,
00111                     EGdijkstraCost_t *path_val,
00112                     EGlist_t *path )
00113 {
00114 
00115   unsigned int cnt = 0;
00116   EGdGraphNode_t *s, *t;
00117   EGdGraphNode_t *curr_s;
00118   EGdGraphEdge_t *curr_e;
00119   EGcycleData_t *cd;
00120   int curr_parity = 0, rem_parity=st_parity;
00121   int e_parity = 0;
00122   int curr_s_bdg_id;
00123   EGdijkstraCost_t e_val, rem_ubound, curr_val;
00124   EGlist_t *curr_path;
00125    
00126   if (!st_parity)
00127   {
00128     s = gdata->bdGtoCycleGmap[ bdg_s->id ];
00129     t = gdata->bdGtoCycleGmap[ bdg_t->id ];
00130   }
00131   else
00132   {
00133     s = gdata->bdGtoCycleGmap[ bdg_s->id ];
00134     t = (EGdGraphNode_t*) gdata->bdGtoCycleGmap[ bdg_t->id ]->cn->next->this;
00135   }
00136 
00137   curr_path = EGnewList(gdata->bdG->mem);
00138   EGlistClear(path, nullFree);
00139 
00140   *path_val = st_ubound;
00141 
00142   // here we could iterate if we wanted to, by adding a while or for.
00143   {
00144 
00145     //fprintf(stderr, "\n*** s = %d, t = %d *** \n\n", s->id, t->id);
00146 
00147     /* initialize */
00148     curr_s = s; 
00149     curr_val = EGdijkstraToCost(0.0);
00150     curr_parity = 0;
00151     rem_ubound = st_ubound;
00152     rem_parity = st_parity;
00153     EGlistClear(curr_path,nullFree);
00154     memset(gdata->bdnodes, 0, sizeof(EGdGraphNode_t*)*gdata->bdG->nodes->size);
00155 
00156     /* iterate through edges */
00157     for(cnt=0; cnt < gdata->cycleG->nodes->size; cnt++)
00158     {
00159 
00160       /* mark the current node as visited */
00161       curr_s_bdg_id = gdata->bdGnodeMap[curr_s->id/2]->id;
00162       gdata->bdnodes[curr_s_bdg_id] = (EGdGraphNode_t*)(1);
00163 
00164       /* sample an edge */
00165       curr_e = EGgreedySampleEdge(curr_s,  
00166                                   t, 
00167                                   rem_ubound, 
00168                                   rem_parity, 
00169                                   gdata);
00170       if (!curr_e)
00171       {
00172         EGlistClear(curr_path, nullFree);
00173         //fprintf(stderr, "[dead end]");
00174         break;
00175       }
00176 
00177       /* update current path information */
00178       cd = (EGcycleData_t*)curr_e->data;
00179       e_parity = (cd->ddom ? 1 : 0);
00180       curr_parity = ( e_parity == curr_parity ? 0 : 1 );
00181       rem_parity = ( st_parity ? 1 - curr_parity : curr_parity );
00182 
00183 /*
00184       fprintf(stderr, "(%d,%d) [%d,%lf] ", curr_e->tail->id, curr_e->head->id,
00185               e_parity, EGdijkstraCostToLf(cd->weight));
00186 */
00187 
00188       e_val = cd->weight;
00189       curr_val = EGdijkstraCostAdd(curr_val, e_val);
00190       rem_ubound = EGdijkstraCostSub(st_ubound, curr_val);
00191  
00192       curr_s = curr_e->head;
00193       EGlistPushBack(curr_path, curr_e);
00194  
00195       /* check if we reached the end */
00196       if ( (curr_s->id/2) == (t->id/2) )
00197         break;
00198     }
00199 
00200     //fprintf(stderr, "\n");  
00201 
00202     /* check if we looped out */
00203     if ( cnt == gdata->cycleG->nodes->size )
00204     {
00205       EGlistClear(curr_path, nullFree);
00206       MESSAGE(1, "WARNING: GOT CAUGHT IN AN INFINITE LOOP");
00207     }
00208 
00209     /* check parity of the path obtained */ 
00210     if ( curr_path->size && (curr_parity != st_parity) )
00211     {
00212         //fprintf(stderr, "bad parity.\n");
00213         EGlistClear(curr_path, nullFree);
00214     }
00215 
00216     /* keep the best list */
00217     if ( curr_path->size && EGdijkstraCostIsLess(curr_val, *path_val) )
00218     {
00219       EGlistClear(path,nullFree);
00220       while(curr_path->size)
00221       { 
00222         EGlistPushBack(path, curr_path->begin->this);
00223         EGlistErase(curr_path, curr_path->begin, nullFree);
00224       }
00225       *path_val = curr_val;
00226     }
00227     EGlistClear(curr_path, nullFree);
00228 
00229   }
00230 
00231   EGfreeList(curr_path);
00232   
00233   return 0;
00234 
00235 }
00236 
00237 EGdGraphEdge_t* EGgreedySampleEdge(EGdGraphNode_t *s, 
00238                                    EGdGraphNode_t *t, 
00239                                    EGdijkstraCost_t st_ubound,
00240                                    int st_parity,
00241                                    EGgreedyData_t *gdata)
00242 {
00243  
00244   int i, e_parity, cnt; 
00245   unsigned int bdg_head, bdg_t;
00246   EGlistNode_t *it;
00247   EGdGraphEdge_t *next_e=0, *e;
00248   EGdijkstraCost_t slack, st_lbound;
00249   double tot = 0.0;
00250   double rvalue;
00251   EGcycleData_t *cd;
00252 
00253   double *cand_weight = gdata->pedgevals;
00254   EGdGraphEdge_t **cand_edge = gdata->pedges;
00255 
00256   //fprintf(stderr, "st_ubound = %lf, st_parity = %d\n", EGdijkstraCostToLf(st_ubound), st_parity);
00257 
00258   //fprintf(stderr," s_out_edges = %u\n", s->out_edges->size);
00259 
00260   for(i=0, cnt=0, it=s->out_edges->begin; it && cnt < gdata->norig_edges; it=it->next, i++)
00261   {
00262 
00263     e = (EGdGraphEdge_t*)(it->this);
00264     cd = (EGcycleData_t*)(e->data);
00265 
00266     e_parity = (cd->ddom ? 1 : 0);
00267 
00268     bdg_head = gdata->bdGnodeMap[ e->head->id / 2 ]->id;
00269     bdg_t = gdata->bdGnodeMap[ t->id / 2 ]->id;
00270 
00271     // check if we have visitied the head node already
00272     if ( gdata->bdnodes[bdg_head] )
00273       continue;
00274 
00275     // we add an extra comparison because even/odd distance might == EG_DIJKSTRA_COST_MAX
00276     if ( st_parity == e_parity )
00277     {
00278       if (EGdijkstraCostIsLess(st_ubound, EGgetEvenDistance(bdg_head, bdg_t, gdata)))
00279         continue;
00280       st_lbound = EGdijkstraCostAdd( cd->weight, EGgetEvenDistance(bdg_head, bdg_t, gdata) );
00281     }
00282     else
00283     {
00284       if (EGdijkstraCostIsLess(st_ubound, EGgetOddDistance(bdg_head, bdg_t, gdata)))
00285         continue;
00286       st_lbound = EGdijkstraCostAdd( cd->weight, EGgetOddDistance(bdg_head, bdg_t, gdata) );
00287     }
00288 
00289     slack = EGdijkstraCostSub( st_ubound, st_lbound );
00290 
00291     #if 0
00292     fprintf(stderr, "%d candidate: (%d, %d) [%d, %lf] dist(%d, %d, %d) = %lf slack=%lf\n", i, 
00293                      e->tail->id, e->head->id, e_parity, EGdijkstraCostToLf(cd->weight),
00294                      e->tail->id, e->head->id, t->id, EGdijkstraCostToLf(st_lbound), EGdijkstraCostToLf(slack));
00295     #endif
00296 
00297     if ( EGdijkstraCostIsLess(slack,EGdijkstraToCost(0.0)) )
00298       continue;
00299 
00300     cand_edge[cnt] = e;
00301     cand_weight[cnt] = EGdijkstraCostToLf(slack);
00302     tot += cand_weight[cnt];
00303     cnt += 1;
00304 
00305   } 
00306 
00307   if (!cnt || cnt == gdata->norig_edges)
00308     goto DONE;
00309 
00310   next_e = cand_edge[0];
00311 
00312   rvalue = random();
00313   rvalue /= EGRAND_MAX;
00314   rvalue *= tot;
00315 
00316   tot = 0.0;
00317 
00318   for(i=0; i<cnt; i++)
00319   {
00320     tot += cand_weight[i];
00321     if ( rvalue < tot )
00322     {
00323       next_e = cand_edge[i];
00324       break;
00325     }
00326   }
00327 
00328   DONE:
00329 
00330   return next_e;
00331 
00332 }
00333 
00334 // assumes the list is sorted, from least slack, to most slack
00335 // clears the item if it is not to go in
00336 int EGaddIPtoList(EGinternalPairs_t *p, EGlist_t *pairs, unsigned int max_size)
00337 {
00338 
00339   EGinternalPairs_t *q, *r;
00340   EGlistNode_t *it=0, *it2=0;
00341 
00342   /* if the list pairs is full, check to see if we have more slack 
00343      than every member of the list */
00344   if ( pairs->size && pairs->size == max_size )
00345   {
00346     q = (EGinternalPairs_t*)(pairs->end->this);
00347     if ( !EGdijkstraCostIsLess(p->value, q->value) )
00348       goto NO_ADD;
00349   }
00350 
00351   /* find the first element in the list who is not better than p */
00352   for(it = pairs->begin; it; it=it->next)
00353   {
00354     q = (EGinternalPairs_t*)(it->this); 
00355     if ( !EGdijkstraCostIsLess(q->value, p->value) )
00356       break;
00357   }
00358   //TEST(!it, "bad list");
00359 
00360   /* make sure p is not already in the list */
00361   /* for this, check every r having the same slack as q */
00362   for(it2 = it; it2; it2=it2->next) 
00363   {
00364     r = (EGinternalPairs_t*)(it2->this);
00365     if (r->value == p->value)
00366     {
00367       if (r->s == p->s)
00368         if (r->t == p->t)
00369           if (r->extpath->size == p->extpath->size)
00370             if (r->extpath->begin->this == p->extpath->begin->this)
00371               if (r->extpath->end->this == p->extpath->end->this)
00372                 goto NO_ADD;
00373     }
00374     else
00375      break;
00376   }
00377 
00378   /* insert p before q */
00379   if (it)
00380     EGlistInsertBefore(pairs,it,p);
00381   else
00382     EGlistPushBack(pairs, p);
00383 
00384   while(pairs->size > max_size)
00385     EGlistEraseMP(pairs, pairs->end, EGfreeInternalPairs, pairs->mempool);
00386 
00387   return 0;
00388 
00389   NO_ADD:
00390 
00391   EGfreeInternalPairs(p,pairs->mempool);
00392 
00393   return 0;
00394 
00395 }
00396 
00397 // careful! This frees the two incoming lists!!
00398 EGlist_t* EGmergeIPlists(EGlist_t *first, EGlist_t *second)
00399 {
00400 
00401   EGlist_t *mlist;
00402   EGlistNode_t *it1, *it2;
00403   EGinternalPairs_t *p1, *p2;
00404 
00405   mlist = EGnewList(first->mempool);
00406 
00407   for(it1=first->begin, it2=second->begin; it1 || it2; )
00408   {
00409     p1 = it1 ? (EGinternalPairs_t*)(it1->this) : 0; 
00410     p2 = it2 ? (EGinternalPairs_t*)(it2->this) : 0;
00411     if (!it1)
00412     {
00413       EGlistPushBack(mlist, p2);
00414       it2=it2->next;
00415     }
00416     else if (!it2)
00417     {
00418       EGlistPushBack(mlist, p1);
00419       it1=it1->next;
00420     }
00421     else if (p1->value < p2->value)
00422     {
00423       EGlistPushBack(mlist, p1);
00424       it1=it1->next;
00425     }
00426     else
00427     {
00428       EGlistPushBack(mlist, p2);
00429       it2=it2->next;
00430     }
00431   }
00432 
00433   EGlistClear(first, nullFree);
00434   EGlistClear(second, nullFree);
00435   EGfreeList(first);
00436   EGfreeList(second);
00437 
00438   return mlist;
00439 
00440 }

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