00001 /* EGlib "Efficient General Library" provides some basic structures and 00002 * algorithms commons in many optimization algorithms. 00003 * 00004 * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea. 00005 * 00006 * This library is free software; you can redistribute it and/or modify it 00007 * under the terms of the GNU Lesser General Public License as published by the 00008 * Free Software Foundation; either version 2.1 of the License, or (at your 00009 * option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, but 00012 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 00013 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00014 * License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this library; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 * */ 00020 /* ========================================================================= */ 00021 /** @defgroup EGalgMinCut EGalgMinCut 00022 * 00023 * Here we implement the min-cut algorithm based on the srinking 00024 * pre-processing of Padberg And Rinaldi in the paper "An Efficient 00025 * Algorithm For The Minimum Capacity Cut Problem", Mathematical Programming 00026 * 47 (1990) pages 19-36. But using as minimum s-t cut code the Push-Relabel 00027 * max flow algorithm as implemented in the @ref EGalgPushRelabel module. This 00028 * implies that we only support positive edge-weights. 00029 * 00030 * This implementation allows uses of diferent numbers as supported by 00031 * @ref EGlpNum module. And follows the philosophy of embeded structures as in 00032 * @ref EGalgPushRelabel module. Also, much of the approach used in this 00033 * implementation come from CONCORDE's implementation. 00034 * 00035 * It is usually the case that the Minimum Cut Problem is just a sub-problem 00036 * of some larger problem, is for that reason that we implement (just as in 00037 * CONCORDE) a callback function that is called whenever an improving solution 00038 * is found, so that the user can do something with the given node-cutset and 00039 * value. for more details see the definition of #EGalgMCcbk_t . 00040 * 00041 * @note 00042 * If run with types like EGfp20_t, if the arithmetic produces an overflow, 00043 * then we are in big trouble, note that the numbers involved in the algorithm 00044 * may range up to \f$\sum(w_e:e\in E(G))\f$. 00045 * 00046 * @version 0.0.1 00047 * @par History: 00048 * - 2005-08-19 00049 * - While computing a minimum S-T cut, choose S randomly. and T 00050 * as a node at maximum distance (number of edges) from S. 00051 * - Fix small problem with shrinking level 4 00052 * - 2005-06-20 00053 * - First Implementation. 00054 * */ 00055 /** @file 00056 * @ingroup EGalgMinCut */ 00057 /** @addtogroup EGalgMinCut */ 00058 /** @{ */ 00059 /** @example eg_min_cut.ex.c */ 00060 /* ========================================================================= */ 00061 #ifndef _EG_MIN_CUT_H 00062 #define _EG_MIN_CUT_H 00063 #include <stdlib.h> 00064 #include <stdio.h> 00065 #include <limits.h> 00066 #include <strings.h> 00067 #include "eg_elist.h" 00068 #include "eg_eset.h" 00069 #include "eg_edgraph.h" 00070 #include "eg_eugraph.h" 00071 #include "eg_lpnum.h" 00072 #include "eg_mempool.h" 00073 #include "eg_push_relabel.h" 00074 #include "eg_shrink_graph.h" 00075 /* ========================================================================= */ 00076 /** @brief Verbosity Level */ 00077 #define __MC_VRBLVL_ 100 00078 00079 /* ========================================================================= */ 00080 /** @brief Level of profiling in the code. */ 00081 #define __MC_DEBUG_ 100 00082 00083 /* ========================================================================= */ 00084 /** @brief Level of profiling in the code. */ 00085 #define __MC_PROFILE_ 100 00086 00087 /* ========================================================================= */ 00088 /** If profiling is enable (i.e. #__MC_PROFILE_ <= DEBUG), print 00089 * some profiling information of the min cut used up to now, and reset 00090 * all internal counters to zero, if profiling is not enabled, nothing 00091 * happen. */ 00092 /** @{ */ 00093 #if __MC_PROFILE_ <= DEBUG 00094 extern unsigned long long __MC_profile_lvl[5];/**< shrinkings per level*/ 00095 extern unsigned long long __MC_profile_tn;/**<Number of calls to #EGalgMCtestNode*/ 00096 extern unsigned long long __MC_profile_up;/**< Number of improving cuts found */ 00097 #define EGalgMCprofile ({\ 00098 fprintf(stderr,"PROFILE FOR EGalgMinCut:\nSrinking:\n\tLVL 1: %llu\n\tLVL"\ 00099 " 2: %llu\n\tLVL 3: %llu\n\tLVL 4: %llu\ns-t Cuts: %llu\nTestNode: "\ 00100 "%llu\nN Cuts: %llu\n", __MC_profile_lvl[1], __MC_profile_lvl[2], \ 00101 __MC_profile_lvl[3], __MC_profile_lvl[4], __MC_profile_lvl[0], \ 00102 __MC_profile_tn, __MC_profile_up); __MC_profile_lvl[0] = \ 00103 __MC_profile_lvl[1] = __MC_profile_lvl[2] = __MC_profile_lvl[3] = \ 00104 __MC_profile_lvl[4] = __MC_profile_tn = __MC_profile_up = 0;}) 00105 #else 00106 #define EGalgMCprofile 00107 #endif 00108 /** @} */ 00109 00110 /* ========================================================================= */ 00111 /** @brief Call-back function, it receives as input the weight of the cut, the 00112 * size of the newly found cut, an array containing the cut (of length at 00113 * least the number of elements in the cut) as integers (as defined by the 00114 * #EGalgMCnode_t::id field), and a pointer to some internal 00115 * data (as stored in #EGalgMCcbk_t::param). The function should return zero 00116 * on success, and non-zero if an error ocours, this error will be propagated 00117 * through the calling functions. */ 00118 typedef int (*EGalgMCdo_f) (EGlpNum_t, 00119 const unsigned int, 00120 const unsigned int *const, 00121 void *); 00122 00123 /* ========================================================================= */ 00124 /** @brief Call-back structure for use when an improving minimum cut is found. 00125 * */ 00126 typedef struct EGalgMCcbk_t 00127 { 00128 EGlpNum_t cutoff; /**< maximum value for the newly found minimum cut, for 00129 the function to be called. */ 00130 void *param; /**< external parameter needed by the function */ 00131 EGalgMCdo_f do_fn;/**< actual function to be called if the cut-off condition 00132 holds */ 00133 } 00134 EGalgMCcbk_t; 00135 00136 /* ========================================================================= */ 00137 /** @brief Initialize a call-back structure. 00138 * @param cb call-back to be initialized. */ 00139 #define EGalgMCcbkInit(cb) ({\ 00140 EGalgMCcbk_t*const _EGalgMCcb = (cb);\ 00141 EGlpNumInitVar(_EGalgMCcb->cutoff);\ 00142 _EGalgMCcb->param = 0;\ 00143 _EGalgMCcb->do_fn = 0;}) 00144 00145 /* ========================================================================= */ 00146 /** @brief Free all internal memory asociated with this structure (not 00147 * allocated by the user). 00148 * @param cb call-back strucure to be cleared */ 00149 #define EGalgMCcbkClear(cb) EGlpNumClearVar((cb)->cutoff) 00150 00151 /* ========================================================================= */ 00152 /** @brief Node structure for Minimum Cut */ 00153 typedef struct EGalgMCnode_t 00154 { 00155 EGsrkNode_t node; /**< Actual shrinkable node */ 00156 unsigned int id; /**< External Identifier for the node */ 00157 EGeList_t lvl_cn; /**< Connector for the level list */ 00158 unsigned int lvl; /**< Current node level test to be performed */ 00159 unsigned int new_id;/**< internal data, it's values can be discarded */ 00160 EGsrkEdge_t *hit; /**< Used to speed-up the Padberg-Rinaldi tests. */ 00161 } 00162 EGalgMCnode_t; 00163 00164 /* ========================================================================= */ 00165 /** @brief Initialize a node structure for use. 00166 * @param N node to be initialized */ 00167 #define EGalgMCnodeInit(N) ({\ 00168 EGalgMCnode_t*const _EGalgMCn = (N);\ 00169 EGsrkNodeInit(&(_EGalgMCn->node));\ 00170 _EGalgMCn->lvl_cn = (EGeList_t){0,0};\ 00171 _EGalgMCn->lvl = 0;\ 00172 _EGalgMCn->id = UINT_MAX;\ 00173 _EGalgMCn->new_id = UINT_MAX;\ 00174 _EGalgMCn->hit = 0;}) 00175 00176 /* ========================================================================= */ 00177 /** @brief Clear any internal memory (not allocated by the user) used by this 00178 * structure. 00179 * @param N node to be cleared */ 00180 #define EGalgMCnodeClear(N) EGsrkNodeClear(&((N)->node)) 00181 00182 /* ========================================================================= */ 00183 /** @brief Edge structure for the Minimum Cut */ 00184 typedef struct EGalgMCedge_t 00185 { 00186 EGsrkEdge_t edge; /**< Actual shrinkable edge */ 00187 unsigned int id; /**< External Identifier for the edge */ 00188 } 00189 EGalgMCedge_t; 00190 00191 /* ========================================================================= */ 00192 /** @brief Initialize an edge structure for use. 00193 * @param E edge to be initialized */ 00194 #define EGalgMCedgeInit(E) ({\ 00195 EGalgMCedge_t*const _EGalgMCe = (E);\ 00196 EGsrkEdgeInit(&(_EGalgMCe->edge));\ 00197 _EGalgMCe->id = UINT_MAX;}) 00198 00199 /* ========================================================================= */ 00200 /** @brief Clear any internal memory (not allocated by the user) used by this 00201 * structure. 00202 * @param E node to be cleared */ 00203 #define EGalgMCedgeClear(E) EGsrkEdgeClear(&((E)->edge)) 00204 00205 /* ========================================================================= */ 00206 /** @brief Graph Structure for Minimum Cut. 00207 * 00208 * Note that this structure also holds some parameters as the epsilon to use 00209 in the comparisons, the current best cut found (or bound), and the current 00210 * cut found so-far. As well as an array containing all edges and nodes in 00211 * thee graph (remember that when we Identify two nodes, we loose any 00212 * reference to the shrinked node in the graph structure as discussed in 00213 * #EGsrkIdentifyNodes ) 00214 * */ 00215 typedef struct EGalgMCgraph_t 00216 { 00217 EGsrkGraph_t G; /**< Actual shrinking graph used */ 00218 EGlpNum_t epsilon; /**< error tolerance used for equality testing */ 00219 EGlpNum_t cut_val; /**< if #EGalgMCgraph_t::cut_sz is not zero, then 00220 this is the value of the (currenlty) best 00221 minimum cut found so far. otherwise is a bound 00222 on the value of the minimum cut (note that this 00223 value should be set before actually computing 00224 the minimum cut, and can be set to the value 00225 of @f$\delta(v)@f$ for some node @a v in the 00226 graph. */ 00227 unsigned int cut_sz; /**< number of nodes in the current best cut, if 00228 set to zero, then no cut has been found 00229 (so far) */ 00230 EGeList_t lvl_list[5]; /**< List of nodes in different levels of tests */ 00231 unsigned int *cut; /**< Array storing the current cut, the size of 00232 this array should be at least 00233 #EGsrkGraph_t::n_onodes */ 00234 EGalgMCnode_t *all_nodes; /**< Array containing all nodes of the graph. */ 00235 EGalgMCedge_t *all_edges; /**< Array containing all edges of the graph. */ 00236 } 00237 EGalgMCgraph_t; 00238 00239 /* ========================================================================= */ 00240 /** @brief Initialize a graph structure for use. 00241 * @param Graph graph to be initialized */ 00242 #define EGalgMCgraphInit(Graph) ({\ 00243 EGalgMCgraph_t*const _EGalgMCg = (Graph);\ 00244 EGsrkGraphInit(&(_EGalgMCg->G));\ 00245 EGlpNumInitVar(_EGalgMCg->epsilon);\ 00246 EGlpNumZero(_EGalgMCg->epsilon);\ 00247 EGlpNumInitVar(_EGalgMCg->cut_val);\ 00248 EGlpNumZero(_EGalgMCg->cut_val);\ 00249 _EGalgMCg->cut_sz = 0;\ 00250 EGeListInit(_EGalgMCg->lvl_list);\ 00251 EGeListInit(_EGalgMCg->lvl_list+1);\ 00252 EGeListInit(_EGalgMCg->lvl_list+2);\ 00253 EGeListInit(_EGalgMCg->lvl_list+3);\ 00254 EGeListInit(_EGalgMCg->lvl_list+4);\ 00255 _EGalgMCg->cut = 0;\ 00256 _EGalgMCg->all_nodes = 0;\ 00257 _EGalgMCg->all_edges = 0;}) 00258 00259 /* ========================================================================= */ 00260 /** @brief Clear internal memory (not allocated by the user) of a graph 00261 * structure. 00262 * @param Graph graph to be cleared. */ 00263 #define EGalgMCgraphClear(Graph) ({\ 00264 EGsrkGraphClear(&((Graph)->G));\ 00265 EGlpNumClearVar((Graph)->epsilon);\ 00266 EGlpNumClearVar((Graph)->cut_val);}) 00267 00268 /* ========================================================================= */ 00269 /** @brief Shrink two nodes in the graph, and update internal structures. 00270 * @param Graph current graph. 00271 * @param N node to keep in graph. 00272 * @param M node to shrink within N. */ 00273 #define EGalgMCidentifyNodes(Graph,N,M) ({\ 00274 EGalgMCgraph_t*const _EGalgMCg = (Graph);\ 00275 EGalgMCnode_t*const _EGalgMCn = (N), *const _EGalgMCm = (M);\ 00276 MESSAGE(__MC_DEBUG_,"Shrinking nodes with weight %lf %lf", \ 00277 EGlpNumToLf(_EGalgMCn->node.weight), \ 00278 EGlpNumToLf(_EGalgMCm->node.weight));\ 00279 EGsrkIdentifyNodes(&(_EGalgMCg->G), &(_EGalgMCn->node), &(_EGalgMCm->node));\ 00280 if(_EGalgMCn->lvl < 5)\ 00281 {\ 00282 EGeListDel(&(_EGalgMCm->lvl_cn));\ 00283 EGeListMoveAfter(&(_EGalgMCn->lvl_cn), _EGalgMCg->lvl_list);\ 00284 }\ 00285 else EGeListAddAfter(&(_EGalgMCn->lvl_cn), _EGalgMCg->lvl_list);\ 00286 _EGalgMCn->lvl = 0;}) 00287 00288 /* ========================================================================= */ 00289 /** @brief Identify all Padberg and Rinaldy edges. i.e. shrink all edges that 00290 * satisfy the conditions in their paper. we choose to make tests over pair of 00291 * nodes linked by an edge. 00292 * @param max_lvl set a limit on wich tests to perform. for example, if set to 00293 * 1, only the first and second tests will be carried out. 00294 * @param G graph over wich we are working. 00295 * @param cb call back structure to use (if set to NULL it is not used). 00296 * @return zero on success, non-zero otherwise. 00297 * 00298 * Note that while doing this identification process, we update the values of 00299 * #EGalgMCgraph_t::cut, #EGalgMCgraph_t::cut_sz and #EGalgMCgraph_t::cut_val, 00300 * as well as performing the actual shrinking procedure. 00301 * 00302 * The original theorem (for local conditions on shrinking) is the following: 00303 * Let @f$ Z @f$ be a proper subset of @f$ V @f$ (the set of all nodes in the 00304 * graph), @f$ |Z|\geq2 @f$, and let 00305 * @f[ P(Z) = \bigcup\left\{ N(u)\cap N(v):u\neq v, u,v\in Z \right\} @f] 00306 * where @f$ N(u) @f$ if the set of neighbours of @f$ u @f$. If there exists 00307 * @f$ Y\subseteq P(Z) @f$ such that for every nonempty proper subset @f$ W 00308 * @f$ of @f$ Z @f$ and for every @f$ T\subseteq Y @f$ either: 00309 * -# @f$ w(\delta(W))/2 \leq w(W:(Y-T)+(Z-W)) @f$ or 00310 * -# @f$ w(\delta(Z-W))/2 \leq w(Z-W:T+W) @f$. 00311 * Then there exists a minimum cut @f$(X:V-X)@f$ such that either @f$ 00312 * Z\subseteq X @f$ or @f$ X\subseteq Z @f$. 00313 * 00314 * And the original theorem (in fact is the corollary 3.5 in the paper) 00315 * regarding global conditions for shrinking is the following: 00316 * Let @f$ u\neq v\in V @f$, and let @f$ q @f$ be an upper bound on the 00317 * minimum cut value, and @f$ lb_{uv} @f$ be a lower bound in the value of a 00318 * minimum @f$ u-v @f$ cut, then if @f$ lb_{uv}\geq q @f$ the set 00319 * @f$ \{u,v\} @f$ is shrinkable. 00320 * 00321 * The actual tests that we perform (for every edge) are the following: 00322 * -# If @f$ w(\delta(u)) < @f$ #EGalgMCgraph_t::cut_val, update the minimum 00323 * cut value and set. 00324 * -# If @f$ w_{uv} \geq \min\{w(\delta(u)),w(\delta(v))\}/2 @f$ then we can 00325 * safely shrink edge @f$ uv @f$. 00326 * -# If we have a triangle @f$ uv,\quad vw,\quad wu @f$, with 00327 * @f$ w_{uv} + w_{vw} \geq w(\delta(v))/2 @f$ and 00328 * @f$ w_{uw} + w_{vw} \geq w(\delta(w))/2 @f$ then we can safely shrink edge 00329 * @f$ wv @f$. 00330 * -# Compute lower bound on the cut that separates the endpoints of the 00331 * current edge as : 00332 * @f[ lb_{uv}=w_{uv}+\sum\limits_{w\in N(u)\cap N(v)}\min\{w_{uw},w_{vw}\} @f] 00333 * If @f$ lb_{uv} \geq @f$ #EGalgMCgraph_t::cut_val , then we can shrink the edge @f$ uv @f$. 00334 * -# Consider the edge @f$ uv @f$ and two common neighbours @f$ x,y @f$. If 00335 * @f$ w_{ux} + w_{uy} + w_{uv} \geq w(\delta(u))/2 @f$ and 00336 * @f$ w_{vx} + w_{vy} + w_{vu} \geq w(\delta(v))/2 @f$ and at least one of 00337 * @f$ w_{uv} + w_{uy} \geq w(\delta(u))/2 @f$ and 00338 * @f$ w_{uv} + w_{vx} \geq w(\delta(v))/2 @f$ and at least one of 00339 * @f$ w_{uv} + w_{ux} \geq w(\delta(u))/2 @f$ and 00340 * @f$ w_{uv} + w_{vy} \geq w(\delta(v))/2 @f$ then we can safely shrink edge 00341 * @f$ uv @f$. 00342 * 00343 * We make thiese tests in order, i.e. first we perform all level 1 tests, 00344 * then level2, and so on, and whenever two nodes are Identify (shrinked) we 00345 * set the level of the node to 1 (i.e. in the next test we will test the 00346 * first condition). This is done using an array of (5) lists, where all nodes 00347 * are distributed. Originally all nodes should be in the first lists (i.e. 00348 * all nodes should be tested to improve the current best cut by themselves). 00349 * */ 00350 int EGalgMCidentifyPRedges (EGalgMCgraph_t * const G, 00351 EGalgMCcbk_t * const cb, 00352 const unsigned int max_lvl); 00353 00354 /* ========================================================================= */ 00355 /** @brief Compute a minimum cut on the given graph. 00356 * @param max_lvl set a limit on wich tests to perform during the 00357 * Padberg-Rinaldy shrinking step. for example, if set to 00358 * 1, only the first and second tests will be carried out. 00359 * @param G graph over wich we are working. 00360 * @param cb call back structure to use (if set to NULL it is not used). 00361 * @return zero on success, non-zero otherwise. 00362 * 00363 * This function takes as input a graph, and perform the minimum cut algorithm 00364 * as described in the paper "An Efficient 00365 * Algorithm For The Minimum Capacity Cut Problem", Mathematical Programming 00366 * 47 (1990) pages 19-36. 00367 * 00368 * Note that the graph should have all fields properly initialized. 00369 * */ 00370 int EGalgMC (EGalgMCgraph_t * const G, 00371 EGalgMCcbk_t * const cb, 00372 const unsigned int max_lvl); 00373 00374 /* ========================================================================= */ 00375 /** @} 00376 * end eg_min_cut.h */ 00377 #endif
1.4.5