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 96 line context
... ...
@@ -613,130 +613,129 @@
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;
... ...
@@ -1284,225 +1283,223 @@
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);
... ...
@@ -2019,100 +2016,99 @@
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

	
Ignore white space 6 line context
... ...
@@ -191,251 +191,274 @@
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);
0 comments (0 inline)