gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Small improvements in NS pivot rules (#298)
0 1 0
default
1 file changed with 47 insertions and 55 deletions:
↑ Collapse diff ↑
Ignore white space 96 line context
... ...
@@ -319,350 +319,342 @@
319 319
          }
320 320
        }
321 321
        return min < 0;
322 322
      }
323 323

	
324 324
    }; //class BestEligiblePivotRule
325 325

	
326 326

	
327 327
    // Implementation of the Block Search pivot rule
328 328
    class BlockSearchPivotRule
329 329
    {
330 330
    private:
331 331

	
332 332
      // References to the NetworkSimplex class
333 333
      const IntVector  &_source;
334 334
      const IntVector  &_target;
335 335
      const CostVector &_cost;
336 336
      const IntVector  &_state;
337 337
      const CostVector &_pi;
338 338
      int &_in_arc;
339 339
      int _search_arc_num;
340 340

	
341 341
      // Pivot rule data
342 342
      int _block_size;
343 343
      int _next_arc;
344 344

	
345 345
    public:
346 346

	
347 347
      // Constructor
348 348
      BlockSearchPivotRule(NetworkSimplex &ns) :
349 349
        _source(ns._source), _target(ns._target),
350 350
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
351 351
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
352 352
        _next_arc(0)
353 353
      {
354 354
        // The main parameters of the pivot rule
355 355
        const double BLOCK_SIZE_FACTOR = 0.5;
356 356
        const int MIN_BLOCK_SIZE = 10;
357 357

	
358 358
        _block_size = std::max( int(BLOCK_SIZE_FACTOR *
359 359
                                    std::sqrt(double(_search_arc_num))),
360 360
                                MIN_BLOCK_SIZE );
361 361
      }
362 362

	
363 363
      // Find next entering arc
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
      }
397 396

	
398 397
    }; //class BlockSearchPivotRule
399 398

	
400 399

	
401 400
    // Implementation of the Candidate List pivot rule
402 401
    class CandidateListPivotRule
403 402
    {
404 403
    private:
405 404

	
406 405
      // References to the NetworkSimplex class
407 406
      const IntVector  &_source;
408 407
      const IntVector  &_target;
409 408
      const CostVector &_cost;
410 409
      const IntVector  &_state;
411 410
      const CostVector &_pi;
412 411
      int &_in_arc;
413 412
      int _search_arc_num;
414 413

	
415 414
      // Pivot rule data
416 415
      IntVector _candidates;
417 416
      int _list_length, _minor_limit;
418 417
      int _curr_length, _minor_count;
419 418
      int _next_arc;
420 419

	
421 420
    public:
422 421

	
423 422
      /// Constructor
424 423
      CandidateListPivotRule(NetworkSimplex &ns) :
425 424
        _source(ns._source), _target(ns._target),
426 425
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
427 426
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
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;
435 434

	
436 435
        _list_length = std::max( int(LIST_LENGTH_FACTOR *
437 436
                                     std::sqrt(double(_search_arc_num))),
438 437
                                 MIN_LIST_LENGTH );
439 438
        _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
440 439
                                 MIN_MINOR_LIMIT );
441 440
        _curr_length = _minor_count = 0;
442 441
        _candidates.resize(_list_length);
443 442
      }
444 443

	
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
452 451
          ++_minor_count;
453 452
          min = 0;
454 453
          for (int i = 0; i < _curr_length; ++i) {
455 454
            e = _candidates[i];
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
472 468
        min = 0;
473 469
        _curr_length = 0;
474 470
        for (e = _next_arc; e < _search_arc_num; ++e) {
475 471
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
476 472
          if (c < 0) {
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
      }
504 499

	
505 500
    }; //class CandidateListPivotRule
506 501

	
507 502

	
508 503
    // Implementation of the Altering Candidate List pivot rule
509 504
    class AlteringListPivotRule
510 505
    {
511 506
    private:
512 507

	
513 508
      // References to the NetworkSimplex class
514 509
      const IntVector  &_source;
515 510
      const IntVector  &_target;
516 511
      const CostVector &_cost;
517 512
      const IntVector  &_state;
518 513
      const CostVector &_pi;
519 514
      int &_in_arc;
520 515
      int _search_arc_num;
521 516

	
522 517
      // Pivot rule data
523 518
      int _block_size, _head_length, _curr_length;
524 519
      int _next_arc;
525 520
      IntVector _candidates;
526 521
      CostVector _cand_cost;
527 522

	
528 523
      // Functor class to compare arcs during sort of the candidate list
529 524
      class SortFunc
530 525
      {
531 526
      private:
532 527
        const CostVector &_map;
533 528
      public:
534 529
        SortFunc(const CostVector &map) : _map(map) {}
535 530
        bool operator()(int left, int right) {
536 531
          return _map[left] > _map[right];
537 532
        }
538 533
      };
539 534

	
540 535
      SortFunc _sort_func;
541 536

	
542 537
    public:
543 538

	
544 539
      // Constructor
545 540
      AlteringListPivotRule(NetworkSimplex &ns) :
546 541
        _source(ns._source), _target(ns._target),
547 542
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
548 543
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
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;
556 551

	
557 552
        _block_size = std::max( int(BLOCK_SIZE_FACTOR *
558 553
                                    std::sqrt(double(_search_arc_num))),
559 554
                                MIN_BLOCK_SIZE );
560 555
        _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
561 556
                                 MIN_HEAD_LENGTH );
562 557
        _candidates.resize(_head_length + _block_size);
563 558
        _curr_length = 0;
564 559
      }
565 560

	
566 561
      // Find next entering arc
567 562
      bool findEnteringArc() {
568 563
        // Check the current candidate list
569 564
        int e;
570 565
        for (int i = 0; i < _curr_length; ++i) {
571 566
          e = _candidates[i];
572 567
          _cand_cost[e] = _state[e] *
573 568
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
574 569
          if (_cand_cost[e] >= 0) {
575 570
            _candidates[i--] = _candidates[--_curr_length];
576 571
          }
577 572
        }
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,
617 608
                   _sort_func );
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);
624 616
        return true;
625 617
      }
626 618

	
627 619
    }; //class AlteringListPivotRule
628 620

	
629 621
  public:
630 622

	
631 623
    /// \brief Constructor.
632 624
    ///
633 625
    /// The constructor of the class.
634 626
    ///
635 627
    /// \param graph The digraph the algorithm runs on.
636 628
    NetworkSimplex(const GR& graph) :
637 629
      _graph(graph), _node_id(graph), _arc_id(graph),
638 630
      INF(std::numeric_limits<Value>::has_infinity ?
639 631
          std::numeric_limits<Value>::infinity() :
640 632
          std::numeric_limits<Value>::max())
641 633
    {
642 634
      // Check the value types
643 635
      LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
644 636
        "The flow type of NetworkSimplex must be signed");
645 637
      LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
646 638
        "The cost type of NetworkSimplex must be signed");
647 639
        
648 640
      // Resize vectors
649 641
      _node_num = countNodes(_graph);
650 642
      _arc_num = countArcs(_graph);
651 643
      int all_node_num = _node_num + 1;
652 644
      int max_arc_num = _arc_num + 2 * _node_num;
653 645

	
654 646
      _source.resize(max_arc_num);
655 647
      _target.resize(max_arc_num);
656 648

	
657 649
      _lower.resize(_arc_num);
658 650
      _upper.resize(_arc_num);
659 651
      _cap.resize(max_arc_num);
660 652
      _cost.resize(max_arc_num);
661 653
      _supply.resize(all_node_num);
662 654
      _flow.resize(max_arc_num);
663 655
      _pi.resize(all_node_num);
664 656

	
665 657
      _parent.resize(all_node_num);
666 658
      _pred.resize(all_node_num);
667 659
      _forward.resize(all_node_num);
668 660
      _thread.resize(all_node_num);
0 comments (0 inline)