eg_min_cut.h

Go to the documentation of this file.
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

Generated on Mon Jan 30 08:48:54 2006 for EGlib by  doxygen 1.4.5