# HG changeset patch
# User Peter Kovacs <kpeter@inf.elte.hu>
# Date 1246458841 -7200
# Node ID cab85bd7859b6b89eee29e8db1619888a513e6a6
# Parent 257e91516e09d8d6be58236c587e3e0199770412
Small improvements in NS pivot rules (#298)
diff --git a/lemon/network_simplex.h b/lemon/network_simplex.h
a
|
b
|
|
364 | 364 | bool findEnteringArc() { |
365 | 365 | Cost c, min = 0; |
366 | 366 | int cnt = _block_size; |
367 | | int e, min_arc = _next_arc; |
| 367 | int e; |
368 | 368 | for (e = _next_arc; e < _search_arc_num; ++e) { |
369 | 369 | c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
370 | 370 | if (c < min) { |
371 | 371 | min = c; |
372 | | min_arc = e; |
| 372 | _in_arc = e; |
373 | 373 | } |
374 | 374 | if (--cnt == 0) { |
375 | | if (min < 0) break; |
| 375 | if (min < 0) goto search_end; |
376 | 376 | cnt = _block_size; |
377 | 377 | } |
378 | 378 | } |
379 | | if (min == 0 || cnt > 0) { |
380 | | for (e = 0; e < _next_arc; ++e) { |
381 | | c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
382 | | if (c < min) { |
383 | | min = c; |
384 | | min_arc = e; |
385 | | } |
386 | | if (--cnt == 0) { |
387 | | if (min < 0) break; |
388 | | cnt = _block_size; |
389 | | } |
| 379 | for (e = 0; e < _next_arc; ++e) { |
| 380 | c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
| 381 | if (c < min) { |
| 382 | min = c; |
| 383 | _in_arc = e; |
| 384 | } |
| 385 | if (--cnt == 0) { |
| 386 | if (min < 0) goto search_end; |
| 387 | cnt = _block_size; |
390 | 388 | } |
391 | 389 | } |
392 | 390 | if (min >= 0) return false; |
393 | | _in_arc = min_arc; |
| 391 | |
| 392 | search_end: |
394 | 393 | _next_arc = e; |
395 | 394 | return true; |
396 | 395 | } |
… |
… |
|
428 | 427 | _next_arc(0) |
429 | 428 | { |
430 | 429 | // The main parameters of the pivot rule |
431 | | const double LIST_LENGTH_FACTOR = 1.0; |
| 430 | const double LIST_LENGTH_FACTOR = 0.25; |
432 | 431 | const int MIN_LIST_LENGTH = 10; |
433 | 432 | const double MINOR_LIMIT_FACTOR = 0.1; |
434 | 433 | const int MIN_MINOR_LIMIT = 3; |
… |
… |
|
445 | 444 | /// Find next entering arc |
446 | 445 | bool findEnteringArc() { |
447 | 446 | Cost min, c; |
448 | | int e, min_arc = _next_arc; |
| 447 | int e; |
449 | 448 | if (_curr_length > 0 && _minor_count < _minor_limit) { |
450 | 449 | // Minor iteration: select the best eligible arc from the |
451 | 450 | // current candidate list |
… |
… |
|
456 | 455 | c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
457 | 456 | if (c < min) { |
458 | 457 | min = c; |
459 | | min_arc = e; |
| 458 | _in_arc = e; |
460 | 459 | } |
461 | | if (c >= 0) { |
| 460 | else if (c >= 0) { |
462 | 461 | _candidates[i--] = _candidates[--_curr_length]; |
463 | 462 | } |
464 | 463 | } |
465 | | if (min < 0) { |
466 | | _in_arc = min_arc; |
467 | | return true; |
468 | | } |
| 464 | if (min < 0) return true; |
469 | 465 | } |
470 | 466 | |
471 | 467 | // Major iteration: build a new candidate list |
… |
… |
|
477 | 473 | _candidates[_curr_length++] = e; |
478 | 474 | if (c < min) { |
479 | 475 | min = c; |
480 | | min_arc = e; |
| 476 | _in_arc = e; |
481 | 477 | } |
482 | | if (_curr_length == _list_length) break; |
| 478 | if (_curr_length == _list_length) goto search_end; |
483 | 479 | } |
484 | 480 | } |
485 | | if (_curr_length < _list_length) { |
486 | | for (e = 0; e < _next_arc; ++e) { |
487 | | c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
488 | | if (c < 0) { |
489 | | _candidates[_curr_length++] = e; |
490 | | if (c < min) { |
491 | | min = c; |
492 | | min_arc = e; |
493 | | } |
494 | | if (_curr_length == _list_length) break; |
| 481 | for (e = 0; e < _next_arc; ++e) { |
| 482 | c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
| 483 | if (c < 0) { |
| 484 | _candidates[_curr_length++] = e; |
| 485 | if (c < min) { |
| 486 | min = c; |
| 487 | _in_arc = e; |
495 | 488 | } |
| 489 | if (_curr_length == _list_length) goto search_end; |
496 | 490 | } |
497 | 491 | } |
498 | 492 | if (_curr_length == 0) return false; |
| 493 | |
| 494 | search_end: |
499 | 495 | _minor_count = 1; |
500 | | _in_arc = min_arc; |
501 | 496 | _next_arc = e; |
502 | 497 | return true; |
503 | 498 | } |
… |
… |
|
549 | 544 | _next_arc(0), _cand_cost(ns._search_arc_num), _sort_func(_cand_cost) |
550 | 545 | { |
551 | 546 | // The main parameters of the pivot rule |
552 | | const double BLOCK_SIZE_FACTOR = 1.5; |
| 547 | const double BLOCK_SIZE_FACTOR = 1.0; |
553 | 548 | const int MIN_BLOCK_SIZE = 10; |
554 | 549 | const double HEAD_LENGTH_FACTOR = 0.1; |
555 | 550 | const int MIN_HEAD_LENGTH = 3; |
… |
… |
|
578 | 573 | |
579 | 574 | // Extend the list |
580 | 575 | int cnt = _block_size; |
581 | | int last_arc = 0; |
582 | 576 | int limit = _head_length; |
583 | 577 | |
584 | | for (int e = _next_arc; e < _search_arc_num; ++e) { |
| 578 | for (e = _next_arc; e < _search_arc_num; ++e) { |
585 | 579 | _cand_cost[e] = _state[e] * |
586 | 580 | (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
587 | 581 | if (_cand_cost[e] < 0) { |
588 | 582 | _candidates[_curr_length++] = e; |
589 | | last_arc = e; |
590 | 583 | } |
591 | 584 | if (--cnt == 0) { |
592 | | if (_curr_length > limit) break; |
| 585 | if (_curr_length > limit) goto search_end; |
593 | 586 | limit = 0; |
594 | 587 | cnt = _block_size; |
595 | 588 | } |
596 | 589 | } |
597 | | if (_curr_length <= limit) { |
598 | | for (int e = 0; e < _next_arc; ++e) { |
599 | | _cand_cost[e] = _state[e] * |
600 | | (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
601 | | if (_cand_cost[e] < 0) { |
602 | | _candidates[_curr_length++] = e; |
603 | | last_arc = e; |
604 | | } |
605 | | if (--cnt == 0) { |
606 | | if (_curr_length > limit) break; |
607 | | limit = 0; |
608 | | cnt = _block_size; |
609 | | } |
| 590 | for (e = 0; e < _next_arc; ++e) { |
| 591 | _cand_cost[e] = _state[e] * |
| 592 | (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
| 593 | if (_cand_cost[e] < 0) { |
| 594 | _candidates[_curr_length++] = e; |
| 595 | } |
| 596 | if (--cnt == 0) { |
| 597 | if (_curr_length > limit) goto search_end; |
| 598 | limit = 0; |
| 599 | cnt = _block_size; |
610 | 600 | } |
611 | 601 | } |
612 | 602 | if (_curr_length == 0) return false; |
613 | | _next_arc = last_arc + 1; |
| 603 | |
| 604 | search_end: |
614 | 605 | |
615 | 606 | // Make heap of the candidate list (approximating a partial sort) |
616 | 607 | make_heap( _candidates.begin(), _candidates.begin() + _curr_length, |
… |
… |
|
618 | 609 | |
619 | 610 | // Pop the first element of the heap |
620 | 611 | _in_arc = _candidates[0]; |
| 612 | _next_arc = e; |
621 | 613 | pop_heap( _candidates.begin(), _candidates.begin() + _curr_length, |
622 | 614 | _sort_func ); |
623 | 615 | _curr_length = std::min(_head_length, _curr_length - 1); |