gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Uniforming primal scale to 2 (#314)
0 2 0
default
2 files changed with 44 insertions and 25 deletions:
↑ Collapse diff ↑
Ignore white space 768 line context
... ...
@@ -277,1858 +277,1854 @@
277 277
      typedef MaxFractionalMatching<Graph, SetElevatorTraits<T> > Create;
278 278
    };
279 279

	
280 280
    template <typename T>
281 281
    struct SetStandardElevatorTraits : public Traits {
282 282
      typedef T Elevator;
283 283
      static Elevator *createElevator(const Graph& graph, int max_level) {
284 284
        return new Elevator(graph, max_level);
285 285
      }
286 286
    };
287 287

	
288 288
    /// \brief \ref named-templ-param "Named parameter" for setting
289 289
    /// Elevator type with automatic allocation
290 290
    ///
291 291
    /// \ref named-templ-param "Named parameter" for setting Elevator
292 292
    /// type with automatic allocation.
293 293
    /// The Elevator should have standard constructor interface to be
294 294
    /// able to automatically created by the algorithm (i.e. the
295 295
    /// graph and the maximum level should be passed to it).
296 296
    /// However an external elevator object could also be passed to the
297 297
    /// algorithm with the \ref elevator(Elevator&) "elevator()" function
298 298
    /// before calling \ref run() or \ref init().
299 299
    /// \sa SetElevator
300 300
    template <typename T>
301 301
    struct SetStandardElevator
302 302
      : public MaxFractionalMatching<Graph, SetStandardElevatorTraits<T> > {
303 303
      typedef MaxFractionalMatching<Graph,
304 304
                                    SetStandardElevatorTraits<T> > Create;
305 305
    };
306 306

	
307 307
    /// @}
308 308

	
309 309
  protected:
310 310

	
311 311
    MaxFractionalMatching() {}
312 312

	
313 313
  public:
314 314

	
315 315
    /// \brief Constructor
316 316
    ///
317 317
    /// Constructor.
318 318
    ///
319 319
    MaxFractionalMatching(const Graph &graph, bool allow_loops = true)
320 320
      : _graph(graph), _allow_loops(allow_loops),
321 321
        _local_matching(false), _matching(0),
322 322
        _local_level(false), _level(0),  _indeg(0)
323 323
    {}
324 324

	
325 325
    ~MaxFractionalMatching() {
326 326
      destroyStructures();
327 327
    }
328 328

	
329 329
    /// \brief Sets the matching map.
330 330
    ///
331 331
    /// Sets the matching map.
332 332
    /// If you don't use this function before calling \ref run() or
333 333
    /// \ref init(), an instance will be allocated automatically.
334 334
    /// The destructor deallocates this automatically allocated map,
335 335
    /// of course.
336 336
    /// \return <tt>(*this)</tt>
337 337
    MaxFractionalMatching& matchingMap(MatchingMap& map) {
338 338
      if (_local_matching) {
339 339
        delete _matching;
340 340
        _local_matching = false;
341 341
      }
342 342
      _matching = &map;
343 343
      return *this;
344 344
    }
345 345

	
346 346
    /// \brief Sets the elevator used by algorithm.
347 347
    ///
348 348
    /// Sets the elevator used by algorithm.
349 349
    /// If you don't use this function before calling \ref run() or
350 350
    /// \ref init(), an instance will be allocated automatically.
351 351
    /// The destructor deallocates this automatically allocated elevator,
352 352
    /// of course.
353 353
    /// \return <tt>(*this)</tt>
354 354
    MaxFractionalMatching& elevator(Elevator& elevator) {
355 355
      if (_local_level) {
356 356
        delete _level;
357 357
        _local_level = false;
358 358
      }
359 359
      _level = &elevator;
360 360
      return *this;
361 361
    }
362 362

	
363 363
    /// \brief Returns a const reference to the elevator.
364 364
    ///
365 365
    /// Returns a const reference to the elevator.
366 366
    ///
367 367
    /// \pre Either \ref run() or \ref init() must be called before
368 368
    /// using this function.
369 369
    const Elevator& elevator() const {
370 370
      return *_level;
371 371
    }
372 372

	
373 373
    /// \name Execution control
374 374
    /// The simplest way to execute the algorithm is to use one of the
375 375
    /// member functions called \c run(). \n
376 376
    /// If you need more control on the execution, first
377 377
    /// you must call \ref init() and then one variant of the start()
378 378
    /// member.
379 379

	
380 380
    /// @{
381 381

	
382 382
    /// \brief Initializes the internal data structures.
383 383
    ///
384 384
    /// Initializes the internal data structures and sets the initial
385 385
    /// matching.
386 386
    void init() {
387 387
      createStructures();
388 388

	
389 389
      _level->initStart();
390 390
      for (NodeIt n(_graph); n != INVALID; ++n) {
391 391
        _indeg->set(n, 0);
392 392
        _matching->set(n, INVALID);
393 393
        _level->initAddItem(n);
394 394
      }
395 395
      _level->initFinish();
396 396

	
397 397
      _empty_level = _node_num;
398 398
      for (NodeIt n(_graph); n != INVALID; ++n) {
399 399
        for (OutArcIt a(_graph, n); a != INVALID; ++a) {
400 400
          if (_graph.target(a) == n && !_allow_loops) continue;
401 401
          _matching->set(n, a);
402 402
          Node v = _graph.target((*_matching)[n]);
403 403
          _indeg->set(v, (*_indeg)[v] + 1);
404 404
          break;
405 405
        }
406 406
      }
407 407

	
408 408
      for (NodeIt n(_graph); n != INVALID; ++n) {
409 409
        if ((*_indeg)[n] == 0) {
410 410
          _level->activate(n);
411 411
        }
412 412
      }
413 413
    }
414 414

	
415 415
    /// \brief Starts the algorithm and computes a fractional matching
416 416
    ///
417 417
    /// The algorithm computes a maximum fractional matching.
418 418
    ///
419 419
    /// \param postprocess The algorithm computes first a matching
420 420
    /// which is a union of a matching with one value edges, cycles
421 421
    /// with half value edges and even length paths with half value
422 422
    /// edges. If the parameter is true, then after the push-relabel
423 423
    /// algorithm it postprocesses the matching to contain only
424 424
    /// matching edges and half value odd cycles.
425 425
    void start(bool postprocess = true) {
426 426
      Node n;
427 427
      while ((n = _level->highestActive()) != INVALID) {
428 428
        int level = _level->highestActiveLevel();
429 429
        int new_level = _level->maxLevel();
430 430
        for (InArcIt a(_graph, n); a != INVALID; ++a) {
431 431
          Node u = _graph.source(a);
432 432
          if (n == u && !_allow_loops) continue;
433 433
          Node v = _graph.target((*_matching)[u]);
434 434
          if ((*_level)[v] < level) {
435 435
            _indeg->set(v, (*_indeg)[v] - 1);
436 436
            if ((*_indeg)[v] == 0) {
437 437
              _level->activate(v);
438 438
            }
439 439
            _matching->set(u, a);
440 440
            _indeg->set(n, (*_indeg)[n] + 1);
441 441
            _level->deactivate(n);
442 442
            goto no_more_push;
443 443
          } else if (new_level > (*_level)[v]) {
444 444
            new_level = (*_level)[v];
445 445
          }
446 446
        }
447 447

	
448 448
        if (new_level + 1 < _level->maxLevel()) {
449 449
          _level->liftHighestActive(new_level + 1);
450 450
        } else {
451 451
          _level->liftHighestActiveToTop();
452 452
        }
453 453
        if (_level->emptyLevel(level)) {
454 454
          _level->liftToTop(level);
455 455
        }
456 456
      no_more_push:
457 457
        ;
458 458
      }
459 459
      for (NodeIt n(_graph); n != INVALID; ++n) {
460 460
        if ((*_matching)[n] == INVALID) continue;
461 461
        Node u = _graph.target((*_matching)[n]);
462 462
        if ((*_indeg)[u] > 1) {
463 463
          _indeg->set(u, (*_indeg)[u] - 1);
464 464
          _matching->set(n, INVALID);
465 465
        }
466 466
      }
467 467
      if (postprocess) {
468 468
        postprocessing();
469 469
      }
470 470
    }
471 471

	
472 472
    /// \brief Starts the algorithm and computes a perfect fractional
473 473
    /// matching
474 474
    ///
475 475
    /// The algorithm computes a perfect fractional matching. If it
476 476
    /// does not exists, then the algorithm returns false and the
477 477
    /// matching is undefined and the barrier.
478 478
    ///
479 479
    /// \param postprocess The algorithm computes first a matching
480 480
    /// which is a union of a matching with one value edges, cycles
481 481
    /// with half value edges and even length paths with half value
482 482
    /// edges. If the parameter is true, then after the push-relabel
483 483
    /// algorithm it postprocesses the matching to contain only
484 484
    /// matching edges and half value odd cycles.
485 485
    bool startPerfect(bool postprocess = true) {
486 486
      Node n;
487 487
      while ((n = _level->highestActive()) != INVALID) {
488 488
        int level = _level->highestActiveLevel();
489 489
        int new_level = _level->maxLevel();
490 490
        for (InArcIt a(_graph, n); a != INVALID; ++a) {
491 491
          Node u = _graph.source(a);
492 492
          if (n == u && !_allow_loops) continue;
493 493
          Node v = _graph.target((*_matching)[u]);
494 494
          if ((*_level)[v] < level) {
495 495
            _indeg->set(v, (*_indeg)[v] - 1);
496 496
            if ((*_indeg)[v] == 0) {
497 497
              _level->activate(v);
498 498
            }
499 499
            _matching->set(u, a);
500 500
            _indeg->set(n, (*_indeg)[n] + 1);
501 501
            _level->deactivate(n);
502 502
            goto no_more_push;
503 503
          } else if (new_level > (*_level)[v]) {
504 504
            new_level = (*_level)[v];
505 505
          }
506 506
        }
507 507

	
508 508
        if (new_level + 1 < _level->maxLevel()) {
509 509
          _level->liftHighestActive(new_level + 1);
510 510
        } else {
511 511
          _level->liftHighestActiveToTop();
512 512
          _empty_level = _level->maxLevel() - 1;
513 513
          return false;
514 514
        }
515 515
        if (_level->emptyLevel(level)) {
516 516
          _level->liftToTop(level);
517 517
          _empty_level = level;
518 518
          return false;
519 519
        }
520 520
      no_more_push:
521 521
        ;
522 522
      }
523 523
      if (postprocess) {
524 524
        postprocessing();
525 525
      }
526 526
      return true;
527 527
    }
528 528

	
529 529
    /// \brief Runs the algorithm
530 530
    ///
531 531
    /// Just a shortcut for the next code:
532 532
    ///\code
533 533
    /// init();
534 534
    /// start();
535 535
    ///\endcode
536 536
    void run(bool postprocess = true) {
537 537
      init();
538 538
      start(postprocess);
539 539
    }
540 540

	
541 541
    /// \brief Runs the algorithm to find a perfect fractional matching
542 542
    ///
543 543
    /// Just a shortcut for the next code:
544 544
    ///\code
545 545
    /// init();
546 546
    /// startPerfect();
547 547
    ///\endcode
548 548
    bool runPerfect(bool postprocess = true) {
549 549
      init();
550 550
      return startPerfect(postprocess);
551 551
    }
552 552

	
553 553
    ///@}
554 554

	
555 555
    /// \name Query Functions
556 556
    /// The result of the %Matching algorithm can be obtained using these
557 557
    /// functions.\n
558 558
    /// Before the use of these functions,
559 559
    /// either run() or start() must be called.
560 560
    ///@{
561 561

	
562 562

	
563 563
    /// \brief Return the number of covered nodes in the matching.
564 564
    ///
565 565
    /// This function returns the number of covered nodes in the matching.
566 566
    ///
567 567
    /// \pre Either run() or start() must be called before using this function.
568 568
    int matchingSize() const {
569 569
      int num = 0;
570 570
      for (NodeIt n(_graph); n != INVALID; ++n) {
571 571
        if ((*_matching)[n] != INVALID) {
572 572
          ++num;
573 573
        }
574 574
      }
575 575
      return num;
576 576
    }
577 577

	
578 578
    /// \brief Returns a const reference to the matching map.
579 579
    ///
580 580
    /// Returns a const reference to the node map storing the found
581 581
    /// fractional matching. This method can be called after
582 582
    /// running the algorithm.
583 583
    ///
584 584
    /// \pre Either \ref run() or \ref init() must be called before
585 585
    /// using this function.
586 586
    const MatchingMap& matchingMap() const {
587 587
      return *_matching;
588 588
    }
589 589

	
590 590
    /// \brief Return \c true if the given edge is in the matching.
591 591
    ///
592 592
    /// This function returns \c true if the given edge is in the
593 593
    /// found matching. The result is scaled by \ref primalScale
594 594
    /// "primal scale".
595 595
    ///
596 596
    /// \pre Either run() or start() must be called before using this function.
597 597
    int matching(const Edge& edge) const {
598 598
      return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0) +
599 599
        (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
600 600
    }
601 601

	
602 602
    /// \brief Return the fractional matching arc (or edge) incident
603 603
    /// to the given node.
604 604
    ///
605 605
    /// This function returns one of the fractional matching arc (or
606 606
    /// edge) incident to the given node in the found matching or \c
607 607
    /// INVALID if the node is not covered by the matching or if the
608 608
    /// node is on an odd length cycle then it is the successor edge
609 609
    /// on the cycle.
610 610
    ///
611 611
    /// \pre Either run() or start() must be called before using this function.
612 612
    Arc matching(const Node& node) const {
613 613
      return (*_matching)[node];
614 614
    }
615 615

	
616 616
    /// \brief Returns true if the node is in the barrier
617 617
    ///
618 618
    /// The barrier is a subset of the nodes. If the nodes in the
619 619
    /// barrier have less adjacent nodes than the size of the barrier,
620 620
    /// then at least as much nodes cannot be covered as the
621 621
    /// difference of the two subsets.
622 622
    bool barrier(const Node& node) const {
623 623
      return (*_level)[node] >= _empty_level;
624 624
    }
625 625

	
626 626
    /// @}
627 627

	
628 628
  };
629 629

	
630 630
  /// \ingroup matching
631 631
  ///
632 632
  /// \brief Weighted fractional matching in general graphs
633 633
  ///
634 634
  /// This class provides an efficient implementation of fractional
635 635
  /// matching algorithm. The implementation uses priority queues and
636 636
  /// provides \f$O(nm\log n)\f$ time complexity.
637 637
  ///
638 638
  /// The maximum weighted fractional matching is a relaxation of the
639 639
  /// maximum weighted matching problem where the odd set constraints
640 640
  /// are omitted.
641 641
  /// It can be formulated with the following linear program.
642 642
  /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
643 643
  /// \f[x_e \ge 0\quad \forall e\in E\f]
644 644
  /// \f[\max \sum_{e\in E}x_ew_e\f]
645 645
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
646 646
  /// \f$X\f$. The result must be the union of a matching with one
647 647
  /// value edges and a set of odd length cycles with half value edges.
648 648
  ///
649 649
  /// The algorithm calculates an optimal fractional matching and a
650 650
  /// proof of the optimality. The solution of the dual problem can be
651 651
  /// used to check the result of the algorithm. The dual linear
652 652
  /// problem is the following.
653 653
  /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
654 654
  /// \f[y_u \ge 0 \quad \forall u \in V\f]
655 655
  /// \f[\min \sum_{u \in V}y_u \f]
656 656
  ///
657 657
  /// The algorithm can be executed with the run() function.
658 658
  /// After it the matching (the primal solution) and the dual solution
659 659
  /// can be obtained using the query functions.
660 660
  ///
661
  /// If the value type is integer, then the primal and the dual
662
  /// solutions are multiplied by
663
  /// \ref MaxWeightedFractionalMatching::primalScale "2" and
664
  /// \ref MaxWeightedFractionalMatching::dualScale "4" respectively.
661
  /// The primal solution is multiplied by
662
  /// \ref MaxWeightedFractionalMatching::primalScale "2".
663
  /// If the value type is integer, then the dual
664
  /// solution is scaled by
665
  /// \ref MaxWeightedFractionalMatching::dualScale "4".
665 666
  ///
666 667
  /// \tparam GR The undirected graph type the algorithm runs on.
667 668
  /// \tparam WM The type edge weight map. The default type is
668 669
  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
669 670
#ifdef DOXYGEN
670 671
  template <typename GR, typename WM>
671 672
#else
672 673
  template <typename GR,
673 674
            typename WM = typename GR::template EdgeMap<int> >
674 675
#endif
675 676
  class MaxWeightedFractionalMatching {
676 677
  public:
677 678

	
678 679
    /// The graph type of the algorithm
679 680
    typedef GR Graph;
680 681
    /// The type of the edge weight map
681 682
    typedef WM WeightMap;
682 683
    /// The value type of the edge weights
683 684
    typedef typename WeightMap::Value Value;
684 685

	
685 686
    /// The type of the matching map
686 687
    typedef typename Graph::template NodeMap<typename Graph::Arc>
687 688
    MatchingMap;
688 689

	
689 690
    /// \brief Scaling factor for primal solution
690 691
    ///
691
    /// Scaling factor for primal solution. It is equal to 2 or 1
692
    /// according to the value type.
693
    static const int primalScale =
694
      std::numeric_limits<Value>::is_integer ? 2 : 1;
692
    /// Scaling factor for primal solution.
693
    static const int primalScale = 2;
695 694

	
696 695
    /// \brief Scaling factor for dual solution
697 696
    ///
698 697
    /// Scaling factor for dual solution. It is equal to 4 or 1
699 698
    /// according to the value type.
700 699
    static const int dualScale =
701 700
      std::numeric_limits<Value>::is_integer ? 4 : 1;
702 701

	
703 702
  private:
704 703

	
705 704
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
706 705

	
707 706
    typedef typename Graph::template NodeMap<Value> NodePotential;
708 707

	
709 708
    const Graph& _graph;
710 709
    const WeightMap& _weight;
711 710

	
712 711
    MatchingMap* _matching;
713 712
    NodePotential* _node_potential;
714 713

	
715 714
    int _node_num;
716 715
    bool _allow_loops;
717 716

	
718 717
    enum Status {
719 718
      EVEN = -1, MATCHED = 0, ODD = 1
720 719
    };
721 720

	
722 721
    typedef typename Graph::template NodeMap<Status> StatusMap;
723 722
    StatusMap* _status;
724 723

	
725 724
    typedef typename Graph::template NodeMap<Arc> PredMap;
726 725
    PredMap* _pred;
727 726

	
728 727
    typedef ExtendFindEnum<IntNodeMap> TreeSet;
729 728

	
730 729
    IntNodeMap *_tree_set_index;
731 730
    TreeSet *_tree_set;
732 731

	
733 732
    IntNodeMap *_delta1_index;
734 733
    BinHeap<Value, IntNodeMap> *_delta1;
735 734

	
736 735
    IntNodeMap *_delta2_index;
737 736
    BinHeap<Value, IntNodeMap> *_delta2;
738 737

	
739 738
    IntEdgeMap *_delta3_index;
740 739
    BinHeap<Value, IntEdgeMap> *_delta3;
741 740

	
742 741
    Value _delta_sum;
743 742

	
744 743
    void createStructures() {
745 744
      _node_num = countNodes(_graph);
746 745

	
747 746
      if (!_matching) {
748 747
        _matching = new MatchingMap(_graph);
749 748
      }
750 749
      if (!_node_potential) {
751 750
        _node_potential = new NodePotential(_graph);
752 751
      }
753 752
      if (!_status) {
754 753
        _status = new StatusMap(_graph);
755 754
      }
756 755
      if (!_pred) {
757 756
        _pred = new PredMap(_graph);
758 757
      }
759 758
      if (!_tree_set) {
760 759
        _tree_set_index = new IntNodeMap(_graph);
761 760
        _tree_set = new TreeSet(*_tree_set_index);
762 761
      }
763 762
      if (!_delta1) {
764 763
        _delta1_index = new IntNodeMap(_graph);
765 764
        _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
766 765
      }
767 766
      if (!_delta2) {
768 767
        _delta2_index = new IntNodeMap(_graph);
769 768
        _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
770 769
      }
771 770
      if (!_delta3) {
772 771
        _delta3_index = new IntEdgeMap(_graph);
773 772
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
774 773
      }
775 774
    }
776 775

	
777 776
    void destroyStructures() {
778 777
      if (_matching) {
779 778
        delete _matching;
780 779
      }
781 780
      if (_node_potential) {
782 781
        delete _node_potential;
783 782
      }
784 783
      if (_status) {
785 784
        delete _status;
786 785
      }
787 786
      if (_pred) {
788 787
        delete _pred;
789 788
      }
790 789
      if (_tree_set) {
791 790
        delete _tree_set_index;
792 791
        delete _tree_set;
793 792
      }
794 793
      if (_delta1) {
795 794
        delete _delta1_index;
796 795
        delete _delta1;
797 796
      }
798 797
      if (_delta2) {
799 798
        delete _delta2_index;
800 799
        delete _delta2;
801 800
      }
802 801
      if (_delta3) {
803 802
        delete _delta3_index;
804 803
        delete _delta3;
805 804
      }
806 805
    }
807 806

	
808 807
    void matchedToEven(Node node, int tree) {
809 808
      _tree_set->insert(node, tree);
810 809
      _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
811 810
      _delta1->push(node, (*_node_potential)[node]);
812 811

	
813 812
      if (_delta2->state(node) == _delta2->IN_HEAP) {
814 813
        _delta2->erase(node);
815 814
      }
816 815

	
817 816
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
818 817
        Node v = _graph.source(a);
819 818
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
820 819
          dualScale * _weight[a];
821 820
        if (node == v) {
822 821
          if (_allow_loops && _graph.direction(a)) {
823 822
            _delta3->push(a, rw / 2);
824 823
          }
825 824
        } else if ((*_status)[v] == EVEN) {
826 825
          _delta3->push(a, rw / 2);
827 826
        } else if ((*_status)[v] == MATCHED) {
828 827
          if (_delta2->state(v) != _delta2->IN_HEAP) {
829 828
            _pred->set(v, a);
830 829
            _delta2->push(v, rw);
831 830
          } else if ((*_delta2)[v] > rw) {
832 831
            _pred->set(v, a);
833 832
            _delta2->decrease(v, rw);
834 833
          }
835 834
        }
836 835
      }
837 836
    }
838 837

	
839 838
    void matchedToOdd(Node node, int tree) {
840 839
      _tree_set->insert(node, tree);
841 840
      _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
842 841

	
843 842
      if (_delta2->state(node) == _delta2->IN_HEAP) {
844 843
        _delta2->erase(node);
845 844
      }
846 845
    }
847 846

	
848 847
    void evenToMatched(Node node, int tree) {
849 848
      _delta1->erase(node);
850 849
      _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
851 850
      Arc min = INVALID;
852 851
      Value minrw = std::numeric_limits<Value>::max();
853 852
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
854 853
        Node v = _graph.source(a);
855 854
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
856 855
          dualScale * _weight[a];
857 856

	
858 857
        if (node == v) {
859 858
          if (_allow_loops && _graph.direction(a)) {
860 859
            _delta3->erase(a);
861 860
          }
862 861
        } else if ((*_status)[v] == EVEN) {
863 862
          _delta3->erase(a);
864 863
          if (minrw > rw) {
865 864
            min = _graph.oppositeArc(a);
866 865
            minrw = rw;
867 866
          }
868 867
        } else if ((*_status)[v]  == MATCHED) {
869 868
          if ((*_pred)[v] == a) {
870 869
            Arc mina = INVALID;
871 870
            Value minrwa = std::numeric_limits<Value>::max();
872 871
            for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
873 872
              Node va = _graph.target(aa);
874 873
              if ((*_status)[va] != EVEN ||
875 874
                  _tree_set->find(va) == tree) continue;
876 875
              Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
877 876
                dualScale * _weight[aa];
878 877
              if (minrwa > rwa) {
879 878
                minrwa = rwa;
880 879
                mina = aa;
881 880
              }
882 881
            }
883 882
            if (mina != INVALID) {
884 883
              _pred->set(v, mina);
885 884
              _delta2->increase(v, minrwa);
886 885
            } else {
887 886
              _pred->set(v, INVALID);
888 887
              _delta2->erase(v);
889 888
            }
890 889
          }
891 890
        }
892 891
      }
893 892
      if (min != INVALID) {
894 893
        _pred->set(node, min);
895 894
        _delta2->push(node, minrw);
896 895
      } else {
897 896
        _pred->set(node, INVALID);
898 897
      }
899 898
    }
900 899

	
901 900
    void oddToMatched(Node node) {
902 901
      _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
903 902
      Arc min = INVALID;
904 903
      Value minrw = std::numeric_limits<Value>::max();
905 904
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
906 905
        Node v = _graph.source(a);
907 906
        if ((*_status)[v] != EVEN) continue;
908 907
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
909 908
          dualScale * _weight[a];
910 909

	
911 910
        if (minrw > rw) {
912 911
          min = _graph.oppositeArc(a);
913 912
          minrw = rw;
914 913
        }
915 914
      }
916 915
      if (min != INVALID) {
917 916
        _pred->set(node, min);
918 917
        _delta2->push(node, minrw);
919 918
      } else {
920 919
        _pred->set(node, INVALID);
921 920
      }
922 921
    }
923 922

	
924 923
    void alternatePath(Node even, int tree) {
925 924
      Node odd;
926 925

	
927 926
      _status->set(even, MATCHED);
928 927
      evenToMatched(even, tree);
929 928

	
930 929
      Arc prev = (*_matching)[even];
931 930
      while (prev != INVALID) {
932 931
        odd = _graph.target(prev);
933 932
        even = _graph.target((*_pred)[odd]);
934 933
        _matching->set(odd, (*_pred)[odd]);
935 934
        _status->set(odd, MATCHED);
936 935
        oddToMatched(odd);
937 936

	
938 937
        prev = (*_matching)[even];
939 938
        _status->set(even, MATCHED);
940 939
        _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
941 940
        evenToMatched(even, tree);
942 941
      }
943 942
    }
944 943

	
945 944
    void destroyTree(int tree) {
946 945
      for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
947 946
        if ((*_status)[n] == EVEN) {
948 947
          _status->set(n, MATCHED);
949 948
          evenToMatched(n, tree);
950 949
        } else if ((*_status)[n] == ODD) {
951 950
          _status->set(n, MATCHED);
952 951
          oddToMatched(n);
953 952
        }
954 953
      }
955 954
      _tree_set->eraseClass(tree);
956 955
    }
957 956

	
958 957

	
959 958
    void unmatchNode(const Node& node) {
960 959
      int tree = _tree_set->find(node);
961 960

	
962 961
      alternatePath(node, tree);
963 962
      destroyTree(tree);
964 963

	
965 964
      _matching->set(node, INVALID);
966 965
    }
967 966

	
968 967

	
969 968
    void augmentOnEdge(const Edge& edge) {
970 969
      Node left = _graph.u(edge);
971 970
      int left_tree = _tree_set->find(left);
972 971

	
973 972
      alternatePath(left, left_tree);
974 973
      destroyTree(left_tree);
975 974
      _matching->set(left, _graph.direct(edge, true));
976 975

	
977 976
      Node right = _graph.v(edge);
978 977
      int right_tree = _tree_set->find(right);
979 978

	
980 979
      alternatePath(right, right_tree);
981 980
      destroyTree(right_tree);
982 981
      _matching->set(right, _graph.direct(edge, false));
983 982
    }
984 983

	
985 984
    void augmentOnArc(const Arc& arc) {
986 985
      Node left = _graph.source(arc);
987 986
      _status->set(left, MATCHED);
988 987
      _matching->set(left, arc);
989 988
      _pred->set(left, arc);
990 989

	
991 990
      Node right = _graph.target(arc);
992 991
      int right_tree = _tree_set->find(right);
993 992

	
994 993
      alternatePath(right, right_tree);
995 994
      destroyTree(right_tree);
996 995
      _matching->set(right, _graph.oppositeArc(arc));
997 996
    }
998 997

	
999 998
    void extendOnArc(const Arc& arc) {
1000 999
      Node base = _graph.target(arc);
1001 1000
      int tree = _tree_set->find(base);
1002 1001

	
1003 1002
      Node odd = _graph.source(arc);
1004 1003
      _tree_set->insert(odd, tree);
1005 1004
      _status->set(odd, ODD);
1006 1005
      matchedToOdd(odd, tree);
1007 1006
      _pred->set(odd, arc);
1008 1007

	
1009 1008
      Node even = _graph.target((*_matching)[odd]);
1010 1009
      _tree_set->insert(even, tree);
1011 1010
      _status->set(even, EVEN);
1012 1011
      matchedToEven(even, tree);
1013 1012
    }
1014 1013

	
1015 1014
    void cycleOnEdge(const Edge& edge, int tree) {
1016 1015
      Node nca = INVALID;
1017 1016
      std::vector<Node> left_path, right_path;
1018 1017

	
1019 1018
      {
1020 1019
        std::set<Node> left_set, right_set;
1021 1020
        Node left = _graph.u(edge);
1022 1021
        left_path.push_back(left);
1023 1022
        left_set.insert(left);
1024 1023

	
1025 1024
        Node right = _graph.v(edge);
1026 1025
        right_path.push_back(right);
1027 1026
        right_set.insert(right);
1028 1027

	
1029 1028
        while (true) {
1030 1029

	
1031 1030
          if (left_set.find(right) != left_set.end()) {
1032 1031
            nca = right;
1033 1032
            break;
1034 1033
          }
1035 1034

	
1036 1035
          if ((*_matching)[left] == INVALID) break;
1037 1036

	
1038 1037
          left = _graph.target((*_matching)[left]);
1039 1038
          left_path.push_back(left);
1040 1039
          left = _graph.target((*_pred)[left]);
1041 1040
          left_path.push_back(left);
1042 1041

	
1043 1042
          left_set.insert(left);
1044 1043

	
1045 1044
          if (right_set.find(left) != right_set.end()) {
1046 1045
            nca = left;
1047 1046
            break;
1048 1047
          }
1049 1048

	
1050 1049
          if ((*_matching)[right] == INVALID) break;
1051 1050

	
1052 1051
          right = _graph.target((*_matching)[right]);
1053 1052
          right_path.push_back(right);
1054 1053
          right = _graph.target((*_pred)[right]);
1055 1054
          right_path.push_back(right);
1056 1055

	
1057 1056
          right_set.insert(right);
1058 1057

	
1059 1058
        }
1060 1059

	
1061 1060
        if (nca == INVALID) {
1062 1061
          if ((*_matching)[left] == INVALID) {
1063 1062
            nca = right;
1064 1063
            while (left_set.find(nca) == left_set.end()) {
1065 1064
              nca = _graph.target((*_matching)[nca]);
1066 1065
              right_path.push_back(nca);
1067 1066
              nca = _graph.target((*_pred)[nca]);
1068 1067
              right_path.push_back(nca);
1069 1068
            }
1070 1069
          } else {
1071 1070
            nca = left;
1072 1071
            while (right_set.find(nca) == right_set.end()) {
1073 1072
              nca = _graph.target((*_matching)[nca]);
1074 1073
              left_path.push_back(nca);
1075 1074
              nca = _graph.target((*_pred)[nca]);
1076 1075
              left_path.push_back(nca);
1077 1076
            }
1078 1077
          }
1079 1078
        }
1080 1079
      }
1081 1080

	
1082 1081
      alternatePath(nca, tree);
1083 1082
      Arc prev;
1084 1083

	
1085 1084
      prev = _graph.direct(edge, true);
1086 1085
      for (int i = 0; left_path[i] != nca; i += 2) {
1087 1086
        _matching->set(left_path[i], prev);
1088 1087
        _status->set(left_path[i], MATCHED);
1089 1088
        evenToMatched(left_path[i], tree);
1090 1089

	
1091 1090
        prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
1092 1091
        _status->set(left_path[i + 1], MATCHED);
1093 1092
        oddToMatched(left_path[i + 1]);
1094 1093
      }
1095 1094
      _matching->set(nca, prev);
1096 1095

	
1097 1096
      for (int i = 0; right_path[i] != nca; i += 2) {
1098 1097
        _status->set(right_path[i], MATCHED);
1099 1098
        evenToMatched(right_path[i], tree);
1100 1099

	
1101 1100
        _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
1102 1101
        _status->set(right_path[i + 1], MATCHED);
1103 1102
        oddToMatched(right_path[i + 1]);
1104 1103
      }
1105 1104

	
1106 1105
      destroyTree(tree);
1107 1106
    }
1108 1107

	
1109 1108
    void extractCycle(const Arc &arc) {
1110 1109
      Node left = _graph.source(arc);
1111 1110
      Node odd = _graph.target((*_matching)[left]);
1112 1111
      Arc prev;
1113 1112
      while (odd != left) {
1114 1113
        Node even = _graph.target((*_matching)[odd]);
1115 1114
        prev = (*_matching)[odd];
1116 1115
        odd = _graph.target((*_matching)[even]);
1117 1116
        _matching->set(even, _graph.oppositeArc(prev));
1118 1117
      }
1119 1118
      _matching->set(left, arc);
1120 1119

	
1121 1120
      Node right = _graph.target(arc);
1122 1121
      int right_tree = _tree_set->find(right);
1123 1122
      alternatePath(right, right_tree);
1124 1123
      destroyTree(right_tree);
1125 1124
      _matching->set(right, _graph.oppositeArc(arc));
1126 1125
    }
1127 1126

	
1128 1127
  public:
1129 1128

	
1130 1129
    /// \brief Constructor
1131 1130
    ///
1132 1131
    /// Constructor.
1133 1132
    MaxWeightedFractionalMatching(const Graph& graph, const WeightMap& weight,
1134 1133
                                  bool allow_loops = true)
1135 1134
      : _graph(graph), _weight(weight), _matching(0),
1136 1135
      _node_potential(0), _node_num(0), _allow_loops(allow_loops),
1137 1136
      _status(0),  _pred(0),
1138 1137
      _tree_set_index(0), _tree_set(0),
1139 1138

	
1140 1139
      _delta1_index(0), _delta1(0),
1141 1140
      _delta2_index(0), _delta2(0),
1142 1141
      _delta3_index(0), _delta3(0),
1143 1142

	
1144 1143
      _delta_sum() {}
1145 1144

	
1146 1145
    ~MaxWeightedFractionalMatching() {
1147 1146
      destroyStructures();
1148 1147
    }
1149 1148

	
1150 1149
    /// \name Execution Control
1151 1150
    /// The simplest way to execute the algorithm is to use the
1152 1151
    /// \ref run() member function.
1153 1152

	
1154 1153
    ///@{
1155 1154

	
1156 1155
    /// \brief Initialize the algorithm
1157 1156
    ///
1158 1157
    /// This function initializes the algorithm.
1159 1158
    void init() {
1160 1159
      createStructures();
1161 1160

	
1162 1161
      for (NodeIt n(_graph); n != INVALID; ++n) {
1163 1162
        (*_delta1_index)[n] = _delta1->PRE_HEAP;
1164 1163
        (*_delta2_index)[n] = _delta2->PRE_HEAP;
1165 1164
      }
1166 1165
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1167 1166
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
1168 1167
      }
1169 1168

	
1170 1169
      for (NodeIt n(_graph); n != INVALID; ++n) {
1171 1170
        Value max = 0;
1172 1171
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1173 1172
          if (_graph.target(e) == n && !_allow_loops) continue;
1174 1173
          if ((dualScale * _weight[e]) / 2 > max) {
1175 1174
            max = (dualScale * _weight[e]) / 2;
1176 1175
          }
1177 1176
        }
1178 1177
        _node_potential->set(n, max);
1179 1178
        _delta1->push(n, max);
1180 1179

	
1181 1180
        _tree_set->insert(n);
1182 1181

	
1183 1182
        _matching->set(n, INVALID);
1184 1183
        _status->set(n, EVEN);
1185 1184
      }
1186 1185

	
1187 1186
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1188 1187
        Node left = _graph.u(e);
1189 1188
        Node right = _graph.v(e);
1190 1189
        if (left == right && !_allow_loops) continue;
1191 1190
        _delta3->push(e, ((*_node_potential)[left] +
1192 1191
                          (*_node_potential)[right] -
1193 1192
                          dualScale * _weight[e]) / 2);
1194 1193
      }
1195 1194
    }
1196 1195

	
1197 1196
    /// \brief Start the algorithm
1198 1197
    ///
1199 1198
    /// This function starts the algorithm.
1200 1199
    ///
1201 1200
    /// \pre \ref init() must be called before using this function.
1202 1201
    void start() {
1203 1202
      enum OpType {
1204 1203
        D1, D2, D3
1205 1204
      };
1206 1205

	
1207 1206
      int unmatched = _node_num;
1208 1207
      while (unmatched > 0) {
1209 1208
        Value d1 = !_delta1->empty() ?
1210 1209
          _delta1->prio() : std::numeric_limits<Value>::max();
1211 1210

	
1212 1211
        Value d2 = !_delta2->empty() ?
1213 1212
          _delta2->prio() : std::numeric_limits<Value>::max();
1214 1213

	
1215 1214
        Value d3 = !_delta3->empty() ?
1216 1215
          _delta3->prio() : std::numeric_limits<Value>::max();
1217 1216

	
1218 1217
        _delta_sum = d3; OpType ot = D3;
1219 1218
        if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1220 1219
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1221 1220

	
1222 1221
        switch (ot) {
1223 1222
        case D1:
1224 1223
          {
1225 1224
            Node n = _delta1->top();
1226 1225
            unmatchNode(n);
1227 1226
            --unmatched;
1228 1227
          }
1229 1228
          break;
1230 1229
        case D2:
1231 1230
          {
1232 1231
            Node n = _delta2->top();
1233 1232
            Arc a = (*_pred)[n];
1234 1233
            if ((*_matching)[n] == INVALID) {
1235 1234
              augmentOnArc(a);
1236 1235
              --unmatched;
1237 1236
            } else {
1238 1237
              Node v = _graph.target((*_matching)[n]);
1239 1238
              if ((*_matching)[n] !=
1240 1239
                  _graph.oppositeArc((*_matching)[v])) {
1241 1240
                extractCycle(a);
1242 1241
                --unmatched;
1243 1242
              } else {
1244 1243
                extendOnArc(a);
1245 1244
              }
1246 1245
            }
1247 1246
          } break;
1248 1247
        case D3:
1249 1248
          {
1250 1249
            Edge e = _delta3->top();
1251 1250

	
1252 1251
            Node left = _graph.u(e);
1253 1252
            Node right = _graph.v(e);
1254 1253

	
1255 1254
            int left_tree = _tree_set->find(left);
1256 1255
            int right_tree = _tree_set->find(right);
1257 1256

	
1258 1257
            if (left_tree == right_tree) {
1259 1258
              cycleOnEdge(e, left_tree);
1260 1259
              --unmatched;
1261 1260
            } else {
1262 1261
              augmentOnEdge(e);
1263 1262
              unmatched -= 2;
1264 1263
            }
1265 1264
          } break;
1266 1265
        }
1267 1266
      }
1268 1267
    }
1269 1268

	
1270 1269
    /// \brief Run the algorithm.
1271 1270
    ///
1272 1271
    /// This method runs the \c %MaxWeightedFractionalMatching algorithm.
1273 1272
    ///
1274 1273
    /// \note mwfm.run() is just a shortcut of the following code.
1275 1274
    /// \code
1276 1275
    ///   mwfm.init();
1277 1276
    ///   mwfm.start();
1278 1277
    /// \endcode
1279 1278
    void run() {
1280 1279
      init();
1281 1280
      start();
1282 1281
    }
1283 1282

	
1284 1283
    /// @}
1285 1284

	
1286 1285
    /// \name Primal Solution
1287 1286
    /// Functions to get the primal solution, i.e. the maximum weighted
1288 1287
    /// matching.\n
1289 1288
    /// Either \ref run() or \ref start() function should be called before
1290 1289
    /// using them.
1291 1290

	
1292 1291
    /// @{
1293 1292

	
1294 1293
    /// \brief Return the weight of the matching.
1295 1294
    ///
1296 1295
    /// This function returns the weight of the found matching. This
1297 1296
    /// value is scaled by \ref primalScale "primal scale".
1298 1297
    ///
1299 1298
    /// \pre Either run() or start() must be called before using this function.
1300 1299
    Value matchingWeight() const {
1301 1300
      Value sum = 0;
1302 1301
      for (NodeIt n(_graph); n != INVALID; ++n) {
1303 1302
        if ((*_matching)[n] != INVALID) {
1304 1303
          sum += _weight[(*_matching)[n]];
1305 1304
        }
1306 1305
      }
1307 1306
      return sum * primalScale / 2;
1308 1307
    }
1309 1308

	
1310 1309
    /// \brief Return the number of covered nodes in the matching.
1311 1310
    ///
1312 1311
    /// This function returns the number of covered nodes in the matching.
1313 1312
    ///
1314 1313
    /// \pre Either run() or start() must be called before using this function.
1315 1314
    int matchingSize() const {
1316 1315
      int num = 0;
1317 1316
      for (NodeIt n(_graph); n != INVALID; ++n) {
1318 1317
        if ((*_matching)[n] != INVALID) {
1319 1318
          ++num;
1320 1319
        }
1321 1320
      }
1322 1321
      return num;
1323 1322
    }
1324 1323

	
1325 1324
    /// \brief Return \c true if the given edge is in the matching.
1326 1325
    ///
1327 1326
    /// This function returns \c true if the given edge is in the
1328 1327
    /// found matching. The result is scaled by \ref primalScale
1329 1328
    /// "primal scale".
1330 1329
    ///
1331 1330
    /// \pre Either run() or start() must be called before using this function.
1332
    Value matching(const Edge& edge) const {
1333
      return Value(edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
1334
        * primalScale / 2 + Value(edge == (*_matching)[_graph.v(edge)] ? 1 : 0)
1335
        * primalScale / 2;
1331
    int matching(const Edge& edge) const {
1332
      return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
1333
        + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
1336 1334
    }
1337 1335

	
1338 1336
    /// \brief Return the fractional matching arc (or edge) incident
1339 1337
    /// to the given node.
1340 1338
    ///
1341 1339
    /// This function returns one of the fractional matching arc (or
1342 1340
    /// edge) incident to the given node in the found matching or \c
1343 1341
    /// INVALID if the node is not covered by the matching or if the
1344 1342
    /// node is on an odd length cycle then it is the successor edge
1345 1343
    /// on the cycle.
1346 1344
    ///
1347 1345
    /// \pre Either run() or start() must be called before using this function.
1348 1346
    Arc matching(const Node& node) const {
1349 1347
      return (*_matching)[node];
1350 1348
    }
1351 1349

	
1352 1350
    /// \brief Return a const reference to the matching map.
1353 1351
    ///
1354 1352
    /// This function returns a const reference to a node map that stores
1355 1353
    /// the matching arc (or edge) incident to each node.
1356 1354
    const MatchingMap& matchingMap() const {
1357 1355
      return *_matching;
1358 1356
    }
1359 1357

	
1360 1358
    /// @}
1361 1359

	
1362 1360
    /// \name Dual Solution
1363 1361
    /// Functions to get the dual solution.\n
1364 1362
    /// Either \ref run() or \ref start() function should be called before
1365 1363
    /// using them.
1366 1364

	
1367 1365
    /// @{
1368 1366

	
1369 1367
    /// \brief Return the value of the dual solution.
1370 1368
    ///
1371 1369
    /// This function returns the value of the dual solution.
1372 1370
    /// It should be equal to the primal value scaled by \ref dualScale
1373 1371
    /// "dual scale".
1374 1372
    ///
1375 1373
    /// \pre Either run() or start() must be called before using this function.
1376 1374
    Value dualValue() const {
1377 1375
      Value sum = 0;
1378 1376
      for (NodeIt n(_graph); n != INVALID; ++n) {
1379 1377
        sum += nodeValue(n);
1380 1378
      }
1381 1379
      return sum;
1382 1380
    }
1383 1381

	
1384 1382
    /// \brief Return the dual value (potential) of the given node.
1385 1383
    ///
1386 1384
    /// This function returns the dual value (potential) of the given node.
1387 1385
    ///
1388 1386
    /// \pre Either run() or start() must be called before using this function.
1389 1387
    Value nodeValue(const Node& n) const {
1390 1388
      return (*_node_potential)[n];
1391 1389
    }
1392 1390

	
1393 1391
    /// @}
1394 1392

	
1395 1393
  };
1396 1394

	
1397 1395
  /// \ingroup matching
1398 1396
  ///
1399 1397
  /// \brief Weighted fractional perfect matching in general graphs
1400 1398
  ///
1401 1399
  /// This class provides an efficient implementation of fractional
1402 1400
  /// matching algorithm. The implementation uses priority queues and
1403 1401
  /// provides \f$O(nm\log n)\f$ time complexity.
1404 1402
  ///
1405 1403
  /// The maximum weighted fractional perfect matching is a relaxation
1406 1404
  /// of the maximum weighted perfect matching problem where the odd
1407 1405
  /// set constraints are omitted.
1408 1406
  /// It can be formulated with the following linear program.
1409 1407
  /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
1410 1408
  /// \f[x_e \ge 0\quad \forall e\in E\f]
1411 1409
  /// \f[\max \sum_{e\in E}x_ew_e\f]
1412 1410
  /// where \f$\delta(X)\f$ is the set of edges incident to a node in
1413 1411
  /// \f$X\f$. The result must be the union of a matching with one
1414 1412
  /// value edges and a set of odd length cycles with half value edges.
1415 1413
  ///
1416 1414
  /// The algorithm calculates an optimal fractional matching and a
1417 1415
  /// proof of the optimality. The solution of the dual problem can be
1418 1416
  /// used to check the result of the algorithm. The dual linear
1419 1417
  /// problem is the following.
1420 1418
  /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
1421 1419
  /// \f[\min \sum_{u \in V}y_u \f]
1422 1420
  ///
1423 1421
  /// The algorithm can be executed with the run() function.
1424 1422
  /// After it the matching (the primal solution) and the dual solution
1425 1423
  /// can be obtained using the query functions.
1426

	
1427
  /// If the value type is integer, then the primal and the dual
1428
  /// solutions are multiplied by
1429
  /// \ref MaxWeightedPerfectFractionalMatching::primalScale "2" and
1430
  /// \ref MaxWeightedPerfectFractionalMatching::dualScale "4" respectively.
1424
  ///
1425
  /// The primal solution is multiplied by
1426
  /// \ref MaxWeightedPerfectFractionalMatching::primalScale "2".
1427
  /// If the value type is integer, then the dual
1428
  /// solution is scaled by
1429
  /// \ref MaxWeightedPerfectFractionalMatching::dualScale "4".
1431 1430
  ///
1432 1431
  /// \tparam GR The undirected graph type the algorithm runs on.
1433 1432
  /// \tparam WM The type edge weight map. The default type is
1434 1433
  /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
1435 1434
#ifdef DOXYGEN
1436 1435
  template <typename GR, typename WM>
1437 1436
#else
1438 1437
  template <typename GR,
1439 1438
            typename WM = typename GR::template EdgeMap<int> >
1440 1439
#endif
1441 1440
  class MaxWeightedPerfectFractionalMatching {
1442 1441
  public:
1443 1442

	
1444 1443
    /// The graph type of the algorithm
1445 1444
    typedef GR Graph;
1446 1445
    /// The type of the edge weight map
1447 1446
    typedef WM WeightMap;
1448 1447
    /// The value type of the edge weights
1449 1448
    typedef typename WeightMap::Value Value;
1450 1449

	
1451 1450
    /// The type of the matching map
1452 1451
    typedef typename Graph::template NodeMap<typename Graph::Arc>
1453 1452
    MatchingMap;
1454 1453

	
1455 1454
    /// \brief Scaling factor for primal solution
1456 1455
    ///
1457
    /// Scaling factor for primal solution. It is equal to 2 or 1
1458
    /// according to the value type.
1459
    static const int primalScale =
1460
      std::numeric_limits<Value>::is_integer ? 2 : 1;
1456
    /// Scaling factor for primal solution.
1457
    static const int primalScale = 2;
1461 1458

	
1462 1459
    /// \brief Scaling factor for dual solution
1463 1460
    ///
1464 1461
    /// Scaling factor for dual solution. It is equal to 4 or 1
1465 1462
    /// according to the value type.
1466 1463
    static const int dualScale =
1467 1464
      std::numeric_limits<Value>::is_integer ? 4 : 1;
1468 1465

	
1469 1466
  private:
1470 1467

	
1471 1468
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1472 1469

	
1473 1470
    typedef typename Graph::template NodeMap<Value> NodePotential;
1474 1471

	
1475 1472
    const Graph& _graph;
1476 1473
    const WeightMap& _weight;
1477 1474

	
1478 1475
    MatchingMap* _matching;
1479 1476
    NodePotential* _node_potential;
1480 1477

	
1481 1478
    int _node_num;
1482 1479
    bool _allow_loops;
1483 1480

	
1484 1481
    enum Status {
1485 1482
      EVEN = -1, MATCHED = 0, ODD = 1
1486 1483
    };
1487 1484

	
1488 1485
    typedef typename Graph::template NodeMap<Status> StatusMap;
1489 1486
    StatusMap* _status;
1490 1487

	
1491 1488
    typedef typename Graph::template NodeMap<Arc> PredMap;
1492 1489
    PredMap* _pred;
1493 1490

	
1494 1491
    typedef ExtendFindEnum<IntNodeMap> TreeSet;
1495 1492

	
1496 1493
    IntNodeMap *_tree_set_index;
1497 1494
    TreeSet *_tree_set;
1498 1495

	
1499 1496
    IntNodeMap *_delta2_index;
1500 1497
    BinHeap<Value, IntNodeMap> *_delta2;
1501 1498

	
1502 1499
    IntEdgeMap *_delta3_index;
1503 1500
    BinHeap<Value, IntEdgeMap> *_delta3;
1504 1501

	
1505 1502
    Value _delta_sum;
1506 1503

	
1507 1504
    void createStructures() {
1508 1505
      _node_num = countNodes(_graph);
1509 1506

	
1510 1507
      if (!_matching) {
1511 1508
        _matching = new MatchingMap(_graph);
1512 1509
      }
1513 1510
      if (!_node_potential) {
1514 1511
        _node_potential = new NodePotential(_graph);
1515 1512
      }
1516 1513
      if (!_status) {
1517 1514
        _status = new StatusMap(_graph);
1518 1515
      }
1519 1516
      if (!_pred) {
1520 1517
        _pred = new PredMap(_graph);
1521 1518
      }
1522 1519
      if (!_tree_set) {
1523 1520
        _tree_set_index = new IntNodeMap(_graph);
1524 1521
        _tree_set = new TreeSet(*_tree_set_index);
1525 1522
      }
1526 1523
      if (!_delta2) {
1527 1524
        _delta2_index = new IntNodeMap(_graph);
1528 1525
        _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
1529 1526
      }
1530 1527
      if (!_delta3) {
1531 1528
        _delta3_index = new IntEdgeMap(_graph);
1532 1529
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
1533 1530
      }
1534 1531
    }
1535 1532

	
1536 1533
    void destroyStructures() {
1537 1534
      if (_matching) {
1538 1535
        delete _matching;
1539 1536
      }
1540 1537
      if (_node_potential) {
1541 1538
        delete _node_potential;
1542 1539
      }
1543 1540
      if (_status) {
1544 1541
        delete _status;
1545 1542
      }
1546 1543
      if (_pred) {
1547 1544
        delete _pred;
1548 1545
      }
1549 1546
      if (_tree_set) {
1550 1547
        delete _tree_set_index;
1551 1548
        delete _tree_set;
1552 1549
      }
1553 1550
      if (_delta2) {
1554 1551
        delete _delta2_index;
1555 1552
        delete _delta2;
1556 1553
      }
1557 1554
      if (_delta3) {
1558 1555
        delete _delta3_index;
1559 1556
        delete _delta3;
1560 1557
      }
1561 1558
    }
1562 1559

	
1563 1560
    void matchedToEven(Node node, int tree) {
1564 1561
      _tree_set->insert(node, tree);
1565 1562
      _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
1566 1563

	
1567 1564
      if (_delta2->state(node) == _delta2->IN_HEAP) {
1568 1565
        _delta2->erase(node);
1569 1566
      }
1570 1567

	
1571 1568
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
1572 1569
        Node v = _graph.source(a);
1573 1570
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
1574 1571
          dualScale * _weight[a];
1575 1572
        if (node == v) {
1576 1573
          if (_allow_loops && _graph.direction(a)) {
1577 1574
            _delta3->push(a, rw / 2);
1578 1575
          }
1579 1576
        } else if ((*_status)[v] == EVEN) {
1580 1577
          _delta3->push(a, rw / 2);
1581 1578
        } else if ((*_status)[v] == MATCHED) {
1582 1579
          if (_delta2->state(v) != _delta2->IN_HEAP) {
1583 1580
            _pred->set(v, a);
1584 1581
            _delta2->push(v, rw);
1585 1582
          } else if ((*_delta2)[v] > rw) {
1586 1583
            _pred->set(v, a);
1587 1584
            _delta2->decrease(v, rw);
1588 1585
          }
1589 1586
        }
1590 1587
      }
1591 1588
    }
1592 1589

	
1593 1590
    void matchedToOdd(Node node, int tree) {
1594 1591
      _tree_set->insert(node, tree);
1595 1592
      _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
1596 1593

	
1597 1594
      if (_delta2->state(node) == _delta2->IN_HEAP) {
1598 1595
        _delta2->erase(node);
1599 1596
      }
1600 1597
    }
1601 1598

	
1602 1599
    void evenToMatched(Node node, int tree) {
1603 1600
      _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
1604 1601
      Arc min = INVALID;
1605 1602
      Value minrw = std::numeric_limits<Value>::max();
1606 1603
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
1607 1604
        Node v = _graph.source(a);
1608 1605
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
1609 1606
          dualScale * _weight[a];
1610 1607

	
1611 1608
        if (node == v) {
1612 1609
          if (_allow_loops && _graph.direction(a)) {
1613 1610
            _delta3->erase(a);
1614 1611
          }
1615 1612
        } else if ((*_status)[v] == EVEN) {
1616 1613
          _delta3->erase(a);
1617 1614
          if (minrw > rw) {
1618 1615
            min = _graph.oppositeArc(a);
1619 1616
            minrw = rw;
1620 1617
          }
1621 1618
        } else if ((*_status)[v]  == MATCHED) {
1622 1619
          if ((*_pred)[v] == a) {
1623 1620
            Arc mina = INVALID;
1624 1621
            Value minrwa = std::numeric_limits<Value>::max();
1625 1622
            for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
1626 1623
              Node va = _graph.target(aa);
1627 1624
              if ((*_status)[va] != EVEN ||
1628 1625
                  _tree_set->find(va) == tree) continue;
1629 1626
              Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
1630 1627
                dualScale * _weight[aa];
1631 1628
              if (minrwa > rwa) {
1632 1629
                minrwa = rwa;
1633 1630
                mina = aa;
1634 1631
              }
1635 1632
            }
1636 1633
            if (mina != INVALID) {
1637 1634
              _pred->set(v, mina);
1638 1635
              _delta2->increase(v, minrwa);
1639 1636
            } else {
1640 1637
              _pred->set(v, INVALID);
1641 1638
              _delta2->erase(v);
1642 1639
            }
1643 1640
          }
1644 1641
        }
1645 1642
      }
1646 1643
      if (min != INVALID) {
1647 1644
        _pred->set(node, min);
1648 1645
        _delta2->push(node, minrw);
1649 1646
      } else {
1650 1647
        _pred->set(node, INVALID);
1651 1648
      }
1652 1649
    }
1653 1650

	
1654 1651
    void oddToMatched(Node node) {
1655 1652
      _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
1656 1653
      Arc min = INVALID;
1657 1654
      Value minrw = std::numeric_limits<Value>::max();
1658 1655
      for (InArcIt a(_graph, node); a != INVALID; ++a) {
1659 1656
        Node v = _graph.source(a);
1660 1657
        if ((*_status)[v] != EVEN) continue;
1661 1658
        Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
1662 1659
          dualScale * _weight[a];
1663 1660

	
1664 1661
        if (minrw > rw) {
1665 1662
          min = _graph.oppositeArc(a);
1666 1663
          minrw = rw;
1667 1664
        }
1668 1665
      }
1669 1666
      if (min != INVALID) {
1670 1667
        _pred->set(node, min);
1671 1668
        _delta2->push(node, minrw);
1672 1669
      } else {
1673 1670
        _pred->set(node, INVALID);
1674 1671
      }
1675 1672
    }
1676 1673

	
1677 1674
    void alternatePath(Node even, int tree) {
1678 1675
      Node odd;
1679 1676

	
1680 1677
      _status->set(even, MATCHED);
1681 1678
      evenToMatched(even, tree);
1682 1679

	
1683 1680
      Arc prev = (*_matching)[even];
1684 1681
      while (prev != INVALID) {
1685 1682
        odd = _graph.target(prev);
1686 1683
        even = _graph.target((*_pred)[odd]);
1687 1684
        _matching->set(odd, (*_pred)[odd]);
1688 1685
        _status->set(odd, MATCHED);
1689 1686
        oddToMatched(odd);
1690 1687

	
1691 1688
        prev = (*_matching)[even];
1692 1689
        _status->set(even, MATCHED);
1693 1690
        _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
1694 1691
        evenToMatched(even, tree);
1695 1692
      }
1696 1693
    }
1697 1694

	
1698 1695
    void destroyTree(int tree) {
1699 1696
      for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
1700 1697
        if ((*_status)[n] == EVEN) {
1701 1698
          _status->set(n, MATCHED);
1702 1699
          evenToMatched(n, tree);
1703 1700
        } else if ((*_status)[n] == ODD) {
1704 1701
          _status->set(n, MATCHED);
1705 1702
          oddToMatched(n);
1706 1703
        }
1707 1704
      }
1708 1705
      _tree_set->eraseClass(tree);
1709 1706
    }
1710 1707

	
1711 1708
    void augmentOnEdge(const Edge& edge) {
1712 1709
      Node left = _graph.u(edge);
1713 1710
      int left_tree = _tree_set->find(left);
1714 1711

	
1715 1712
      alternatePath(left, left_tree);
1716 1713
      destroyTree(left_tree);
1717 1714
      _matching->set(left, _graph.direct(edge, true));
1718 1715

	
1719 1716
      Node right = _graph.v(edge);
1720 1717
      int right_tree = _tree_set->find(right);
1721 1718

	
1722 1719
      alternatePath(right, right_tree);
1723 1720
      destroyTree(right_tree);
1724 1721
      _matching->set(right, _graph.direct(edge, false));
1725 1722
    }
1726 1723

	
1727 1724
    void augmentOnArc(const Arc& arc) {
1728 1725
      Node left = _graph.source(arc);
1729 1726
      _status->set(left, MATCHED);
1730 1727
      _matching->set(left, arc);
1731 1728
      _pred->set(left, arc);
1732 1729

	
1733 1730
      Node right = _graph.target(arc);
1734 1731
      int right_tree = _tree_set->find(right);
1735 1732

	
1736 1733
      alternatePath(right, right_tree);
1737 1734
      destroyTree(right_tree);
1738 1735
      _matching->set(right, _graph.oppositeArc(arc));
1739 1736
    }
1740 1737

	
1741 1738
    void extendOnArc(const Arc& arc) {
1742 1739
      Node base = _graph.target(arc);
1743 1740
      int tree = _tree_set->find(base);
1744 1741

	
1745 1742
      Node odd = _graph.source(arc);
1746 1743
      _tree_set->insert(odd, tree);
1747 1744
      _status->set(odd, ODD);
1748 1745
      matchedToOdd(odd, tree);
1749 1746
      _pred->set(odd, arc);
1750 1747

	
1751 1748
      Node even = _graph.target((*_matching)[odd]);
1752 1749
      _tree_set->insert(even, tree);
1753 1750
      _status->set(even, EVEN);
1754 1751
      matchedToEven(even, tree);
1755 1752
    }
1756 1753

	
1757 1754
    void cycleOnEdge(const Edge& edge, int tree) {
1758 1755
      Node nca = INVALID;
1759 1756
      std::vector<Node> left_path, right_path;
1760 1757

	
1761 1758
      {
1762 1759
        std::set<Node> left_set, right_set;
1763 1760
        Node left = _graph.u(edge);
1764 1761
        left_path.push_back(left);
1765 1762
        left_set.insert(left);
1766 1763

	
1767 1764
        Node right = _graph.v(edge);
1768 1765
        right_path.push_back(right);
1769 1766
        right_set.insert(right);
1770 1767

	
1771 1768
        while (true) {
1772 1769

	
1773 1770
          if (left_set.find(right) != left_set.end()) {
1774 1771
            nca = right;
1775 1772
            break;
1776 1773
          }
1777 1774

	
1778 1775
          if ((*_matching)[left] == INVALID) break;
1779 1776

	
1780 1777
          left = _graph.target((*_matching)[left]);
1781 1778
          left_path.push_back(left);
1782 1779
          left = _graph.target((*_pred)[left]);
1783 1780
          left_path.push_back(left);
1784 1781

	
1785 1782
          left_set.insert(left);
1786 1783

	
1787 1784
          if (right_set.find(left) != right_set.end()) {
1788 1785
            nca = left;
1789 1786
            break;
1790 1787
          }
1791 1788

	
1792 1789
          if ((*_matching)[right] == INVALID) break;
1793 1790

	
1794 1791
          right = _graph.target((*_matching)[right]);
1795 1792
          right_path.push_back(right);
1796 1793
          right = _graph.target((*_pred)[right]);
1797 1794
          right_path.push_back(right);
1798 1795

	
1799 1796
          right_set.insert(right);
1800 1797

	
1801 1798
        }
1802 1799

	
1803 1800
        if (nca == INVALID) {
1804 1801
          if ((*_matching)[left] == INVALID) {
1805 1802
            nca = right;
1806 1803
            while (left_set.find(nca) == left_set.end()) {
1807 1804
              nca = _graph.target((*_matching)[nca]);
1808 1805
              right_path.push_back(nca);
1809 1806
              nca = _graph.target((*_pred)[nca]);
1810 1807
              right_path.push_back(nca);
1811 1808
            }
1812 1809
          } else {
1813 1810
            nca = left;
1814 1811
            while (right_set.find(nca) == right_set.end()) {
1815 1812
              nca = _graph.target((*_matching)[nca]);
1816 1813
              left_path.push_back(nca);
1817 1814
              nca = _graph.target((*_pred)[nca]);
1818 1815
              left_path.push_back(nca);
1819 1816
            }
1820 1817
          }
1821 1818
        }
1822 1819
      }
1823 1820

	
1824 1821
      alternatePath(nca, tree);
1825 1822
      Arc prev;
1826 1823

	
1827 1824
      prev = _graph.direct(edge, true);
1828 1825
      for (int i = 0; left_path[i] != nca; i += 2) {
1829 1826
        _matching->set(left_path[i], prev);
1830 1827
        _status->set(left_path[i], MATCHED);
1831 1828
        evenToMatched(left_path[i], tree);
1832 1829

	
1833 1830
        prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
1834 1831
        _status->set(left_path[i + 1], MATCHED);
1835 1832
        oddToMatched(left_path[i + 1]);
1836 1833
      }
1837 1834
      _matching->set(nca, prev);
1838 1835

	
1839 1836
      for (int i = 0; right_path[i] != nca; i += 2) {
1840 1837
        _status->set(right_path[i], MATCHED);
1841 1838
        evenToMatched(right_path[i], tree);
1842 1839

	
1843 1840
        _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
1844 1841
        _status->set(right_path[i + 1], MATCHED);
1845 1842
        oddToMatched(right_path[i + 1]);
1846 1843
      }
1847 1844

	
1848 1845
      destroyTree(tree);
1849 1846
    }
1850 1847

	
1851 1848
    void extractCycle(const Arc &arc) {
1852 1849
      Node left = _graph.source(arc);
1853 1850
      Node odd = _graph.target((*_matching)[left]);
1854 1851
      Arc prev;
1855 1852
      while (odd != left) {
1856 1853
        Node even = _graph.target((*_matching)[odd]);
1857 1854
        prev = (*_matching)[odd];
1858 1855
        odd = _graph.target((*_matching)[even]);
1859 1856
        _matching->set(even, _graph.oppositeArc(prev));
1860 1857
      }
1861 1858
      _matching->set(left, arc);
1862 1859

	
1863 1860
      Node right = _graph.target(arc);
1864 1861
      int right_tree = _tree_set->find(right);
1865 1862
      alternatePath(right, right_tree);
1866 1863
      destroyTree(right_tree);
1867 1864
      _matching->set(right, _graph.oppositeArc(arc));
1868 1865
    }
1869 1866

	
1870 1867
  public:
1871 1868

	
1872 1869
    /// \brief Constructor
1873 1870
    ///
1874 1871
    /// Constructor.
1875 1872
    MaxWeightedPerfectFractionalMatching(const Graph& graph,
1876 1873
                                         const WeightMap& weight,
1877 1874
                                         bool allow_loops = true)
1878 1875
      : _graph(graph), _weight(weight), _matching(0),
1879 1876
      _node_potential(0), _node_num(0), _allow_loops(allow_loops),
1880 1877
      _status(0),  _pred(0),
1881 1878
      _tree_set_index(0), _tree_set(0),
1882 1879

	
1883 1880
      _delta2_index(0), _delta2(0),
1884 1881
      _delta3_index(0), _delta3(0),
1885 1882

	
1886 1883
      _delta_sum() {}
1887 1884

	
1888 1885
    ~MaxWeightedPerfectFractionalMatching() {
1889 1886
      destroyStructures();
1890 1887
    }
1891 1888

	
1892 1889
    /// \name Execution Control
1893 1890
    /// The simplest way to execute the algorithm is to use the
1894 1891
    /// \ref run() member function.
1895 1892

	
1896 1893
    ///@{
1897 1894

	
1898 1895
    /// \brief Initialize the algorithm
1899 1896
    ///
1900 1897
    /// This function initializes the algorithm.
1901 1898
    void init() {
1902 1899
      createStructures();
1903 1900

	
1904 1901
      for (NodeIt n(_graph); n != INVALID; ++n) {
1905 1902
        (*_delta2_index)[n] = _delta2->PRE_HEAP;
1906 1903
      }
1907 1904
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1908 1905
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
1909 1906
      }
1910 1907

	
1911 1908
      for (NodeIt n(_graph); n != INVALID; ++n) {
1912 1909
        Value max = - std::numeric_limits<Value>::max();
1913 1910
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1914 1911
          if (_graph.target(e) == n && !_allow_loops) continue;
1915 1912
          if ((dualScale * _weight[e]) / 2 > max) {
1916 1913
            max = (dualScale * _weight[e]) / 2;
1917 1914
          }
1918 1915
        }
1919 1916
        _node_potential->set(n, max);
1920 1917

	
1921 1918
        _tree_set->insert(n);
1922 1919

	
1923 1920
        _matching->set(n, INVALID);
1924 1921
        _status->set(n, EVEN);
1925 1922
      }
1926 1923

	
1927 1924
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1928 1925
        Node left = _graph.u(e);
1929 1926
        Node right = _graph.v(e);
1930 1927
        if (left == right && !_allow_loops) continue;
1931 1928
        _delta3->push(e, ((*_node_potential)[left] +
1932 1929
                          (*_node_potential)[right] -
1933 1930
                          dualScale * _weight[e]) / 2);
1934 1931
      }
1935 1932
    }
1936 1933

	
1937 1934
    /// \brief Start the algorithm
1938 1935
    ///
1939 1936
    /// This function starts the algorithm.
1940 1937
    ///
1941 1938
    /// \pre \ref init() must be called before using this function.
1942 1939
    bool start() {
1943 1940
      enum OpType {
1944 1941
        D2, D3
1945 1942
      };
1946 1943

	
1947 1944
      int unmatched = _node_num;
1948 1945
      while (unmatched > 0) {
1949 1946
        Value d2 = !_delta2->empty() ?
1950 1947
          _delta2->prio() : std::numeric_limits<Value>::max();
1951 1948

	
1952 1949
        Value d3 = !_delta3->empty() ?
1953 1950
          _delta3->prio() : std::numeric_limits<Value>::max();
1954 1951

	
1955 1952
        _delta_sum = d3; OpType ot = D3;
1956 1953
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1957 1954

	
1958 1955
        if (_delta_sum == std::numeric_limits<Value>::max()) {
1959 1956
          return false;
1960 1957
        }
1961 1958

	
1962 1959
        switch (ot) {
1963 1960
        case D2:
1964 1961
          {
1965 1962
            Node n = _delta2->top();
1966 1963
            Arc a = (*_pred)[n];
1967 1964
            if ((*_matching)[n] == INVALID) {
1968 1965
              augmentOnArc(a);
1969 1966
              --unmatched;
1970 1967
            } else {
1971 1968
              Node v = _graph.target((*_matching)[n]);
1972 1969
              if ((*_matching)[n] !=
1973 1970
                  _graph.oppositeArc((*_matching)[v])) {
1974 1971
                extractCycle(a);
1975 1972
                --unmatched;
1976 1973
              } else {
1977 1974
                extendOnArc(a);
1978 1975
              }
1979 1976
            }
1980 1977
          } break;
1981 1978
        case D3:
1982 1979
          {
1983 1980
            Edge e = _delta3->top();
1984 1981

	
1985 1982
            Node left = _graph.u(e);
1986 1983
            Node right = _graph.v(e);
1987 1984

	
1988 1985
            int left_tree = _tree_set->find(left);
1989 1986
            int right_tree = _tree_set->find(right);
1990 1987

	
1991 1988
            if (left_tree == right_tree) {
1992 1989
              cycleOnEdge(e, left_tree);
1993 1990
              --unmatched;
1994 1991
            } else {
1995 1992
              augmentOnEdge(e);
1996 1993
              unmatched -= 2;
1997 1994
            }
1998 1995
          } break;
1999 1996
        }
2000 1997
      }
2001 1998
      return true;
2002 1999
    }
2003 2000

	
2004 2001
    /// \brief Run the algorithm.
2005 2002
    ///
2006 2003
    /// This method runs the \c %MaxWeightedPerfectFractionalMatching 
2007 2004
    /// algorithm.
2008 2005
    ///
2009 2006
    /// \note mwfm.run() is just a shortcut of the following code.
2010 2007
    /// \code
2011 2008
    ///   mwpfm.init();
2012 2009
    ///   mwpfm.start();
2013 2010
    /// \endcode
2014 2011
    bool run() {
2015 2012
      init();
2016 2013
      return start();
2017 2014
    }
2018 2015

	
2019 2016
    /// @}
2020 2017

	
2021 2018
    /// \name Primal Solution
2022 2019
    /// Functions to get the primal solution, i.e. the maximum weighted
2023 2020
    /// matching.\n
2024 2021
    /// Either \ref run() or \ref start() function should be called before
2025 2022
    /// using them.
2026 2023

	
2027 2024
    /// @{
2028 2025

	
2029 2026
    /// \brief Return the weight of the matching.
2030 2027
    ///
2031 2028
    /// This function returns the weight of the found matching. This
2032 2029
    /// value is scaled by \ref primalScale "primal scale".
2033 2030
    ///
2034 2031
    /// \pre Either run() or start() must be called before using this function.
2035 2032
    Value matchingWeight() const {
2036 2033
      Value sum = 0;
2037 2034
      for (NodeIt n(_graph); n != INVALID; ++n) {
2038 2035
        if ((*_matching)[n] != INVALID) {
2039 2036
          sum += _weight[(*_matching)[n]];
2040 2037
        }
2041 2038
      }
2042 2039
      return sum * primalScale / 2;
2043 2040
    }
2044 2041

	
2045 2042
    /// \brief Return the number of covered nodes in the matching.
2046 2043
    ///
2047 2044
    /// This function returns the number of covered nodes in the matching.
2048 2045
    ///
2049 2046
    /// \pre Either run() or start() must be called before using this function.
2050 2047
    int matchingSize() const {
2051 2048
      int num = 0;
2052 2049
      for (NodeIt n(_graph); n != INVALID; ++n) {
2053 2050
        if ((*_matching)[n] != INVALID) {
2054 2051
          ++num;
2055 2052
        }
2056 2053
      }
2057 2054
      return num;
2058 2055
    }
2059 2056

	
2060 2057
    /// \brief Return \c true if the given edge is in the matching.
2061 2058
    ///
2062 2059
    /// This function returns \c true if the given edge is in the
2063 2060
    /// found matching. The result is scaled by \ref primalScale
2064 2061
    /// "primal scale".
2065 2062
    ///
2066 2063
    /// \pre Either run() or start() must be called before using this function.
2067
    Value matching(const Edge& edge) const {
2068
      return Value(edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
2069
        * primalScale / 2 + Value(edge == (*_matching)[_graph.v(edge)] ? 1 : 0)
2070
        * primalScale / 2;
2064
    int matching(const Edge& edge) const {
2065
      return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
2066
        + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
2071 2067
    }
2072 2068

	
2073 2069
    /// \brief Return the fractional matching arc (or edge) incident
2074 2070
    /// to the given node.
2075 2071
    ///
2076 2072
    /// This function returns one of the fractional matching arc (or
2077 2073
    /// edge) incident to the given node in the found matching or \c
2078 2074
    /// INVALID if the node is not covered by the matching or if the
2079 2075
    /// node is on an odd length cycle then it is the successor edge
2080 2076
    /// on the cycle.
2081 2077
    ///
2082 2078
    /// \pre Either run() or start() must be called before using this function.
2083 2079
    Arc matching(const Node& node) const {
2084 2080
      return (*_matching)[node];
2085 2081
    }
2086 2082

	
2087 2083
    /// \brief Return a const reference to the matching map.
2088 2084
    ///
2089 2085
    /// This function returns a const reference to a node map that stores
2090 2086
    /// the matching arc (or edge) incident to each node.
2091 2087
    const MatchingMap& matchingMap() const {
2092 2088
      return *_matching;
2093 2089
    }
2094 2090

	
2095 2091
    /// @}
2096 2092

	
2097 2093
    /// \name Dual Solution
2098 2094
    /// Functions to get the dual solution.\n
2099 2095
    /// Either \ref run() or \ref start() function should be called before
2100 2096
    /// using them.
2101 2097

	
2102 2098
    /// @{
2103 2099

	
2104 2100
    /// \brief Return the value of the dual solution.
2105 2101
    ///
2106 2102
    /// This function returns the value of the dual solution.
2107 2103
    /// It should be equal to the primal value scaled by \ref dualScale
2108 2104
    /// "dual scale".
2109 2105
    ///
2110 2106
    /// \pre Either run() or start() must be called before using this function.
2111 2107
    Value dualValue() const {
2112 2108
      Value sum = 0;
2113 2109
      for (NodeIt n(_graph); n != INVALID; ++n) {
2114 2110
        sum += nodeValue(n);
2115 2111
      }
2116 2112
      return sum;
2117 2113
    }
2118 2114

	
2119 2115
    /// \brief Return the dual value (potential) of the given node.
2120 2116
    ///
2121 2117
    /// This function returns the dual value (potential) of the given node.
2122 2118
    ///
2123 2119
    /// \pre Either run() or start() must be called before using this function.
2124 2120
    Value nodeValue(const Node& n) const {
2125 2121
      return (*_node_potential)[n];
2126 2122
    }
2127 2123

	
2128 2124
    /// @}
2129 2125

	
2130 2126
  };
2131 2127

	
2132 2128
} //END OF NAMESPACE LEMON
2133 2129

	
2134 2130
#endif //LEMON_FRACTIONAL_MATCHING_H
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#include <iostream>
20 20
#include <sstream>
21 21
#include <vector>
22 22
#include <queue>
23 23
#include <cstdlib>
24 24

	
25 25
#include <lemon/fractional_matching.h>
26 26
#include <lemon/smart_graph.h>
27 27
#include <lemon/concepts/graph.h>
28 28
#include <lemon/concepts/maps.h>
29 29
#include <lemon/lgf_reader.h>
30 30
#include <lemon/math.h>
31 31

	
32 32
#include "test_tools.h"
33 33

	
34 34
using namespace std;
35 35
using namespace lemon;
36 36

	
37 37
GRAPH_TYPEDEFS(SmartGraph);
38 38

	
39 39

	
40 40
const int lgfn = 4;
41 41
const std::string lgf[lgfn] = {
42 42
  "@nodes\n"
43 43
  "label\n"
44 44
  "0\n"
45 45
  "1\n"
46 46
  "2\n"
47 47
  "3\n"
48 48
  "4\n"
49 49
  "5\n"
50 50
  "6\n"
51 51
  "7\n"
52 52
  "@edges\n"
53 53
  "     label  weight\n"
54 54
  "7 4  0      984\n"
55 55
  "0 7  1      73\n"
56 56
  "7 1  2      204\n"
57 57
  "2 3  3      583\n"
58 58
  "2 7  4      565\n"
59 59
  "2 1  5      582\n"
60 60
  "0 4  6      551\n"
61 61
  "2 5  7      385\n"
62 62
  "1 5  8      561\n"
63 63
  "5 3  9      484\n"
64 64
  "7 5  10     904\n"
65 65
  "3 6  11     47\n"
66 66
  "7 6  12     888\n"
67 67
  "3 0  13     747\n"
68 68
  "6 1  14     310\n",
69 69

	
70 70
  "@nodes\n"
71 71
  "label\n"
72 72
  "0\n"
73 73
  "1\n"
74 74
  "2\n"
75 75
  "3\n"
76 76
  "4\n"
77 77
  "5\n"
78 78
  "6\n"
79 79
  "7\n"
80 80
  "@edges\n"
81 81
  "     label  weight\n"
82 82
  "2 5  0      710\n"
83 83
  "0 5  1      241\n"
84 84
  "2 4  2      856\n"
85 85
  "2 6  3      762\n"
86 86
  "4 1  4      747\n"
87 87
  "6 1  5      962\n"
88 88
  "4 7  6      723\n"
89 89
  "1 7  7      661\n"
90 90
  "2 3  8      376\n"
91 91
  "1 0  9      416\n"
92 92
  "6 7  10     391\n",
93 93

	
94 94
  "@nodes\n"
95 95
  "label\n"
96 96
  "0\n"
97 97
  "1\n"
98 98
  "2\n"
99 99
  "3\n"
100 100
  "4\n"
101 101
  "5\n"
102 102
  "6\n"
103 103
  "7\n"
104 104
  "@edges\n"
105 105
  "     label  weight\n"
106 106
  "6 2  0      553\n"
107 107
  "0 7  1      653\n"
108 108
  "6 3  2      22\n"
109 109
  "4 7  3      846\n"
110 110
  "7 2  4      981\n"
111 111
  "7 6  5      250\n"
112 112
  "5 2  6      539\n",
113 113

	
114 114
  "@nodes\n"
115 115
  "label\n"
116 116
  "0\n"
117 117
  "@edges\n"
118 118
  "     label  weight\n"
119 119
  "0 0  0      100\n"
120 120
};
121 121

	
122 122
void checkMaxFractionalMatchingCompile()
123 123
{
124 124
  typedef concepts::Graph Graph;
125 125
  typedef Graph::Node Node;
126 126
  typedef Graph::Edge Edge;
127 127

	
128 128
  Graph g;
129 129
  Node n;
130 130
  Edge e;
131 131

	
132 132
  MaxFractionalMatching<Graph> mat_test(g);
133 133
  const MaxFractionalMatching<Graph>&
134 134
    const_mat_test = mat_test;
135 135

	
136 136
  mat_test.init();
137 137
  mat_test.start();
138 138
  mat_test.start(true);
139 139
  mat_test.startPerfect();
140 140
  mat_test.startPerfect(true);
141 141
  mat_test.run();
142 142
  mat_test.run(true);
143 143
  mat_test.runPerfect();
144 144
  mat_test.runPerfect(true);
145 145

	
146 146
  const_mat_test.matchingSize();
147 147
  const_mat_test.matching(e);
148 148
  const_mat_test.matching(n);
149 149
  const MaxFractionalMatching<Graph>::MatchingMap& mmap =
150 150
    const_mat_test.matchingMap();
151 151
  e = mmap[n];
152 152

	
153 153
  const_mat_test.barrier(n);
154 154
}
155 155

	
156 156
void checkMaxWeightedFractionalMatchingCompile()
157 157
{
158 158
  typedef concepts::Graph Graph;
159 159
  typedef Graph::Node Node;
160 160
  typedef Graph::Edge Edge;
161 161
  typedef Graph::EdgeMap<int> WeightMap;
162 162

	
163 163
  Graph g;
164 164
  Node n;
165 165
  Edge e;
166 166
  WeightMap w(g);
167 167

	
168 168
  MaxWeightedFractionalMatching<Graph> mat_test(g, w);
169 169
  const MaxWeightedFractionalMatching<Graph>&
170 170
    const_mat_test = mat_test;
171 171

	
172 172
  mat_test.init();
173 173
  mat_test.start();
174 174
  mat_test.run();
175 175

	
176 176
  const_mat_test.matchingWeight();
177 177
  const_mat_test.matchingSize();
178 178
  const_mat_test.matching(e);
179 179
  const_mat_test.matching(n);
180 180
  const MaxWeightedFractionalMatching<Graph>::MatchingMap& mmap =
181 181
    const_mat_test.matchingMap();
182 182
  e = mmap[n];
183 183

	
184 184
  const_mat_test.dualValue();
185 185
  const_mat_test.nodeValue(n);
186 186
}
187 187

	
188 188
void checkMaxWeightedPerfectFractionalMatchingCompile()
189 189
{
190 190
  typedef concepts::Graph Graph;
191 191
  typedef Graph::Node Node;
192 192
  typedef Graph::Edge Edge;
193 193
  typedef Graph::EdgeMap<int> WeightMap;
194 194

	
195 195
  Graph g;
196 196
  Node n;
197 197
  Edge e;
198 198
  WeightMap w(g);
199 199

	
200 200
  MaxWeightedPerfectFractionalMatching<Graph> mat_test(g, w);
201 201
  const MaxWeightedPerfectFractionalMatching<Graph>&
202 202
    const_mat_test = mat_test;
203 203

	
204 204
  mat_test.init();
205 205
  mat_test.start();
206 206
  mat_test.run();
207 207

	
208 208
  const_mat_test.matchingWeight();
209 209
  const_mat_test.matching(e);
210 210
  const_mat_test.matching(n);
211 211
  const MaxWeightedPerfectFractionalMatching<Graph>::MatchingMap& mmap =
212 212
    const_mat_test.matchingMap();
213 213
  e = mmap[n];
214 214

	
215 215
  const_mat_test.dualValue();
216 216
  const_mat_test.nodeValue(n);
217 217
}
218 218

	
219 219
void checkFractionalMatching(const SmartGraph& graph,
220 220
                             const MaxFractionalMatching<SmartGraph>& mfm,
221 221
                             bool allow_loops = true) {
222 222
  int pv = 0;
223 223
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
224 224
    int indeg = 0;
225 225
    for (InArcIt a(graph, n); a != INVALID; ++a) {
226 226
      if (mfm.matching(graph.source(a)) == a) {
227 227
        ++indeg;
228 228
      }
229 229
    }
230 230
    if (mfm.matching(n) != INVALID) {
231 231
      check(indeg == 1, "Invalid matching");
232 232
      ++pv;
233 233
    } else {
234 234
      check(indeg == 0, "Invalid matching");
235 235
    }
236 236
  }
237 237
  check(pv == mfm.matchingSize(), "Wrong matching size");
238 238

	
239
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
240
    check((e == mfm.matching(graph.u(e)) ? 1 : 0) +
241
          (e == mfm.matching(graph.v(e)) ? 1 : 0) == 
242
          mfm.matching(e), "Invalid matching");
243
  }
244

	
239 245
  SmartGraph::NodeMap<bool> processed(graph, false);
240 246
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
241 247
    if (processed[n]) continue;
242 248
    processed[n] = true;
243 249
    if (mfm.matching(n) == INVALID) continue;
244 250
    int num = 1;
245 251
    Node v = graph.target(mfm.matching(n));
246 252
    while (v != n) {
247 253
      processed[v] = true;
248 254
      ++num;
249 255
      v = graph.target(mfm.matching(v));
250 256
    }
251 257
    check(num == 2 || num % 2 == 1, "Wrong cycle size");
252 258
    check(allow_loops || num != 1, "Wrong cycle size");
253 259
  }
254 260

	
255 261
  int anum = 0, bnum = 0;
256 262
  SmartGraph::NodeMap<bool> neighbours(graph, false);
257 263
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
258 264
    if (!mfm.barrier(n)) continue;
259 265
    ++anum;
260 266
    for (SmartGraph::InArcIt a(graph, n); a != INVALID; ++a) {
261 267
      Node u = graph.source(a);
262 268
      if (!allow_loops && u == n) continue;
263 269
      if (!neighbours[u]) {
264 270
        neighbours[u] = true;
265 271
        ++bnum;
266 272
      }
267 273
    }
268 274
  }
269 275
  check(anum - bnum + mfm.matchingSize() == countNodes(graph),
270 276
        "Wrong barrier");
271 277
}
272 278

	
273 279
void checkPerfectFractionalMatching(const SmartGraph& graph,
274 280
                             const MaxFractionalMatching<SmartGraph>& mfm,
275 281
                             bool perfect, bool allow_loops = true) {
276 282
  if (perfect) {
277 283
    for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
278 284
      int indeg = 0;
279 285
      for (InArcIt a(graph, n); a != INVALID; ++a) {
280 286
        if (mfm.matching(graph.source(a)) == a) {
281 287
          ++indeg;
282 288
        }
283 289
      }
284 290
      check(mfm.matching(n) != INVALID, "Invalid matching");
285 291
      check(indeg == 1, "Invalid matching");
286 292
    }
293
    for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
294
      check((e == mfm.matching(graph.u(e)) ? 1 : 0) +
295
            (e == mfm.matching(graph.v(e)) ? 1 : 0) == 
296
            mfm.matching(e), "Invalid matching");
297
    }
287 298
  } else {
288 299
    int anum = 0, bnum = 0;
289 300
    SmartGraph::NodeMap<bool> neighbours(graph, false);
290 301
    for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
291 302
      if (!mfm.barrier(n)) continue;
292 303
      ++anum;
293 304
      for (SmartGraph::InArcIt a(graph, n); a != INVALID; ++a) {
294 305
        Node u = graph.source(a);
295 306
        if (!allow_loops && u == n) continue;
296 307
        if (!neighbours[u]) {
297 308
          neighbours[u] = true;
298 309
          ++bnum;
299 310
        }
300 311
      }
301 312
    }
302 313
    check(anum - bnum > 0, "Wrong barrier");
303 314
  }
304 315
}
305 316

	
306 317
void checkWeightedFractionalMatching(const SmartGraph& graph,
307 318
                   const SmartGraph::EdgeMap<int>& weight,
308 319
                   const MaxWeightedFractionalMatching<SmartGraph>& mwfm,
309 320
                   bool allow_loops = true) {
310 321
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
311 322
    if (graph.u(e) == graph.v(e) && !allow_loops) continue;
312 323
    int rw = mwfm.nodeValue(graph.u(e)) + mwfm.nodeValue(graph.v(e))
313 324
      - weight[e] * mwfm.dualScale;
314 325

	
315 326
    check(rw >= 0, "Negative reduced weight");
316 327
    check(rw == 0 || !mwfm.matching(e),
317 328
          "Non-zero reduced weight on matching edge");
318 329
  }
319 330

	
320 331
  int pv = 0;
321 332
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
322 333
    int indeg = 0;
323 334
    for (InArcIt a(graph, n); a != INVALID; ++a) {
324 335
      if (mwfm.matching(graph.source(a)) == a) {
325 336
        ++indeg;
326 337
      }
327 338
    }
328 339
    check(indeg <= 1, "Invalid matching");
329 340
    if (mwfm.matching(n) != INVALID) {
330 341
      check(mwfm.nodeValue(n) >= 0, "Invalid node value");
331 342
      check(indeg == 1, "Invalid matching");
332 343
      pv += weight[mwfm.matching(n)];
333 344
      SmartGraph::Node o = graph.target(mwfm.matching(n));
334 345
    } else {
335 346
      check(mwfm.nodeValue(n) == 0, "Invalid matching");
336 347
      check(indeg == 0, "Invalid matching");
337 348
    }
338 349
  }
339 350

	
351
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
352
    check((e == mwfm.matching(graph.u(e)) ? 1 : 0) +
353
          (e == mwfm.matching(graph.v(e)) ? 1 : 0) == 
354
          mwfm.matching(e), "Invalid matching");
355
  }
356

	
340 357
  int dv = 0;
341 358
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
342 359
    dv += mwfm.nodeValue(n);
343 360
  }
344 361

	
345 362
  check(pv * mwfm.dualScale == dv * 2, "Wrong duality");
346 363

	
347 364
  SmartGraph::NodeMap<bool> processed(graph, false);
348 365
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
349 366
    if (processed[n]) continue;
350 367
    processed[n] = true;
351 368
    if (mwfm.matching(n) == INVALID) continue;
352 369
    int num = 1;
353 370
    Node v = graph.target(mwfm.matching(n));
354 371
    while (v != n) {
355 372
      processed[v] = true;
356 373
      ++num;
357 374
      v = graph.target(mwfm.matching(v));
358 375
    }
359 376
    check(num == 2 || num % 2 == 1, "Wrong cycle size");
360 377
    check(allow_loops || num != 1, "Wrong cycle size");
361 378
  }
362 379

	
363 380
  return;
364 381
}
365 382

	
366 383
void checkWeightedPerfectFractionalMatching(const SmartGraph& graph,
367 384
                const SmartGraph::EdgeMap<int>& weight,
368 385
                const MaxWeightedPerfectFractionalMatching<SmartGraph>& mwpfm,
369 386
                bool allow_loops = true) {
370 387
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
371 388
    if (graph.u(e) == graph.v(e) && !allow_loops) continue;
372 389
    int rw = mwpfm.nodeValue(graph.u(e)) + mwpfm.nodeValue(graph.v(e))
373 390
      - weight[e] * mwpfm.dualScale;
374 391

	
375 392
    check(rw >= 0, "Negative reduced weight");
376 393
    check(rw == 0 || !mwpfm.matching(e),
377 394
          "Non-zero reduced weight on matching edge");
378 395
  }
379 396

	
380 397
  int pv = 0;
381 398
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
382 399
    int indeg = 0;
383 400
    for (InArcIt a(graph, n); a != INVALID; ++a) {
384 401
      if (mwpfm.matching(graph.source(a)) == a) {
385 402
        ++indeg;
386 403
      }
387 404
    }
388 405
    check(mwpfm.matching(n) != INVALID, "Invalid perfect matching");
389 406
    check(indeg == 1, "Invalid perfect matching");
390 407
    pv += weight[mwpfm.matching(n)];
391 408
    SmartGraph::Node o = graph.target(mwpfm.matching(n));
392 409
  }
393 410

	
411
  for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
412
    check((e == mwpfm.matching(graph.u(e)) ? 1 : 0) +
413
          (e == mwpfm.matching(graph.v(e)) ? 1 : 0) == 
414
          mwpfm.matching(e), "Invalid matching");
415
  }
416

	
394 417
  int dv = 0;
395 418
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
396 419
    dv += mwpfm.nodeValue(n);
397 420
  }
398 421

	
399 422
  check(pv * mwpfm.dualScale == dv * 2, "Wrong duality");
400 423

	
401 424
  SmartGraph::NodeMap<bool> processed(graph, false);
402 425
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
403 426
    if (processed[n]) continue;
404 427
    processed[n] = true;
405 428
    if (mwpfm.matching(n) == INVALID) continue;
406 429
    int num = 1;
407 430
    Node v = graph.target(mwpfm.matching(n));
408 431
    while (v != n) {
409 432
      processed[v] = true;
410 433
      ++num;
411 434
      v = graph.target(mwpfm.matching(v));
412 435
    }
413 436
    check(num == 2 || num % 2 == 1, "Wrong cycle size");
414 437
    check(allow_loops || num != 1, "Wrong cycle size");
415 438
  }
416 439

	
417 440
  return;
418 441
}
419 442

	
420 443

	
421 444
int main() {
422 445

	
423 446
  for (int i = 0; i < lgfn; ++i) {
424 447
    SmartGraph graph;
425 448
    SmartGraph::EdgeMap<int> weight(graph);
426 449

	
427 450
    istringstream lgfs(lgf[i]);
428 451
    graphReader(graph, lgfs).
429 452
      edgeMap("weight", weight).run();
430 453

	
431 454
    bool perfect_with_loops;
432 455
    {
433 456
      MaxFractionalMatching<SmartGraph> mfm(graph, true);
434 457
      mfm.run();
435 458
      checkFractionalMatching(graph, mfm, true);
436 459
      perfect_with_loops = mfm.matchingSize() == countNodes(graph);
437 460
    }
438 461

	
439 462
    bool perfect_without_loops;
440 463
    {
441 464
      MaxFractionalMatching<SmartGraph> mfm(graph, false);
442 465
      mfm.run();
443 466
      checkFractionalMatching(graph, mfm, false);
444 467
      perfect_without_loops = mfm.matchingSize() == countNodes(graph);
445 468
    }
446 469

	
447 470
    {
448 471
      MaxFractionalMatching<SmartGraph> mfm(graph, true);
449 472
      bool result = mfm.runPerfect();
450 473
      checkPerfectFractionalMatching(graph, mfm, result, true);
451 474
      check(result == perfect_with_loops, "Wrong perfect matching");
452 475
    }
453 476

	
454 477
    {
455 478
      MaxFractionalMatching<SmartGraph> mfm(graph, false);
456 479
      bool result = mfm.runPerfect();
457 480
      checkPerfectFractionalMatching(graph, mfm, result, false);
458 481
      check(result == perfect_without_loops, "Wrong perfect matching");
459 482
    }
460 483

	
461 484
    {
462 485
      MaxWeightedFractionalMatching<SmartGraph> mwfm(graph, weight, true);
463 486
      mwfm.run();
464 487
      checkWeightedFractionalMatching(graph, weight, mwfm, true);
465 488
    }
466 489

	
467 490
    {
468 491
      MaxWeightedFractionalMatching<SmartGraph> mwfm(graph, weight, false);
469 492
      mwfm.run();
470 493
      checkWeightedFractionalMatching(graph, weight, mwfm, false);
471 494
    }
472 495

	
473 496
    {
474 497
      MaxWeightedPerfectFractionalMatching<SmartGraph> mwpfm(graph, weight,
475 498
                                                             true);
476 499
      bool perfect = mwpfm.run();
477 500
      check(perfect == (mwpfm.matchingSize() == countNodes(graph)),
478 501
            "Perfect matching found");
479 502
      check(perfect == perfect_with_loops, "Wrong perfect matching");
480 503

	
481 504
      if (perfect) {
482 505
        checkWeightedPerfectFractionalMatching(graph, weight, mwpfm, true);
483 506
      }
484 507
    }
485 508

	
486 509
    {
487 510
      MaxWeightedPerfectFractionalMatching<SmartGraph> mwpfm(graph, weight,
488 511
                                                             false);
489 512
      bool perfect = mwpfm.run();
490 513
      check(perfect == (mwpfm.matchingSize() == countNodes(graph)),
491 514
            "Perfect matching found");
492 515
      check(perfect == perfect_without_loops, "Wrong perfect matching");
493 516

	
494 517
      if (perfect) {
495 518
        checkWeightedPerfectFractionalMatching(graph, weight, mwpfm, false);
496 519
      }
497 520
    }
498 521

	
499 522
  }
500 523

	
501 524
  return 0;
502 525
}
0 comments (0 inline)