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 24 line context
... ...
@@ -649,28 +649,29 @@
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:
... ...
@@ -679,28 +680,26 @@
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

	
... ...
@@ -1320,28 +1319,27 @@
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.
... ...
@@ -1414,29 +1412,30 @@
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:
... ...
@@ -1445,28 +1444,26 @@
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

	
... ...
@@ -2055,28 +2052,27 @@
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.
Ignore white space 6 line context
... ...
@@ -227,24 +227,30 @@
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
    }
... ...
@@ -275,24 +281,29 @@
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;
... ...
@@ -328,24 +339,30 @@
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;
... ...
@@ -382,24 +399,30 @@
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;
0 comments (0 inline)