eg_dptighten.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include "dp_config.h"
00004 #include "eg_mempool.h"
00005 #include "eg_dptighten.h"
00006 #define DPT_ENABLE 1
00007 #if DPT_ENABLE
00008 #include "eg_ugraph.h"
00009 #include "eg_bit.h"
00010 #include "eg_util.h"
00011 #include "eg_bbtree.h"
00012 /* ========================================================================= */
00013 /* various size, note that the maximujm sizes must be of the form 2^n */
00014 #define DPT_MAX_DOM 512U
00015 #define DPT_MAX_DOM_LOG 9U
00016 #define DPT_MAX_NODE 131072U
00017 #define DPT_MAX_NODE_LOG 17U
00018 #define DPT_MAX_DEPTH 1U
00019 /* ========================================================================= */
00020 /* data structure to handle information about the graph */
00021 /* ========================================================================= */
00022 
00023 /* ========================================================================= */
00025 typedef struct
00026 {
00027   unsigned int n_id:DPT_MAX_NODE_LOG; 
00029   unsigned int move_id:5;             
00030   unsigned int dom;                   
00031 }
00032 DPTMove_t;
00033 
00034 /* ========================================================================= */
00036 typedef struct
00037 {
00038   DPTMove_t move[DPT_MAX_DEPTH];    
00039   double val;                       
00040   unsigned int depth;               
00041 }
00042 DPTFullMove_t;
00043 
00044 /* ========================================================================= */
00046 typedef struct
00047 {
00048   unsigned int n_H[2];
00049   unsigned int n_dominos:DPT_MAX_DOM_LOG;
00050   unsigned int n_nodes:DPT_MAX_NODE_LOG;  
00051   unsigned int n_A[DPT_MAX_DOM];          
00052   unsigned int n_B[DPT_MAX_DOM];          
00053   unsigned int n_Tc[DPT_MAX_DOM];     
00054 }
00055 DPTGdata_t;
00056 
00057 /* ========================================================================= */
00059 typedef struct
00060 {
00061   unsigned int n_AtoB:DPT_MAX_DOM_LOG;  
00063   unsigned int n_dT:DPT_MAX_DOM_LOG;  
00065   unsigned int in_F:1;        
00066 }
00067 DPTEdata_t;
00068 
00069 /* ========================================================================= */
00071 struct DPTNdata_t
00072 {
00073   /* ======================================================================= */
00074   /* link to the internal information */
00075   /* ======================================================================= */
00076   EGbbtreeNode_t *tree_cn;      
00078   /* ======================================================================= */
00079   /* cut description, this HAVE to be keeped wright at every iteration */
00080   /* ======================================================================= */
00081   EGbitset_t Ia[DPT_MAX_DOM >> __EGBIT_SHIFT__];
00084   EGbitset_t Ib[DPT_MAX_DOM >> __EGBIT_SHIFT__];
00087   EGbitset_t added[DPT_MAX_DOM >> __EGBIT_SHIFT__];
00090   EGbitset_t flipA[DPT_MAX_DOM >> __EGBIT_SHIFT__];
00093   EGbitset_t flipB[DPT_MAX_DOM >> __EGBIT_SHIFT__];
00096   unsigned int n_in_A:DPT_MAX_DOM_LOG;
00098   unsigned int n_in_T:DPT_MAX_DOM_LOG;
00100   unsigned int in_H:1;          
00101   unsigned int added_H:1;       
00102   /* ======================================================================= */
00103   /* move information, this may be changed later on */
00104   /* ======================================================================= */
00105   DPTFullMove_t full_move;      
00106 };
00107 typedef struct DPTNdata_t DPTNdata_t;
00108 
00109 /* ========================================================================= */
00110 /* static variables, these variables hold the graphData, node data and edge
00111  * data, the later two indexed by node->id and edge->id respectivelly. */
00112 static DPTNdata_t *nodeData = 0;
00113 static DPTEdata_t *edgeData = 0;
00114 static DPTGdata_t graphData;
00115 static EGuGraph_t *G = 0;
00116 static EGuGraphNode_t **all_nodes;
00117 static EGuGraphEdge_t **all_edges;
00118 static double const *weight;
00119 static EGbbtree_t *tree;
00120 static EGbitset_t node_update[DPT_MAX_NODE >> __EGBIT_SHIFT__];
00121 
00122 /* ========================================================================= */
00123 /* some macros to make access easy */
00124 /* ========================================================================= */
00125 /* the minimum improvement is for the local search, if negative it means that
00126  * it will allow movements that may worsen the inequality */
00127 #define DPTMinImprovement (-1e-6)
00128 
00129 /* constants for the moves */
00130 enum move
00131 {
00132   DPT_Tc_A,                     /* move a node from A to Tc */
00133   DPT_Tc_B,                     /* move a node from B to Tc */
00134   DPT_Hc_H,                     /* move a node from H to Hc */
00135   DPT_A_B,                      /* move a node from A to B */
00136   DPT_B_A,                      /* move a node from A to B */
00137   DPT_B_A_flipH,                /* move a node from A to B */
00138   DPT_A_B_flipH,                /* move a node from A to B */
00139   DPT_A_Tc,                     /* move a node from A to Tc */
00140   DPT_B_Tc,                     /* move a node from B to Tc */
00141   DPT_H_Hc,                     /* move a node from H to Hc */
00142   DPT_no_move                   /* no feasible move found */
00143 };
00144 
00145 /* string names for the moves */
00146 static const char move_name[11][20] = {[DPT_no_move] = "DPT_no_move",
00147   [DPT_A_Tc] = "DPT_A_Tc",
00148   [DPT_B_Tc] = "DPT_B_Tc",
00149   [DPT_A_B] = "DPT_A_B",
00150   [DPT_H_Hc] = "DPT_H_Hc",
00151   [DPT_Tc_A] = "DPT_Tc_A",
00152   [DPT_Tc_B] = "DPT_Tc_B",
00153   [DPT_B_A] = "DPT_B_A",
00154   [DPT_Hc_H] = "DPT_Hc_H",
00155   [DPT_A_B_flipH] = "DPT_A_B_flipH",
00156   [DPT_B_A_flipH] = "DPT_B_A_flipH"
00157 };
00158 /* inverse move for every move */
00159 static unsigned char DPT_inv_move[11] = {[DPT_no_move] = DPT_no_move,
00160   [DPT_A_Tc] = DPT_Tc_A,
00161   [DPT_B_Tc] = DPT_Tc_B,
00162   [DPT_A_B] = DPT_B_A,
00163   [DPT_H_Hc] = DPT_Hc_H,
00164   [DPT_Tc_A] = DPT_A_Tc,
00165   [DPT_Tc_B] = DPT_B_Tc,
00166   [DPT_B_A] = DPT_A_B,
00167   [DPT_Hc_H] = DPT_H_Hc,
00168   [DPT_A_B_flipH] = DPT_B_A_flipH,
00169   [DPT_B_A_flipH] = DPT_A_B_flipH
00170 };
00171 
00172 /* ========================================================================= */
00173 /* some macros */
00174 #define DPTgetEdge(__e_it) ((EGuGraphEdge_t*)(__e_it->this))
00175 #define DPTgetOtherEndId(__n_id,__e_it) (__n_id == DPTgetEdge(__e_it)->head->id ? DPTgetEdge(__e_it)->tail->id : DPTgetEdge(__e_it)->head->id)
00176 #define DPTgetEdgeId(__e_it) (DPTgetEdge(__e_it)->id)
00177 #define DPTNdata(__this) ((DPTNdata_t*)(__this))
00178 
00179 /* ========================================================================= */
00180 /* local static functions */
00181 /* ========================================================================= */
00182 
00183 #if DPT_VRB <= DEBUG || DPT_DBG < DEBUG || DPT_EDBG < DEBUG
00184 /* ========================================================================= */
00185 /* this function display on the screen what move are we performing */
00186 /* ========================================================================= */
00187 static inline void DPdisplaySingleMove (const DPTMove_t * const move)
00188 {
00189   /* local variables */
00190   EGlistNode_t *e_it;
00191   unsigned no_id,
00192     e_id,
00193     dom = move->dom;
00194   /* printing information */
00195   fprintf (stderr, "\tNode %u:%s:%u", move->n_id, move_name[move->move_id],
00196            dom);
00197   switch (move->move_id)
00198   {
00199   case DPT_A_Tc:
00200   case DPT_Tc_A:
00201     fprintf (stderr, ":%u(%u,%u,%u):%s", dom, graphData.n_A[dom],
00202              graphData.n_B[dom], graphData.n_Tc[dom],
00203              EGbitTest (nodeData[move->n_id].Ia, dom) ? "A" :
00204              EGbitTest (nodeData[move->n_id].Ib, dom) ? "B" : "T^c");
00205     /* printing adjacent edges information */
00206     for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
00207     {
00208       no_id = DPTgetOtherEndId (move->n_id, e_it);
00209       e_id = DPTgetEdgeId (e_it);
00210       fprintf (stderr, "\n\t\te=(%u:%s,%u:%s)[%8.6lf]F[%u]",
00211                move->n_id, EGbitTest (nodeData[move->n_id].Ia, dom) ? "A" :
00212                EGbitTest (nodeData[move->n_id].Ib, dom) ? "B" : "T^c",
00213                no_id, EGbitTest (nodeData[no_id].Ia, dom) ? "A" :
00214                EGbitTest (nodeData[no_id].Ib, dom) ? "B" : "T^c",
00215                weight[e_id], edgeData[e_id].in_F);
00216     }
00217     break;
00218   case DPT_B_Tc:
00219   case DPT_Tc_B:
00220     fprintf (stderr, ":%u(%u,%u,%u):%s", dom, graphData.n_B[dom],
00221              graphData.n_A[dom], graphData.n_Tc[dom],
00222              EGbitTest (nodeData[move->n_id].Ia, dom) ? "A" :
00223              EGbitTest (nodeData[move->n_id].Ib, dom) ? "B" : "T^c");
00224     /* printing adjacent edges information */
00225     for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
00226     {
00227       no_id = DPTgetOtherEndId (move->n_id, e_it);
00228       e_id = DPTgetEdgeId (e_it);
00229       fprintf (stderr, "\n\t\te=(%u:%s,%u:%s)[%8.6lf]F[%u]",
00230                move->n_id,
00231                EGbitTest (nodeData[move->n_id].Ia, dom) ? "A" :
00232                EGbitTest (nodeData[move->n_id].Ib, dom) ? "B" : "T^c",
00233                no_id, EGbitTest (nodeData[no_id].Ia, dom) ? "A" :
00234                EGbitTest (nodeData[no_id].Ib, dom) ? "B" : "T^c",
00235                weight[e_id], edgeData[e_id].in_F);
00236     }
00237     break;
00238   case DPT_A_B_flipH:
00239   case DPT_B_A_flipH:
00240   case DPT_A_B:
00241   case DPT_B_A:
00242     fprintf (stderr, ":%u(%u,%u,%u):%s", dom, graphData.n_A[dom],
00243              graphData.n_B[dom], graphData.n_Tc[dom],
00244              EGbitTest (nodeData[move->n_id].Ia, dom) ? "A" : "B");
00245     /* printing adjacent edges information */
00246     for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
00247     {
00248       no_id = DPTgetOtherEndId (move->n_id, e_it);
00249       e_id = DPTgetEdgeId (e_it);
00250       fprintf (stderr, "\n\t\te=(%u:%s,%u:%s)[%8.6lf]F[%u]",
00251                move->n_id, EGbitTest (nodeData[move->n_id].Ia, dom) ? "A" :
00252                EGbitTest (nodeData[move->n_id].Ib, dom) ? "B" : "T^c",
00253                no_id, EGbitTest (nodeData[no_id].Ia, dom) ? "A" :
00254                EGbitTest (nodeData[no_id].Ib, dom) ? "B" : "T^c",
00255                weight[e_id], edgeData[e_id].in_F);
00256     }
00257     break;
00258   case DPT_Hc_H:
00259   case DPT_H_Hc:
00260     fprintf (stderr, "(%u,%u):%s", graphData.n_H[1], graphData.n_H[0],
00261              (nodeData[move->n_id].in_H & 1U) ? "H" : "H^c");
00262     /* printing adjacent edges information */
00263     for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
00264     {
00265       no_id = DPTgetOtherEndId (move->n_id, e_it);
00266       e_id = DPTgetEdgeId (e_it);
00267       fprintf (stderr, "\n\t\te=(%u,%u)[%8.6lf]F[%u]",
00268                move->n_id, no_id, weight[e_id], edgeData[e_id].in_F);
00269     }
00270     break;
00271   }
00272   fprintf (stderr, "\n");
00273 }
00274 
00275 /* ========================================================================= */
00276 /* this function display on the screen what move are we performing */
00277 /* ========================================================================= */
00278 static inline int DPdisplayMove (unsigned int const nc_id)
00279 {
00280   unsigned depth = nodeData[nc_id].full_move.depth;
00281   fprintf (stderr, "Move Stored for node %u:%u\n", nc_id,
00282            nodeData[nc_id].full_move.depth);
00283   while (depth--)
00284     DPdisplaySingleMove (nodeData[nc_id].full_move.move + depth);
00285   fprintf (stderr, "\tValue %lf\n", nodeData[nc_id].full_move.val);
00286   fprintf (stderr, "\t");
00287   __EG_PRINTLOC2__;
00288   return 1;
00289 }
00290 #endif
00291 
00292 /* ========================================================================= */
00293 /* this function compute the violation of the curently stored constraint */
00294 /* ========================================================================= */
00295 static inline void DPTpriceConstraint (double *l_violation)
00296 {
00297   register unsigned int i;
00298   /* finally we compute the in_F field for all edges */
00299   for (i = G->nedges; i--;)
00300   {
00301     (*l_violation) += (edgeData[i].in_F + edgeData[i].n_AtoB +
00302                        edgeData[i].n_dT) * weight[i];
00303   }
00304   return;
00305 }
00306 
00307 #if (DPT_VRB <= DEBUG-1) || (DPT_EDBG <= DEBUG)
00308 /* ========================================================================= */
00310 /* ========================================================================= */
00311 static inline int DPTDisplayEdges (void)
00312 {
00313   register unsigned int i;
00314   register unsigned j;
00315   unsigned h_id,
00316     t_id;
00317   /* finally we compute the in_F field for all edges */
00318   for (i = G->nedges; i--;)
00319   {
00320     h_id = all_edges[i]->head->id;
00321     t_id = all_edges[i]->tail->id;
00322     if (weight[i] > 1e-3)
00323     {
00324       fprintf (stderr, "e(%u)[%u,%u][%8.6lf] bellongs to: ", i,
00325                h_id, t_id, weight[i]);
00326       for (j = graphData.n_dominos; j--;)
00327       {
00328         if (EGbitTest (nodeData[h_id].Ia, j) !=
00329             EGbitTest (nodeData[t_id].Ia, j))
00330           fprintf (stderr, "delta(A_%u) ", j);
00331         if (EGbitTest (nodeData[h_id].Ib, j) !=
00332             EGbitTest (nodeData[t_id].Ib, j))
00333           fprintf (stderr, "delta(B_%u) ", j);
00334       }
00335       if (nodeData[h_id].in_H != nodeData[t_id].in_H)
00336         fprintf (stderr, "delta(H) ");
00337       if (edgeData[i].in_F)
00338         fprintf (stderr, "F ");
00339       fprintf (stderr, "\n");
00340     }
00341   }
00342   return 1;
00343 }
00344 #endif
00345 
00346 /* ========================================================================= */
00348 /* ========================================================================= */
00349 static int EGdpTightNdataCompare (const void *N1,
00350                                   const void *N2)
00351 {
00352   /* we first check if the values are near-zero, if so, we sort according to 
00353    * the type of the movement */
00354   if ((fabs (((const DPTNdata_t *) N1)->full_move.val) <
00355        fabs (DPTMinImprovement))
00356       && (fabs (((const DPTNdata_t *) N2)->full_move.val) <
00357           fabs (DPTMinImprovement)))
00358   {
00359     /* Sort by first move order */
00360     if (((const DPTNdata_t *) N1)->full_move.move[0].move_id <
00361         ((const DPTNdata_t *) N2)->full_move.move[0].move_id)
00362       return -1;
00363     if (((const DPTNdata_t *) N1)->full_move.move[0].move_id >
00364         ((const DPTNdata_t *) N2)->full_move.move[0].move_id)
00365       return 1;
00366     /* if they have the same type. choose by simplicity */
00367     if (((const DPTNdata_t *) N1)->full_move.depth <
00368         ((const DPTNdata_t *) N2)->full_move.depth)
00369       return -1;
00370     if (((const DPTNdata_t *) N1)->full_move.depth >
00371         ((const DPTNdata_t *) N2)->full_move.depth)
00372       return 1;
00373     if( N1 < N2) return -1;
00374     if( N1 > N2) return 1;
00375     return 0;
00376   }
00377   /* otherwise we sort by value */
00378   if (((const DPTNdata_t *) N1)->full_move.val <
00379       ((const DPTNdata_t *) N2)->full_move.val)
00380     return -1;
00381   if (((const DPTNdata_t *) N1)->full_move.val >
00382       ((const DPTNdata_t *) N2)->full_move.val)
00383     return 1;
00384   if( N1 < N2) return -1;
00385   if( N1 > N2) return 1;
00386   return 0;
00387 }
00388 
00389 /* ========================================================================= */
00391 /* ========================================================================= */
00392 #if DPT_EDBG < DEBUG
00393 #define DPTupdateMove(__cmove,__bmove) __DPTupdateMove(__cmove,__bmove,__FILE__,__LINE__,__func__)
00394 #else
00395 #define DPTupdateMove(__cmove,__bmove) __DPTupdateMove(__cmove,__bmove)
00396 #endif
00397 static inline int __DPTupdateMove (const DPTFullMove_t * const cur_move,
00398                                    DPTFullMove_t * const best_move
00399 #if DPT_EDBG < DEBUG
00400                                    ,
00401                                    const char *file,
00402                                    const int line,
00403                                    const char *function
00404 #endif
00405   )
00406 {
00407   if ((cur_move->val + fabs (DPTMinImprovement) < best_move->val) ||
00408       (cur_move->move[0].move_id < best_move->move[0].move_id &&
00409        (fabs (cur_move->val - best_move->val) < fabs (DPTMinImprovement))))
00410   {
00411 #if DPT_VRB+1900<DEBUG
00412     fprintf (stderr, "Storing Move for node %u\n", cur_move->move[0].n_id);
00413     {
00414       unsigned l_depth = cur_move->depth + 1;
00415       while (l_depth--)
00416         DPdisplaySingleMove (cur_move->move + l_depth);
00417       fprintf (stderr, "\tValue %lf\n", cur_move->val);
00418     }
00419 #endif
00420 #if DPT_EDBG < DEBUG
00421     {
00422       unsigned int l_depth = cur_move->depth;
00423       while (l_depth--)
00424         EXIT (cur_move->move[l_depth].move_id == DPT_no_move,
00425               "Storing DPT_no_move for depth %u, called from %s at %s:%d",
00426               l_depth, function, file, line);
00427     }
00428 #endif
00429     memcpy (best_move, cur_move, sizeof (DPTFullMove_t));
00430   }
00431   return 0;
00432 }
00433 
00434 /* ========================================================================= */
00436 /* ========================================================================= */
00437 static inline int DPTpriceTcA (const DPTMove_t * const cur_move,
00438                                double *const move_val)
00439 {
00440   /* local variables */
00441   EGlistNode_t *e_it = all_nodes[cur_move->n_id]->edges->begin;
00442   unsigned e_id,
00443     no_id,
00444     pos;
00445 
00446   /* we have to compute every move */
00447   for (; e_it; e_it = e_it->next)
00448   {
00449     e_id = DPTgetEdgeId (e_it);
00450     no_id = DPTgetOtherEndId (cur_move->n_id, e_it);
00451     pos = (EGbitTest (nodeData[no_id].Ia, cur_move->dom) ? 2U : 0U) |
00452       (EGbitTest (nodeData[no_id].Ib, cur_move->dom) ? 1U : 0U);
00453     switch (pos)
00454     {
00455     case 0U:
00456       /* in this case the only change is that we have to pay for this edge in the
00457        * Delta(T) */
00458       (*move_val) += weight[e_id];
00459       break;
00460       /* in this case we save one Delta(T), pay one E(A:B) and flip in_F because
00461        * we are changing parity of \sum E(A:B) */
00462     case 1U:
00463       if (edgeData[e_id].in_F)
00464         (*move_val) -= weight[e_id];
00465       else
00466         (*move_val) += weight[e_id];
00467       break;
00468       /* in this case we save one Delta(T) */
00469     case 2U:
00470       (*move_val) -= weight[e_id];
00471       break;
00472     default:
00473       EXIT (1, "This should not happen");
00474     }                           /* end switch */
00475   }                             /* end loop through all incident edges */
00476   return 0;
00477 }
00478 
00479 /* ========================================================================= */
00481 /* ========================================================================= */
00482 static inline int DPTpriceTcB (const DPTMove_t * const cur_move,
00483                                double *const move_val)
00484 {
00485   /* local variables */
00486   EGlistNode_t *e_it = all_nodes[cur_move->n_id]->edges->begin;
00487   unsigned e_id,
00488     no_id,
00489     pos;
00490 
00491   /* we have to compute every move */
00492   for (; e_it; e_it = e_it->next)
00493   {
00494     e_id = DPTgetEdgeId (e_it);
00495     no_id = DPTgetOtherEndId (cur_move->n_id, e_it);
00496     pos = (EGbitTest (nodeData[no_id].Ia, cur_move->dom) ? 2U : 0U) |
00497       (EGbitTest (nodeData[no_id].Ib, cur_move->dom) ? 1U : 0U);
00498     switch (pos)
00499     {
00500     case 0U:
00501       /* in this case the only change is that we have to pay for this edge in the
00502        * Delta(T) */
00503       (*move_val) += weight[e_id];
00504       break;
00505       /* in this case we save one Delta(T), pay one E(A:B) and flip in_F because
00506        * we are changing parity of \sum E(A:B) */
00507     case 2U:
00508       if (edgeData[e_id].in_F)
00509         (*move_val) -= weight[e_id];
00510       else
00511         (*move_val) += weight[e_id];
00512       break;
00513       /* in this case we save one Delta(T) */
00514     case 1U:
00515       (*move_val) -= weight[e_id];
00516       break;
00517     default:
00518       EXIT (1, "This should not happen");
00519     }                           /* end switch */
00520   }                             /* end loop through all incident edges */
00521   return 0;
00522 }
00523 
00524 /* ========================================================================= */
00526 /* ========================================================================= */
00527 static inline int DPTpriceAB (const DPTMove_t * const cur_move,
00528                               double *const move_val)
00529 {
00530   /* local variables */
00531   EGlistNode_t *e_it = all_nodes[cur_move->n_id]->edges->begin;
00532   unsigned e_id,
00533     no_id,
00534     pos;
00535 
00536   /* we have to compute every move */
00537   for (; e_it; e_it = e_it->next)
00538   {
00539     e_id = DPTgetEdgeId (e_it);
00540     no_id = DPTgetOtherEndId (cur_move->n_id, e_it);
00541     pos = (EGbitTest (nodeData[no_id].Ia, cur_move->dom) ? 2U : 0U) |
00542       (EGbitTest (nodeData[no_id].Ib, cur_move->dom) ? 1U : 0U);
00543     switch (pos)
00544     {
00545     case 0U:
00546       /* in this case nathing change */
00547       break;
00548       /* in this case we save one E(A:B) but have to flip in_F */
00549     case 1U:
00550       if (edgeData[e_id].in_F)
00551         (*move_val) -= 2 * weight[e_id];
00552       break;
00553       /* in this case we pay one E(A:B) but have to flip in_F */
00554     case 2U:
00555       if (!edgeData[e_id].in_F)
00556         (*move_val) += 2 * weight[e_id];
00557       break;
00558     default:
00559       EXIT (1, "This should not happen");
00560     }                           /* end switch */
00561   }                             /* end loop through all incident edges */
00562   return 0;
00563 }
00564 
00565 /* ========================================================================= */
00568 /* ========================================================================= */
00569 static inline int DPTpriceABflipH (DPTMove_t const *const cur_move,
00570                                    double *const move_val)
00571 {
00572   /* local variables */
00573   EGlistNode_t *e_it;
00574   unsigned e_id,
00575     no_id,
00576     pos;
00577 
00578   /* we have to compute every move */
00579   for (e_it = all_nodes[cur_move->n_id]->edges->begin; e_it; e_it = e_it->next)
00580   {
00581     e_id = DPTgetEdgeId (e_it);
00582     no_id = DPTgetOtherEndId (cur_move->n_id, e_it);
00583     pos = (EGbitTest (nodeData[no_id].Ia, cur_move->dom) ? 2U : 0U) |
00584       (EGbitTest (nodeData[no_id].Ib, cur_move->dom) ? 1U : 0U);
00585     switch (pos)
00586     {
00587     case 0U:
00588       /* in this case nathing change */
00589       if (edgeData[e_id].in_F)
00590         (*move_val) -= weight[e_id];
00591       else
00592         (*move_val) += weight[e_id];
00593       break;
00594       /* in this case we save one E(A:B) but have to double flip in_F */
00595     case 1U:
00596       (*move_val) -= weight[e_id];
00597       break;
00598       /* in this case we pay one E(A:B) but have to double flip in_F */
00599     case 2U:
00600       (*move_val) += weight[e_id];
00601       break;
00602     default:
00603       EXIT (1, "This should not happen");
00604     }                           /* end switch */
00605   }                             /* end loop through all incident edges */
00606   return 0;
00607 }
00608 
00609 /* ========================================================================= */
00611 /* ========================================================================= */
00612 static inline int DPTpriceBA (DPTMove_t const *const cur_move,
00613                               double *const move_val)
00614 {
00615   /* local variables */
00616   EGlistNode_t *e_it;
00617   unsigned e_id,
00618     no_id,
00619     pos;
00620 
00621   /* we have to compute every move */
00622   for (e_it = all_nodes[cur_move->n_id]->edges->begin; e_it; e_it = e_it->next)
00623   {
00624     e_id = DPTgetEdgeId (e_it);
00625     no_id = DPTgetOtherEndId (cur_move->n_id, e_it);
00626     pos = (EGbitTest (nodeData[no_id].Ia, cur_move->dom) ? 2U : 0U) |
00627       (EGbitTest (nodeData[no_id].Ib, cur_move->dom) ? 1U : 0U);
00628     switch (pos)
00629     {
00630     case 0U:
00631       /* in this case nathing change */
00632       break;
00633       /* in this case we save one E(A:B) but have to flip in_F */
00634     case 2U:
00635       if (edgeData[e_id].in_F)
00636         (*move_val) -= 2 * weight[e_id];
00637       break;
00638       /* in this case we pay one E(A:B) but have to flip in_F */
00639     case 1U:
00640       if (!edgeData[e_id].in_F)
00641         (*move_val) += 2 * weight[e_id];
00642       break;
00643     default:
00644       EXIT (1, "This should not happen");
00645     }                           /* end switch */
00646   }                             /* end loop through all incident edges */
00647   return 0;
00648 }
00649 
00650 /* ========================================================================= */
00653 /* ========================================================================= */
00654 static inline int DPTpriceBAflipH (DPTMove_t const *const cur_move,
00655                                    double *const move_val)
00656 {
00657   /* local variables */
00658   EGlistNode_t *e_it;
00659   unsigned e_id,
00660     no_id,
00661     pos;
00662 
00663   /* we have to compute every move */
00664   for (e_it = all_nodes[cur_move->n_id]->edges->begin; e_it; e_it = e_it->next)
00665   {
00666     e_id = DPTgetEdgeId (e_it);
00667     no_id = DPTgetOtherEndId (cur_move->n_id, e_it);
00668     pos = (EGbitTest (nodeData[no_id].Ia, cur_move->dom) ? 2U : 0U) |
00669       (EGbitTest (nodeData[no_id].Ib, cur_move->dom) ? 1U : 0U);
00670     switch (pos)
00671     {
00672     case 0U:
00673       /* in this case nathing change */
00674       if (edgeData[e_id].in_F)
00675         (*move_val) -= weight[e_id];
00676       else
00677         (*move_val) += weight[e_id];
00678       break;
00679       /* in this case we save one E(A:B) but have to double flip in_F */
00680     case 2U:
00681       (*move_val) -= weight[e_id];
00682       break;
00683       /* in this case we pay one E(A:B) but have to double flip in_F */
00684     case 1U:
00685       (*move_val) += weight[e_id];
00686       break;
00687     default:
00688       EXIT (1, "This should not happen");
00689     }                           /* end switch */
00690   }                             /* end loop through all incident edges */
00691   return 0;
00692 }
00693 
00694 /* ========================================================================= */
00696 /* ========================================================================= */
00697 static inline int DPTpriceHHc (DPTMove_t const *const cur_move,
00698                                double *const move_val)
00699 {
00700   /* local variables */
00701   EGlistNode_t *e_it;
00702   unsigned e_id;
00703 
00704   /* we have to compute every move */
00705   for (e_it = all_nodes[cur_move->n_id]->edges->begin; e_it; e_it = e_it->next)
00706   {
00707     e_id = DPTgetEdgeId (e_it);
00708     if (edgeData[e_id].in_F)
00709       (*move_val) -= weight[e_id];
00710     else
00711       (*move_val) += weight[e_id];
00712   }                             /* end loop through all incident edges */
00713   return 0;
00714 }
00715 
00716 /* ========================================================================= */
00718 /* ========================================================================= */
00719 #define DPTpriceHcH(__id,__val) DPTpriceHHc(__id,__val)
00720 
00721 /* ========================================================================= */
00723 /* ========================================================================= */
00724 static inline int DPTpriceBTc (DPTMove_t const *const cur_move,
00725                                double *const move_val)
00726 {
00727   /* local variables */
00728   EGlistNode_t *e_it;
00729   unsigned e_id,
00730     no_id,
00731     pos;
00732 
00733   /* we have to compute every move */
00734   for (e_it = all_nodes[cur_move->n_id]->edges->begin; e_it; e_it = e_it->next)
00735   {
00736     e_id = DPTgetEdgeId (e_it);
00737     no_id = DPTgetOtherEndId (cur_move->n_id, e_it);
00738     pos = (EGbitTest (nodeData[no_id].Ia, cur_move->dom) ? 2U : 0U) |
00739       (EGbitTest (nodeData[no_id].Ib, cur_move->dom) ? 1U : 0U);
00740     switch (pos)
00741     {
00742       /* in this case we save one Delta(T) */
00743     case 0U:
00744       (*move_val) -= weight[e_id];
00745       break;
00746       /* in this case we save one E(A:B), pay one Delta(T) and flip the F */
00747     case 2U:
00748       if (edgeData[e_id].in_F)
00749         (*move_val) -= weight[e_id];
00750       else
00751         (*move_val) += weight[e_id];
00752       break;
00753       /* in this case we pay one Delta(T) */
00754     case 1U:
00755       (*move_val) += weight[e_id];
00756       break;
00757     default:
00758       EXIT (1, "This should not happen");
00759     }                           /* end switch */
00760   }                             /* end loop through all incident edges */
00761   return 0;
00762 }
00763 
00764 /* ========================================================================= */
00766 /* ========================================================================= */
00767 static inline int DPTpriceATc (DPTMove_t const *const cur_move,
00768                                double *const move_val)
00769 {
00770   /* local variables */
00771   EGlistNode_t *e_it;
00772   unsigned e_id,
00773     no_id,
00774     pos;
00775 
00776   /* we have to compute every move */
00777   for (e_it = all_nodes[cur_move->n_id]->edges->begin; e_it; e_it = e_it->next)
00778   {
00779     e_id = DPTgetEdgeId (e_it);
00780     no_id = DPTgetOtherEndId (cur_move->n_id, e_it);
00781     pos = (EGbitTest (nodeData[no_id].Ia, cur_move->dom) ? 2U : 0U) |
00782       (EGbitTest (nodeData[no_id].Ib, cur_move->dom) ? 1U : 0U);
00783     switch (pos)
00784     {
00785       /* in this case we save one Delta(T) */
00786     case 0U:
00787       (*move_val) -= weight[e_id];
00788       break;
00789       /* in this case we save one E(A:B), pay one Delta(T) and flip the F */
00790     case 1U:
00791       if (edgeData[e_id].in_F)
00792         (*move_val) -= weight[e_id];
00793       else
00794         (*move_val) += weight[e_id];
00795       break;
00796       /* in this case we pay one Delta(T) */
00797     case 2U:
00798       (*move_val) += weight[e_id];
00799       break;
00800     default:
00801       EXIT (1, "This should not happen");
00802     }                           /* end switch */
00803   }                             /* end loop through all incident edges */
00804   return 0;
00805 }
00806 
00807 /* ========================================================================= */
00809 /* ========================================================================= */
00810 static inline int DPTmakeMoveTcA (DPTMove_t const *const move,
00811                                   const unsigned int update_flags)
00812 {
00813   /* local vaariables */
00814   EGlistNode_t *e_it;
00815   unsigned e_id,
00816     no_id,
00817     pos;
00818 
00819   /* we have to change all related edges */
00820   for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
00821   {
00822     e_id = DPTgetEdgeId (e_it);
00823     no_id = DPTgetOtherEndId (move->n_id, e_it);
00824     pos = (EGbitTest (nodeData[no_id].Ia, move->dom) ? 2U : 0U) |
00825       (EGbitTest (nodeData[no_id].Ib, move->dom) ? 1U : 0U);
00826     switch (pos)
00827     {
00828     case 0U:
00829       /* in this case the only change is that we have to pay for this edge in the
00830        * Delta(T) */
00831       edgeData[e_id].n_dT++;
00832       break;
00833       /* in this case we save one Delta(T), pay one E(A:B) and flip in_F because
00834        * we are changing parity of \sum E(A:B) */
00835     case 1U:
00836       edgeData[e_id].n_dT--;
00837       edgeData[e_id].n_AtoB++;
00838       edgeData[e_id].in_F++;
00839       break;
00840       /* in this case we save one Delta(T) */
00841     case 2U:
00842       edgeData[e_id].n_dT--;
00843       break;
00844     default:
00845       EXIT (1, "This should not happen");
00846     }                           /* end switch */
00847   }
00848 
00849   /* move the node */
00850   graphData.n_Tc[move->dom]--;
00851   graphData.n_A[move->dom]++;
00852   EGbitSet (nodeData[move->n_id].Ia, move->dom);
00853   nodeData[move->n_id].n_in_A++;
00854   nodeData[move->n_id].n_in_T++;
00855   if (update_flags)
00856     EGbitSet (nodeData[move->n_id].added, move->dom);
00857   /* ending */
00858   return 0;
00859 }
00860 
00861 /* ========================================================================= */
00863 /* ========================================================================= */
00864 static inline int DPTmakeMoveTcB (DPTMove_t const *const move,
00865                                   const unsigned int update_flags)
00866 {
00867   /* local vaariables */
00868   EGlistNode_t *e_it;
00869   unsigned e_id,
00870     no_id,
00871     pos;
00872 
00873   /* move the node */
00874   graphData.n_Tc[move->dom]--;
00875   graphData.n_B[move->dom]++;
00876   EGbitSet (nodeData[move->n_id].Ib, move->dom);
00877   nodeData[move->n_id].n_in_T++;
00878   if (update_flags)
00879     EGbitSet (nodeData[move->n_id].added, move->dom);
00880 
00881   /* we have to change all related edges */
00882   for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
00883   {
00884     e_id = DPTgetEdgeId (e_it);
00885     no_id = DPTgetOtherEndId (move->n_id, e_it);
00886     pos = (EGbitTest (nodeData[no_id].Ia, move->dom) ? 2U : 0U) |
00887       (EGbitTest (nodeData[no_id].Ib, move->dom) ? 1U : 0U);
00888     switch (pos)
00889     {
00890     case 0U:
00891       /* in this case the only change is that we have to pay for this edge in the
00892        * Delta(T) */
00893       edgeData[e_id].n_dT++;
00894       break;
00895       /* in this case we save one Delta(T), pay one E(A:B) and flip in_F because
00896        * we are changing parity of \sum E(A:B) */
00897     case 2U:
00898       edgeData[e_id].n_dT--;
00899       edgeData[e_id].n_AtoB++;
00900       edgeData[e_id].in_F++;
00901       break;
00902       /* in this case we save one Delta(T) */
00903     case 1U:
00904       edgeData[e_id].n_dT--;
00905       break;
00906     default:
00907       EXIT (1, "This should not happen");
00908     }                           /* end switch */
00909   }
00910   return 0;
00911 }
00912 
00913 /* ========================================================================= */
00915 /* ========================================================================= */
00916 static inline int DPTmakeMoveAB (DPTMove_t const *const move,
00917                                  const unsigned int update_flags)
00918 {
00919   /* local vaariables */
00920   EGlistNode_t *e_it;
00921   unsigned e_id,
00922     no_id,
00923     pos;
00924 
00925   /* move the node */
00926   graphData.n_A[move->dom]--;
00927   graphData.n_B[move->dom]++;
00928   EGbitUnset (nodeData[move->n_id].Ia, move->dom);
00929   EGbitSet (nodeData[move->n_id].Ib, move->dom);
00930   nodeData[move->n_id].n_in_A--;
00931   if (update_flags)
00932     EGbitSet (nodeData[move->n_id].flipA, move->dom);
00933 
00934   /* we have to change all related edges */
00935   for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
00936   {
00937     e_id = DPTgetEdgeId (e_it);
00938     no_id = DPTgetOtherEndId (move->n_id, e_it);
00939     pos = (EGbitTest (nodeData[no_id].Ia, move->dom) ? 2U : 0U) |
00940       (EGbitTest (nodeData[no_id].Ib, move->dom) ? 1U : 0U);
00941     switch (pos)
00942     {
00943     case 0U:
00944       /* in this case nathing change */
00945       break;
00946       /* in this case we save one E(A:B) but have to flip in_F */
00947     case 1U:
00948       edgeData[e_id].in_F++;
00949       edgeData[e_id].n_AtoB--;
00950       break;
00951       /* in this case we pay one E(A:B) but have to flip in_F */
00952     case 2U:
00953       edgeData[e_id].in_F++;
00954       edgeData[e_id].n_AtoB++;
00955       break;
00956     default:
00957       EXIT (1, "This should not happen");
00958     }                           /* end switch */
00959   }
00960   return 0;
00961 }
00962 
00963 /* ========================================================================= */
00965 /* ========================================================================= */
00966 static inline int DPTmakeMoveBA (DPTMove_t const *const move,
00967                                  const unsigned int update_flags)
00968 {
00969   /* local vaariables */
00970   EGlistNode_t *e_it;
00971   unsigned e_id,
00972     no_id,
00973     pos;
00974 
00975   /* move the node */
00976   graphData.n_B[move->dom]--;
00977   graphData.n_A[move->dom]++;
00978   EGbitUnset (nodeData[move->n_id].Ib, move->dom);
00979   EGbitSet (nodeData[move->n_id].Ia, move->dom);
00980   nodeData[move->n_id].n_in_A++;
00981   if (update_flags)
00982     EGbitSet (nodeData[move->n_id].flipB, move->dom);
00983 
00984   /* we have to change all related edges */
00985   for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
00986   {
00987     e_id = DPTgetEdgeId (e_it);
00988     no_id = DPTgetOtherEndId (move->n_id, e_it);
00989     pos = (EGbitTest (nodeData[no_id].Ia, move->dom) ? 2U : 0U) |
00990       (EGbitTest (nodeData[no_id].Ib, move->dom) ? 1U : 0U);
00991     switch (pos)
00992     {
00993     case 0U:
00994       /* in this case nathing change */
00995       break;
00996       /* in this case we save one E(A:B) but have to flip in_F */
00997     case 2U:
00998       edgeData[e_id].in_F++;
00999       edgeData[e_id].n_AtoB--;
01000       break;
01001       /* in this case we pay one E(A:B) but have to flip in_F */
01002     case 1U:
01003       edgeData[e_id].in_F++;
01004       edgeData[e_id].n_AtoB++;
01005       break;
01006     default:
01007       EXIT (1, "This should not happen");
01008     }                           /* end switch */
01009   }
01010   return 0;
01011 }
01012 
01013 /* ========================================================================= */
01015 /* ========================================================================= */
01016 static inline int DPTmakeMoveBAflipH (DPTMove_t const *const move,
01017                                       const unsigned int update_flags)
01018 {
01019   /* local vaariables */
01020   EGlistNode_t *e_it;
01021   unsigned e_id,
01022     no_id,
01023     pos;
01024 
01025   /* we have to change all related edges */
01026   for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
01027   {
01028     e_id = DPTgetEdgeId (e_it);
01029     no_id = DPTgetOtherEndId (move->n_id, e_it);
01030     pos = (EGbitTest (nodeData[no_id].Ia, move->dom) ? 2U : 0U) |
01031       (EGbitTest (nodeData[no_id].Ib, move->dom) ? 1U : 0U);
01032     switch (pos)
01033     {
01034     case 0U:
01035       /* in this case nathing change */
01036       edgeData[e_id].in_F++;
01037       break;
01038       /* in this case we save one E(A:B) but have to double flip in_F */
01039     case 2U:
01040       edgeData[e_id].n_AtoB--;
01041       break;
01042       /* in this case we pay one E(A:B) but have to double flip in_F */
01043     case 1U:
01044       edgeData[e_id].n_AtoB++;
01045       break;
01046     default:
01047       EXIT (1, "This should not happen");
01048     }                           /* end switch */
01049   }
01050 
01051   /* update flags if necesary */
01052   if (update_flags)
01053   {
01054     EGbitSet (nodeData[move->n_id].flipB, move->dom);
01055   }
01056   /* flip the node in the handle */
01057   graphData.n_H[nodeData[move->n_id].in_H]--;
01058   nodeData[move->n_id].in_H++;
01059   graphData.n_H[nodeData[move->n_id].in_H]++;
01060   /* change the node from B to A */
01061   graphData.n_B[move->dom]--;
01062   graphData.n_A[move->dom]++;
01063   EGbitUnset (nodeData[move->n_id].Ib, move->dom);
01064   EGbitSet (nodeData[move->n_id].Ia, move->dom);
01065   nodeData[move->n_id].n_in_A++;
01066 
01067   return 0;
01068 }
01069 
01070 /* ========================================================================= */
01072 /* ========================================================================= */
01073 static inline int DPTmakeMoveABflipH (DPTMove_t const *const move,
01074                                       const unsigned int update_flags)
01075 {
01076   /* local vaariables */
01077   EGlistNode_t *e_it;
01078   unsigned e_id,
01079     no_id,
01080     pos;
01081 
01082   /* we have to change all related edges */
01083   for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
01084   {
01085     e_id = DPTgetEdgeId (e_it);
01086     no_id = DPTgetOtherEndId (move->n_id, e_it);
01087     pos = (EGbitTest (nodeData[no_id].Ia, move->dom) ? 2U : 0U) |
01088       (EGbitTest (nodeData[no_id].Ib, move->dom) ? 1U : 0U);
01089     switch (pos)
01090     {
01091     case 0U:
01092       /* in this case nathing change */
01093       edgeData[e_id].in_F++;
01094       break;
01095       /* in this case we save one E(A:B) but have to double flip in_F */
01096     case 1U:
01097       edgeData[e_id].n_AtoB--;
01098       break;
01099       /* in this case we pay one E(A:B) but have to double flip in_F */
01100     case 2U:
01101       edgeData[e_id].n_AtoB++;
01102       break;
01103     default:
01104       EXIT (1, "This should not happen");
01105     }                           /* end switch */
01106   }
01107   /* update flags if necesary */
01108   if (update_flags)
01109   {
01110     EGbitSet (nodeData[move->n_id].flipA, move->dom);
01111   }
01112   /* flip the node in the handle */
01113   graphData.n_H[nodeData[move->n_id].in_H]--;
01114   nodeData[move->n_id].in_H++;
01115   graphData.n_H[nodeData[move->n_id].in_H]++;
01116   /* change the node from B to A */
01117   graphData.n_A[move->dom]--;
01118   graphData.n_B[move->dom]++;
01119   EGbitUnset (nodeData[move->n_id].Ia, move->dom);
01120   EGbitSet (nodeData[move->n_id].Ib, move->dom);
01121   nodeData[move->n_id].n_in_A--;
01122 
01123   return 0;
01124 }
01125 
01126 /* ========================================================================= */
01128 /* ========================================================================= */
01129 static inline int DPTmakeMoveHHc (DPTMove_t const *const move,
01130                                   const unsigned int update_flags)
01131 {
01132   /* local vaariables */
01133   EGlistNode_t *e_it;
01134 
01135   /* update flags if necesary */
01136   if (update_flags)
01137     if (nodeData[move->n_id].in_H)
01138       nodeData[move->n_id].added_H = 1U;
01139   /* flip the node in the handle */
01140   graphData.n_H[nodeData[move->n_id].in_H]--;
01141   nodeData[move->n_id].in_H++;
01142   graphData.n_H[nodeData[move->n_id].in_H]++;
01143 
01144   /* we have to change all related edges */
01145   for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
01146     edgeData[DPTgetEdgeId (e_it)].in_F++;
01147   return 0;
01148 }
01149 
01150 /* ========================================================================= */
01152 /* ========================================================================= */
01153 #define DPTmakeMoveHcH(__move,__flags) DPTmakeMoveHHc(__move,__flags)
01154 
01155 /* ========================================================================= */
01157 /* ========================================================================= */
01158 static inline int DPTmakeMoveBTc (DPTMove_t const *const move)
01159 {
01160   /* local vaariables */
01161   EGlistNode_t *e_it;
01162   unsigned e_id,
01163     no_id,
01164     pos;
01165 
01166   /* change the node from B to Tc */
01167   graphData.n_B[move->dom]--;
01168   graphData.n_Tc[move->dom]++;
01169   EGbitUnset (nodeData[move->n_id].Ib, move->dom);
01170   nodeData[move->n_id].n_in_T--;
01171 
01172   /* we have to change all related edges */
01173   for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
01174   {
01175     e_id = DPTgetEdgeId (e_it);
01176     no_id = DPTgetOtherEndId (move->n_id, e_it);
01177     pos = (EGbitTest (nodeData[no_id].Ia, move->dom) ? 2U : 0U) |
01178       (EGbitTest (nodeData[no_id].Ib, move->dom) ? 1U : 0U);
01179     switch (pos)
01180     {
01181       /* in this case we save one Delta(T) */
01182     case 0U:
01183       edgeData[e_id].n_dT--;
01184       break;
01185       /* in this case we save one E(A:B), pay one Delta(T) and flip the F */
01186     case 2U:
01187       edgeData[e_id].in_F++;
01188       edgeData[e_id].n_AtoB--;
01189       edgeData[e_id].n_dT++;
01190       break;
01191       /* in this case we pay one Delta(T) */
01192     case 1U:
01193       edgeData[e_id].n_dT++;
01194       break;
01195     default:
01196       EXIT (1, "This should not happen");
01197     }                           /* end switch */
01198   }
01199   return 0;
01200 }
01201 
01202 /* ========================================================================= */
01205 /* ========================================================================= */
01206 static inline int DPTTestEdges (void)
01207 {
01208   /* local variables */
01209   register unsigned int i = G->nedges,
01210     j;
01211   unsigned int n_AtoB,
01212     n_dT,
01213     N1_id,
01214     N2_id,
01215     N1_inA,
01216     N1_inB,
01217     N1_inTc,
01218     N2_inA,
01219     N2_inB,
01220     N2_inTc,
01221     in_F,
01222     pos;
01223   while (i--)
01224   {
01225     N1_id = all_edges[i]->head->id;
01226     N2_id = all_edges[i]->tail->id;
01227     n_AtoB = n_dT = in_F = 0;
01228     for (j = graphData.n_dominos; j--;)
01229     {
01230       N1_inA = EGbitTest (nodeData[N1_id].Ia, j);
01231       N1_inB = EGbitTest (nodeData[N1_id].Ib, j);
01232       N2_inA = EGbitTest (nodeData[N2_id].Ia, j);
01233       N2_inB = EGbitTest (nodeData[N2_id].Ib, j);
01234       N1_inTc = !(N1_inA || N1_inB);
01235       N2_inTc = !(N2_inA || N2_inB);
01236       if ((!N1_inTc && N2_inTc) || (N1_inTc && !N2_inTc))
01237         n_dT++;
01238       if ((N1_inA && N2_inB) || (N1_inB && N2_inA))
01239         n_AtoB++;
01240     }
01241     pos =
01242       1U & ((nodeData[N1_id].in_H ^ nodeData[N2_id].in_H) ^ edgeData[i].n_AtoB);
01243     if (pos)
01244       in_F = 1U;
01245     TEST (in_F != edgeData[i].in_F || n_dT != edgeData[i].n_dT ||
01246           n_AtoB != edgeData[i].n_AtoB, "in_F(%u,%u) n_dT(%u,%u) n_AtoB(%u,%u)"
01247           " don't match for edge %u", in_F, edgeData[i].in_F, n_dT,
01248           edgeData[i].n_dT, n_AtoB, edgeData[i].n_AtoB, i);
01249   }
01250   return 0;
01251 }
01252 
01253 /* ========================================================================= */
01255 /* ========================================================================= */
01256 static inline int DPTmakeMoveATc (DPTMove_t const *const move)
01257 {
01258   /* local vaariables */
01259   EGlistNode_t *e_it;
01260   unsigned e_id,
01261     no_id,
01262     pos;
01263 
01264   /* change the node from B to Tc */
01265   graphData.n_A[move->dom]--;
01266   graphData.n_Tc[move->dom]++;
01267   EGbitUnset (nodeData[move->n_id].Ia, move->dom);
01268   nodeData[move->n_id].n_in_T--;
01269   nodeData[move->n_id].n_in_A--;
01270 
01271   /* we have to change all related edges */
01272   for (e_it = all_nodes[move->n_id]->edges->begin; e_it; e_it = e_it->next)
01273   {
01274     e_id = DPTgetEdgeId (e_it);
01275     no_id = DPTgetOtherEndId (move->n_id, e_it);
01276     pos = (EGbitTest (nodeData[no_id].Ia, move->dom) ? 2U : 0U) |
01277       (EGbitTest (nodeData[no_id].Ib, move->dom) ? 1U : 0U);
01278     switch (pos)
01279     {
01280       /* in this case we save one Delta(T) */
01281     case 0U:
01282       edgeData[e_id].n_dT--;
01283       break;
01284       /* in this case we save one E(A:B), pay one Delta(T) and flip the F */
01285     case 1U:
01286       edgeData[e_id].in_F++;
01287       edgeData[e_id].n_AtoB--;
01288       edgeData[e_id].n_dT++;
01289       break;
01290       /* in this case we pay one Delta(T) */
01291     case 2U:
01292       edgeData[e_id].n_dT++;
01293       break;
01294     default:
01295       EXIT (1, "This should not happen");
01296     }                           /* end switch */
01297   }
01298   return 0;
01299 }
01300 
01301 /* ========================================================================= */
01303 /* ========================================================================= */
01304 #define DPTmakeMove(__move,__flags) __DPTmakeMove(__move,__flags,__LINE__,__FILE__,__func__)
01305 static int __DPTmakeMove (DPTMove_t const *const move,
01306                           const unsigned int update_flags,
01307                           const int line,
01308                           const char *file,
01309                           const char *function)
01310 {
01311   /* we just switch the correct call */
01312   MESSAGE (DPT_VRB + 19, "doing move %s for node %u from %s at %s:%d",
01313            move_name[move->move_id], move->n_id, function, file, line);
01314   switch (move->move_id)
01315   {
01316   case DPT_A_Tc:
01317     DPTmakeMoveATc (move);
01318     break;
01319   case DPT_B_Tc:
01320     DPTmakeMoveBTc (move);
01321     break;
01322   case DPT_H_Hc:
01323     DPTmakeMoveHHc (move, update_flags);
01324     break;
01325   case DPT_Hc_H:
01326     DPTmakeMoveHcH (move, update_flags);
01327     break;
01328   case DPT_A_B:
01329     DPTmakeMoveAB (move, update_flags);
01330     break;
01331   case DPT_B_A:
01332     DPTmakeMoveBA (move, update_flags);
01333     break;
01334   case DPT_A_B_flipH:
01335     DPTmakeMoveABflipH (move, update_flags);
01336     break;
01337   case DPT_B_A_flipH:
01338     DPTmakeMoveBAflipH (move, update_flags);
01339     break;
01340   case DPT_Tc_A:
01341     DPTmakeMoveTcA (move, update_flags);
01342     break;
01343   case DPT_Tc_B:
01344     DPTmakeMoveTcB (move, update_flags);
01345     break;
01346   case DPT_no_move:
01347     break;
01348   default:
01349     EXIT (1, "unknown move %d", move->move_id);
01350   }
01351   /* ending */
01352   //#if DPT_EDBG <= DEBUG
01353   //EXITRVAL(DPTTestEdges());
01354   //#endif
01355   return 0;
01356 }
01357 
01358 /* ========================================================================= */
01360 /* ========================================================================= */
01361 static int DPTmakeInvMove (DPTMove_t const *const move,
01362                            const unsigned int update_flags)
01363 {
01364   /* we just switch the correct call */
01365   MESSAGE (DPT_VRB + 19, "doing inv move %s for node %u",
01366            move_name[move->move_id], move->n_id);
01367   switch (DPT_inv_move[move->move_id])
01368   {
01369   case DPT_A_Tc:
01370     DPTmakeMoveATc (move);
01371     break;
01372   case DPT_B_Tc:
01373     DPTmakeMoveBTc (move);
01374     break;
01375   case DPT_H_Hc:
01376     DPTmakeMoveHHc (move, update_flags);
01377     break;
01378   case DPT_Hc_H:
01379     DPTmakeMoveHcH (move, update_flags);
01380     break;
01381   case DPT_A_B:
01382     DPTmakeMoveAB (move, update_flags);
01383     break;
01384   case DPT_B_A:
01385     DPTmakeMoveBA (move, update_flags);
01386     break;
01387   case DPT_A_B_flipH:
01388     DPTmakeMoveABflipH (move, update_flags);
01389     break;
01390   case DPT_B_A_flipH:
01391     DPTmakeMoveBAflipH (move, update_flags);
01392     break;
01393   case DPT_Tc_A:
01394     DPTmakeMoveTcA (move, update_flags);
01395     break;
01396   case DPT_Tc_B:
01397     DPTmakeMoveTcB (move, update_flags);
01398     break;
01399   case DPT_no_move:
01400     break;
01401   default:
01402     EXIT (1, "unknown move %d", move->move_id);
01403   }
01404   /* ending */
01405   //#if DPT_EDBG <= DEBUG
01406   //EXITRVAL(DPTTestEdges());
01407   //#endif
01408   return 0;
01409 }
01410 
01411 /* ========================================================================= */
01413 /* ========================================================================= */
01414 static inline int DPTmakeFullMove (DPTFullMove_t const *const full_move)
01415 {
01416   unsigned int depth = 0;
01417   for (; depth < full_move->depth; depth++)
01418     DPTmakeMove (full_move->move + depth, 1);
01419   return 0;
01420 }
01421 
01422 /* ========================================================================= */
01424 /* ========================================================================= */
01425 #define DPTgoDeeper(__depth) if(__depth+1<DPT_MAX_DEPTH){\
01426   /* now we call for deeper moves */\
01427   DPTmakeMove(base_move->move+__depth,0);\
01428   for( e_it = all_nodes[nc_id]->edges->begin; e_it ; e_it=e_it->next){\
01429     /*if(DPTgetOtherEndId(nc_id,e_it)<nc_id)*/\
01430     DPTSetBestMove( DPTgetOtherEndId( nc_id, e_it), best_move, \
01431                     base_move, __depth + 1);}\
01432   /* undo the last move */\
01433   DPTmakeInvMove(base_move->move+__depth,0);\
01434   }
01435 
01436 
01437 /* ========================================================================= */
01444 /* ========================================================================= */
01445 static int DPTSetBestMove (const unsigned int nc_id,
01446                            DPTFullMove_t * const best_move,
01447                            DPTFullMove_t * const base_move,
01448                            const unsigned int depth)
01449 {
01450   /* local variables */
01451   unsigned nc_inA,
01452     nc_inB,
01453     nc_inTc;
01454   const double move_val = base_move->val;
01455   EGlistNode_t *e_it;
01456   MESSAGE (DPT_VRB + 19, "entering depth %u", depth);
01457   /* check that the depth is OK, if no, we return back */
01458   if (depth >= DPT_MAX_DEPTH)
01459     return 0;
01460   /* basic set-up */
01461   base_move->move[depth].n_id = nc_id;
01462   base_move->move[depth].move_id = DPT_no_move;
01463   base_move->depth = depth + 1;
01464   /* now we check the adding moves if they can be considered */
01465   base_move->move[depth].dom = graphData.n_dominos;
01466   for (; base_move->move[depth].dom--;)
01467   {
01468     nc_inA = EGbitTest (nodeData[nc_id].Ia, base_move->move[depth].dom);
01469     nc_inB = EGbitTest (nodeData[nc_id].Ib, base_move->move[depth].dom);
01470     nc_inTc = !(nc_inA || nc_inB);
01471     /* first check for addind moves, but only if they have not been done */
01472     if (nc_inTc &&
01473         !EGbitTest (nodeData[nc_id].added, base_move->move[depth].dom) &&
01474         (graphData.n_Tc[base_move->move[depth].dom] > 1))
01475     {
01476       /* ------------------------------------------------------------------- */
01477       /* Check DPT_Tc_A */
01478       base_move->val = move_val;
01479       base_move->move[depth].move_id = DPT_Tc_A;
01480       DPTpriceTcA (base_move->move + depth, &(base_move->val));
01481       DPTupdateMove (base_move, best_move);
01482       /* now we call for deeper moves */
01483       DPTgoDeeper (depth);
01484       /* ------------------------------------------------------------------- */
01485       /* Check DPT_Tc_B */
01486       base_move->val = move_val;
01487       base_move->move[depth].move_id = DPT_Tc_B;
01488       DPTpriceTcB (base_move->move + depth, &(base_move->val));
01489       DPTupdateMove (base_move, best_move);
01490       /* now we call for deeper moves */
01491       DPTgoDeeper (depth);
01492       /* ------------------------------------------------------------------- */
01493     }                           /* end checking adding moves */
01494   }                             /* end loop through all dominos */
01495   /* now we check if this node can be added to the handle */
01496   if (!nodeData[nc_id].in_H && !nodeData[nc_id].added_H
01497       && (graphData.n_H[0] > 1))
01498   {
01499     /* --------------------------------------------------------------------- */
01500     /* Check DPT_Hc_H */
01501     base_move->val = move_val;
01502     base_move->move[depth].move_id = DPT_Hc_H;
01503     DPTpriceHcH (base_move->move + depth, &(base_move->val));
01504     DPTupdateMove (base_move, best_move);
01505     /* now we call for deeper moves */
01506     DPTgoDeeper (depth);
01507     /* --------------------------------------------------------------------- */
01508   }                             /* end checking move to add this node into H */
01509   /* now we check for moves that flip this node from A to B */
01510   base_move->move[depth].dom = graphData.n_dominos;
01511   for (; base_move->move[depth].dom--;)
01512   {
01513     nc_inA = EGbitTest (nodeData[nc_id].Ia, base_move->move[depth].dom);
01514     nc_inB = EGbitTest (nodeData[nc_id].Ib, base_move->move[depth].dom);
01515     nc_inTc = !(nc_inA || nc_inB);
01516     /* --------------------------------------------------------------------- */
01517     /* check DPT_A_B */
01518     if (nc_inA && (graphData.n_A[base_move->move[depth].dom] > 1) &&
01519         !EGbitTest (nodeData[nc_id].flipA, base_move->move[depth].dom))
01520     {
01521       base_move->val = move_val;
01522       base_move->move[depth].move_id = DPT_A_B;
01523       DPTpriceAB (base_move->move + depth, &(base_move->val));
01524       DPTupdateMove (base_move, best_move);
01525       /* now we call for deeper moves */
01526       DPTgoDeeper (depth);
01527       /* --------------------------------------------------------------------- */
01528       /* check DPT_A_B_flipH */
01529       if (graphData.n_H[nodeData[nc_id].in_H] > 1)
01530       {
01531         base_move->val = move_val;
01532         base_move->move[depth].move_id = DPT_A_B_flipH;
01533         DPTpriceABflipH (base_move->move + depth, &(base_move->val));
01534         DPTupdateMove (base_move, best_move);
01535         /* now we call for deeper moves */
01536         DPTgoDeeper (depth);
01537       }
01538     }
01539     /* --------------------------------------------------------------------- */
01540     /* check DPT_B_A */
01541     else if (nc_inB && (graphData.n_B[base_move->move[depth].dom] > 1) &&
01542              !EGbitTest (nodeData[nc_id].flipB, base_move->move[depth].dom))
01543     {
01544       base_move->val = move_val;
01545       base_move->move[depth].move_id = DPT_B_A;
01546       DPTpriceBA (base_move->move + depth, &(base_move->val));
01547       DPTupdateMove (base_move, best_move);
01548       /* now we call for deeper moves */
01549       DPTgoDeeper (depth);
01550       /* --------------------------------------------------------------------- */
01551       /* check DPT_B_A_flipH */
01552       if (graphData.n_H[nodeData[nc_id].in_H] > 1)
01553       {
01554         base_move->val = move_val;
01555         base_move->move[depth].move_id = DPT_B_A_flipH;
01556         DPTpriceBAflipH (base_move->move + depth, &(base_move->val));
01557         DPTupdateMove (base_move, best_move);
01558         /* now we call for deeper moves */
01559         DPTgoDeeper (depth);
01560       }
01561     }
01562     /* --------------------------------------------------------------------- */
01563   }                             /* end checking non-growing moves */
01564   /* now we check for moves that may get this node out of a teeth */
01565   base_move->move[depth].dom = graphData.n_dominos;
01566   for (; base_move->move[depth].dom--;)
01567   {
01568     nc_inA = EGbitTest (nodeData[nc_id].Ia, base_move->move[depth].dom);
01569     nc_inB = EGbitTest (nodeData[nc_id].Ib, base_move->move[depth].dom);
01570     nc_inTc = !(nc_inA || nc_inB);
01571     /* --------------------------------------------------------------------- */
01572     /* check DPT_A_Tc */
01573     if (nc_inA && (graphData.n_A[base_move->move[depth].dom] > 1))
01574     {
01575       base_move->val = move_val;
01576       base_move->move[depth].move_id = DPT_A_Tc;
01577       DPTpriceATc (base_move->move + depth, &(base_move->val));
01578       DPTupdateMove (base_move, best_move);
01579       /* now we call for deeper moves */
01580       DPTgoDeeper (depth);
01581     }
01582     /* --------------------------------------------------------------------- */
01583     /* check DPT_B_Tc */
01584     else if (nc_inB && (graphData.n_B[base_move->move[depth].dom] > 1))
01585     {
01586       base_move->val = move_val;
01587       base_move->move[depth].move_id = DPT_B_Tc;
01588       DPTpriceBTc (base_move->move + depth, &(base_move->val));
01589       DPTupdateMove (base_move, best_move);
01590       /* now we call for deeper moves */
01591       DPTgoDeeper (depth);
01592     }
01593     /* --------------------------------------------------------------------- */
01594   }                             /*end checking moves to shrink T */
01595   /* now we check if this node can be shrinked from the handle */
01596   if (nodeData[nc_id].in_H && (graphData.n_H[1] > 1))
01597   {
01598     /* --------------------------------------------------------------------- */
01599     /* check DPT_H_Hc */
01600     base_move->val = move_val;
01601     base_move->move[depth].move_id = DPT_H_Hc;
01602     DPTpriceHHc (base_move->move + depth, &(base_move->val));
01603     DPTupdateMove (base_move, best_move);
01604     /* now we call for deeper moves */
01605     DPTgoDeeper (depth);
01606   }                             /* end checking for shrinking moves for H */
01607   //base_move->move[depth].move_id = DPT_no_move;
01608   base_move->val = move_val;
01609   base_move->depth = depth;
01610   MESSAGE (DPT_VRB + 19, "done");
01611   return 0;
01612 }
01613 
01614 /* ========================================================================= */
01617 /* ========================================================================= */
01618 static inline int DPTisMoveFeasible (DPTMove_t const *const move,
01619                                      const unsigned int update_flags)
01620 {
01621   int rval = 0;
01622   /* we just switch the correct call */
01623   switch (move->move_id)
01624   {
01625   case DPT_A_Tc:
01626     rval = (EGbitTest (nodeData[move->n_id].Ia, move->dom) &&
01627             graphData.n_A[move->dom] > 1);
01628     break;
01629   case DPT_B_Tc:
01630     rval = (EGbitTest (nodeData[move->n_id].Ib, move->dom) &&
01631             graphData.n_B[move->dom] > 1);
01632     break;
01633   case DPT_H_Hc:
01634     rval = (nodeData[move->n_id].in_H && graphData.n_H[1] > 1);
01635     break;
01636   case DPT_Hc_H:
01637     rval = (!nodeData[move->n_id].in_H && graphData.n_H[0] > 1 &&
01638             (!update_flags || !nodeData[move->n_id].added_H));
01639     break;
01640   case DPT_A_B:
01641     rval = (EGbitTest (nodeData[move->n_id].Ia, move->dom) &&
01642             graphData.n_A[move->dom] > 1 &&
01643             (!update_flags
01644              || !EGbitTest (nodeData[move->n_id].flipA, move->dom)));
01645     break;
01646   case DPT_B_A:
01647     rval = (EGbitTest (nodeData[move->n_id].Ib, move->dom) &&
01648             graphData.n_B[move->dom] > 1 &&
01649             (!update_flags
01650              || !EGbitTest (nodeData[move->n_id].flipB, move->dom)));
01651     break;
01652   case DPT_A_B_flipH:
01653     rval = (EGbitTest (nodeData[move->n_id].Ia, move->dom) &&
01654             graphData.n_A[move->dom] > 1 &&
01655             graphData.n_H[nodeData[move->n_id].in_H] > 1 &&
01656             (!update_flags
01657              || (!EGbitTest (nodeData[move->n_id].flipA, move->dom))));
01658     break;
01659   case DPT_B_A_flipH:
01660     rval = (EGbitTest (nodeData[move->n_id].Ib, move->dom) &&
01661             graphData.n_B[move->dom] > 1 &&
01662             graphData.n_H[nodeData[move->n_id].in_H] > 1 &&
01663             (!update_flags
01664              || (!EGbitTest (nodeData[move->n_id].flipB, move->dom))));
01665     break;
01666   case DPT_Tc_A:
01667     rval = (!EGbitTest (nodeData[move->n_id].Ia, move->dom) &&
01668             !EGbitTest (nodeData[move->n_id].Ib, move->dom) &&
01669             graphData.n_Tc[move->dom] > 1 &&
01670             (!update_flags
01671              || !EGbitTest (nodeData[move->n_id].added, move->dom)));
01672     break;
01673   case DPT_Tc_B:
01674     rval = (!EGbitTest (nodeData[move->n_id].Ia, move->dom) &&
01675             !EGbitTest (nodeData[move->n_id].Ib, move->dom) &&
01676             graphData.n_Tc[move->dom] > 1 &&
01677             (!update_flags
01678              || !EGbitTest (nodeData[move->n_id].added, move->dom)));
01679     break;
01680   case DPT_no_move:
01681     rval = 1;
01682     break;
01683   default:
01684     EXIT (1, "unknown move %d", move->move_id);
01685   }
01686   /* ending */
01687   return rval;
01688 }
01689 
01690 /* ========================================================================= */
01692 static inline int DPTisFullMoveFeasible (DPTFullMove_t const *const full_move)
01693 {
01694   int rval = 1;
01695   unsigned int depth = 0;
01696   MESSAGE (DPT_VRB + 19, "entering");
01697   /* check if each move is feasible, make it, and check next move */
01698   for (; depth + 1 < full_move->depth &&
01699        (rval = DPTisMoveFeasible (full_move->move + depth, 1)); depth++)
01700     DPTmakeMove (full_move->move + depth, 0);
01701   WARNINGL (DPT_VRB + 19, !rval, "move level %u is infeasible", depth);
01702   if (rval)
01703     rval = DPTisMoveFeasible (full_move->move + depth, 1);
01704   WARNINGL (DPT_VRB + 19, !rval, "move level %u is infeasible", depth);
01705   /* undo the moves */
01706   while (depth--)
01707   {
01708     DPTmakeInvMove (full_move->move + depth, 0);
01709   }
01710   MESSAGE (DPT_VRB + 19, "done, return %d", rval);
01711   return rval;
01712 }
01713 
01714 /* ========================================================================= */
01717 /* ========================================================================= */
01718 static inline int DPTresetFlags (void)
01719 {
01720   /* local variables */
01721   register unsigned int i = G->nodes->size;
01722   /* loop through all nodes */
01723   while (i--)
01724   {
01725     memset (nodeData[i].added, 0, DPT_MAX_DOM >> 3);
01726     memset (nodeData[i].flipA, 0, DPT_MAX_DOM >> 3);
01727     memset (nodeData[i].flipB, 0, DPT_MAX_DOM >> 3);
01728     nodeData[i].added_H = 0;
01729   }
01730   return 0;
01731 }
01732 
01733 /* ========================================================================= */
01735 /* ========================================================================= */
01736 static inline int DPTStoreFullMove (const unsigned int nc_id,
01737                                     DPTFullMove_t const *const full_move)
01738 {
01739   unsigned int l_depth = full_move->depth;
01740   memcpy (&(nodeData[nc_id].full_move), full_move, sizeof (DPTFullMove_t));
01741   while (l_depth--)
01742   {
01743 #if DPT_EDBG < DEBUG
01744     EXIT (full_move->move[l_depth].move_id == DPT_no_move, "Storing "
01745           "DPT_no_move for node %u, depth %u", nc_id, l_depth);
01746 #endif
01747   }
01748   EGbbtreeRemove (tree, nodeData[nc_id].tree_cn);
01749   nodeData[nc_id].tree_cn = EGbbtreeAdd (tree, nodeData + nc_id);
01750   return 0;
01751 }
01752 
01753 /* ========================================================================= */
01755 /* ========================================================================= */
01756 static inline int DPTResetMove (DPTFullMove_t * move)
01757 {
01758   memset (move, 0, sizeof (DPTFullMove_t));
01759   return 0;
01760 }
01761 
01762 /* ========================================================================= */
01764 /* ========================================================================= */
01765 static inline int DPTupdateNeighMove (DPTFullMove_t * full_move)
01766 {
01767   unsigned int const max_depth = full_move->depth + DPT_MAX_DEPTH;
01768   unsigned int no_id[2 * DPT_MAX_DEPTH + 1],
01769     n_depth = 0;
01770   EGlistNode_t *e_it[DPT_MAX_DEPTH * 2];
01771   DPTFullMove_t base_move,
01772     cur_move;
01773   memset (&base_move, 0, sizeof (base_move));
01774   memset (&cur_move, 0, sizeof (base_move));
01775   DPTResetMove (&cur_move);
01776   cur_move.val = DBL_MAX;
01777   base_move.val = 0;
01778   no_id[0] = full_move->move[0].n_id;
01779   DPTSetBestMove (no_id[0], &cur_move, &base_move, 0);
01780   DPTStoreFullMove (no_id[0], &cur_move);
01781   EGbitSet (node_update, no_id[0]);
01782 #if DPT_VRB+19<DEBUG
01783   DPdisplayMove (no_id);
01784 #endif
01785   e_it[0] = all_nodes[no_id[0]]->edges->begin;
01786   n_depth = 0;
01787   /* for each depth move, we update the neighbours up to depth
01788    * DPT_MAX_DEPTH+full_move->depth */
01789   while (e_it[0])
01790   {
01791     no_id[n_depth + 1] = DPTgetOtherEndId (no_id[n_depth], e_it[n_depth]);
01792     if (!EGbitTest (node_update, no_id[n_depth + 1]))
01793     {
01794       DPTResetMove (&cur_move);
01795       cur_move.val = DBL_MAX;
01796       base_move.val = 0;
01797       DPTSetBestMove (no_id[n_depth + 1], &cur_move, &base_move, 0);
01798       DPTStoreFullMove (no_id[n_depth + 1], &cur_move);
01799 #if DPT_VRB+19<DEBUG
01800       DPdisplayMove (no_id);
01801 #endif
01802       EGbitSet (node_update, no_id[n_depth + 1]);
01803     }
01804     /* now we look at the next neighbour, if we are not at the end of the
01805      * recursion, we go down one more level */
01806     if (n_depth + 1 < max_depth)
01807     {
01808       n_depth++;
01809       e_it[n_depth] = all_nodes[no_id[n_depth]]->edges->begin;
01810     }
01811     /* otherwise we move horizontally in the current level */
01812     else
01813     {
01814       e_it[n_depth] = e_it[n_depth]->next;
01815       /* if the next e_it is null, we have to move up one level, 
01816        * if posible */
01817       while (n_depth && !e_it[n_depth])
01818       {
01819         n_depth--;
01820         e_it[n_depth] = e_it[n_depth]->next;
01821       }
01822     }                           /* end looking at next neighbour */
01823   }                             /* end updating for the given simple move */
01824 /* ========================================================================= */
01825 /*
01826 #warning Note that here we update a node too many times, we could \
01827   decrease this by adding a flag for each node and update only if they \
01828   haven't been updated so far. of course, this would need to reset the \
01829   flags after we are done.
01830 */
01831 /* ========================================================================= */
01832   memset (node_update, 0, sizeof (node_update));
01833   return 0;
01834 }
01835 
01836 /* ========================================================================= */
01837 /* given a residual graph G^*, and a valid DP inequality, it will try to find a
01838  * 'more' violated DP-inequality constraint; the function will not touch the
01839  * data abour the graph nor about the original inequality, but it will alloc
01840  * memory for all data in the new returned inequality. Note too that the number
01841  * of dominos of the new inequality is the same as in the original inequality.
01842  * Finaly, the violation (if it is positive) of the new inequality is returned
01843  * in (*violation). If an error occurs the function will return 1, zero on
01844  * success (this doesn't imply that we were able to find a violated constraint
01845  * from the original onw */
01846 /* ========================================================================= */
01847 int DPtighten (                 /* graph G* data */
01848                 int n_nodes,
01849                 int n_edges,
01850                 int *edges,
01851                 double const *const external_weight,
01852                 /* original constrain to tighten */
01853                 int n_dominos,
01854                 int *n_aset,
01855                 int *n_bset,
01856                 int n_handle,
01857                 int **aset,
01858                 int **bset,
01859                 int *handle,
01860                 /* new generated constraint */
01861                 int **new_n_aset,
01862                 int **new_n_bset,
01863                 int *new_n_handle,
01864                 int ***new_aset,
01865                 int ***new_bset,
01866                 int **new_handle,
01867                 double *violation)
01868 {
01869   /* --------------------------------------------------------------------- */
01870   /* local variables */
01871   EGmemPool_t *mem;
01872   int rval = 0;
01873   unsigned pos,
01874     max_iter = n_nodes * 5,
01875     in_H = 0,
01876     N1_inA,
01877     N1_inB,
01878     N2_inA,
01879     N2_inB,
01880     N1_id,
01881     N2_id,
01882     N1_inTc,
01883     N2_inTc;
01884   double cost_tmp,
01885     l_violation,
01886     o_violation;
01887   register unsigned int i,
01888     j;
01889   DPTNdata_t *nc_data = 0,
01890    *n_data;
01891   DPTFullMove_t cur_move,
01892     base_move;
01893 
01894   /* --------------------------------------------------------------------- */
01895   /* we test that the necesary input is not NULL */
01896   MESSAGE (DPT_VRB + 19, "Entering with n_nodes %d n_edges %d n_dominos %d",
01897            n_nodes, n_edges, n_dominos);
01898   EXIT ((unsigned) n_dominos > DPT_MAX_DOM,
01899         "n_dominos (%d) exced max_n_dom (%u)"
01900         "change the value of DPT_MAX_NODE to an apropiate value", n_dominos,
01901         DPT_MAX_DOM);
01902   EXIT ((unsigned) n_nodes > DPT_MAX_NODE,
01903         "n_nodes (%d) exced max_n_nodes (%u)"
01904         "change the value of DPT_MAX_NODE to an apropiate value", n_nodes,
01905         DPT_MAX_NODE);
01906   TEST (!n_nodes, "graph has no nodes");
01907   TEST (!n_edges, "graph has no edges");
01908   TEST (!n_dominos, "inequality has no dominos");
01909   TEST (!n_handle, "inequality has handle");
01910   TEST (!edges, "edges is NULL");
01911   TEST (!external_weight, "weight is NULL");
01912   TEST (!n_aset, "n_aset is NULL");
01913   TEST (!n_bset, "n_bset is NULL");
01914   TEST (!aset, "aset is NULL");
01915   TEST (!bset, "bset is NULL");
01916   TEST (!handle, "handle is NULL");
01917   TEST (!new_n_aset, "new_n_aset is NULL");
01918   TEST (!new_n_bset, "new_n_bset is NULL");
01919   TEST (!new_n_handle, "new_n_handle is NULL");
01920   TEST (!new_aset, "new_aset is NULL");
01921   TEST (!new_bset, "new_bset is NULL");
01922   TEST (!new_handle, "new_handle is NULL");
01923   TEST (!violation, "violation is NULL");
01924 #if LOG_MODE
01925   /* we save the graph if necesary */
01926   saveGraph ("graph_tighten.x", n_nodes, n_edges, edges, external_weight);
01927 #endif
01928   /* basic tests */
01929   ADVTESTL (DPT_DBG, (n_nodes < 2) || (n_edges < 1) || !(n_dominos & 1) ||
01930             (n_handle < 1) || (n_nodes - n_handle < 1),
01931             1, "either n_nodes (%d), n_edges (%d), n_dominos (%d) or n_handle"
01932             " (%d) has wrong value", n_nodes, n_edges, n_dominos, n_handle);
01933   for (i = n_dominos; i--;)
01934     ADVTESTL (DPT_EDBG, (n_aset[i] < 1) || (n_bset[i] < 1) ||
01935               (n_nodes - n_aset[i] - n_bset[i] < 1), 1, "either "
01936               "n_aset[%d] (%d) or n_bset[%d] (%d) or n_Tc[%d] (%d) is < 1",
01937               i, n_aset[i], i, n_bset[i], i, n_nodes - n_aset[i]);
01938 
01939   /* --------------------------------------------------------------------- */
01940   /* basic set-up */
01941   weight = external_weight;
01942   memset (node_update, 0, sizeof (node_update));
01943   mem = EGnewMemPool (512, EGmemPoolNewSize, 4096);
01944   tree = EGnewBbtree (mem, EGdpTightNdataCompare);
01945   nodeData = EGsMalloc (DPTNdata_t, n_nodes);
01946   edgeData = EGsMalloc (DPTEdata_t, n_edges);
01947   all_nodes = EGsMalloc (EGuGraphNode_t *, n_nodes);
01948   all_edges = EGsMalloc (EGuGraphEdge_t *, n_edges);
01949   memset (all_nodes, 0, sizeof (EGuGraphNode_t *) * n_nodes);
01950   memset (nodeData, 0, sizeof (DPTNdata_t) * n_nodes);
01951   memset (edgeData, 0, sizeof (DPTEdata_t) * n_edges);
01952   memset (all_edges, 0, sizeof (EGuGraphEdge_t *) * n_nodes);
01953   memset (&cur_move, 0, sizeof (DPTFullMove_t));
01954   memset (&base_move, 0, sizeof (DPTFullMove_t));
01955   l_violation = ((3 * n_dominos + 1));
01956   (*new_n_aset) = 0;
01957   (*new_n_bset) = 0;
01958   (*new_n_handle) = 0;
01959   (*new_aset) = 0;
01960   (*new_bset) = 0;
01961   (*new_handle) = 0;
01962 
01963   /* first we build the graph with its internal data */
01964   memset (&graphData, 0, sizeof (DPTGdata_t));
01965   graphData.n_dominos = n_dominos;
01966   graphData.n_nodes = n_nodes;
01967   G = EGnewUGraph (mem);
01968   G->data = &graphData;
01969 
01970   /* now we initialize all the data structures */
01971   MESSAGE (DPT_VRB + 19, "Initializing");
01972   /* add all nodes */
01973   for (i = 0; i < (unsigned) n_nodes; i++)
01974   {
01975     nodeData[i].full_move.val = DBL_MAX;
01976     all_nodes[i] = EGuGraphAddNode (G, nodeData + i);
01977     nodeData[i].tree_cn = EGbbtreeAdd (tree, nodeData + i);
01978   }
01979   /* add all edges */
01980   for (i = 0; i < (unsigned) n_edges; i++)
01981   {
01982     all_edges[i] = EGuGraphAddEdge (G, edgeData + i,
01983                                     all_nodes[edges[i << 1]],
01984                                     all_nodes[edges[(i << 1) | 1]]);
01985   }
01986   /* compute handle stuff */
01987   for (i = n_handle; i--;)
01988   {
01989     nodeData[handle[i]].in_H = 1U;
01990     graphData.n_H[1]++;
01991   }
01992   graphData.n_H[0] = n_nodes - graphData.n_H[1];
01993   /* now we update information related to the dominoes */
01994   for (i = n_dominos; i--;)
01995   {
01996     graphData.n_A[i] = n_aset[i];
01997     graphData.n_B[i] = n_bset[i];
01998     graphData.n_Tc[i] = n_nodes - n_aset[i] - n_bset[i];
01999     for (j = n_aset[i]; j--;)
02000     {
02001       pos = aset[i][j];
02002       EGbitSet (nodeData[pos].Ia, i);
02003       nodeData[pos].n_in_A++;
02004       nodeData[pos].n_in_T++;
02005     }
02006     for (j = n_bset[i]; j--;)
02007     {
02008       pos = bset[i][j];
02009       ADVTESTL (DPT_EDBG, EGbitTest (nodeData[pos].Ia, i), 1, "a node (%d)"
02010                 "is in A_%d and B_%d at the same time", pos, i, i);
02011       EGbitSet (nodeData[pos].Ib, i);
02012       nodeData[pos].n_in_T++;
02013     }
02014   }
02015   /* now we update the information for all edges */
02016   for (i = n_edges; i--;)
02017   {
02018     N1_id = all_edges[i]->head->id;
02019     N2_id = all_edges[i]->tail->id;
02020     for (j = n_dominos; j--;)
02021     {
02022       N1_inA = EGbitTest (nodeData[N1_id].Ia, j);
02023       N1_inB = EGbitTest (nodeData[N1_id].Ib, j);
02024       N2_inA = EGbitTest (nodeData[N2_id].Ia, j);
02025       N2_inB = EGbitTest (nodeData[N2_id].Ib, j);
02026       N1_inTc = !(N1_inA || N1_inB);
02027       N2_inTc = !(N2_inA || N2_inB);
02028       if ((!N1_inTc && N2_inTc) || (N1_inTc && !N2_inTc))
02029         edgeData[i].n_dT++;
02030       if ((N1_inA && N2_inB) || (N1_inB && N2_inA))
02031         edgeData[i].n_AtoB++;
02032     }
02033     pos =
02034       1U & ((nodeData[N1_id].in_H ^ nodeData[N2_id].in_H) ^ edgeData[i].n_AtoB);
02035     if (pos)
02036       edgeData[i].in_F = 1U;
02037   }
02038 #if DPT_VRB <= DEBUG-1
02039   //DPTDisplayEdges();
02040 #endif
02041   /* --------------------------------------------------------------------- */
02042   /* now we need to get the best move for each node */
02043   MESSAGE (DPT_VRB + 19, "Setting up best move for all nodes");
02044   /* note that we only need to update moves for nodes whose edges has an edge
02045    * with coefficient of non-zero */
02046   for (i = n_edges; i--;)
02047   {
02048     /* if the edge has a non-zero coefficient, we update it's both ends if they
02049      * haven't been update yet. */
02050     if (edgeData[i].n_dT || edgeData[i].n_AtoB || edgeData[i].in_F)
02051     {
02052       if (!EGbitTest (node_update, all_edges[i]->tail->id))
02053       {
02054         DPTResetMove (&cur_move);
02055         cur_move.val = DBL_MAX;
02056         base_move.val = 0;
02057         DPTSetBestMove (all_edges[i]->tail->id, &cur_move, &base_move, 0);
02058         DPTStoreFullMove (all_edges[i]->tail->id, &cur_move);
02059         EGbitSet (node_update, all_edges[i]->tail->id);
02060 #if DPT_VRB+19<DEBUG
02061         DPdisplayMove (all_edges[i]->tail->id);
02062 #endif
02063       }
02064       if (!EGbitTest (node_update, all_edges[i]->head->id))
02065       {
02066         DPTResetMove (&cur_move);
02067         cur_move.val = DBL_MAX;
02068         base_move.val = 0;
02069         DPTSetBestMove (all_edges[i]->head->id, &cur_move, &base_move, 0);
02070         DPTStoreFullMove (all_edges[i]->head->id, &cur_move);
02071         EGbitSet (node_update, all_edges[i]->head->id);
02072 #if DPT_VRB+19<DEBUG
02073         DPdisplayMove (all_edges[i]->head->id);
02074 #endif
02075       }
02076     }
02077   }                             /* end checking all edges */
02078   /* reset the node update flags */
02079   memset (node_update, 0, sizeof (node_update));
02080 #if 0
02081   for (i = n_nodes; i--;)
02082   {
02083     DPTResetMove (&cur_move);
02084     cur_move.val = DBL_MAX;
02085     base_move.val = 0;
02086     DPTSetBestMove (i, &cur_move, &base_move, 0);
02087     DPTStoreFullMove (i, &cur_move);
02088 #if DPT_VRB+19<DEBUG
02089     DPdisplayMove (i);
02090 #endif
02091   }
02092 #endif
02093   MESSAGE (DPT_VRB + 19, "Best move set for all nodes");
02094 
02095   /* --------------------------------------------------------------------- */
02096   /* now we compute the original violation */
02097   o_violation = -(3 * n_dominos + 1);
02098   DPTpriceConstraint (&o_violation);
02099   MESSAGE (DPT_VRB + 19, "Computing Original violation %lg", o_violation);
02100   l_violation = o_violation;
02101 
02102   /* --------------------------------------------------------------------- */
02103   /* now we enter our main loop, while there is a negative move, we keep going
02104    * */
02105   while (((cost_tmp = (nc_data =
02106                        DPTNdata (EGbbtreeMin (tree)->this))->full_move.val)
02107           < -DPTMinImprovement) && max_iter--)
02108   {
02109     MESSAGE (DPT_VRB + 19, "Try to find best move (current best %8.6lf)",
02110              cost_tmp);
02111     memcpy (&cur_move, &(nc_data->full_move), sizeof (DPTFullMove_t));
02112 #if DPT_VRB+19<DEBUG
02113     DPdisplayMove (cur_move.move[0].n_id);
02114 #endif
02115     /* now check if the movement is infeasible, if so, update the best move and
02116      * move-on */
02117     if (!DPTisFullMoveFeasible (&cur_move))
02118     {
02119       i = cur_move.move[0].n_id;
02120 #if DPT_VRB+0<DEBUG
02121       DPdisplayMove (i);
02122 #endif
02123       MESSAGE (DPT_VRB + 1, "Move for node %u dom %u infeasible", i,
02124                cur_move.move[0].dom);
02125       DPTResetMove (&cur_move);
02126       cur_move.val = DBL_MAX;
02127       base_move.val = 0;
02128       DPTSetBestMove (i, &cur_move, &base_move, 0);
02129       DPTStoreFullMove (i, &cur_move);
02130 #if DPT_VRB+0<DEBUG
02131       DPdisplayMove (i);
02132 #endif
02133       continue;
02134     }
02135     /* now, if the move is good (i.e. non-zero) we reset the flags */
02136     if (cost_tmp < DPTMinImprovement)
02137       DPTresetFlags ();
02138     /* else we check if it is an adding move, if no such move, check for a flip
02139      * move, and finally, if no such move, check for a shrink move. Note that
02140      * the ordering of the moves assures that all zero-valued moves are well
02141      * ordered. */
02142     /* now we perform the move */
02143     MESSAGE (DPT_VRB + 19, "Imp: %8.6lf Tot: %8.6lf node %u move %s depth %u",
02144              cost_tmp, l_violation, cur_move.move[0].n_id,
02145              move_name[cur_move.move[0].move_id], nc_data->full_move.depth);
02146     DPTmakeFullMove (&cur_move);
02147     l_violation += cost_tmp;
02148     /* this check is to be sure if the violation predicted is OK */
02149 #if DPT_EDBG <= DEBUG
02150     EXITRVAL (DPTTestEdges ());
02151     cost_tmp = -(3 * n_dominos + 1);
02152     DPTpriceConstraint (&cost_tmp);
02153     EXIT ((fabs (cost_tmp - l_violation) > 1e-3) &&
02154           DPdisplayMove (cur_move.move[0].n_id), "Error computing violation"
02155           ", predicted %8.6lf computed %8.6lf diference %8.6lf",
02156           l_violation, cost_tmp, l_violation - cost_tmp);
02157 #endif
02158     /* now update best move for the node and all its neighbours */
02159     /* update moves */
02160     DPTupdateNeighMove (&cur_move);
02161   }
02162   /* --------------------------------------------------------------------- */
02163   cost_tmp = ((DPTNdata_t *) (EGbbtreeMin (tree)->this))->full_move.val;
02164   MESSAGE (DPT_VRB + 19, "No good moves left (current best %8.6lf)",
02165            (cost_tmp));
02166 
02167   /* --------------------------------------------------------------------- */
02168   if (o_violation > l_violation + 1e-4)
02169     /* now, if we have a violated and better inequality, we save it and send it
02170      * back to the calling function. */
02171   {
02172     MESSAGE (DPT_VRB - 1, "Original: %8.6lf New: %8.6lf Diff: %lg", o_violation,
02173              l_violation, fabs (o_violation - l_violation));
02174     /* look for memory */
02175     (*new_n_aset) = EGsMalloc (int,
02176                                n_dominos);
02177     (*new_n_bset) = EGsMalloc (int,
02178                                n_dominos);
02179     (*new_aset) = EGsMalloc (int *,
02180                              n_dominos);
02181     (*new_bset) = EGsMalloc (int *,
02182                              n_dominos);
02183     (*new_n_handle) = 0;
02184     in_H = graphData.n_H[1] < graphData.n_H[0] ? 1 : 0;
02185     TESTL (DPT_EDBG, !(graphData.n_H[in_H]), "handle is empty!");
02186     (*new_handle) = EGsMalloc (int,
02187                                graphData.n_H[in_H]);
02188     for (i = n_dominos; i--;)
02189     {
02190       TESTL (DPT_EDBG, !(graphData.n_A[i]) || !(graphData.n_B[i]) ||
02191              !(graphData.n_Tc[i]),
02192              "domino(%u) with empty component A=%u, B=%u, " "T^c=%u", i,
02193              graphData.n_A[i], graphData.n_B[i], graphData.n_Tc[i]);
02194       (*new_aset)[i] = EGsMalloc (int,
02195                                   graphData.n_A[i]);
02196       (*new_bset)[i] = EGsMalloc (int,
02197                                   graphData.n_B[i]);
02198       (*new_n_aset)[i] = 0;
02199       (*new_n_bset)[i] = 0;
02200     }
02201 
02202     /* we loop through all nodes and put them where they should go */
02203     for (i = n_nodes; i--;)
02204     {
02205       n_data = nodeData + i;
02206       if ((n_data->in_H & 1U) == in_H)
02207         (*new_handle)[(*new_n_handle)++] = i;
02208       /* loop through all dominos to check to which one the node belong */
02209       for (j = n_dominos; j--;)
02210       {
02211         if (EGbitTest (n_data->Ia, j))
02212           (*new_aset)[j][(*new_n_aset)[j]++] = i;
02213         if (EGbitTest (n_data->Ib, j))
02214           (*new_bset)[j][(*new_n_bset)[j]++] = i;
02215       }                         /* end loop through dominos for each node */
02216     }                           /* end loop every node */
02217 
02218     TESTL (DPT_EDBG, (in_H ? ((*new_n_handle) != (signed) graphData.n_H[1]) :
02219                       ((*new_n_handle) != (signed) graphData.n_H[0])),
02220            "handle size " "doesn't agree with what we have found");
02221     for (i = n_dominos; i--;)
02222     {
02223       TESTL (DPT_EDBG, (*new_n_aset)[i] != (signed) graphData.n_A[i],
02224              "size of A_[%u] doesn't match", i);
02225       TESTL (DPT_EDBG, (*new_n_bset)[i] != (signed) graphData.n_B[i],
02226              "size of B_[%u] doesn't match", i);
02227     }
02228   }                             /* end saving newly found constraint */
02229   /* --------------------------------------------------------------------- */
02230   /* ending */
02231   MESSAGE (DPT_VRB + 19, "Clearing graph");
02232   EGuGraphClearMP (G, nullFreeMP, nullFreeMP, nullFreeMP, mem, mem, mem);
02233   MESSAGE (DPT_VRB + 19, "Freing graph");
02234   EGfreeUGraph (G);
02235   MESSAGE (DPT_VRB + 19, "Freing all_nodes");
02236   EGfree (all_nodes);
02237   MESSAGE (DPT_VRB + 19, "Freing all_edges");
02238   EGfree (all_edges);
02239   MESSAGE (DPT_VRB + 19, "Freing tree");
02240   EGfreeBbtree (tree);
02241   MESSAGE (DPT_VRB + 19, "Freing nodeData");
02242   EGfree (nodeData);
02243   MESSAGE (DPT_VRB + 19, "Freing edgeData");
02244   EGfree (edgeData);
02245   MESSAGE (DPT_VRB + 19, "Freing mempool");
02246   EGfreeMemPool (mem);
02247   *violation = l_violation;
02248   MESSAGE (DPT_VRB + 19, "Ending with violation %8.6lf", *violation);
02249   return rval;
02250 }
02251 #else
02252 int DPtighten (                 /* graph G* data */
02253                 int n_nodes,
02254                 int n_edges,
02255                 int *edges,
02256                 double *weight,
02257                 /* original constrain to tighten */
02258                 int n_dominos,
02259                 int *n_aset,
02260                 int *n_bset,
02261                 int n_handle,
02262                 int **aset,
02263                 int **bset,
02264                 int *handle,
02265                 /* new generated constraint */
02266                 int **new_n_aset,
02267                 int **new_n_bset,
02268                 int *new_n_handle,
02269                 int ***new_aset,
02270                 int ***new_bset,
02271                 int **new_handle,
02272                 double *violation)
02273 {
02274   register int i;
02275   *new_n_aset = EGsMalloc (int,
02276                            n_dominos);
02277   *new_n_bset = EGsMalloc (int,
02278                            n_dominos);
02279   *new_aset = EGsMalloc (int *,
02280                          n_dominos);
02281   *new_bset = EGsMalloc (int *,
02282                          n_dominos);
02283   *new_n_handle = n_handle;
02284   *new_handle = EGsMalloc (int,
02285                            n_handle);
02286   memcpy (*new_handle, handle, sizeof (int) * n_handle);
02287   memcpy (*new_n_aset, n_aset, sizeof (int) * n_dominos);
02288   memcpy (*new_n_bset, n_bset, sizeof (int) * n_dominos);
02289   for (i = n_dominos; i--;)
02290   {
02291     (*new_aset)[i] = EGsMalloc (int,
02292                                 n_aset[i]);
02293     (*new_bset)[i] = EGsMalloc (int,
02294                                 n_bset[i]);
02295     memcpy (((*new_aset)[i]), (aset[i]), sizeof (int) * n_aset[i]);
02296     memcpy (((*new_bset)[i]), (bset[i]), sizeof (int) * n_bset[i]);
02297   }
02298   *violation = 0;
02299   return 0;
02300 }
02301 #endif

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