├── Makefile ├── README.txt ├── mcmf.cpp └── mcmf.h /Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | 3 | CLASSDIR = /home/cristinel/projects/mcmf 4 | INCDIRS = $(CLASSDIR)/ 5 | LIB_DIR = -L/usr/lib/X11 6 | LIB = -lX11 -lm 7 | 8 | #OPT_FLAGS = 9 | OPT_FLAGS = -O3 10 | WARN_FLAGS = 11 | #WARN_FLAGS = -Wall -Wpointer-arith -Wcast-qual -Wstrict-prototypes -O -D__USE_FIXED_PROTOTYPES__ -ansi -pedantic -Wmissing-prototypes -Wshadow -Wcast-align -D_POSIX_SOURCE 12 | DEBUG_FLAGS = 13 | #DEBUG_FLAGS = -g 14 | 15 | FLAGS = $(OPT_FLAGS) 16 | FLAGS += $(WARN_FLAGS) 17 | FLAGS += $(DEBUG_FLAGS) 18 | FLAGS += $(addprefix -I, $(INCDIRS)) 19 | 20 | EXE = mcmf 21 | OBJ = mcmf.o 22 | SRC = mcmf.cpp 23 | H = mcmf.h 24 | 25 | $(EXE): $(OBJ) 26 | $(CC) $(FLAGS) $(OBJ) -o $(EXE) $(LIB_DIR) $(LIB) 27 | 28 | mcmf.o: mcmf.cpp $(H) 29 | $(CC) -c $(FLAGS) mcmf.cpp 30 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | Cristinel Ababei 2 | January 2009, Fargo ND 3 | cristinel.ababei@ndsu.edu 4 | 5 | 6 | SUMMARY 7 | ======= 8 | 9 | This is a C++ implementation of CS2 min-cost-max-flow scaling algorithm. 10 | 11 | This is intended to be one of the cleanest and simplest to use minimum-cost 12 | max-flow (MCMF) implementation using C++. If you have a C++ application in 13 | which you need to use a MCMF algo, then this may be your most elegant bet. 14 | See main() function for an example of how to use it. 15 | 16 | I compiled it on Linux Fedora, using g++. If you have any question please 17 | contact Cristinel. 18 | 19 | 20 | CREDITS 21 | ======= 22 | 23 | This is an adapted (i.e., ported to C++) version of the faimous CS2 algo; 24 | CS2 is the second version of scaling algorithm for minimum-cost max-flow 25 | problems. For a detailed description of this famous algo, see: 26 | A.V. Goldberg, "An Efficient Implementation of a Scaling Minimum-Cost 27 | Flow Algorithm", Journal of Algorithms, vol. 22, pp. 1-29, 1997. 28 | 29 | CS2 was developed by Andrew Goldberg (goldberg@intertrust.com) and 30 | Boris Cherkassky (cher@cher.msk.su). 31 | 32 | The original C version is located in cs2-4.3/ 33 | 34 | 35 | COPYRIGHT 36 | ========= 37 | 38 | The program is available on "as is" basis. It is not guaranteed to 39 | be free of bugs, and the author assumes no responsibility for any 40 | potential problems. 41 | The original copyright notice of the C version applies to this C++ 42 | version as well. 43 | 44 | 45 | ACADEMIA 46 | ======== 47 | 48 | If you use this C++ version in any research project and want to 49 | include references to it, then please use: 50 | 51 | [1] Cristinel Ababei, C++ Implementation of Goldberg's CS2 Scaling 52 | Minimum-Cost Flow Algorithm, 2009, [Online], Available: 53 | http://www.ece.ndsu.nodak.edu/~cris/software.html 54 | 55 | [2] A.V. Goldberg, An Efficient Implementation of a Scaling 56 | Minimum-Cost Flow Algorithm, Journal of Algorithms, Vol. 22, 57 | pp. 1-29, 1997. 58 | 59 | 60 | FINAL NOTE 61 | ========== 62 | 63 | If you'll ever hit it big (to be read: make a lot of money :-) ), 64 | and this code helped you in any way, then please consider 65 | donating some to support my research (I need it :-) ). 66 | -------------------------------------------------------------------------------- /mcmf.cpp: -------------------------------------------------------------------------------- 1 | #include "mcmf.h" 2 | #include 3 | 4 | using namespace std; 5 | 6 | //////////////////////////////////////////////////////////////////////////////// 7 | // 8 | // MCMF_CS2 9 | // 10 | //////////////////////////////////////////////////////////////////////////////// 11 | 12 | #define WHITE 0 13 | #define GREY 1 14 | #define BLACK 2 15 | #define OPEN( a ) ( a->rez_capacity() > 0 ) 16 | #define CLOSED( a ) ( a->rez_capacity() <= 0 ) 17 | #define REDUCED_COST( i, j, a ) ( i->price() + a->cost() - j->price() ) 18 | #define FEASIBLE( i, j, a ) ( i->price() + a->cost() < j->price() ) 19 | #define ADMISSIBLE( i, j, a ) ( OPEN( a ) && FEASIBLE( i, j, a ) ) 20 | #define SUSPENDED( i, a ) ( a < i->first() ) 21 | 22 | 23 | #define REMOVE_FROM_EXCESS_Q( i ) \ 24 | { \ 25 | i = _excq_first; \ 26 | _excq_first = i -> q_next(); \ 27 | i ->set_q_next( _sentinel_node ); \ 28 | } 29 | 30 | #define STACKQ_POP( i ) \ 31 | { \ 32 | i = _excq_first; \ 33 | _excq_first = i -> q_next(); \ 34 | i ->set_q_next( _sentinel_node ); \ 35 | } 36 | 37 | #define GET_FROM_BUCKET( i, b ) \ 38 | { \ 39 | i = ( b -> p_first() ); \ 40 | b ->set_p_first( i -> b_next() ); \ 41 | } 42 | #define REMOVE_FROM_BUCKET( i, b ) \ 43 | { \ 44 | if ( i == ( b -> p_first() ) ) \ 45 | b ->set_p_first( i -> b_next() ); \ 46 | else \ 47 | { \ 48 | ( i -> b_prev() )->set_b_next( i -> b_next() ); \ 49 | ( i -> b_next() )->set_b_prev( i -> b_prev() ); \ 50 | } \ 51 | } 52 | 53 | 54 | void MCMF_CS2::err_end( int cc) 55 | { 56 | // abnormal finish 57 | printf ("\nError %d\n", cc ); 58 | // 2 - problem is unfeasible 59 | // 5 - allocation fault 60 | // 6 - price overflow 61 | exit( cc); 62 | } 63 | 64 | void MCMF_CS2::allocate_arrays() 65 | { 66 | // (1) allocate memory for 'nodes', 'arcs' and internal arrays; 67 | 68 | _nodes = (NODE*) calloc ( _n+2, sizeof(NODE) ); 69 | _arcs = (ARC*) calloc ( 2*_m+1, sizeof(ARC) ); 70 | _cap = (long*) calloc ( 2*_m, sizeof(long) ); 71 | 72 | _arc_tail = (long*) calloc ( 2*_m, sizeof(long) ); 73 | _arc_first = (long*) calloc ( _n+2, sizeof(long) ); 74 | // arc_first [ 0 .. n+1 ] = 0 - initialized by calloc; 75 | 76 | for ( NODE *in = _nodes; in <= _nodes + _n; in ++ ) { 77 | in->set_excess( 0); 78 | } 79 | if ( _nodes == NULL || _arcs == NULL || _arc_first == NULL || _arc_tail == NULL) { 80 | printf("Error: Memory allocation problem inside CS2\n"); 81 | exit( 1); 82 | } 83 | 84 | // (2) resets; 85 | _pos_current = 0; 86 | _arc_current = _arcs; // set "current" pointer to the first arc 87 | _node_max = 0; 88 | _node_min = _n; 89 | _max_cost = 0; 90 | _total_p = _total_n = 0; 91 | // at this moment we are ready to add arcs and build the network, 92 | // by using set_arc()... 93 | } 94 | 95 | void MCMF_CS2::deallocate_arrays() 96 | { 97 | if ( _arcs) free ( _arcs ); 98 | if ( _dnode) delete _dnode; 99 | if ( _cap) free ( _cap ); 100 | if ( _buckets) free ( _buckets ); 101 | if ( _check_solution == true) free ( _node_balance ); 102 | if ( _nodes) { 103 | _nodes = _nodes - _node_min; 104 | free ( _nodes ); 105 | } 106 | } 107 | 108 | void MCMF_CS2::set_arc( long tail_node_id, long head_node_id, 109 | long low_bound, long up_bound, // up_bound is basically capacity; 110 | price_t cost) 111 | { 112 | // DIMACS format: 113 | // c arc has 114 | 115 | if ( tail_node_id < 0 || tail_node_id > _n || 116 | head_node_id < 0 || head_node_id > _n ) { 117 | printf("Error: Arc with head or tail out of bounds inside CS2\n"); 118 | exit( 1); 119 | } 120 | if ( up_bound < 0 ) { 121 | up_bound = MAX_32; 122 | printf("Warning: Infinite capacity replaced by BIGGEST_FLOW\n"); 123 | } 124 | if ( low_bound < 0 || low_bound > up_bound ) { 125 | printf("Error: Wrong capacity bounds inside CS2\n"); 126 | exit( 1); 127 | } 128 | 129 | // no of arcs incident to node i is placed in _arc_first[i+1] 130 | _arc_first[tail_node_id + 1] ++; 131 | _arc_first[head_node_id + 1] ++; 132 | _i_node = _nodes + tail_node_id; 133 | _j_node = _nodes + head_node_id; 134 | 135 | // store information about the arc 136 | _arc_tail[_pos_current] = tail_node_id; 137 | _arc_tail[_pos_current+1] = head_node_id; 138 | _arc_current->set_head( _j_node ); 139 | _arc_current->set_rez_capacity( up_bound - low_bound ); 140 | _cap[_pos_current] = up_bound; 141 | _arc_current->set_cost( cost ); 142 | _arc_current->set_sister( _arc_current + 1 ); 143 | ( _arc_current + 1 )->set_head( _nodes + tail_node_id ); 144 | ( _arc_current + 1 )->set_rez_capacity( 0 ); 145 | _cap[_pos_current+1] = 0; 146 | ( _arc_current + 1 )->set_cost( -cost ); 147 | ( _arc_current + 1 )->set_sister( _arc_current ); 148 | 149 | _i_node->dec_excess( low_bound ); 150 | _j_node->inc_excess( low_bound ); 151 | 152 | // searching for minimum and maximum node 153 | if ( head_node_id < _node_min ) _node_min = head_node_id; 154 | if ( tail_node_id < _node_min ) _node_min = tail_node_id; 155 | if ( head_node_id > _node_max ) _node_max = head_node_id; 156 | if ( tail_node_id > _node_max ) _node_max = tail_node_id; 157 | 158 | if ( cost < 0 ) cost = -cost; 159 | if ( cost > _max_cost && up_bound > 0 ) _max_cost = cost; 160 | 161 | // prepare for next arc to be added; 162 | _arc_current += 2; 163 | _pos_current += 2; 164 | } 165 | 166 | void MCMF_CS2::set_supply_demand_of_node( long id, long excess) 167 | { 168 | // set supply and demand of nodes; not used for transhipment nodes; 169 | if ( id < 0 || id > _n ) { 170 | printf("Error: Unbalanced problem inside CS2\n"); 171 | exit( 1); 172 | } 173 | (_nodes + id)->set_excess( excess); 174 | if ( excess > 0) _total_p += excess; 175 | if ( excess < 0) _total_n -= excess; 176 | } 177 | 178 | void MCMF_CS2::pre_processing() 179 | { 180 | // called after the arcs were just added and before run_cs2(); 181 | // ordering arcs - linear time algorithm; 182 | long i; 183 | long last, arc_num, arc_new_num;; 184 | long tail_node_id; 185 | NODE *head_p; 186 | ARC *arc_new, *arc_tmp; 187 | long up_bound; 188 | price_t cost; // arc cost; 189 | excess_t cap_out; // sum of outgoing capacities 190 | excess_t cap_in; // sum of incoming capacities 191 | 192 | if ( ABS( _total_p - _total_n ) > 0.5 ) { 193 | printf("Error: Unbalanced problem inside CS2\n"); 194 | exit( 1); 195 | } 196 | 197 | // first arc from the first node 198 | ( _nodes + _node_min )->set_first( _arcs ); 199 | 200 | // before below loop arc_first[i+1] is the number of arcs outgoing from i; 201 | // after this loop arc_first[i] is the position of the first 202 | // outgoing from node i arcs after they would be ordered; 203 | // this value is transformed to pointer and written to node.first[i] 204 | for ( i = _node_min + 1; i <= _node_max + 1; i ++ ) { 205 | _arc_first[i] += _arc_first[i-1]; 206 | ( _nodes + i )->set_first( _arcs + _arc_first[i] ); 207 | } 208 | 209 | // scanning all the nodes except the last 210 | for ( i = _node_min; i < _node_max; i ++ ) { 211 | 212 | last = ( ( _nodes + i + 1 )->first() ) - _arcs; 213 | // arcs outgoing from i must be cited 214 | // from position arc_first[i] to the position 215 | // equal to initial value of arc_first[i+1]-1 216 | 217 | for ( arc_num = _arc_first[i]; arc_num < last; arc_num ++ ) { 218 | tail_node_id = _arc_tail[arc_num]; 219 | 220 | while ( tail_node_id != i ) { 221 | // the arc no arc_num is not in place because arc cited here 222 | // must go out from i; 223 | // we'll put it to its place and continue this process 224 | // until an arc in this position would go out from i 225 | 226 | arc_new_num = _arc_first[tail_node_id]; 227 | _arc_current = _arcs + arc_num; 228 | arc_new = _arcs + arc_new_num; 229 | 230 | // arc_current must be cited in the position arc_new 231 | // swapping these arcs: 232 | 233 | head_p = arc_new->head(); 234 | arc_new->set_head( _arc_current->head() ); 235 | _arc_current->set_head( head_p ); 236 | 237 | up_bound = _cap[arc_new_num]; 238 | _cap[arc_new_num] = _cap[arc_num]; 239 | _cap[arc_num] = up_bound; 240 | 241 | up_bound = arc_new->rez_capacity(); 242 | arc_new->set_rez_capacity( _arc_current->rez_capacity() ); 243 | _arc_current->set_rez_capacity( up_bound) ; 244 | 245 | cost = arc_new->cost(); 246 | arc_new->set_cost( _arc_current->cost() ); 247 | _arc_current->set_cost( cost ); 248 | 249 | if ( arc_new != _arc_current->sister() ) { 250 | arc_tmp = arc_new->sister(); 251 | arc_new->set_sister( _arc_current->sister() ); 252 | _arc_current->set_sister( arc_tmp ); 253 | 254 | _arc_current->sister()->set_sister( _arc_current ); 255 | arc_new->sister()->set_sister( arc_new ); 256 | } 257 | 258 | _arc_tail[arc_num] = _arc_tail[arc_new_num]; 259 | _arc_tail[arc_new_num] = tail_node_id; 260 | 261 | // we increase arc_first[tail_node_id] 262 | _arc_first[tail_node_id] ++ ; 263 | 264 | tail_node_id = _arc_tail[arc_num]; 265 | } 266 | } 267 | // all arcs outgoing from i are in place 268 | } 269 | // arcs are ordered by now! 270 | 271 | 272 | // testing network for possible excess overflow 273 | for ( NODE *ndp = _nodes + _node_min; ndp <= _nodes + _node_max; ndp ++ ) { 274 | cap_in = ( ndp->excess() ); 275 | cap_out = - ( ndp->excess() ); 276 | for ( _arc_current = ndp->first(); _arc_current != (ndp+1)->first(); 277 | _arc_current ++ ) { 278 | arc_num = _arc_current - _arcs; 279 | if ( _cap[arc_num] > 0 ) cap_out += _cap[arc_num]; 280 | if ( _cap[arc_num] == 0 ) 281 | cap_in += _cap[ _arc_current->sister() - _arcs ]; 282 | } 283 | } 284 | if ( _node_min < 0 || _node_min > 1 ) { 285 | printf("Error: Node ids must start from 0 or 1 inside CS2\n"); 286 | exit( 1); 287 | } 288 | 289 | // adjustments due to nodes' ids being between _node_min - _node_max; 290 | _n = _node_max - _node_min + 1; 291 | _nodes = _nodes + _node_min; 292 | 293 | // () free internal memory, not needed anymore inside CS2; 294 | free ( _arc_first ); 295 | free ( _arc_tail ); 296 | } 297 | 298 | void MCMF_CS2::cs2_initialize() 299 | { 300 | // initialization; 301 | // called after allocate_arrays() and all nodes and arcs have been inputed; 302 | 303 | NODE *i; // current node 304 | ARC *a; // current arc 305 | ARC *a_stop; 306 | BUCKET *b; // current bucket 307 | long df; 308 | 309 | _f_scale = (long) SCALE_DEFAULT; 310 | _sentinel_node = _nodes + _n; 311 | _sentinel_arc = _arcs + _m; 312 | 313 | for ( i = _nodes; i != _sentinel_node; i ++ ) { 314 | i->set_price( 0); 315 | i->set_suspended( i->first()); 316 | i->set_q_next( _sentinel_node); 317 | } 318 | 319 | _sentinel_node->set_first( _sentinel_arc); 320 | _sentinel_node->set_suspended( _sentinel_arc); 321 | 322 | // saturate negative arcs, e.g. in the circulation problem case 323 | for ( i = _nodes; i != _sentinel_node; i ++ ) { 324 | for ( a = i->first(), a_stop = (i + 1)->suspended(); a != a_stop; a ++ ) { 325 | if ( a->cost() < 0) { 326 | if ( ( df = a->rez_capacity()) > 0) { 327 | increase_flow( i, a->head(), a, df); 328 | } 329 | } 330 | } 331 | } 332 | 333 | _dn = _n + 1; 334 | if ( _no_zero_cycles == true) { // NO_ZERO_CYCLES 335 | _dn = 2 * _dn; 336 | } 337 | 338 | for ( a = _arcs; a != _sentinel_arc; a ++ ) { 339 | a->multiply_cost( _dn); 340 | } 341 | 342 | if ( _no_zero_cycles == true) { // NO_ZERO_CYCLES 343 | for ( a = _arcs; a != _sentinel_arc; a ++ ) { 344 | if ((a->cost() == 0) && (a->sister()->cost() == 0)) { 345 | a->set_cost( 1); 346 | a->sister()->set_cost( -1); 347 | } 348 | } 349 | } 350 | 351 | if ((double) _max_cost * (double) _dn > MAX_64) { 352 | printf("Warning: Arc lengths too large, overflow possible\n"); 353 | } 354 | _mmc = _max_cost * _dn; 355 | 356 | _linf = (long) (_dn * ceil(_f_scale) + 2); 357 | 358 | _buckets = (BUCKET*) calloc ( _linf, sizeof(BUCKET)); 359 | if ( _buckets == NULL ) 360 | err_end( ALLOCATION_FAULT); 361 | 362 | _l_bucket = _buckets + _linf; 363 | 364 | _dnode = new NODE; // used as reference; 365 | 366 | for ( b = _buckets; b != _l_bucket; b ++ ) { 367 | reset_bucket( b); 368 | } 369 | 370 | _epsilon = _mmc; 371 | if ( _epsilon < 1) { 372 | _epsilon = 1; 373 | } 374 | 375 | _price_min = -PRICE_MAX; 376 | 377 | _cut_off_factor = CUT_OFF_COEF * pow( (double)_n, CUT_OFF_POWER); 378 | 379 | _cut_off_factor = MAX( _cut_off_factor, CUT_OFF_MIN); 380 | 381 | _n_ref = 0; 382 | 383 | _flag_price = 0; 384 | 385 | _dummy_node = &_d_node; 386 | 387 | _excq_first = NULL; 388 | 389 | //print_graph(); // debug; 390 | } 391 | 392 | void MCMF_CS2::up_node_scan( NODE *i) 393 | { 394 | NODE *j; // opposite node 395 | ARC *a; // (i, j) 396 | ARC *a_stop; // first arc from the next node 397 | ARC *ra; // (j, i) 398 | BUCKET *b_old; // old bucket contained j 399 | BUCKET *b_new; // new bucket for j 400 | long i_rank; 401 | long j_rank; // ranks of nodes 402 | long j_new_rank; 403 | price_t rc; // reduced cost of (j, i) 404 | price_t dr; // rank difference 405 | 406 | _n_scan ++; 407 | 408 | i_rank = i->rank(); 409 | 410 | // scanning arcs; 411 | for ( a = i->first(), a_stop = (i + 1)->suspended(); a != a_stop; a ++ ) { 412 | 413 | ra = a->sister(); 414 | 415 | if ( OPEN ( ra ) ) { 416 | j = a->head(); 417 | j_rank = j->rank(); 418 | 419 | if ( j_rank > i_rank ) { 420 | if ( ( rc = REDUCED_COST( j, i, ra ) ) < 0 ) { 421 | j_new_rank = i_rank; 422 | } else { 423 | dr = rc / _epsilon; 424 | j_new_rank = ( dr < _linf ) ? i_rank + (long)dr + 1 : _linf; 425 | } 426 | 427 | if ( j_rank > j_new_rank ) { 428 | j->set_rank( j_new_rank); 429 | j->set_current( ra); 430 | 431 | if ( j_rank < _linf ) { 432 | b_old = _buckets + j_rank; 433 | REMOVE_FROM_BUCKET( j, b_old ); 434 | } 435 | 436 | b_new = _buckets + j_new_rank; 437 | insert_to_bucket( j, b_new ); 438 | } 439 | } 440 | } 441 | } 442 | 443 | i->dec_price( i_rank * _epsilon); 444 | i->set_rank( -1); 445 | } 446 | 447 | void MCMF_CS2::price_update() 448 | { 449 | register NODE *i; 450 | excess_t remain; 451 | // total excess of unscanned nodes with positive excess; 452 | BUCKET *b; // current bucket; 453 | price_t dp; // amount to be subtracted from prices; 454 | 455 | _n_update ++; 456 | 457 | for ( i = _nodes; i != _sentinel_node; i ++ ) { 458 | if ( i->excess() < 0 ) { 459 | insert_to_bucket( i, _buckets ); 460 | i->set_rank( 0); 461 | } else { 462 | i->set_rank( _linf); 463 | } 464 | } 465 | 466 | remain = _total_excess; 467 | if ( remain < 0.5 ) return; 468 | 469 | // scanning buckets, main loop; 470 | for ( b = _buckets; b != _l_bucket; b ++ ) { 471 | 472 | while ( nonempty_bucket( b) ) { 473 | 474 | GET_FROM_BUCKET( i, b ); 475 | up_node_scan( i ); 476 | 477 | if ( i ->excess() > 0 ) { 478 | remain -= ( i->excess()); 479 | if ( remain <= 0 ) break; 480 | } 481 | } 482 | if ( remain <= 0 ) break; 483 | } 484 | 485 | if ( remain > 0.5 ) _flag_updt = 1; 486 | 487 | // finishup 488 | // changing prices for nodes which were not scanned during main loop; 489 | dp = ( b - _buckets ) * _epsilon; 490 | 491 | for ( i = _nodes; i != _sentinel_node; i ++ ) { 492 | 493 | if ( i->rank() >= 0 ) { 494 | if ( i->rank() < _linf ) { 495 | REMOVE_FROM_BUCKET( i, ( _buckets + i->rank()) ); 496 | } 497 | if ( i->price() > _price_min ) { 498 | i->dec_price( dp); 499 | } 500 | } 501 | } 502 | } 503 | 504 | int MCMF_CS2::relabel( NODE *i) 505 | { 506 | register ARC *a; // current arc from i 507 | register ARC *a_stop; // first arc from the next node 508 | register ARC *a_max; // arc which provides maximum price 509 | register price_t p_max; // current maximal price 510 | register price_t i_price; // price of node i 511 | register price_t dp; // current arc partial residual cost 512 | 513 | p_max = _price_min; 514 | i_price = i->price(); 515 | 516 | a_max = NULL; 517 | 518 | // 1/2 arcs are scanned; 519 | for ( a = i->current() + 1, a_stop = (i + 1)->suspended(); a != a_stop; a ++ ) { 520 | 521 | if ( OPEN(a) && ( (dp = (a->head()->price() - a->cost())) > p_max ) ) { 522 | if ( i_price < dp ) { 523 | i->set_current( a); 524 | return ( 1); 525 | } 526 | p_max = dp; 527 | a_max = a; 528 | } 529 | } 530 | 531 | // 2/2 arcs are scanned; 532 | for ( a = i->first(), a_stop = i->current() + 1; a != a_stop; a ++ ) { 533 | if ( OPEN( a) && ( (dp = (a->head()->price() - a->cost())) > p_max ) ) { 534 | if ( i_price < dp ) { 535 | i->set_current( a); 536 | return ( 1); 537 | } 538 | p_max = dp; 539 | a_max = a; 540 | } 541 | } 542 | 543 | // finishup 544 | if ( p_max != _price_min ) { 545 | i->set_price( p_max - _epsilon); 546 | i->set_current( a_max); 547 | } 548 | else { // node can't be relabelled; 549 | if ( i->suspended() == i->first() ) { 550 | if ( i->excess() == 0 ) { 551 | i->set_price( _price_min); 552 | } else { 553 | if ( _n_ref == 1 ) { 554 | err_end( UNFEASIBLE ); 555 | } else { 556 | err_end( PRICE_OFL ); 557 | } 558 | } 559 | } else { // node can't be relabelled because of suspended arcs; 560 | _flag_price = 1; 561 | } 562 | } 563 | 564 | _n_relabel ++; 565 | _n_rel ++; 566 | return ( 0); 567 | } 568 | 569 | void MCMF_CS2::discharge( NODE *i) 570 | { 571 | register ARC *a;// an arc from i 572 | register NODE *j; // head of a 573 | register long df; // amoumt of flow to be pushed through a 574 | excess_t j_exc; // former excess of j 575 | 576 | _n_discharge ++; 577 | 578 | a = i->current(); 579 | j = a->head(); 580 | 581 | if ( !ADMISSIBLE( i, j, a ) ) { 582 | relabel( i ); 583 | a = i->current(); 584 | j = a->head(); 585 | } 586 | 587 | while ( 1 ) { 588 | 589 | j_exc = j->excess(); 590 | if ( j_exc >= 0 ) { 591 | 592 | df = MIN( i->excess(), a->rez_capacity() ); 593 | if ( j_exc == 0) _n_src++; 594 | increase_flow( i, j, a, df ); // INCREASE_FLOW 595 | _n_push ++; 596 | 597 | if ( out_of_excess_q( j ) ) { 598 | insert_to_excess_q( j ); 599 | } 600 | } 601 | else { // j_exc < 0; 602 | 603 | df = MIN( i->excess(), a->rez_capacity() ); 604 | increase_flow( i, j, a, df ); // INCREASE_FLOW 605 | _n_push ++; 606 | 607 | if ( j->excess() >= 0 ) { 608 | if ( j->excess() > 0 ) { 609 | _n_src ++; 610 | relabel( j ); 611 | insert_to_excess_q( j ); 612 | } 613 | _total_excess += j_exc; 614 | } 615 | else { 616 | _total_excess -= df; 617 | } 618 | } 619 | 620 | if ( i->excess() <= 0) _n_src --; 621 | if ( i->excess() <= 0 || _flag_price ) break; 622 | 623 | relabel( i ); 624 | 625 | a = i->current(); 626 | j = a->head(); 627 | } 628 | 629 | i->set_current( a); 630 | } 631 | 632 | int MCMF_CS2::price_in() 633 | { 634 | NODE *i; // current node 635 | NODE *j; 636 | ARC *a; // current arc from i 637 | ARC *a_stop; // first arc from the next node 638 | ARC *b; // arc to be exchanged with suspended 639 | ARC *ra; // opposite to a 640 | ARC *rb; // opposite to b 641 | price_t rc; // reduced cost 642 | int n_in_bad; // number of priced_in arcs with negative reduced cost 643 | int bad_found; // if 1 we are at the second scan if 0 we are at the first scan 644 | excess_t i_exc; // excess of i 645 | excess_t df; // an amount to increase flow 646 | 647 | 648 | bad_found = 0; 649 | n_in_bad = 0; 650 | 651 | restart: 652 | 653 | for ( i = _nodes; i != _sentinel_node; i ++ ) { 654 | 655 | for ( a = i->first() - 1, a_stop = i->suspended() - 1; a != a_stop; a -- ) { 656 | 657 | rc = REDUCED_COST( i, a->head(), a ); 658 | if ( ( rc < 0) && ( a->rez_capacity() > 0) ) { // bad case; 659 | if ( bad_found == 0 ) { 660 | bad_found = 1; 661 | update_cut_off(); 662 | goto restart; 663 | } 664 | df = a->rez_capacity(); 665 | increase_flow( i, a->head(), a, df ); 666 | 667 | ra = a->sister(); 668 | j = a->head(); 669 | 670 | i->dec_first(); 671 | b = i->first(); 672 | exchange( a, b ); 673 | 674 | if ( SUSPENDED( j, ra ) ) { 675 | j->dec_first(); 676 | rb = j->first(); 677 | exchange( ra, rb ); 678 | } 679 | 680 | n_in_bad ++; 681 | } 682 | else { 683 | if ( ( rc < _cut_on ) && ( rc > -_cut_on ) ) { 684 | i->dec_first(); 685 | b = i->first(); 686 | exchange( a, b ); 687 | } 688 | } 689 | } 690 | } 691 | 692 | 693 | if ( n_in_bad != 0 ) { 694 | 695 | _n_bad_pricein ++; 696 | 697 | // recalculating excess queue; 698 | _total_excess = 0; 699 | _n_src = 0; 700 | reset_excess_q(); 701 | 702 | for ( i = _nodes; i != _sentinel_node; i ++ ) { 703 | i->set_current( i->first()); 704 | i_exc = i->excess(); 705 | if ( i_exc > 0 ) { // i is a source; 706 | _total_excess += i_exc; 707 | _n_src ++; 708 | insert_to_excess_q( i ); 709 | } 710 | } 711 | 712 | insert_to_excess_q( _dummy_node ); 713 | } 714 | 715 | if ( _time_for_price_in == TIME_FOR_PRICE_IN2) 716 | _time_for_price_in = TIME_FOR_PRICE_IN3; 717 | if ( _time_for_price_in == TIME_FOR_PRICE_IN1) 718 | _time_for_price_in = TIME_FOR_PRICE_IN2; 719 | 720 | return ( n_in_bad); 721 | } 722 | 723 | void MCMF_CS2::refine() 724 | { 725 | NODE *i; // current node 726 | excess_t i_exc; // excess of i 727 | long np, nr, ns; // variables for additional print 728 | int pr_in_int; // current number of updates between price_in 729 | 730 | np = _n_push; 731 | nr = _n_relabel; 732 | ns = _n_scan; 733 | 734 | _n_refine ++; 735 | _n_ref ++; 736 | _n_rel = 0; 737 | pr_in_int = 0; 738 | 739 | // initialize; 740 | _total_excess = 0; 741 | _n_src = 0; 742 | reset_excess_q(); 743 | 744 | _time_for_price_in = TIME_FOR_PRICE_IN1; 745 | 746 | for ( i = _nodes; i != _sentinel_node; i ++ ) { 747 | i->set_current( i->first()); 748 | i_exc = i->excess(); 749 | if ( i_exc > 0 ) { // i is a source 750 | _total_excess += i_exc; 751 | _n_src++; 752 | insert_to_excess_q( i ); 753 | } 754 | } 755 | 756 | if ( _total_excess <= 0 ) return; 757 | 758 | // (2) main loop 759 | 760 | while ( 1 ) { 761 | 762 | if ( empty_excess_q() ) { 763 | if ( _n_ref > PRICE_OUT_START ) { 764 | pr_in_int = 0; 765 | price_in(); 766 | } 767 | 768 | if ( empty_excess_q() ) break; 769 | } 770 | 771 | REMOVE_FROM_EXCESS_Q( i ); 772 | 773 | // push all excess out of i 774 | if ( i->excess() > 0 ) { 775 | discharge( i ); 776 | 777 | if ( time_for_update() || _flag_price ) { 778 | if ( i->excess() > 0 ) { 779 | insert_to_excess_q( i ); 780 | } 781 | 782 | if ( _flag_price && ( _n_ref > PRICE_OUT_START ) ) { 783 | pr_in_int = 0; 784 | price_in(); 785 | _flag_price = 0; 786 | } 787 | 788 | price_update(); 789 | 790 | while ( _flag_updt ) { 791 | if ( _n_ref == 1 ) { 792 | err_end( UNFEASIBLE ); 793 | } else { 794 | _flag_updt = 0; 795 | update_cut_off(); 796 | _n_bad_relabel ++; 797 | pr_in_int = 0; 798 | price_in(); 799 | price_update(); 800 | } 801 | } 802 | _n_rel = 0; 803 | 804 | if ( _n_ref > PRICE_OUT_START && (pr_in_int ++ > _time_for_price_in) ) { 805 | pr_in_int = 0; 806 | price_in(); 807 | } 808 | } 809 | } 810 | } 811 | 812 | return; 813 | } 814 | 815 | int MCMF_CS2::price_refine() 816 | { 817 | NODE *i; // current node 818 | NODE *j; // opposite node 819 | NODE *ir; // nodes for passing over the negative cycle 820 | NODE *is; 821 | ARC *a; // arc (i,j) 822 | ARC *a_stop; // first arc from the next node 823 | ARC *ar; 824 | long bmax; // number of farest nonempty bucket 825 | long i_rank; // rank of node i 826 | long j_rank; // rank of node j 827 | long j_new_rank; // new rank of node j 828 | BUCKET *b; // current bucket 829 | BUCKET *b_old; // old and new buckets of current node 830 | BUCKET *b_new; 831 | price_t rc = 0; // reduced cost of a 832 | price_t dr; // ranks difference 833 | price_t dp; 834 | int cc; 835 | // return code: 1 - flow is epsilon optimal 836 | // 0 - refine is needed 837 | long df; // cycle capacity 838 | int nnc; // number of negative cycles cancelled during one iteration 839 | int snc; // total number of negative cycle cancelled 840 | 841 | _n_prefine ++; 842 | 843 | cc = 1; 844 | snc = 0; 845 | 846 | _snc_max = ( _n_ref >= START_CYCLE_CANCEL) ? MAX_CYCLES_CANCELLED : 0; 847 | 848 | 849 | // (1) main loop 850 | // while negative cycle is found or eps-optimal solution is constructed 851 | while ( 1 ) { 852 | 853 | nnc = 0; 854 | for ( i = _nodes; i != _sentinel_node; i ++ ) { 855 | i->set_rank( 0); 856 | i->set_inp( WHITE); 857 | i->set_current( i->first()); 858 | } 859 | reset_stackq(); 860 | 861 | for ( i = _nodes; i != _sentinel_node; i ++ ) { 862 | if ( i->inp() == BLACK ) continue; 863 | 864 | i->set_b_next( NULL); 865 | 866 | // deapth first search 867 | while ( 1 ) { 868 | i->set_inp( GREY); 869 | 870 | // scanning arcs from node i starting from current 871 | for ( a = i->current(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 872 | if ( OPEN( a ) ) { 873 | j = a->head(); 874 | if ( REDUCED_COST ( i, j, a ) < 0 ) { 875 | if ( j->inp() == WHITE ) { // fresh node - step forward 876 | i->set_current( a); 877 | j->set_b_next( i); 878 | i = j; 879 | a = j->current(); 880 | a_stop = (j+1)->suspended(); 881 | break; 882 | } 883 | 884 | if ( j->inp() == GREY ) { // cycle detected 885 | cc = 0; 886 | nnc ++; 887 | i->set_current( a); 888 | is = ir = i; 889 | df = MAX_32; 890 | 891 | while ( 1 ) { 892 | ar = ir->current(); 893 | if ( ar->rez_capacity() <= df ) { 894 | df = ar->rez_capacity(); 895 | is = ir; 896 | } 897 | if ( ir == j ) break; 898 | ir = ir->b_next(); 899 | } 900 | 901 | ir = i; 902 | 903 | while ( 1 ) { 904 | ar = ir->current(); 905 | increase_flow( ir, ar->head(), ar, df); 906 | if ( ir == j ) break; 907 | ir = ir->b_next(); 908 | } 909 | 910 | if ( is != i ) { 911 | for ( ir = i; ir != is; ir = ir->b_next() ) { 912 | ir->set_inp( WHITE); 913 | } 914 | i = is; 915 | a = is->current() + 1; 916 | a_stop = (is+1)->suspended(); 917 | break; 918 | } 919 | } 920 | } 921 | // if j-color is BLACK - continue search from i 922 | } 923 | } // all arcs from i are scanned 924 | 925 | if ( a == a_stop ) { 926 | // step back 927 | i->set_inp( BLACK); 928 | _n_prscan1 ++; 929 | j = i->b_next(); 930 | stackq_push( i ); 931 | if ( j == NULL ) break; 932 | i = j; 933 | i->inc_current(); 934 | } 935 | 936 | } // end of deapth first search 937 | } // all nodes are scanned 938 | 939 | 940 | // () no negative cycle 941 | // computing longest paths with eps-precision 942 | 943 | snc += nnc; 944 | if ( snc < _snc_max ) cc = 1; 945 | if ( cc == 0 ) break; 946 | bmax = 0; 947 | 948 | while ( nonempty_stackq() ) { 949 | 950 | _n_prscan2 ++; 951 | STACKQ_POP( i ); 952 | i_rank = i->rank(); 953 | for ( a = i->first(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 954 | 955 | if ( OPEN( a ) ) { 956 | j = a->head(); 957 | rc = REDUCED_COST( i, j, a ); 958 | 959 | if ( rc < 0 ) { // admissible arc; 960 | dr = (price_t) (( - rc - 0.5 ) / _epsilon); 961 | if (( j_rank = dr + i_rank ) < _linf ) { 962 | if ( j_rank > j->rank() ) 963 | j->set_rank( j_rank); 964 | } 965 | } 966 | } 967 | } // all arcs from i are scanned 968 | 969 | if ( i_rank > 0 ) { 970 | if ( i_rank > bmax ) bmax = i_rank; 971 | b = _buckets + i_rank; 972 | insert_to_bucket( i, b ); 973 | } 974 | } // end of while-cycle: all nodes are scanned - longest distancess are computed; 975 | 976 | 977 | if ( bmax == 0 ) // preflow is eps-optimal; 978 | { break; } 979 | 980 | 981 | for ( b = _buckets + bmax; b != _buckets; b -- ) { 982 | i_rank = b - _buckets; 983 | dp = i_rank * _epsilon; 984 | 985 | while ( nonempty_bucket( b) ) { 986 | GET_FROM_BUCKET( i, b ); 987 | _n_prscan ++; 988 | 989 | for ( a = i->first(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 990 | if ( OPEN( a ) ) { 991 | j = a->head(); 992 | j_rank = j->rank(); 993 | if ( j_rank < i_rank ) { 994 | rc = REDUCED_COST( i, j, a ); 995 | if ( rc < 0 ) { 996 | j_new_rank = i_rank; 997 | } else { 998 | dr = rc / _epsilon; 999 | j_new_rank = ( dr < _linf ) ? i_rank - ( (long)dr + 1 ) : 0; 1000 | } 1001 | if ( j_rank < j_new_rank ) { 1002 | if ( cc == 1 ) { 1003 | j->set_rank( j_new_rank); 1004 | if ( j_rank > 0 ) { 1005 | b_old = _buckets + j_rank; 1006 | REMOVE_FROM_BUCKET( j, b_old ); 1007 | } 1008 | b_new = _buckets + j_new_rank; 1009 | insert_to_bucket( j, b_new ); 1010 | } 1011 | else { 1012 | df = a->rez_capacity(); 1013 | increase_flow( i, j, a, df ); 1014 | } 1015 | } 1016 | } 1017 | } // end if opened arc 1018 | } // all arcs are scanned 1019 | 1020 | i->dec_price( dp); 1021 | 1022 | } // end of while-cycle: the bucket is scanned 1023 | } // end of for-cycle: all buckets are scanned 1024 | 1025 | if ( cc == 0 ) break; 1026 | 1027 | } // end of main loop 1028 | 1029 | 1030 | 1031 | // (2) finish 1032 | // if refine needed - saturate non-epsilon-optimal arcs; 1033 | 1034 | if ( cc == 0 ) { 1035 | for ( i = _nodes; i != _sentinel_node; i ++) { 1036 | for ( a = i->first(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 1037 | if ( REDUCED_COST( i, a->head(), a ) < - _epsilon ) { 1038 | if ( ( df = a->rez_capacity() ) > 0 ) { 1039 | increase_flow( i, a->head(), a, df ); 1040 | } 1041 | } 1042 | } 1043 | } 1044 | } 1045 | 1046 | return ( cc ); 1047 | } 1048 | 1049 | void MCMF_CS2::compute_prices() 1050 | { 1051 | NODE *i; // current node 1052 | NODE *j; // opposite node 1053 | ARC *a; // arc (i,j) 1054 | ARC *a_stop; // first arc from the next node 1055 | long bmax; // number of farest nonempty bucket 1056 | long i_rank; // rank of node i 1057 | long j_rank; // rank of node j 1058 | long j_new_rank; // new rank of node j 1059 | BUCKET *b; // current bucket 1060 | BUCKET *b_old; // old and new buckets of current node 1061 | BUCKET *b_new; 1062 | price_t rc; // reduced cost of a 1063 | price_t dr; // ranks difference 1064 | price_t dp; 1065 | int cc; // return code: 1 - flow is epsilon optimal 0 - refine is needed 1066 | 1067 | _n_prefine ++; 1068 | cc = 1; 1069 | 1070 | // (1) main loop 1071 | // while negative cycle is found or eps-optimal solution is constructed 1072 | while ( 1 ) { 1073 | 1074 | for ( i = _nodes; i != _sentinel_node; i ++) { 1075 | i->set_rank( 0); 1076 | i->set_inp( WHITE); 1077 | i->set_current( i->first()); 1078 | } 1079 | reset_stackq(); 1080 | 1081 | for ( i = _nodes; i != _sentinel_node; i ++ ) { 1082 | if ( i->inp() == BLACK ) continue; 1083 | 1084 | i->set_b_next( NULL); 1085 | // depth first search 1086 | while ( 1 ) { 1087 | i->set_inp( GREY); 1088 | 1089 | // scanning arcs from node i 1090 | for ( a = i->suspended(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 1091 | if ( OPEN( a ) ) { 1092 | j = a->head(); 1093 | if ( REDUCED_COST( i, j, a ) < 0 ) { 1094 | if ( j->inp() == WHITE ) { // fresh node - step forward 1095 | i->set_current( a); 1096 | j->set_b_next( i); 1097 | i = j; 1098 | a = j->current(); 1099 | a_stop = (j+1)->suspended(); 1100 | break; 1101 | } 1102 | 1103 | if ( j->inp() == GREY ) { // cycle detected; should not happen 1104 | cc = 0; 1105 | } 1106 | } 1107 | // if j-color is BLACK - continue search from i 1108 | } 1109 | } // all arcs from i are scanned 1110 | 1111 | if ( a == a_stop ) { 1112 | // step back 1113 | i->set_inp( BLACK); 1114 | _n_prscan1 ++; 1115 | j = i->b_next(); 1116 | stackq_push( i ); 1117 | if ( j == NULL ) break; 1118 | i = j; 1119 | i->inc_current(); 1120 | } 1121 | 1122 | } // end of deapth first search 1123 | } // all nodes are scanned 1124 | 1125 | 1126 | // no negative cycle 1127 | // computing longest paths 1128 | 1129 | if ( cc == 0 ) break; 1130 | bmax = 0; 1131 | 1132 | while ( nonempty_stackq() ) { 1133 | _n_prscan2 ++; 1134 | STACKQ_POP( i ); 1135 | i_rank = i->rank(); 1136 | for ( a = i->suspended(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 1137 | if ( OPEN( a ) ) { 1138 | j = a->head(); 1139 | rc = REDUCED_COST( i, j, a ); 1140 | 1141 | 1142 | if ( rc < 0 ) {// admissible arc 1143 | dr = - rc; 1144 | if (( j_rank = dr + i_rank ) < _linf ) { 1145 | if ( j_rank > j->rank() ) 1146 | j->set_rank( j_rank); 1147 | } 1148 | } 1149 | } 1150 | } // all arcs from i are scanned 1151 | 1152 | if ( i_rank > 0 ) { 1153 | if ( i_rank > bmax ) bmax = i_rank; 1154 | b = _buckets + i_rank; 1155 | insert_to_bucket( i, b ); 1156 | } 1157 | } // end of while-cycle: all nodes are scanned - longest distancess are computed; 1158 | 1159 | if ( bmax == 0 ) 1160 | { break; } 1161 | 1162 | for ( b = _buckets + bmax; b != _buckets; b -- ) { 1163 | i_rank = b - _buckets; 1164 | dp = i_rank; 1165 | 1166 | while ( nonempty_bucket( b) ) { 1167 | GET_FROM_BUCKET( i, b ); 1168 | _n_prscan ++; 1169 | 1170 | for ( a = i->suspended(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 1171 | if ( OPEN( a ) ) { 1172 | j = a->head(); 1173 | j_rank = j->rank(); 1174 | if ( j_rank < i_rank ) { 1175 | rc = REDUCED_COST( i, j, a ); 1176 | 1177 | if ( rc < 0 ) { 1178 | j_new_rank = i_rank; 1179 | } else { 1180 | dr = rc; 1181 | j_new_rank = ( dr < _linf ) ? i_rank - ( (long)dr + 1 ) : 0; 1182 | } 1183 | if ( j_rank < j_new_rank ) { 1184 | if ( cc == 1 ) { 1185 | j->set_rank( j_new_rank); 1186 | if ( j_rank > 0 ) { 1187 | b_old = _buckets + j_rank; 1188 | REMOVE_FROM_BUCKET( j, b_old ); 1189 | } 1190 | b_new = _buckets + j_new_rank; 1191 | insert_to_bucket( j, b_new ); 1192 | } 1193 | } 1194 | } 1195 | } // end if opened arc 1196 | } // all arcs are scanned 1197 | 1198 | i->dec_price( dp); 1199 | 1200 | } // end of while-cycle: the bucket is scanned 1201 | } // end of for-cycle: all buckets are scanned 1202 | 1203 | if ( cc == 0 ) break; 1204 | 1205 | } // end of main loop 1206 | } 1207 | 1208 | void MCMF_CS2::price_out() 1209 | { 1210 | NODE *i; // current node 1211 | ARC *a; // current arc from i 1212 | ARC *a_stop; // first arc from the next node 1213 | ARC *b; // arc to be exchanged with suspended 1214 | double n_cut_off; // -cut_off 1215 | double rc; // reduced cost 1216 | 1217 | n_cut_off = - _cut_off; 1218 | 1219 | for ( i = _nodes; i != _sentinel_node; i ++) { 1220 | for ( a = i->first(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 1221 | 1222 | rc = REDUCED_COST( i, a->head(), a ); 1223 | if ( ( rc > _cut_off && CLOSED(a->sister()) ) || 1224 | ( rc < n_cut_off && CLOSED(a) ) ) { // suspend the arc 1225 | 1226 | b = i->first(); 1227 | i->inc_first(); 1228 | exchange( a, b ); 1229 | } 1230 | } 1231 | } 1232 | } 1233 | 1234 | int MCMF_CS2::update_epsilon() 1235 | { 1236 | // decrease epsilon after epsilon-optimal flow is constructed; 1237 | if ( _epsilon <= 1 ) return ( 1 ); 1238 | 1239 | _epsilon = (price_t) (ceil ( (double) _epsilon / _f_scale )); 1240 | _cut_off = _cut_off_factor * _epsilon; 1241 | _cut_on = _cut_off * CUT_OFF_GAP; 1242 | 1243 | return ( 0 ); 1244 | } 1245 | 1246 | int MCMF_CS2::check_feas() 1247 | { 1248 | if ( _check_solution == false) 1249 | return ( 0); 1250 | 1251 | NODE *i; 1252 | ARC *a, *a_stop; 1253 | long fa; 1254 | int ans = 1; 1255 | 1256 | for ( i = _nodes; i != _sentinel_node; i ++) { 1257 | for ( a = i->suspended(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 1258 | if ( _cap[ N_ARC(a) ] > 0) { 1259 | fa = _cap[ N_ARC(a) ] - a->rez_capacity(); 1260 | if ( fa < 0) { 1261 | ans = 0; 1262 | break; 1263 | } 1264 | _node_balance[ i - _nodes ] -= fa; 1265 | _node_balance[ a->head() - _nodes ] += fa; 1266 | } 1267 | } 1268 | } 1269 | 1270 | for ( i = _nodes; i != _sentinel_node; i ++) { 1271 | if ( _node_balance[ i - _nodes ] != 0) { 1272 | ans = 0; 1273 | break; 1274 | } 1275 | } 1276 | 1277 | return ( ans); 1278 | } 1279 | 1280 | int MCMF_CS2::check_cs() 1281 | { 1282 | // check complimentary slackness; 1283 | NODE *i; 1284 | ARC *a, *a_stop; 1285 | 1286 | for ( i = _nodes; i != _sentinel_node; i ++) { 1287 | for ( a = i->suspended(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 1288 | 1289 | if ( OPEN(a) && (REDUCED_COST(i, a->head(), a) < 0) ) { 1290 | return ( 0); 1291 | } 1292 | } 1293 | } 1294 | return(1); 1295 | } 1296 | 1297 | int MCMF_CS2::check_eps_opt() 1298 | { 1299 | NODE *i; 1300 | ARC *a, *a_stop; 1301 | 1302 | for ( i = _nodes; i != _sentinel_node; i ++) { 1303 | for ( a = i->suspended(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 1304 | 1305 | if ( OPEN(a) && (REDUCED_COST(i, a->head(), a) < - _epsilon) ) { 1306 | return ( 0); 1307 | } 1308 | } 1309 | } 1310 | return(1); 1311 | } 1312 | 1313 | void MCMF_CS2::init_solution() 1314 | { 1315 | ARC *a; // current arc (i,j) 1316 | NODE *i; // tail of a 1317 | NODE *j; // head of a 1318 | long df; // residual capacity 1319 | 1320 | for ( a = _arcs; a != _sentinel_arc; a ++ ) { 1321 | if ( a->rez_capacity() > 0 && a->cost() < 0 ) { 1322 | df = a->rez_capacity(); 1323 | i = a->sister()->head(); 1324 | j = a->head(); 1325 | increase_flow( i, j, a, df ); 1326 | } 1327 | } 1328 | } 1329 | 1330 | void MCMF_CS2::cs_cost_reinit() 1331 | { 1332 | if ( _cost_restart == false) 1333 | return; 1334 | 1335 | NODE *i; // current node 1336 | ARC *a; // current arc 1337 | ARC *a_stop; 1338 | BUCKET *b; // current bucket 1339 | price_t rc, minc, sum; 1340 | 1341 | 1342 | for ( b = _buckets; b != _l_bucket; b ++) { 1343 | reset_bucket( b); 1344 | } 1345 | 1346 | rc = 0; 1347 | for ( i = _nodes; i != _sentinel_node; i ++) { 1348 | rc = MIN(rc, i->price()); 1349 | i->set_first( i->suspended()); 1350 | i->set_current( i->first()); 1351 | i->set_q_next( _sentinel_node); 1352 | } 1353 | 1354 | // make prices nonnegative and multiply 1355 | for ( i = _nodes; i != _sentinel_node; i ++) { 1356 | i->set_price( (i->price() - rc) * _dn); 1357 | } 1358 | 1359 | // multiply arc costs 1360 | for (a = _arcs; a != _sentinel_arc; a ++) { 1361 | a->multiply_cost( _dn); 1362 | } 1363 | 1364 | sum = 0; 1365 | for ( i = _nodes; i != _sentinel_node; i ++) { 1366 | minc = 0; 1367 | for ( a = i->first(), a_stop = (i + 1)->suspended(); a != a_stop; a ++) { 1368 | if ( (OPEN(a) && ((rc = REDUCED_COST(i, a->head(), a)) < 0)) ) 1369 | minc = MAX( _epsilon, -rc); 1370 | } 1371 | sum += minc; 1372 | } 1373 | 1374 | _epsilon = ceil(sum / _dn); 1375 | 1376 | _cut_off_factor = CUT_OFF_COEF * pow((double)_n, CUT_OFF_POWER); 1377 | 1378 | _cut_off_factor = MAX( _cut_off_factor, CUT_OFF_MIN); 1379 | 1380 | _n_ref = 0; 1381 | 1382 | _n_refine = _n_discharge = _n_push = _n_relabel = 0; 1383 | _n_update = _n_scan = _n_prefine = _n_prscan = _n_prscan1 = 1384 | _n_bad_pricein = _n_bad_relabel = 0; 1385 | 1386 | _flag_price = 0; 1387 | 1388 | _excq_first = NULL; 1389 | } 1390 | 1391 | void MCMF_CS2::cs2_cost_restart( double *objective_cost) 1392 | { 1393 | // restart after a cost update; 1394 | if ( _cost_restart == false) 1395 | return; 1396 | 1397 | int cc; // for storing return code; 1398 | 1399 | printf("c \nc ******************************\n"); 1400 | printf("c Restarting after a cost update\n"); 1401 | printf("c ******************************\nc\n"); 1402 | 1403 | cs_cost_reinit(); 1404 | 1405 | printf ("c Init. epsilon = %6.0f\n", _epsilon); 1406 | cc = update_epsilon(); 1407 | 1408 | if (cc != 0) { 1409 | printf("c Old solution is optimal\n"); 1410 | } 1411 | else { 1412 | do { // scaling loop 1413 | while ( 1 ) { 1414 | if ( ! price_refine() ) 1415 | break; 1416 | 1417 | if ( _n_ref >= PRICE_OUT_START ) { 1418 | if ( price_in() ) 1419 | break; 1420 | } 1421 | if ((cc = update_epsilon ())) 1422 | break; 1423 | } 1424 | if (cc) break; 1425 | refine(); 1426 | if ( _n_ref >= PRICE_OUT_START ) { 1427 | price_out(); 1428 | } 1429 | if ( update_epsilon() ) 1430 | break; 1431 | } while ( cc == 0 ); 1432 | } 1433 | 1434 | finishup( objective_cost ); 1435 | } 1436 | 1437 | void MCMF_CS2::print_solution() 1438 | { 1439 | if ( _print_ans == false) 1440 | return; 1441 | 1442 | NODE *i; 1443 | ARC *a; 1444 | long ni; 1445 | price_t cost; 1446 | printf ("c\ns %.0l\n", cost ); 1447 | 1448 | for ( i = _nodes; i < _nodes + _n; i ++ ) { 1449 | ni = N_NODE( i ); 1450 | for ( a = i->suspended(); a != (i+1)->suspended(); a ++) { 1451 | if ( _cap[ N_ARC (a) ] > 0 ) { 1452 | printf("f %7ld %7ld %10ld\n", 1453 | ni, N_NODE(a->head()), _cap[ N_ARC(a) ] - a->rez_capacity()); 1454 | } 1455 | } 1456 | } 1457 | 1458 | // COMP_DUALS? 1459 | if ( _comp_duals == true) { // find minimum price; 1460 | cost = MAX_32; 1461 | for ( i = _nodes; i != _sentinel_node; i ++) { 1462 | cost = MIN(cost, i->price()); 1463 | } 1464 | for ( i = _nodes; i != _sentinel_node; i ++) { 1465 | printf("p %7ld %7.2lld\n", N_NODE(i), i->price() - cost); 1466 | } 1467 | } 1468 | 1469 | printf("c\n"); 1470 | } 1471 | 1472 | void MCMF_CS2::print_graph() 1473 | { 1474 | NODE *i; 1475 | ARC *a; 1476 | long ni, na; 1477 | printf ("\nGraph: %d\n", _n); 1478 | for ( i = _nodes; i < _nodes + _n; i ++ ) { 1479 | ni = N_NODE( i ); 1480 | printf("\nNode %d", ni); 1481 | for ( a = i->suspended(); a != (i+1)->suspended(); a ++) { 1482 | na = N_ARC( a ); 1483 | printf("\n {%d} %d -> %d cap: %d cost: %d", na, 1484 | ni, N_NODE(a->head()), _cap[N_ARC(a)], a->cost()); 1485 | } 1486 | } 1487 | } 1488 | 1489 | void MCMF_CS2::finishup( double *objective_cost) 1490 | { 1491 | ARC *a; // current arc 1492 | long na; // corresponding position in capacity array 1493 | double obj_internal = 0; // objective 1494 | price_t cs; // actual arc cost 1495 | long flow; // flow through an arc 1496 | NODE *i; 1497 | 1498 | // (1) NO_ZERO_CYCLES? 1499 | if ( _no_zero_cycles == true) { 1500 | for ( a = _arcs; a != _sentinel_arc; a ++ ) { 1501 | if ( a->cost() == 1) { 1502 | assert( a->sister()->cost() == -1); 1503 | a->set_cost( 0); 1504 | a->sister()->set_cost( 0); 1505 | } 1506 | } 1507 | } 1508 | 1509 | // (2) 1510 | for ( a = _arcs, na = 0; a != _sentinel_arc ; a ++, na ++ ) { 1511 | cs = a->cost() / _dn; 1512 | if ( _cap[na] > 0 && (flow = _cap[na] - a->rez_capacity()) != 0 ) 1513 | obj_internal += (double) cs * (double) flow; 1514 | a->set_cost( cs); 1515 | } 1516 | 1517 | for ( i = _nodes; i != _sentinel_node; i ++) { 1518 | i->set_price( (i->price() / _dn)); 1519 | } 1520 | 1521 | // (3) COMP_DUALS? 1522 | if ( _comp_duals == true) { 1523 | compute_prices(); 1524 | } 1525 | 1526 | *objective_cost = obj_internal; 1527 | } 1528 | 1529 | void MCMF_CS2::cs2( double *objective_cost) 1530 | { 1531 | // the main calling function; 1532 | int cc = 0; // for storing return code; 1533 | 1534 | 1535 | // (1) update epsilon first; 1536 | update_epsilon(); 1537 | 1538 | 1539 | // (2) scaling loop; 1540 | do { 1541 | refine(); 1542 | 1543 | if ( _n_ref >= PRICE_OUT_START ) 1544 | price_out(); 1545 | 1546 | if ( update_epsilon() ) 1547 | break; 1548 | 1549 | while (1) { 1550 | if ( ! price_refine() ) 1551 | break; 1552 | 1553 | if ( _n_ref >= PRICE_OUT_START ) { 1554 | if ( price_in() ) break; 1555 | if ( (cc = update_epsilon()) ) break; 1556 | } 1557 | } 1558 | } while ( cc == 0 ); 1559 | 1560 | 1561 | // (3) finishup; 1562 | finishup( objective_cost ); 1563 | } 1564 | 1565 | int MCMF_CS2::run_cs2() 1566 | { 1567 | // example of flow network in DIMACS format: 1568 | // 1569 | //"p min 6 8 1570 | //c min-cost flow problem with 6 nodes and 8 arcs 1571 | //n 1 10 1572 | //c supply of 10 at node 1 1573 | //n 6 -10 1574 | //c demand of 10 at node 6 1575 | //c arc list follows 1576 | //c arc has 1577 | //a 1 2 0 4 1 1578 | //a 1 3 0 8 5 1579 | //a 2 3 0 5 0 1580 | //a 3 5 0 10 1 1581 | //a 5 4 0 8 0 1582 | //a 5 6 0 8 9 1583 | //a 4 2 0 8 1 1584 | //a 4 6 0 8 1" 1585 | // 1586 | // in order to solve this flow problem we have to follow these steps: 1587 | // 1. ctor of MCMF_CS2 // sets num of nodes and arcs 1588 | // // it also calls allocate_arrays() 1589 | // 2. call set_arc() for each arc 1590 | // 3. call set_supply_demand_of_node() for non-transhipment nodes 1591 | // 4. pre_processing() 1592 | // 5. cs2_initialize() 1593 | // 6. cs2() 1594 | // 7. retreive results 1595 | // 1596 | // this function is basically a wrapper to implement steps 4, 5, 6; 1597 | 1598 | double objective_cost; 1599 | 1600 | 1601 | // (4) ordering, etc.; 1602 | pre_processing(); 1603 | 1604 | 1605 | // () CHECK_SOLUTION? 1606 | if ( _check_solution == true) { 1607 | _node_balance = (long long int *) calloc (_n+1, sizeof(long long int)); 1608 | for ( NODE *i = _nodes; i < _nodes + _n; i ++ ) { 1609 | _node_balance[i - _nodes] = i->excess(); 1610 | } 1611 | } 1612 | 1613 | 1614 | // (5) initializations; 1615 | _m = 2 * _m; 1616 | cs2_initialize(); // works already with 2*m; 1617 | print_graph(); // exit(1); // debug; 1618 | 1619 | printf("\nc CS 4.3\n"); 1620 | printf("c nodes: %ld arcs: %ld\n", _n, _m/2 ); 1621 | printf("c scale-factor: %f cut-off-factor: %f\nc\n", 1622 | _f_scale, _cut_off_factor); 1623 | 1624 | 1625 | // (6) run CS2; 1626 | cs2( &objective_cost ); 1627 | double t = 0.0; 1628 | 1629 | printf("c time: %15.2f cost: %15.0f\n", t, objective_cost); 1630 | printf("c refines: %10ld discharges: %10ld\n", _n_refine, _n_discharge); 1631 | printf("c pushes: %10ld relabels: %10ld\n", _n_push, _n_relabel); 1632 | printf("c updates: %10ld u-scans: %10ld\n", _n_update, _n_scan); 1633 | printf("c p-refines: %10ld r-scans: %10ld\n", _n_prefine, _n_prscan); 1634 | printf("c dfs-scans: %10ld bad-in: %4ld + %2ld\n", 1635 | _n_prscan1, _n_bad_pricein, _n_bad_relabel); 1636 | 1637 | 1638 | // () CHECK_SOLUTION? 1639 | if ( _check_solution == true ) { 1640 | printf("c checking feasibility...\n"); 1641 | if ( check_feas() ) 1642 | printf("c ...OK\n"); 1643 | else 1644 | printf("c ERROR: solution infeasible\n"); 1645 | printf("c computing prices and checking CS...\n"); 1646 | compute_prices(); 1647 | if ( check_cs() ) 1648 | printf("c ...OK\n"); 1649 | else 1650 | printf("ERROR: CS violation\n"); 1651 | } 1652 | 1653 | // () PRINT_ANS? 1654 | if ( _print_ans == true ) { 1655 | print_solution(); 1656 | } 1657 | 1658 | // () cleanup; 1659 | deallocate_arrays(); 1660 | return 0; 1661 | } 1662 | 1663 | 1664 | //////////////////////////////////////////////////////////////////////////////// 1665 | // 1666 | // main 1667 | // 1668 | //////////////////////////////////////////////////////////////////////////////// 1669 | 1670 | int main( int argc, char *argv[]) 1671 | { 1672 | //"p min 6 8 1673 | //c min-cost flow problem with 6 nodes and 8 arcs 1674 | //n 1 10 1675 | //c supply of 10 at node 1 1676 | //n 6 -10 1677 | //c demand of 10 at node 6 1678 | //c arc list follows 1679 | //c arc has 1680 | //a 1 2 0 4 1 1681 | //a 1 3 0 8 5 1682 | //a 2 3 0 5 0 1683 | //a 3 5 0 10 1 1684 | //a 5 4 0 8 0 1685 | //a 5 6 0 8 9 1686 | //a 4 2 0 8 1 1687 | //a 4 6 0 8 1" 1688 | int num_nodes = 6; 1689 | int num_arcs = 8; 1690 | MCMF_CS2 my_mcmf_problem( num_nodes, num_arcs); 1691 | 1692 | my_mcmf_problem.set_arc( 1, 2, 0, 4, 1); 1693 | my_mcmf_problem.set_arc( 1, 3, 0, 8, 5); 1694 | my_mcmf_problem.set_arc( 2, 3, 0, 5, 0); 1695 | my_mcmf_problem.set_arc( 3, 5, 0, 10, 1); 1696 | my_mcmf_problem.set_arc( 5, 4, 0, 8, 0); 1697 | my_mcmf_problem.set_arc( 5, 6, 0, 8, 9); 1698 | my_mcmf_problem.set_arc( 4, 2, 0, 8, 1); 1699 | my_mcmf_problem.set_arc( 4, 6, 0, 8, 1); 1700 | my_mcmf_problem.set_supply_demand_of_node( 1, 10); 1701 | my_mcmf_problem.set_supply_demand_of_node( 6, -10); 1702 | 1703 | my_mcmf_problem.run_cs2(); 1704 | 1705 | return 0; 1706 | } 1707 | -------------------------------------------------------------------------------- /mcmf.h: -------------------------------------------------------------------------------- 1 | // Cristinel Ababei, January 2009, Fargo ND 2 | // E-mail: cristinel.ababei@ndsu.edu 3 | // 4 | // This is a C++ implementation of CS2 min-cost-max-flow scaling algorithm. 5 | // 6 | // This is intended to be one of the cleanest and simplest to use minimum-cost 7 | // max-flow (MCMF) implementation using C++. If you have a C++ application in 8 | // which you need to use a MCMF algo, then this may be your most elegant bet. 9 | // See main() function for an example of how to use it. 10 | // 11 | // This is an adapted (i.e., ported to C++) version of the faimous CS2 algo; 12 | // CS2 is the second version of scaling algorithm for minimum-cost max-flow 13 | // problems. For a detailed description of this famous algo, see: 14 | // A.V. Goldberg, "An Efficient Implementation of a Scaling Minimum-Cost 15 | // Flow Algorithm", Journal of Algorithms, Vol. 22, pp. 1-29, 1997. 16 | 17 | #ifndef _MCMF_H_ 18 | #define _MCMF_H_ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | using namespace std; 26 | 27 | //////////////////////////////////////////////////////////////////////////////// 28 | // 29 | // MCMF_CS2 30 | // 31 | //////////////////////////////////////////////////////////////////////////////// 32 | 33 | #define MAX_64 (0x7fffffffffffffffLL) 34 | #define MAX_32 (0x7fffffff) 35 | #define PRICE_MAX MAX_64 36 | 37 | #define MAXLINE 100 // max line length in the input file 38 | #define ARC_FIELDS 5 // no of fields in arc line 39 | #define NODE_FIELDS 2 // no of fields in node line 40 | #define P_FIELDS 3 // no of fields in problem line 41 | #define PROBLEM_TYPE "min" // name of problem type 42 | 43 | #define UNFEASIBLE 2 44 | #define ALLOCATION_FAULT 5 45 | #define PRICE_OFL 6 46 | 47 | // parameters 48 | #define UPDT_FREQ 0.4 49 | #define UPDT_FREQ_S 30 50 | #define SCALE_DEFAULT 12.0 51 | // PRICE_OUT_START may not be less than 1 52 | #define PRICE_OUT_START 1 53 | #define CUT_OFF_POWER 0.44 54 | #define CUT_OFF_COEF 1.5 55 | #define CUT_OFF_POWER2 0.75 56 | #define CUT_OFF_COEF2 1 57 | #define CUT_OFF_GAP 0.8 58 | #define CUT_OFF_MIN 12 59 | #define CUT_OFF_INCREASE 4 60 | 61 | #define TIME_FOR_PRICE_IN1 2 62 | #define TIME_FOR_PRICE_IN2 4 63 | #define TIME_FOR_PRICE_IN3 6 64 | 65 | #define MAX_CYCLES_CANCELLED 0 66 | #define START_CYCLE_CANCEL 100 67 | 68 | #define MAX( x, y ) ( ( (x) > (y) ) ? x : y ) 69 | #define MIN( x, y ) ( ( (x) < (y) ) ? x : y ) 70 | #define ABS( x ) ( (x) >= 0 ) ? (x) : -(x) 71 | #define N_NODE( i ) ( ( (i) == NULL ) ? -1 : ( (i) - _nodes + _node_min ) ) 72 | #define N_ARC( a ) ( ( (a) == NULL )? -1 : (a) - _arcs ) 73 | 74 | class MCMF_CS2 75 | { 76 | public: 77 | typedef long long int excess_t; 78 | typedef long long int price_t; 79 | 80 | class NODE; 81 | 82 | class ARC { 83 | public: 84 | long _rez_capacity; // residual capacity; 85 | price_t _cost; // cost of arc; 86 | NODE *_head; // head node; 87 | ARC *_sister; // opposite arc; 88 | public: 89 | ARC() {} 90 | ~ARC() {} 91 | 92 | void set_rez_capacity( long rez_capacity) { _rez_capacity = rez_capacity; } 93 | void dec_rez_capacity( long delta) { _rez_capacity -= delta; } 94 | void inc_rez_capacity( long delta) { _rez_capacity += delta; } 95 | void set_cost( price_t cost) { _cost = cost; } 96 | void multiply_cost( price_t mult) { _cost *= mult; } 97 | void set_head( NODE *head) { _head = head; } 98 | void set_sister( ARC *sister) { _sister = sister; } 99 | long rez_capacity() { return _rez_capacity; } 100 | price_t cost() { return _cost; } 101 | NODE *head() { return _head; } 102 | ARC *sister() { return _sister; } 103 | }; 104 | 105 | class NODE { 106 | public: 107 | excess_t _excess; // excess of the node; 108 | price_t _price; // distance from a sink; 109 | ARC *_first; // first outgoing arc; 110 | ARC *_current; // current outgoing arc; 111 | ARC *_suspended; 112 | NODE *_q_next; // next node in push queue 113 | NODE *_b_next; // next node in bucket-list; 114 | NODE *_b_prev; // previous node in bucket-list; 115 | long _rank; // bucket number; 116 | long _inp; // auxilary field; 117 | public: 118 | NODE() {} 119 | ~NODE() {} 120 | 121 | void set_excess( excess_t excess) { _excess = excess; } 122 | void dec_excess( long delta) { _excess -= delta; } 123 | void inc_excess( long delta) { _excess += delta; } 124 | void set_price( price_t price) { _price = price; } 125 | void dec_price( long delta) { _price -= delta; } 126 | void set_first( ARC *first) { _first = first; } 127 | void set_current( ARC *current) { _current = current; } 128 | void inc_current() { _current ++; } 129 | void set_suspended( ARC *suspended) { _suspended = suspended; } 130 | void set_q_next( NODE *q_next) { _q_next = q_next; } 131 | void set_b_next( NODE *b_next) { _b_next = b_next; } 132 | void set_b_prev( NODE *b_prev) { _b_prev = b_prev; } 133 | void set_rank( long rank) { _rank = rank; } 134 | void set_inp( long inp) { _inp = inp; } 135 | excess_t excess() { return _excess; } 136 | price_t price() { return _price; } 137 | ARC *first() { return _first; } 138 | void dec_first() { _first --; } 139 | void inc_first() { _first ++; } 140 | ARC *current() { return _current; } 141 | ARC *suspended() { return _suspended; } 142 | NODE *q_next() { return _q_next; } 143 | NODE *b_next() { return _b_next; } 144 | NODE *b_prev() { return _b_prev; } 145 | long rank() { return _rank; } 146 | long inp() { return _inp; } 147 | }; 148 | 149 | class BUCKET { 150 | private: 151 | // 1st node with positive excess or simply 1st node in the buket; 152 | NODE *_p_first; 153 | public: 154 | BUCKET( NODE *p_first) : _p_first(p_first) {} 155 | BUCKET() {} 156 | ~BUCKET() {} 157 | 158 | void set_p_first( NODE *p_first) { _p_first = p_first; } 159 | NODE *p_first() { return _p_first; } 160 | }; 161 | 162 | public: 163 | long _n; // number of nodes 164 | long _m; // number of arcs 165 | 166 | long *_cap; // array containig capacities 167 | NODE *_nodes; // array of nodes 168 | NODE *_sentinel_node; // next after last 169 | NODE *_excq_first; // first node in push-queue 170 | NODE *_excq_last; // last node in push-queue 171 | ARC *_arcs; // array of arcs 172 | ARC *_sentinel_arc; // next after last 173 | 174 | BUCKET *_buckets; // array of buckets 175 | BUCKET *_l_bucket; // last bucket 176 | long _linf; // number of l_bucket + 1 177 | int _time_for_price_in; 178 | 179 | price_t _epsilon; // quality measure 180 | price_t _dn; // cost multiplier = number of nodes + 1 181 | price_t _price_min; // lowest bound for prices 182 | price_t _mmc; // multiplied maximal cost 183 | double _f_scale; // scale factor 184 | double _cut_off_factor; // multiplier to produce cut_on and cut_off from n and epsilon 185 | double _cut_on; // the bound for returning suspended arcs 186 | double _cut_off; // the bound for suspending arcs 187 | excess_t _total_excess; // total excess 188 | 189 | // if = 1 - signal to start price-in ASAP - 190 | // maybe there is infeasibility because of susoended arcs 191 | int _flag_price; 192 | // if = 1 - update failed some sources are unreachable: either the 193 | // problem is unfeasible or you have to return suspended arcs 194 | int _flag_updt; 195 | // maximal number of cycles cancelled during price refine 196 | int _snc_max; 197 | 198 | // dummy variables; 199 | ARC _d_arc; // dummy arc - for technical reasons 200 | NODE _d_node; // dummy node - for technical reasons 201 | NODE *_dummy_node; // the address of d_node 202 | NODE *_dnode; 203 | 204 | long _n_rel; // number of relabels from last price update 205 | long _n_ref; // current number of refines 206 | long _n_src; // current number of nodes with excess 207 | long _n_push; 208 | long _n_relabel; 209 | long _n_discharge; 210 | long _n_refine; 211 | long _n_update; 212 | long _n_scan; 213 | long _n_prscan; 214 | long _n_prscan1; 215 | long _n_prscan2; 216 | long _n_bad_pricein; 217 | long _n_bad_relabel; 218 | long _n_prefine; 219 | 220 | bool _no_zero_cycles; // finds an optimal flow with no zero-cost cycles 221 | bool _check_solution; // check feasibility/optimality. HIGH OVERHEAD! 222 | bool _comp_duals; // compute prices? 223 | bool _cost_restart; // to be able to restart after a cost function change 224 | bool _print_ans; 225 | long long int *_node_balance; 226 | 227 | // sketch variables used during reading in arcs; 228 | long _node_min; // minimal no of nodes 229 | long _node_max; // maximal no of nodes 230 | long *_arc_first; // internal array for holding 231 | // - node degree 232 | // - position of the first outgoing arc 233 | long *_arc_tail; // internal array: tails of the arcs 234 | long _pos_current; 235 | ARC *_arc_current; 236 | ARC *_arc_new; 237 | ARC *_arc_tmp; 238 | price_t _max_cost; // maximum cost 239 | excess_t _total_p; // total supply 240 | excess_t _total_n; // total demand 241 | // pointers to the node structure 242 | NODE *_i_node; 243 | NODE *_j_node; 244 | 245 | public: 246 | MCMF_CS2( long num_nodes, long num_arcs) { 247 | _n = num_nodes; 248 | _m = num_arcs; 249 | 250 | _flag_price = 0; 251 | _flag_updt = 0; 252 | _n_push = 0; 253 | _n_relabel = 0; 254 | _n_discharge = 0; 255 | _n_refine = 0; 256 | _n_update = 0; 257 | _n_scan = 0; 258 | _n_prscan = 0; 259 | _n_prscan1 = 0; 260 | _n_prscan2 = 0; 261 | _n_bad_pricein = 0; 262 | _n_bad_relabel = 0; 263 | _n_prefine = 0; 264 | _no_zero_cycles = false; 265 | _check_solution = false; 266 | _comp_duals = false; 267 | _cost_restart = false; 268 | _print_ans = true; 269 | // allocate arrays and prepare for "receiving" arcs; 270 | // will also reset _pos_current, etc.; 271 | allocate_arrays(); 272 | } 273 | ~MCMF_CS2() {} 274 | 275 | void err_end( int cc); 276 | void allocate_arrays(); 277 | void deallocate_arrays(); 278 | void set_arc( long tail_node_id, long head_node_id, 279 | long low_bound, long up_bound, price_t cost); 280 | void set_supply_demand_of_node( long id, long excess); 281 | void pre_processing(); 282 | void cs2_initialize(); 283 | void up_node_scan( NODE *i); 284 | void price_update(); 285 | int relabel( NODE *i); 286 | void discharge( NODE *i); 287 | int price_in(); 288 | void refine(); 289 | int price_refine(); 290 | void compute_prices(); 291 | void price_out(); 292 | int update_epsilon(); 293 | int check_feas(); 294 | int check_cs(); 295 | int check_eps_opt(); 296 | void init_solution(); 297 | void cs_cost_reinit(); 298 | void cs2_cost_restart( double *objective_cost); 299 | void print_solution(); 300 | void print_graph(); 301 | void finishup( double *objective_cost); 302 | void cs2( double *objective_cost); 303 | int run_cs2(); 304 | 305 | // shared utils; 306 | void increase_flow( NODE *i, NODE *j, ARC *a, long df) { 307 | i->dec_excess( df); 308 | j->inc_excess( df); 309 | a->dec_rez_capacity( df); 310 | a->sister()->inc_rez_capacity( df); 311 | } 312 | bool time_for_update() { 313 | return ( _n_rel > _n * UPDT_FREQ + _n_src * UPDT_FREQ_S); 314 | } 315 | // utils for excess queue; 316 | void reset_excess_q() { 317 | for ( ; _excq_first != NULL; _excq_first = _excq_last ) { 318 | _excq_last = _excq_first->q_next(); 319 | _excq_first->set_q_next( _sentinel_node); 320 | } 321 | } 322 | bool out_of_excess_q( NODE *i) { return ( i->q_next() == _sentinel_node); } 323 | bool empty_excess_q() { return ( _excq_first == NULL); } 324 | bool nonempty_excess_q() { return ( _excq_first != NULL); } 325 | void insert_to_excess_q( NODE *i) { 326 | if ( nonempty_excess_q() ) { 327 | _excq_last->set_q_next( i); 328 | } else { 329 | _excq_first = i; 330 | } 331 | i->set_q_next( NULL); 332 | _excq_last = i; 333 | } 334 | void insert_to_front_excess_q( NODE *i) { 335 | if ( empty_excess_q() ) { 336 | _excq_last = i; 337 | } 338 | i->set_q_next( _excq_first); 339 | _excq_first = i; 340 | } 341 | void remove_from_excess_q( NODE *i) { 342 | i = _excq_first; 343 | _excq_first = i->q_next(); 344 | i->set_q_next( _sentinel_node); 345 | } 346 | // utils for excess queue as a stack; 347 | bool empty_stackq() { return empty_excess_q(); } 348 | bool nonempty_stackq() { return nonempty_excess_q(); } 349 | void reset_stackq() { reset_excess_q(); } 350 | void stackq_push( NODE *i) { 351 | i->set_q_next( _excq_first); 352 | _excq_first = i; 353 | } 354 | void stackq_pop( NODE *i) { 355 | remove_from_excess_q( i); 356 | } 357 | // utils for buckets; 358 | void reset_bucket( BUCKET *b) { b->set_p_first( _dnode); } 359 | bool nonempty_bucket( BUCKET *b) { return ( (b->p_first()) != _dnode); } 360 | void insert_to_bucket( NODE *i, BUCKET *b) { 361 | i->set_b_next( b->p_first() ); 362 | b->p_first()->set_b_prev( i); 363 | b->set_p_first( i); 364 | } 365 | void get_from_bucket( NODE *i, BUCKET *b) { 366 | i = b->p_first(); 367 | b->set_p_first( i->b_next()); 368 | } 369 | void remove_from_bucket( NODE *i, BUCKET *b) { 370 | if ( i == b->p_first() ) { 371 | b->set_p_first( i->b_next()); 372 | } else { 373 | i->b_prev()->set_b_next( i->b_next()); 374 | i->b_next()->set_b_prev( i->b_prev()); 375 | } 376 | } 377 | // misc utils; 378 | void update_cut_off() { 379 | if ( _n_bad_pricein + _n_bad_relabel == 0) { 380 | _cut_off_factor = CUT_OFF_COEF2 * pow( (double)_n, CUT_OFF_POWER2 ); 381 | _cut_off_factor = MAX ( _cut_off_factor, CUT_OFF_MIN ); 382 | _cut_off = _cut_off_factor * _epsilon; 383 | _cut_on = _cut_off * CUT_OFF_GAP; 384 | } else { 385 | _cut_off_factor *= CUT_OFF_INCREASE; 386 | _cut_off = _cut_off_factor * _epsilon; 387 | _cut_on = _cut_off * CUT_OFF_GAP; 388 | } 389 | } 390 | void exchange( ARC *a, ARC *b) { 391 | if ( a != b) { 392 | ARC *sa = a->sister(); 393 | ARC *sb = b->sister(); 394 | long d_cap; 395 | 396 | _d_arc.set_rez_capacity( a->rez_capacity()); 397 | _d_arc.set_cost( a->cost()); 398 | _d_arc.set_head( a->head()); 399 | 400 | a->set_rez_capacity( b->rez_capacity()); 401 | a->set_cost( b->cost()); 402 | a->set_head( b->head()); 403 | 404 | b->set_rez_capacity( _d_arc.rez_capacity()); 405 | b->set_cost( _d_arc.cost()); 406 | b->set_head( _d_arc.head()); 407 | 408 | if ( a != sb) { 409 | b->set_sister( sa); 410 | a->set_sister( sb); 411 | sa->set_sister( b); 412 | sb->set_sister( a); 413 | } 414 | 415 | d_cap = _cap[ a - _arcs]; 416 | _cap[ a - _arcs] = _cap[ b - _arcs]; 417 | _cap[ b - _arcs] = d_cap; 418 | } 419 | } 420 | }; 421 | 422 | #endif 423 | --------------------------------------------------------------------------------