├── CHANGES.txt ├── MANIFEST.in ├── README.txt ├── block.h ├── graph.cpp ├── graph.h ├── instances.inc ├── maxflow.cpp ├── pymaxflow.pyx ├── setup.py └── test.py /CHANGES.txt: -------------------------------------------------------------------------------- 1 | List of changes from version 3.0: 2 | - Moved line 3 | #include "instances.inc" 4 | to the end of cpp files to make it compile under GNU c++ compilers 4.2(?) and above 5 | 6 | List of changes from version 2.2: 7 | 8 | - Added functions for accessing graph structure, residual capacities, etc. 9 | (They are needed for implementing maxflow-based algorithms such as primal-dual algorithm for convex MRFs.) 10 | - Added option of reusing trees. 11 | - node_id's are now integers starting from 0. Thus, it is not necessary to store node_id's in a separate array. 12 | - Capacity types are now templated. 13 | - Fixed bug in block.h. (After Block::Reset, ScanFirst() and ScanNext() did not work properly). 14 | - Implementation with a forward star representation of the graph is no longer supported. (It needs less memory, but slightly slower than adjacency list representation.) If you still wish to use it, download version 2.2. 15 | - Note: version 3.0 is released under a different license than version 2.2. 16 | 17 | List of changes from version 2.1: 18 | 19 | - Put the code under GPL license 20 | 21 | List of changes from version 2.02: 22 | 23 | - Fixed a bug in the implementation that uses forward star representation 24 | 25 | List of changes from version 2.01: 26 | 27 | - Added new interface function - Graph::add_tweights(Node_id, captype, captype) 28 | (necessary for the "ENERGY" software package) 29 | 30 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include CHANGES.txt 2 | include README.txt 3 | include block.h 4 | include graph.cpp 5 | include graph.h 6 | include instances.inc 7 | include maxflow.cpp 8 | include pymaxflow.pyx 9 | include setup.py 10 | include test.py 11 | 12 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | This is a simple Cython wrapper around the MAXFLOW library from Boykov 2 | and Kolmogorov. Their original README and License information are 3 | included below. Cython wrapper by Thouis (Ray) Jones. 4 | 5 | Installation 6 | ============ 7 | 8 | Requirements 9 | ------------ 10 | 11 | - cython (version 0.19.1 works, version 0.16 not) 12 | - numpy 13 | - matplotlib (only for example test.py) 14 | 15 | Installation with Pip 16 | --------------------- 17 | 18 | $ pip install git+#egg=pymaxflow 19 | 20 | Manual Installation 21 | ------------------- 22 | - download the package 23 | 24 | $ python setup.py build_ext --inplace 25 | 26 | install the package with pip (can be uninstalled) 27 | $ pip install . 28 | 29 | or install the package with distutils 30 | $ python setup.py install 31 | 32 | Test the Package 33 | ---------------- 34 | 35 | $ python test.py someimage.png 36 | ... figure with input image segmentation should pop up 37 | 38 | 39 | 40 | ################################################################### 41 | # # 42 | # MAXFLOW - software for computing mincut/maxflow in a graph # 43 | # Version 3.01 # 44 | # http://www.cs.ucl.ac.uk/staff/V.Kolmogorov/software.html # 45 | # # 46 | # Yuri Boykov (yuri@csd.uwo.ca) # 47 | # Vladimir Kolmogorov (v.kolmogorov@cs.ucl.ac.uk) # 48 | # 2001-2006 # 49 | # # 50 | ################################################################### 51 | 52 | 1. Introduction. 53 | 54 | This software library implements the maxflow algorithm described in 55 | 56 | "An Experimental Comparison of Min-Cut/Max-Flow Algorithms for Energy Minimization in Vision." 57 | Yuri Boykov and Vladimir Kolmogorov. 58 | In IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI), 59 | September 2004 60 | 61 | This algorithm was developed by Yuri Boykov and Vladimir Kolmogorov 62 | at Siemens Corporate Research. To make it available for public use, 63 | it was later reimplemented by Vladimir Kolmogorov based on open publications. 64 | 65 | If you use this software for research purposes, you should cite 66 | the aforementioned paper in any resulting publication. 67 | 68 | ---------------------------------------------------------------------- 69 | 70 | REUSING TREES: 71 | 72 | Starting with version 3.0, there is a also an option of reusing search 73 | trees from one maxflow computation to the next, as described in 74 | 75 | "Efficiently Solving Dynamic Markov Random Fields Using Graph Cuts." 76 | Pushmeet Kohli and Philip H.S. Torr 77 | International Conference on Computer Vision (ICCV), 2005 78 | 79 | If you use this option, you should cite 80 | the aforementioned paper in any resulting publication. 81 | 82 | Tested under windows, Visual C++ 6.0 compiler and unix (SunOS 5.8 83 | and RedHat Linux 7.0, GNU c++ compiler). 84 | 85 | ################################################################## 86 | 87 | 2. License & disclaimer. 88 | 89 | Copyright 2001-2006 Vladimir Kolmogorov (v.kolmogorov@cs.ucl.ac.uk), Yuri Boykov (yuri@csd.uwo.ca). 90 | 91 | This software can be used for research purposes only. 92 | If you require another license, you may consider using version 2.21 93 | (which implements exactly the same algorithm, but does not have the option of reusing search trees). 94 | 95 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 96 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 97 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 98 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 99 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 100 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 101 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 102 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 103 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 104 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 105 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 106 | 107 | ################################################################## 108 | 109 | 3. Example usage. 110 | 111 | This section shows how to use the library to compute 112 | a minimum cut on the following graph: 113 | 114 | SOURCE 115 | / \ 116 | 1/ \2 117 | / 3 \ 118 | node0 -----> node1 119 | | <----- | 120 | | 4 | 121 | \ / 122 | 5\ /6 123 | \ / 124 | SINK 125 | 126 | /////////////////////////////////////////////////// 127 | 128 | #include 129 | #include "graph.h" 130 | 131 | int main() 132 | { 133 | typedef Graph GraphType; 134 | GraphType *g = new GraphType(/*estimated # of nodes*/ 2, /*estimated # of edges*/ 1); 135 | 136 | g -> add_node(); 137 | g -> add_node(); 138 | 139 | g -> add_tweights( 0, /* capacities */ 1, 5 ); 140 | g -> add_tweights( 1, /* capacities */ 2, 6 ); 141 | g -> add_edge( 0, 1, /* capacities */ 3, 4 ); 142 | 143 | int flow = g -> maxflow(); 144 | 145 | printf("Flow = %d\n", flow); 146 | printf("Minimum cut:\n"); 147 | if (g->what_segment(0) == GraphType::SOURCE) 148 | printf("node0 is in the SOURCE set\n"); 149 | else 150 | printf("node0 is in the SINK set\n"); 151 | if (g->what_segment(1) == GraphType::SOURCE) 152 | printf("node1 is in the SOURCE set\n"); 153 | else 154 | printf("node1 is in the SINK set\n"); 155 | 156 | delete g; 157 | 158 | return 0; 159 | } 160 | 161 | 162 | /////////////////////////////////////////////////// 163 | -------------------------------------------------------------------------------- /block.h: -------------------------------------------------------------------------------- 1 | /* block.h */ 2 | /* 3 | Template classes Block and DBlock 4 | Implement adding and deleting items of the same type in blocks. 5 | 6 | If there there are many items then using Block or DBlock 7 | is more efficient than using 'new' and 'delete' both in terms 8 | of memory and time since 9 | (1) On some systems there is some minimum amount of memory 10 | that 'new' can allocate (e.g., 64), so if items are 11 | small that a lot of memory is wasted. 12 | (2) 'new' and 'delete' are designed for items of varying size. 13 | If all items has the same size, then an algorithm for 14 | adding and deleting can be made more efficient. 15 | (3) All Block and DBlock functions are inline, so there are 16 | no extra function calls. 17 | 18 | Differences between Block and DBlock: 19 | (1) DBlock allows both adding and deleting items, 20 | whereas Block allows only adding items. 21 | (2) Block has an additional operation of scanning 22 | items added so far (in the order in which they were added). 23 | (3) Block allows to allocate several consecutive 24 | items at a time, whereas DBlock can add only a single item. 25 | 26 | Note that no constructors or destructors are called for items. 27 | 28 | Example usage for items of type 'MyType': 29 | 30 | /////////////////////////////////////////////////// 31 | #include "block.h" 32 | #define BLOCK_SIZE 1024 33 | typedef struct { int a, b; } MyType; 34 | MyType *ptr, *array[10000]; 35 | 36 | ... 37 | 38 | Block *block = new Block(BLOCK_SIZE); 39 | 40 | // adding items 41 | for (int i=0; i New(); 44 | ptr -> a = ptr -> b = rand(); 45 | } 46 | 47 | // reading items 48 | for (ptr=block->ScanFirst(); ptr; ptr=block->ScanNext()) 49 | { 50 | printf("%d %d\n", ptr->a, ptr->b); 51 | } 52 | 53 | delete block; 54 | 55 | ... 56 | 57 | DBlock *dblock = new DBlock(BLOCK_SIZE); 58 | 59 | // adding items 60 | for (int i=0; i New(); 63 | } 64 | 65 | // deleting items 66 | for (int i=0; i Delete(array[i]); 69 | } 70 | 71 | // adding items 72 | for (int i=0; i New(); 75 | } 76 | 77 | delete dblock; 78 | 79 | /////////////////////////////////////////////////// 80 | 81 | Note that DBlock deletes items by marking them as 82 | empty (i.e., by adding them to the list of free items), 83 | so that this memory could be used for subsequently 84 | added items. Thus, at each moment the memory allocated 85 | is determined by the maximum number of items allocated 86 | simultaneously at earlier moments. All memory is 87 | deallocated only when the destructor is called. 88 | */ 89 | 90 | #ifndef __BLOCK_H__ 91 | #define __BLOCK_H__ 92 | 93 | #include 94 | 95 | /***********************************************************************/ 96 | /***********************************************************************/ 97 | /***********************************************************************/ 98 | 99 | template class Block 100 | { 101 | public: 102 | /* Constructor. Arguments are the block size and 103 | (optionally) the pointer to the function which 104 | will be called if allocation failed; the message 105 | passed to this function is "Not enough memory!" */ 106 | Block(int size, void (*err_function)(const char *) = NULL) { first = last = NULL; block_size = size; error_function = err_function; } 107 | 108 | /* Destructor. Deallocates all items added so far */ 109 | ~Block() { while (first) { block *next = first -> next; delete[] ((char*)first); first = next; } } 110 | 111 | /* Allocates 'num' consecutive items; returns pointer 112 | to the first item. 'num' cannot be greater than the 113 | block size since items must fit in one block */ 114 | Type *New(int num = 1) 115 | { 116 | Type *t; 117 | 118 | if (!last || last->current + num > last->last) 119 | { 120 | if (last && last->next) last = last -> next; 121 | else 122 | { 123 | block *next = (block *) new char [sizeof(block) + (block_size-1)*sizeof(Type)]; 124 | if (!next) { if (error_function) (*error_function)("Not enough memory!"); exit(1); } 125 | if (last) last -> next = next; 126 | else first = next; 127 | last = next; 128 | last -> current = & ( last -> data[0] ); 129 | last -> last = last -> current + block_size; 130 | last -> next = NULL; 131 | } 132 | } 133 | 134 | t = last -> current; 135 | last -> current += num; 136 | return t; 137 | } 138 | 139 | /* Returns the first item (or NULL, if no items were added) */ 140 | Type *ScanFirst() 141 | { 142 | for (scan_current_block=first; scan_current_block; scan_current_block = scan_current_block->next) 143 | { 144 | scan_current_data = & ( scan_current_block -> data[0] ); 145 | if (scan_current_data < scan_current_block -> current) return scan_current_data ++; 146 | } 147 | return NULL; 148 | } 149 | 150 | /* Returns the next item (or NULL, if all items have been read) 151 | Can be called only if previous ScanFirst() or ScanNext() 152 | call returned not NULL. */ 153 | Type *ScanNext() 154 | { 155 | while (scan_current_data >= scan_current_block -> current) 156 | { 157 | scan_current_block = scan_current_block -> next; 158 | if (!scan_current_block) return NULL; 159 | scan_current_data = & ( scan_current_block -> data[0] ); 160 | } 161 | return scan_current_data ++; 162 | } 163 | 164 | /* Marks all elements as empty */ 165 | void Reset() 166 | { 167 | block *b; 168 | if (!first) return; 169 | for (b=first; ; b=b->next) 170 | { 171 | b -> current = & ( b -> data[0] ); 172 | if (b == last) break; 173 | } 174 | last = first; 175 | } 176 | 177 | /***********************************************************************/ 178 | 179 | private: 180 | 181 | typedef struct block_st 182 | { 183 | Type *current, *last; 184 | struct block_st *next; 185 | Type data[1]; 186 | } block; 187 | 188 | int block_size; 189 | block *first; 190 | block *last; 191 | 192 | block *scan_current_block; 193 | Type *scan_current_data; 194 | 195 | void (*error_function)(const char *); 196 | }; 197 | 198 | /***********************************************************************/ 199 | /***********************************************************************/ 200 | /***********************************************************************/ 201 | 202 | template class DBlock 203 | { 204 | public: 205 | /* Constructor. Arguments are the block size and 206 | (optionally) the pointer to the function which 207 | will be called if allocation failed; the message 208 | passed to this function is "Not enough memory!" */ 209 | DBlock(int size, void (*err_function)(const char *) = NULL) { first = NULL; first_free = NULL; block_size = size; error_function = err_function; } 210 | 211 | /* Destructor. Deallocates all items added so far */ 212 | ~DBlock() { while (first) { block *next = first -> next; delete[] ((char*)first); first = next; } } 213 | 214 | /* Allocates one item */ 215 | Type *New() 216 | { 217 | block_item *item; 218 | 219 | if (!first_free) 220 | { 221 | block *next = first; 222 | first = (block *) new char [sizeof(block) + (block_size-1)*sizeof(block_item)]; 223 | if (!first) { if (error_function) (*error_function)("Not enough memory!"); exit(1); } 224 | first_free = & (first -> data[0] ); 225 | for (item=first_free; item next_free = item + 1; 227 | item -> next_free = NULL; 228 | first -> next = next; 229 | } 230 | 231 | item = first_free; 232 | first_free = item -> next_free; 233 | return (Type *) item; 234 | } 235 | 236 | /* Deletes an item allocated previously */ 237 | void Delete(Type *t) 238 | { 239 | ((block_item *) t) -> next_free = first_free; 240 | first_free = (block_item *) t; 241 | } 242 | 243 | /***********************************************************************/ 244 | 245 | private: 246 | 247 | typedef union block_item_st 248 | { 249 | Type t; 250 | block_item_st *next_free; 251 | } block_item; 252 | 253 | typedef struct block_st 254 | { 255 | struct block_st *next; 256 | block_item data[1]; 257 | } block; 258 | 259 | int block_size; 260 | block *first; 261 | block_item *first_free; 262 | 263 | void (*error_function)(const char *); 264 | }; 265 | 266 | 267 | #endif 268 | 269 | -------------------------------------------------------------------------------- /graph.cpp: -------------------------------------------------------------------------------- 1 | /* graph.cpp */ 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | #include "graph.h" 8 | 9 | 10 | template 11 | Graph::Graph(int node_num_max, int edge_num_max, void (*err_function)(const char *)) 12 | : node_num(0), 13 | nodeptr_block(NULL), 14 | error_function(err_function) 15 | { 16 | if (node_num_max < 16) node_num_max = 16; 17 | if (edge_num_max < 16) edge_num_max = 16; 18 | 19 | nodes = (node*) malloc(node_num_max*sizeof(node)); 20 | arcs = (arc*) malloc(2*edge_num_max*sizeof(arc)); 21 | if (!nodes || !arcs) { if (error_function) (*error_function)("Not enough memory!"); exit(1); } 22 | 23 | node_last = nodes; 24 | node_max = nodes + node_num_max; 25 | arc_last = arcs; 26 | arc_max = arcs + 2*edge_num_max; 27 | 28 | maxflow_iteration = 0; 29 | flow = 0; 30 | } 31 | 32 | template 33 | Graph::~Graph() 34 | { 35 | if (nodeptr_block) 36 | { 37 | delete nodeptr_block; 38 | nodeptr_block = NULL; 39 | } 40 | free(nodes); 41 | free(arcs); 42 | } 43 | 44 | template 45 | void Graph::reset() 46 | { 47 | node_last = nodes; 48 | arc_last = arcs; 49 | node_num = 0; 50 | 51 | if (nodeptr_block) 52 | { 53 | delete nodeptr_block; 54 | nodeptr_block = NULL; 55 | } 56 | 57 | maxflow_iteration = 0; 58 | flow = 0; 59 | } 60 | 61 | template 62 | void Graph::reallocate_nodes(int num) 63 | { 64 | int node_num_max = (int)(node_max - nodes); 65 | node* nodes_old = nodes; 66 | 67 | node_num_max += node_num_max / 2; 68 | if (node_num_max < node_num + num) node_num_max = node_num + num; 69 | nodes = (node*) realloc(nodes_old, node_num_max*sizeof(node)); 70 | if (!nodes) { if (error_function) (*error_function)("Not enough memory!"); exit(1); } 71 | 72 | node_last = nodes + node_num; 73 | node_max = nodes + node_num_max; 74 | 75 | if (nodes != nodes_old) 76 | { 77 | arc* a; 78 | for (a=arcs; ahead = (node*) ((char*)a->head + (((char*) nodes) - ((char*) nodes_old))); 81 | } 82 | } 83 | } 84 | 85 | template 86 | void Graph::reallocate_arcs() 87 | { 88 | int arc_num_max = (int)(arc_max - arcs); 89 | int arc_num = (int)(arc_last - arcs); 90 | arc* arcs_old = arcs; 91 | 92 | arc_num_max += arc_num_max / 2; if (arc_num_max & 1) arc_num_max ++; 93 | arcs = (arc*) realloc(arcs_old, arc_num_max*sizeof(arc)); 94 | if (!arcs) { if (error_function) (*error_function)("Not enough memory!"); exit(1); } 95 | 96 | arc_last = arcs + arc_num; 97 | arc_max = arcs + arc_num_max; 98 | 99 | if (arcs != arcs_old) 100 | { 101 | node* i; 102 | arc* a; 103 | for (i=nodes; ifirst) i->first = (arc*) ((char*)i->first + (((char*) arcs) - ((char*) arcs_old))); 106 | } 107 | for (a=arcs; anext) a->next = (arc*) ((char*)a->next + (((char*) arcs) - ((char*) arcs_old))); 110 | a->sister = (arc*) ((char*)a->sister + (((char*) arcs) - ((char*) arcs_old))); 111 | } 112 | } 113 | } 114 | 115 | #include "instances.inc" 116 | -------------------------------------------------------------------------------- /graph.h: -------------------------------------------------------------------------------- 1 | /* graph.h */ 2 | /* 3 | This software library implements the maxflow algorithm 4 | described in 5 | 6 | "An Experimental Comparison of Min-Cut/Max-Flow Algorithms for Energy Minimization in Vision." 7 | Yuri Boykov and Vladimir Kolmogorov. 8 | In IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI), 9 | September 2004 10 | 11 | This algorithm was developed by Yuri Boykov and Vladimir Kolmogorov 12 | at Siemens Corporate Research. To make it available for public use, 13 | it was later reimplemented by Vladimir Kolmogorov based on open publications. 14 | 15 | If you use this software for research purposes, you should cite 16 | the aforementioned paper in any resulting publication. 17 | 18 | ---------------------------------------------------------------------- 19 | 20 | REUSING TREES: 21 | 22 | Starting with version 3.0, there is a also an option of reusing search 23 | trees from one maxflow computation to the next, as described in 24 | 25 | "Efficiently Solving Dynamic Markov Random Fields Using Graph Cuts." 26 | Pushmeet Kohli and Philip H.S. Torr 27 | International Conference on Computer Vision (ICCV), 2005 28 | 29 | If you use this option, you should cite 30 | the aforementioned paper in any resulting publication. 31 | */ 32 | 33 | 34 | 35 | /* 36 | For description, license, example usage see README.TXT. 37 | */ 38 | 39 | #ifndef __GRAPH_H__ 40 | #define __GRAPH_H__ 41 | 42 | #include 43 | #include "block.h" 44 | 45 | #include 46 | // NOTE: in UNIX you need to use -DNDEBUG preprocessor option to supress assert's!!! 47 | 48 | 49 | 50 | // captype: type of edge capacities (excluding t-links) 51 | // tcaptype: type of t-links (edges between nodes and terminals) 52 | // flowtype: type of total flow 53 | // 54 | // Current instantiations are in instances.inc 55 | template class Graph 56 | { 57 | public: 58 | typedef enum 59 | { 60 | SOURCE = 0, 61 | SINK = 1 62 | } termtype; // terminals 63 | typedef int node_id; 64 | 65 | ///////////////////////////////////////////////////////////////////////// 66 | // BASIC INTERFACE FUNCTIONS // 67 | // (should be enough for most applications) // 68 | ///////////////////////////////////////////////////////////////////////// 69 | 70 | // Constructor. 71 | // The first argument gives an estimate of the maximum number of nodes that can be added 72 | // to the graph, and the second argument is an estimate of the maximum number of edges. 73 | // The last (optional) argument is the pointer to the function which will be called 74 | // if an error occurs; an error message is passed to this function. 75 | // If this argument is omitted, exit(1) will be called. 76 | // 77 | // IMPORTANT: It is possible to add more nodes to the graph than node_num_max 78 | // (and node_num_max can be zero). However, if the count is exceeded, then 79 | // the internal memory is reallocated (increased by 50%) which is expensive. 80 | // Also, temporarily the amount of allocated memory would be more than twice than needed. 81 | // Similarly for edges. 82 | // If you wish to avoid this overhead, you can download version 2.2, where nodes and edges are stored in blocks. 83 | Graph(int node_num_max, int edge_num_max, void (*err_function)(const char *) = NULL); 84 | 85 | // Destructor 86 | ~Graph(); 87 | 88 | // Adds node(s) to the graph. By default, one node is added (num=1); then first call returns 0, second call returns 1, and so on. 89 | // If num>1, then several nodes are added, and node_id of the first one is returned. 90 | // IMPORTANT: see note about the constructor 91 | node_id add_node(int num = 1); 92 | 93 | // Adds a bidirectional edge between 'i' and 'j' with the weights 'cap' and 'rev_cap'. 94 | // IMPORTANT: see note about the constructor 95 | void add_edge(node_id i, node_id j, captype cap, captype rev_cap); 96 | 97 | // Adds new edges 'SOURCE->i' and 'i->SINK' with corresponding weights. 98 | // Can be called multiple times for each node. 99 | // Weights can be negative. 100 | // NOTE: the number of such edges is not counted in edge_num_max. 101 | // No internal memory is allocated by this call. 102 | void add_tweights(node_id i, tcaptype cap_source, tcaptype cap_sink); 103 | 104 | 105 | // Computes the maxflow. Can be called several times. 106 | // FOR DESCRIPTION OF reuse_trees, SEE mark_node(). 107 | // FOR DESCRIPTION OF changed_list, SEE remove_from_changed_list(). 108 | flowtype maxflow(bool reuse_trees = false, Block* changed_list = NULL); 109 | 110 | // After the maxflow is computed, this function returns to which 111 | // segment the node 'i' belongs (Graph::SOURCE or Graph::SINK). 112 | // 113 | // Occasionally there may be several minimum cuts. If a node can be assigned 114 | // to both the source and the sink, then default_segm is returned. 115 | termtype what_segment(node_id i, termtype default_segm = SOURCE); 116 | 117 | 118 | 119 | ////////////////////////////////////////////// 120 | // ADVANCED INTERFACE FUNCTIONS // 121 | // (provide access to the graph) // 122 | ////////////////////////////////////////////// 123 | 124 | private: 125 | struct node; 126 | struct arc; 127 | 128 | public: 129 | 130 | //////////////////////////// 131 | // 1. Reallocating graph. // 132 | //////////////////////////// 133 | 134 | // Removes all nodes and edges. 135 | // After that functions add_node() and add_edge() must be called again. 136 | // 137 | // Advantage compared to deleting Graph and allocating it again: 138 | // no calls to delete/new (which could be quite slow). 139 | // 140 | // If the graph structure stays the same, then an alternative 141 | // is to go through all nodes/edges and set new residual capacities 142 | // (see functions below). 143 | void reset(); 144 | 145 | //////////////////////////////////////////////////////////////////////////////// 146 | // 2. Functions for getting pointers to arcs and for reading graph structure. // 147 | // NOTE: adding new arcs may invalidate these pointers (if reallocation // 148 | // happens). So it's best not to add arcs while reading graph structure. // 149 | //////////////////////////////////////////////////////////////////////////////// 150 | 151 | // The following two functions return arcs in the same order that they 152 | // were added to the graph. NOTE: for each call add_edge(i,j,cap,cap_rev) 153 | // the first arc returned will be i->j, and the second j->i. 154 | // If there are no more arcs, then the function can still be called, but 155 | // the returned arc_id is undetermined. 156 | typedef arc* arc_id; 157 | arc_id get_first_arc(); 158 | arc_id get_next_arc(arc_id a); 159 | 160 | // other functions for reading graph structure 161 | int get_node_num() { return node_num; } 162 | int get_arc_num() { return (int)(arc_last - arcs); } 163 | void get_arc_ends(arc_id a, node_id& i, node_id& j); // returns i,j to that a = i->j 164 | 165 | /////////////////////////////////////////////////// 166 | // 3. Functions for reading residual capacities. // 167 | /////////////////////////////////////////////////// 168 | 169 | // returns residual capacity of SOURCE->i minus residual capacity of i->SINK 170 | tcaptype get_trcap(node_id i); 171 | // returns residual capacity of arc a 172 | captype get_rcap(arc* a); 173 | 174 | ///////////////////////////////////////////////////////////////// 175 | // 4. Functions for setting residual capacities. // 176 | // NOTE: If these functions are used, the value of the flow // 177 | // returned by maxflow() will not be valid! // 178 | ///////////////////////////////////////////////////////////////// 179 | 180 | void set_trcap(node_id i, tcaptype trcap); 181 | void set_rcap(arc* a, captype rcap); 182 | 183 | //////////////////////////////////////////////////////////////////// 184 | // 5. Functions related to reusing trees & list of changed nodes. // 185 | //////////////////////////////////////////////////////////////////// 186 | 187 | // If flag reuse_trees is true while calling maxflow(), then search trees 188 | // are reused from previous maxflow computation. 189 | // In this case before calling maxflow() the user must 190 | // specify which parts of the graph have changed by calling mark_node(): 191 | // add_tweights(i),set_trcap(i) => call mark_node(i) 192 | // add_edge(i,j),set_rcap(a) => call mark_node(i); mark_node(j) 193 | // 194 | // This option makes sense only if a small part of the graph is changed. 195 | // The initialization procedure goes only through marked nodes then. 196 | // 197 | // mark_node(i) can either be called before or after graph modification. 198 | // Can be called more than once per node, but calls after the first one 199 | // do not have any effect. 200 | // 201 | // NOTE: 202 | // - This option cannot be used in the first call to maxflow(). 203 | // - It is not necessary to call mark_node() if the change is ``not essential'', 204 | // i.e. sign(trcap) is preserved for a node and zero/nonzero status is preserved for an arc. 205 | // - To check that you marked all necessary nodes, you can call maxflow(false) after calling maxflow(true). 206 | // If everything is correct, the two calls must return the same value of flow. (Useful for debugging). 207 | void mark_node(node_id i); 208 | 209 | // If changed_list is not NULL while calling maxflow(), then the algorithm 210 | // keeps a list of nodes which could potentially have changed their segmentation label. 211 | // Nodes which are not in the list are guaranteed to keep their old segmentation label (SOURCE or SINK). 212 | // Example usage: 213 | // 214 | // typedef Graph G; 215 | // G* g = new Graph(nodeNum, edgeNum); 216 | // Block* changed_list = new Block(128); 217 | // 218 | // ... // add nodes and edges 219 | // 220 | // g->maxflow(); // first call should be without arguments 221 | // for (int iter=0; iter<10; iter++) 222 | // { 223 | // ... // change graph, call mark_node() accordingly 224 | // 225 | // g->maxflow(true, changed_list); 226 | // G::node_id* ptr; 227 | // for (ptr=changed_list->ScanFirst(); ptr; ptr=changed_list->ScanNext()) 228 | // { 229 | // G::node_id i = *ptr; assert(i>=0 && iremove_from_changed_list(i); 231 | // // do something with node i... 232 | // if (g->what_segment(i) == G::SOURCE) { ... } 233 | // } 234 | // changed_list->Reset(); 235 | // } 236 | // delete changed_list; 237 | // 238 | // NOTE: 239 | // - If changed_list option is used, then reuse_trees must be used as well. 240 | // - In the example above, the user may omit calls g->remove_from_changed_list(i) and changed_list->Reset() in a given iteration. 241 | // Then during the next call to maxflow(true, &changed_list) new nodes will be added to changed_list. 242 | // - If the next call to maxflow() does not use option reuse_trees, then calling remove_from_changed_list() 243 | // is not necessary. ("changed_list->Reset()" or "delete changed_list" should still be called, though). 244 | void remove_from_changed_list(node_id i) 245 | { 246 | assert(i>=0 && i 0 then tr_cap is residual capacity of the arc SOURCE->node 276 | // otherwise -tr_cap is residual capacity of the arc node->SINK 277 | 278 | }; 279 | 280 | struct arc 281 | { 282 | node *head; // node the arc points to 283 | arc *next; // next arc with the same originating node 284 | arc *sister; // reverse arc 285 | 286 | captype r_cap; // residual capacity 287 | }; 288 | 289 | struct nodeptr 290 | { 291 | node *ptr; 292 | nodeptr *next; 293 | }; 294 | static const int NODEPTR_BLOCK_SIZE = 128; 295 | 296 | node *nodes, *node_last, *node_max; // node_last = nodes+node_num, node_max = nodes+node_num_max; 297 | arc *arcs, *arc_last, *arc_max; // arc_last = arcs+2*edge_num, arc_max = arcs+2*edge_num_max; 298 | 299 | int node_num; 300 | 301 | DBlock *nodeptr_block; 302 | 303 | void (*error_function)(const char *); // this function is called if a error occurs, 304 | // with a corresponding error message 305 | // (or exit(1) is called if it's NULL) 306 | 307 | flowtype flow; // total flow 308 | 309 | // reusing trees & list of changed pixels 310 | int maxflow_iteration; // counter 311 | Block *changed_list; 312 | 313 | ///////////////////////////////////////////////////////////////////////// 314 | 315 | node *queue_first[2], *queue_last[2]; // list of active nodes 316 | nodeptr *orphan_first, *orphan_last; // list of pointers to orphans 317 | int TIME; // monotonically increasing global counter 318 | 319 | ///////////////////////////////////////////////////////////////////////// 320 | 321 | void reallocate_nodes(int num); // num is the number of new nodes 322 | void reallocate_arcs(); 323 | 324 | // functions for processing active list 325 | void set_active(node *i); 326 | node *next_active(); 327 | 328 | // functions for processing orphans list 329 | void set_orphan_front(node* i); // add to the beginning of the list 330 | void set_orphan_rear(node* i); // add to the end of the list 331 | 332 | void add_to_changed_list(node* i); 333 | 334 | void maxflow_init(); // called if reuse_trees == false 335 | void maxflow_reuse_trees_init(); // called if reuse_trees == true 336 | void augment(arc *middle_arc); 337 | void process_source_orphan(node *i); 338 | void process_sink_orphan(node *i); 339 | 340 | void test_consistency(node* current_node=NULL); // debug function 341 | }; 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | /////////////////////////////////////// 354 | // Implementation - inline functions // 355 | /////////////////////////////////////// 356 | 357 | 358 | 359 | template 360 | inline typename Graph::node_id Graph::add_node(int num) 361 | { 362 | assert(num > 0); 363 | 364 | if (node_last + num > node_max) reallocate_nodes(num); 365 | 366 | if (num == 1) 367 | { 368 | node_last -> first = NULL; 369 | node_last -> tr_cap = 0; 370 | node_last -> is_marked = 0; 371 | node_last -> is_in_changed_list = 0; 372 | 373 | node_last ++; 374 | return node_num ++; 375 | } 376 | else 377 | { 378 | memset(node_last, 0, num*sizeof(node)); 379 | 380 | node_id i = node_num; 381 | node_num += num; 382 | node_last += num; 383 | return i; 384 | } 385 | } 386 | 387 | template 388 | inline void Graph::add_tweights(node_id i, tcaptype cap_source, tcaptype cap_sink) 389 | { 390 | assert(i >= 0 && i < node_num); 391 | 392 | tcaptype delta = nodes[i].tr_cap; 393 | if (delta > 0) cap_source += delta; 394 | else cap_sink -= delta; 395 | flow += (cap_source < cap_sink) ? cap_source : cap_sink; 396 | nodes[i].tr_cap = cap_source - cap_sink; 397 | } 398 | 399 | template 400 | inline void Graph::add_edge(node_id _i, node_id _j, captype cap, captype rev_cap) 401 | { 402 | assert(_i >= 0 && _i < node_num); 403 | assert(_j >= 0 && _j < node_num); 404 | assert(_i != _j); 405 | assert(cap >= 0); 406 | assert(rev_cap >= 0); 407 | 408 | if (arc_last == arc_max) reallocate_arcs(); 409 | 410 | arc *a = arc_last ++; 411 | arc *a_rev = arc_last ++; 412 | 413 | node* i = nodes + _i; 414 | node* j = nodes + _j; 415 | 416 | a -> sister = a_rev; 417 | a_rev -> sister = a; 418 | a -> next = i -> first; 419 | i -> first = a; 420 | a_rev -> next = j -> first; 421 | j -> first = a_rev; 422 | a -> head = j; 423 | a_rev -> head = i; 424 | a -> r_cap = cap; 425 | a_rev -> r_cap = rev_cap; 426 | } 427 | 428 | template 429 | inline typename Graph::arc* Graph::get_first_arc() 430 | { 431 | return arcs; 432 | } 433 | 434 | template 435 | inline typename Graph::arc* Graph::get_next_arc(arc* a) 436 | { 437 | return a + 1; 438 | } 439 | 440 | template 441 | inline void Graph::get_arc_ends(arc* a, node_id& i, node_id& j) 442 | { 443 | assert(a >= arcs && a < arc_last); 444 | i = (node_id) (a->sister->head - nodes); 445 | j = (node_id) (a->head - nodes); 446 | } 447 | 448 | template 449 | inline tcaptype Graph::get_trcap(node_id i) 450 | { 451 | assert(i>=0 && i 456 | inline captype Graph::get_rcap(arc* a) 457 | { 458 | assert(a >= arcs && a < arc_last); 459 | return a->r_cap; 460 | } 461 | 462 | template 463 | inline void Graph::set_trcap(node_id i, tcaptype trcap) 464 | { 465 | assert(i>=0 && i 470 | inline void Graph::set_rcap(arc* a, captype rcap) 471 | { 472 | assert(a >= arcs && a < arc_last); 473 | a->r_cap = rcap; 474 | } 475 | 476 | 477 | template 478 | inline typename Graph::termtype Graph::what_segment(node_id i, termtype default_segm) 479 | { 480 | if (nodes[i].parent) 481 | { 482 | return (nodes[i].is_sink) ? SINK : SOURCE; 483 | } 484 | else 485 | { 486 | return default_segm; 487 | } 488 | } 489 | 490 | template 491 | inline void Graph::mark_node(node_id _i) 492 | { 493 | node* i = nodes + _i; 494 | if (!i->next) 495 | { 496 | /* it's not in the list yet */ 497 | if (queue_last[1]) queue_last[1] -> next = i; 498 | else queue_first[1] = i; 499 | queue_last[1] = i; 500 | i -> next = i; 501 | } 502 | i->is_marked = 1; 503 | } 504 | 505 | 506 | #endif 507 | -------------------------------------------------------------------------------- /instances.inc: -------------------------------------------------------------------------------- 1 | #include "graph.h" 2 | 3 | #ifdef _MSC_VER 4 | #pragma warning(disable: 4661) 5 | #endif 6 | 7 | // Instantiations: 8 | // IMPORTANT: 9 | // flowtype should be 'larger' than tcaptype 10 | // tcaptype should be 'larger' than captype 11 | 12 | //template class Graph; 13 | //template class Graph; 14 | template class Graph; 15 | //template class Graph; 16 | 17 | -------------------------------------------------------------------------------- /maxflow.cpp: -------------------------------------------------------------------------------- 1 | /* maxflow.cpp */ 2 | 3 | 4 | #include 5 | #include "graph.h" 6 | 7 | 8 | /* 9 | special constants for node->parent 10 | */ 11 | #define TERMINAL ( (arc *) 1 ) /* to terminal */ 12 | #define ORPHAN ( (arc *) 2 ) /* orphan */ 13 | 14 | 15 | #define INFINITE_D ((int)(((unsigned)-1)/2)) /* infinite distance to the terminal */ 16 | 17 | /***********************************************************************/ 18 | 19 | /* 20 | Functions for processing active list. 21 | i->next points to the next node in the list 22 | (or to i, if i is the last node in the list). 23 | If i->next is NULL iff i is not in the list. 24 | 25 | There are two queues. Active nodes are added 26 | to the end of the second queue and read from 27 | the front of the first queue. If the first queue 28 | is empty, it is replaced by the second queue 29 | (and the second queue becomes empty). 30 | */ 31 | 32 | 33 | template 34 | inline void Graph::set_active(node *i) 35 | { 36 | if (!i->next) 37 | { 38 | /* it's not in the list yet */ 39 | if (queue_last[1]) queue_last[1] -> next = i; 40 | else queue_first[1] = i; 41 | queue_last[1] = i; 42 | i -> next = i; 43 | } 44 | } 45 | 46 | /* 47 | Returns the next active node. 48 | If it is connected to the sink, it stays in the list, 49 | otherwise it is removed from the list 50 | */ 51 | template 52 | inline typename Graph::node* Graph::next_active() 53 | { 54 | node *i; 55 | 56 | while ( 1 ) 57 | { 58 | if (!(i=queue_first[0])) 59 | { 60 | queue_first[0] = i = queue_first[1]; 61 | queue_last[0] = queue_last[1]; 62 | queue_first[1] = NULL; 63 | queue_last[1] = NULL; 64 | if (!i) return NULL; 65 | } 66 | 67 | /* remove it from the active list */ 68 | if (i->next == i) queue_first[0] = queue_last[0] = NULL; 69 | else queue_first[0] = i -> next; 70 | i -> next = NULL; 71 | 72 | /* a node in the list is active iff it has a parent */ 73 | if (i->parent) return i; 74 | } 75 | } 76 | 77 | /***********************************************************************/ 78 | 79 | template 80 | inline void Graph::set_orphan_front(node *i) 81 | { 82 | nodeptr *np; 83 | i -> parent = ORPHAN; 84 | np = nodeptr_block -> New(); 85 | np -> ptr = i; 86 | np -> next = orphan_first; 87 | orphan_first = np; 88 | } 89 | 90 | template 91 | inline void Graph::set_orphan_rear(node *i) 92 | { 93 | nodeptr *np; 94 | i -> parent = ORPHAN; 95 | np = nodeptr_block -> New(); 96 | np -> ptr = i; 97 | if (orphan_last) orphan_last -> next = np; 98 | else orphan_first = np; 99 | orphan_last = np; 100 | np -> next = NULL; 101 | } 102 | 103 | /***********************************************************************/ 104 | 105 | template 106 | inline void Graph::add_to_changed_list(node *i) 107 | { 108 | if (changed_list && !i->is_in_changed_list) 109 | { 110 | node_id* ptr = changed_list->New(); 111 | *ptr = (node_id)(i - nodes); 112 | i->is_in_changed_list = true; 113 | } 114 | } 115 | 116 | /***********************************************************************/ 117 | 118 | template 119 | void Graph::maxflow_init() 120 | { 121 | node *i; 122 | 123 | queue_first[0] = queue_last[0] = NULL; 124 | queue_first[1] = queue_last[1] = NULL; 125 | orphan_first = NULL; 126 | 127 | TIME = 0; 128 | 129 | for (i=nodes; i next = NULL; 132 | i -> is_marked = 0; 133 | i -> is_in_changed_list = 0; 134 | i -> TS = TIME; 135 | if (i->tr_cap > 0) 136 | { 137 | /* i is connected to the source */ 138 | i -> is_sink = 0; 139 | i -> parent = TERMINAL; 140 | set_active(i); 141 | i -> DIST = 1; 142 | } 143 | else if (i->tr_cap < 0) 144 | { 145 | /* i is connected to the sink */ 146 | i -> is_sink = 1; 147 | i -> parent = TERMINAL; 148 | set_active(i); 149 | i -> DIST = 1; 150 | } 151 | else 152 | { 153 | i -> parent = NULL; 154 | } 155 | } 156 | } 157 | 158 | template 159 | void Graph::maxflow_reuse_trees_init() 160 | { 161 | node* i; 162 | node* j; 163 | node* queue = queue_first[1]; 164 | arc* a; 165 | nodeptr* np; 166 | 167 | queue_first[0] = queue_last[0] = NULL; 168 | queue_first[1] = queue_last[1] = NULL; 169 | orphan_first = orphan_last = NULL; 170 | 171 | TIME ++; 172 | 173 | while ((i=queue)) 174 | { 175 | queue = i->next; 176 | if (queue == i) queue = NULL; 177 | i->next = NULL; 178 | i->is_marked = 0; 179 | set_active(i); 180 | 181 | if (i->tr_cap == 0) 182 | { 183 | if (i->parent) set_orphan_rear(i); 184 | continue; 185 | } 186 | 187 | if (i->tr_cap > 0) 188 | { 189 | if (!i->parent || i->is_sink) 190 | { 191 | i->is_sink = 0; 192 | for (a=i->first; a; a=a->next) 193 | { 194 | j = a->head; 195 | if (!j->is_marked) 196 | { 197 | if (j->parent == a->sister) set_orphan_rear(j); 198 | if (j->parent && j->is_sink && a->r_cap > 0) set_active(j); 199 | } 200 | } 201 | add_to_changed_list(i); 202 | } 203 | } 204 | else 205 | { 206 | if (!i->parent || !i->is_sink) 207 | { 208 | i->is_sink = 1; 209 | for (a=i->first; a; a=a->next) 210 | { 211 | j = a->head; 212 | if (!j->is_marked) 213 | { 214 | if (j->parent == a->sister) set_orphan_rear(j); 215 | if (j->parent && !j->is_sink && a->sister->r_cap > 0) set_active(j); 216 | } 217 | } 218 | add_to_changed_list(i); 219 | } 220 | } 221 | i->parent = TERMINAL; 222 | i -> TS = TIME; 223 | i -> DIST = 1; 224 | } 225 | 226 | //test_consistency(); 227 | 228 | /* adoption */ 229 | while ((np=orphan_first)) 230 | { 231 | orphan_first = np -> next; 232 | i = np -> ptr; 233 | nodeptr_block -> Delete(np); 234 | if (!orphan_first) orphan_last = NULL; 235 | if (i->is_sink) process_sink_orphan(i); 236 | else process_source_orphan(i); 237 | } 238 | /* adoption end */ 239 | 240 | //test_consistency(); 241 | } 242 | 243 | template 244 | void Graph::augment(arc *middle_arc) 245 | { 246 | node *i; 247 | arc *a; 248 | tcaptype bottleneck; 249 | 250 | 251 | /* 1. Finding bottleneck capacity */ 252 | /* 1a - the source tree */ 253 | bottleneck = middle_arc -> r_cap; 254 | for (i=middle_arc->sister->head; ; i=a->head) 255 | { 256 | a = i -> parent; 257 | if (a == TERMINAL) break; 258 | if (bottleneck > a->sister->r_cap) bottleneck = a -> sister -> r_cap; 259 | } 260 | if (bottleneck > i->tr_cap) bottleneck = i -> tr_cap; 261 | /* 1b - the sink tree */ 262 | for (i=middle_arc->head; ; i=a->head) 263 | { 264 | a = i -> parent; 265 | if (a == TERMINAL) break; 266 | if (bottleneck > a->r_cap) bottleneck = a -> r_cap; 267 | } 268 | if (bottleneck > - i->tr_cap) bottleneck = - i -> tr_cap; 269 | 270 | 271 | /* 2. Augmenting */ 272 | /* 2a - the source tree */ 273 | middle_arc -> sister -> r_cap += bottleneck; 274 | middle_arc -> r_cap -= bottleneck; 275 | for (i=middle_arc->sister->head; ; i=a->head) 276 | { 277 | a = i -> parent; 278 | if (a == TERMINAL) break; 279 | a -> r_cap += bottleneck; 280 | a -> sister -> r_cap -= bottleneck; 281 | if (!a->sister->r_cap) 282 | { 283 | set_orphan_front(i); // add i to the beginning of the adoption list 284 | } 285 | } 286 | i -> tr_cap -= bottleneck; 287 | if (!i->tr_cap) 288 | { 289 | set_orphan_front(i); // add i to the beginning of the adoption list 290 | } 291 | /* 2b - the sink tree */ 292 | for (i=middle_arc->head; ; i=a->head) 293 | { 294 | a = i -> parent; 295 | if (a == TERMINAL) break; 296 | a -> sister -> r_cap += bottleneck; 297 | a -> r_cap -= bottleneck; 298 | if (!a->r_cap) 299 | { 300 | set_orphan_front(i); // add i to the beginning of the adoption list 301 | } 302 | } 303 | i -> tr_cap += bottleneck; 304 | if (!i->tr_cap) 305 | { 306 | set_orphan_front(i); // add i to the beginning of the adoption list 307 | } 308 | 309 | 310 | flow += bottleneck; 311 | } 312 | 313 | /***********************************************************************/ 314 | 315 | template 316 | void Graph::process_source_orphan(node *i) 317 | { 318 | node *j; 319 | arc *a0, *a0_min = NULL, *a; 320 | int d, d_min = INFINITE_D; 321 | 322 | /* trying to find a new parent */ 323 | for (a0=i->first; a0; a0=a0->next) 324 | if (a0->sister->r_cap) 325 | { 326 | j = a0 -> head; 327 | if (!j->is_sink && (a=j->parent)) 328 | { 329 | /* checking the origin of j */ 330 | d = 0; 331 | while ( 1 ) 332 | { 333 | if (j->TS == TIME) 334 | { 335 | d += j -> DIST; 336 | break; 337 | } 338 | a = j -> parent; 339 | d ++; 340 | if (a==TERMINAL) 341 | { 342 | j -> TS = TIME; 343 | j -> DIST = 1; 344 | break; 345 | } 346 | if (a==ORPHAN) { d = INFINITE_D; break; } 347 | j = a -> head; 348 | } 349 | if (dhead; j->TS!=TIME; j=j->parent->head) 358 | { 359 | j -> TS = TIME; 360 | j -> DIST = d --; 361 | } 362 | } 363 | } 364 | } 365 | 366 | if ((i->parent = a0_min)) 367 | { 368 | i -> TS = TIME; 369 | i -> DIST = d_min + 1; 370 | } 371 | else 372 | { 373 | /* no parent is found */ 374 | add_to_changed_list(i); 375 | 376 | /* process neighbors */ 377 | for (a0=i->first; a0; a0=a0->next) 378 | { 379 | j = a0 -> head; 380 | if (!j->is_sink && (a=j->parent)) 381 | { 382 | if (a0->sister->r_cap) set_active(j); 383 | if (a!=TERMINAL && a!=ORPHAN && a->head==i) 384 | { 385 | set_orphan_rear(j); // add j to the end of the adoption list 386 | } 387 | } 388 | } 389 | } 390 | } 391 | 392 | template 393 | void Graph::process_sink_orphan(node *i) 394 | { 395 | node *j; 396 | arc *a0, *a0_min = NULL, *a; 397 | int d, d_min = INFINITE_D; 398 | 399 | /* trying to find a new parent */ 400 | for (a0=i->first; a0; a0=a0->next) 401 | if (a0->r_cap) 402 | { 403 | j = a0 -> head; 404 | if (j->is_sink && (a=j->parent)) 405 | { 406 | /* checking the origin of j */ 407 | d = 0; 408 | while ( 1 ) 409 | { 410 | if (j->TS == TIME) 411 | { 412 | d += j -> DIST; 413 | break; 414 | } 415 | a = j -> parent; 416 | d ++; 417 | if (a==TERMINAL) 418 | { 419 | j -> TS = TIME; 420 | j -> DIST = 1; 421 | break; 422 | } 423 | if (a==ORPHAN) { d = INFINITE_D; break; } 424 | j = a -> head; 425 | } 426 | if (dhead; j->TS!=TIME; j=j->parent->head) 435 | { 436 | j -> TS = TIME; 437 | j -> DIST = d --; 438 | } 439 | } 440 | } 441 | } 442 | 443 | if ((i->parent = a0_min)) 444 | { 445 | i -> TS = TIME; 446 | i -> DIST = d_min + 1; 447 | } 448 | else 449 | { 450 | /* no parent is found */ 451 | add_to_changed_list(i); 452 | 453 | /* process neighbors */ 454 | for (a0=i->first; a0; a0=a0->next) 455 | { 456 | j = a0 -> head; 457 | if (j->is_sink && (a=j->parent)) 458 | { 459 | if (a0->r_cap) set_active(j); 460 | if (a!=TERMINAL && a!=ORPHAN && a->head==i) 461 | { 462 | set_orphan_rear(j); // add j to the end of the adoption list 463 | } 464 | } 465 | } 466 | } 467 | } 468 | 469 | /***********************************************************************/ 470 | 471 | template 472 | flowtype Graph::maxflow(bool reuse_trees, Block* _changed_list) 473 | { 474 | node *i, *j, *current_node = NULL; 475 | arc *a; 476 | nodeptr *np, *np_next; 477 | 478 | if (!nodeptr_block) 479 | { 480 | nodeptr_block = new DBlock(NODEPTR_BLOCK_SIZE, error_function); 481 | } 482 | 483 | changed_list = _changed_list; 484 | if (maxflow_iteration == 0 && reuse_trees) { if (error_function) (*error_function)("reuse_trees cannot be used in the first call to maxflow()!"); exit(1); } 485 | if (changed_list && !reuse_trees) { if (error_function) (*error_function)("changed_list cannot be used without reuse_trees!"); exit(1); } 486 | 487 | if (reuse_trees) maxflow_reuse_trees_init(); 488 | else maxflow_init(); 489 | 490 | // main loop 491 | while ( 1 ) 492 | { 493 | // test_consistency(current_node); 494 | 495 | if ((i=current_node)) 496 | { 497 | i -> next = NULL; /* remove active flag */ 498 | if (!i->parent) i = NULL; 499 | } 500 | if (!i) 501 | { 502 | if (!(i = next_active())) break; 503 | } 504 | 505 | /* growth */ 506 | if (!i->is_sink) 507 | { 508 | /* grow source tree */ 509 | for (a=i->first; a; a=a->next) 510 | if (a->r_cap) 511 | { 512 | j = a -> head; 513 | if (!j->parent) 514 | { 515 | j -> is_sink = 0; 516 | j -> parent = a -> sister; 517 | j -> TS = i -> TS; 518 | j -> DIST = i -> DIST + 1; 519 | set_active(j); 520 | add_to_changed_list(j); 521 | } 522 | else if (j->is_sink) break; 523 | else if (j->TS <= i->TS && 524 | j->DIST > i->DIST) 525 | { 526 | /* heuristic - trying to make the distance from j to the source shorter */ 527 | j -> parent = a -> sister; 528 | j -> TS = i -> TS; 529 | j -> DIST = i -> DIST + 1; 530 | } 531 | } 532 | } 533 | else 534 | { 535 | /* grow sink tree */ 536 | for (a=i->first; a; a=a->next) 537 | if (a->sister->r_cap) 538 | { 539 | j = a -> head; 540 | if (!j->parent) 541 | { 542 | j -> is_sink = 1; 543 | j -> parent = a -> sister; 544 | j -> TS = i -> TS; 545 | j -> DIST = i -> DIST + 1; 546 | set_active(j); 547 | add_to_changed_list(j); 548 | } 549 | else if (!j->is_sink) { a = a -> sister; break; } 550 | else if (j->TS <= i->TS && 551 | j->DIST > i->DIST) 552 | { 553 | /* heuristic - trying to make the distance from j to the sink shorter */ 554 | j -> parent = a -> sister; 555 | j -> TS = i -> TS; 556 | j -> DIST = i -> DIST + 1; 557 | } 558 | } 559 | } 560 | 561 | TIME ++; 562 | 563 | if (a) 564 | { 565 | i -> next = i; /* set active flag */ 566 | current_node = i; 567 | 568 | /* augmentation */ 569 | augment(a); 570 | /* augmentation end */ 571 | 572 | /* adoption */ 573 | while ((np=orphan_first)) 574 | { 575 | np_next = np -> next; 576 | np -> next = NULL; 577 | 578 | while ((np=orphan_first)) 579 | { 580 | orphan_first = np -> next; 581 | i = np -> ptr; 582 | nodeptr_block -> Delete(np); 583 | if (!orphan_first) orphan_last = NULL; 584 | if (i->is_sink) process_sink_orphan(i); 585 | else process_source_orphan(i); 586 | } 587 | 588 | orphan_first = np_next; 589 | } 590 | /* adoption end */ 591 | } 592 | else current_node = NULL; 593 | } 594 | // test_consistency(); 595 | 596 | if (!reuse_trees || (maxflow_iteration % 64) == 0) 597 | { 598 | delete nodeptr_block; 599 | nodeptr_block = NULL; 600 | } 601 | 602 | maxflow_iteration ++; 603 | return flow; 604 | } 605 | 606 | /***********************************************************************/ 607 | 608 | 609 | template 610 | void Graph::test_consistency(node* current_node) 611 | { 612 | node *i; 613 | arc *a; 614 | int r; 615 | int num1 = 0, num2 = 0; 616 | 617 | // test whether all nodes i with i->next!=NULL are indeed in the queue 618 | for (i=nodes; inext || i==current_node) num1 ++; 621 | } 622 | for (r=0; r<3; r++) 623 | { 624 | i = (r == 2) ? current_node : queue_first[r]; 625 | if (i) 626 | for ( ; ; i=i->next) 627 | { 628 | num2 ++; 629 | if (i->next == i) 630 | { 631 | if (r<2) assert(i == queue_last[r]); 632 | else assert(i == current_node); 633 | break; 634 | } 635 | } 636 | } 637 | assert(num1 == num2); 638 | 639 | for (i=nodes; iparent == NULL) {} 643 | else if (i->parent == ORPHAN) {} 644 | else if (i->parent == TERMINAL) 645 | { 646 | if (!i->is_sink) assert(i->tr_cap > 0); 647 | else assert(i->tr_cap < 0); 648 | } 649 | else 650 | { 651 | if (!i->is_sink) assert (i->parent->sister->r_cap > 0); 652 | else assert (i->parent->r_cap > 0); 653 | } 654 | // test whether passive nodes in search trees have neighbors in 655 | // a different tree through non-saturated edges 656 | if (i->parent && !i->next) 657 | { 658 | if (!i->is_sink) 659 | { 660 | assert(i->tr_cap >= 0); 661 | for (a=i->first; a; a=a->next) 662 | { 663 | if (a->r_cap > 0) assert(a->head->parent && !a->head->is_sink); 664 | } 665 | } 666 | else 667 | { 668 | assert(i->tr_cap <= 0); 669 | for (a=i->first; a; a=a->next) 670 | { 671 | if (a->sister->r_cap > 0) assert(a->head->parent && a->head->is_sink); 672 | } 673 | } 674 | } 675 | // test marking invariants 676 | if (i->parent && i->parent!=ORPHAN && i->parent!=TERMINAL) 677 | { 678 | assert(i->TS <= i->parent->head->TS); 679 | if (i->TS == i->parent->head->TS) assert(i->DIST > i->parent->head->DIST); 680 | } 681 | } 682 | } 683 | 684 | #include "instances.inc" 685 | -------------------------------------------------------------------------------- /pymaxflow.pyx: -------------------------------------------------------------------------------- 1 | # distutils: language = c++ 2 | # distutils: sources = maxflow.cpp graph.cpp 3 | 4 | import numpy as np 5 | cimport numpy as np 6 | cimport cython 7 | 8 | cdef extern from "graph.h": 9 | cdef cppclass Block[T]: 10 | pass 11 | cdef enum termtype: 12 | SOURCE, SINK 13 | cdef cppclass Graph[capT, tcapT, flowT]: 14 | Graph(int node_num_max, int edge_num_max) except + 15 | int add_node(int) 16 | void add_edge(int i, int j, capT cap, capT rev_cap) 17 | void add_tweights(int i, tcapT cap_source, tcapT cap_sink) 18 | flowT maxflow() 19 | termtype what_segment(int i) 20 | int get_node_num() 21 | 22 | cdef class PyGraph: 23 | cdef Graph[float,float,float] *thisptr # hold a C++ instance which we're wrapping 24 | def __cinit__(self, int node_num_max, int edge_num_max): 25 | self.thisptr = new Graph[float,float,float](node_num_max, edge_num_max) 26 | def __dealloc__(self): 27 | del self.thisptr 28 | def add_node(self, int num=1): 29 | return self.thisptr.add_node(num) 30 | def add_edge(self, int i, int j, float cap, float rev_cap): 31 | self.thisptr.add_edge(i, j, cap, rev_cap) 32 | def add_tweights(self, int i, float cap_source, float cap_sink): 33 | self.thisptr.add_tweights(i, cap_source, cap_sink) 34 | def maxflow(self): 35 | return self.thisptr.maxflow() 36 | def what_segment(self, int i): 37 | return self.thisptr.what_segment(i) 38 | 39 | @cython.boundscheck(False) 40 | def add_edge_vectorized(self, 41 | np.ndarray[dtype=np.int32_t, ndim=1, negative_indices=False] i, 42 | np.ndarray[dtype=np.int32_t, ndim=1, negative_indices=False] j, 43 | np.ndarray[dtype=np.float32_t, ndim=1, negative_indices=False] cap, 44 | np.ndarray[dtype=np.float32_t, ndim=1, negative_indices=False] rev_cap): 45 | assert i.size == j.size 46 | assert i.size == cap.size 47 | assert i.size == rev_cap.size 48 | cdef int l 49 | for l in range(i.size): 50 | self.thisptr.add_edge(i[l], j[l], cap[l], rev_cap[l]) 51 | 52 | @cython.boundscheck(False) 53 | def add_tweights_vectorized(self, 54 | np.ndarray[dtype=np.int32_t, ndim=1, negative_indices=False] i, 55 | np.ndarray[dtype=np.float32_t, ndim=1, negative_indices=False] cap_source, 56 | np.ndarray[dtype=np.float32_t, ndim=1, negative_indices=False] cap_sink): 57 | assert i.size == cap_source.size 58 | assert i.size == cap_sink.size 59 | cdef int l 60 | for l in range(i.size): 61 | self.thisptr.add_tweights(i[l], cap_source[l], cap_sink[l]) 62 | 63 | @cython.boundscheck(False) 64 | def what_segment_vectorized(self): 65 | cpdef np.ndarray[dtype=np.int32_t, ndim=1, negative_indices=False] out_segments = np.empty(self.thisptr.get_node_num(), np.int32) 66 | cdef int l 67 | for l in range(self.thisptr.get_node_num()): 68 | out_segments[l] = self.thisptr.what_segment(l) 69 | return out_segments 70 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | from Cython.Build import cythonize 3 | import numpy as np 4 | 5 | 6 | setup( 7 | name = "pymaxflow", 8 | include_dirs=[np.get_include()], 9 | ext_modules = cythonize('pymaxflow.pyx') 10 | ) 11 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import pymaxflow 3 | import pylab 4 | import numpy as np 5 | 6 | eps = 0.01 7 | 8 | im = pylab.imread(sys.argv[1]).astype(np.float32) 9 | 10 | indices = np.arange(im.size).reshape(im.shape).astype(np.int32) 11 | g = pymaxflow.PyGraph(im.size, im.size * 3) 12 | 13 | g.add_node(im.size) 14 | 15 | # adjacent 16 | diffs = np.abs(im[:, 1:] - im[:, :-1]).ravel() + eps 17 | e1 = indices[:, :-1].ravel() 18 | e2 = indices[:, 1:].ravel() 19 | g.add_edge_vectorized(e1, e2, diffs, 0 * diffs) 20 | 21 | # adjacent up 22 | diffs = np.abs(im[1:, 1:] - im[:-1, :-1]).ravel() + eps 23 | e1 = indices[1:, :-1].ravel() 24 | e2 = indices[:-1, 1:].ravel() 25 | g.add_edge_vectorized(e1, e2, diffs, 0 * diffs) 26 | 27 | # adjacent down 28 | diffs = np.abs(im[:-1, 1:] - im[1:, :-1]).ravel() + eps 29 | e1 = indices[:-1, :-1].flatten() 30 | e2 = indices[1:, 1:].ravel() 31 | g.add_edge_vectorized(e1, e2, diffs, 0 * diffs) 32 | 33 | # link to source/sink 34 | g.add_tweights_vectorized(indices[:, 0], (np.ones(indices.shape[0]) * 1.e9).astype(np.float32), np.zeros(indices.shape[0], np.float32)) 35 | g.add_tweights_vectorized(indices[:, -1], np.zeros(indices.shape[0], np.float32), (np.ones(indices.shape[0]) * 1.e9).astype(np.float32)) 36 | 37 | print "calling maxflow" 38 | g.maxflow() 39 | 40 | out = g.what_segment_vectorized() 41 | pylab.imshow(out.reshape(im.shape)) 42 | pylab.show() 43 | --------------------------------------------------------------------------------