test/bipartite_matching_test.cc
author deba
Fri, 14 Apr 2006 18:07:33 +0000
changeset 2051 08652c1763f6
parent 2040 c7bd55c0d820
child 2058 0b1fc1566fdb
permissions -rw-r--r--
MaxWeightedBipartiteMatching
MinCostMaxBipartiteMatching

Both algorithms are based on successive shortest
path algorithm with dijkstra shortest path
finding
deba@2040
     1
#include <cstdlib>
deba@2040
     2
#include <iostream>
deba@2040
     3
#include <sstream>
deba@2040
     4
deba@2040
     5
#include <lemon/list_graph.h>
deba@2040
     6
deba@2040
     7
#include <lemon/bpugraph_adaptor.h>
deba@2040
     8
#include <lemon/bipartite_matching.h>
deba@2040
     9
deba@2040
    10
#include <lemon/graph_utils.h>
deba@2040
    11
deba@2051
    12
#include <lemon/maps.h>
deba@2051
    13
deba@2040
    14
#include "test_tools.h"
deba@2040
    15
deba@2040
    16
using namespace std;
deba@2040
    17
using namespace lemon;
deba@2040
    18
deba@2040
    19
typedef ListBpUGraph Graph;
deba@2040
    20
BPUGRAPH_TYPEDEFS(Graph);
deba@2040
    21
deba@2040
    22
int main(int argc, const char *argv[]) {
deba@2040
    23
  Graph graph;
deba@2040
    24
  vector<Node> aNodes;
deba@2040
    25
  vector<Node> bNodes;
deba@2040
    26
  int n = argc > 1 ? atoi(argv[1]) : 100;
deba@2040
    27
  int m = argc > 2 ? atoi(argv[2]) : 100;
deba@2040
    28
  int e = argc > 3 ? atoi(argv[3]) : (int)((n+m) * log(n+m));
deba@2051
    29
  int c = argc > 4 ? atoi(argv[4]) : 100;
deba@2051
    30
deba@2051
    31
  Graph::UEdgeMap<int> weight(graph);
deba@2051
    32
deba@2051
    33
  int max_cardinality;
deba@2051
    34
  int max_weight;
deba@2051
    35
  int max_cardinality_max_weight;
deba@2040
    36
deba@2040
    37
  for (int i = 0; i < n; ++i) {
deba@2040
    38
    Node node = graph.addANode();
deba@2040
    39
    aNodes.push_back(node);
deba@2040
    40
  }
deba@2040
    41
  for (int i = 0; i < m; ++i) {
deba@2040
    42
    Node node = graph.addBNode();
deba@2040
    43
    bNodes.push_back(node);
deba@2040
    44
  }
deba@2040
    45
  for (int i = 0; i < e; ++i) {
deba@2040
    46
    Node aNode = aNodes[urandom(n)];
deba@2040
    47
    Node bNode = bNodes[urandom(m)];
deba@2051
    48
    UEdge uedge = graph.addEdge(aNode, bNode);
deba@2051
    49
    weight[uedge] = urandom(c);
deba@2040
    50
  }
deba@2040
    51
deba@2040
    52
  {
deba@2040
    53
    MaxBipartiteMatching<Graph> bpmatch(graph);
deba@2040
    54
deba@2040
    55
    bpmatch.run();
deba@2040
    56
deba@2040
    57
    Graph::UEdgeMap<bool> mm(graph);
deba@2040
    58
    Graph::NodeMap<bool> cs(graph);
deba@2040
    59
    
deba@2040
    60
    check(bpmatch.coverSet(cs) == bpmatch.matching(mm), "INVALID PRIMAL-DUAL");
deba@2040
    61
    
deba@2040
    62
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2040
    63
      check(cs[graph.aNode(it)] || cs[graph.bNode(it)], "INVALID DUAL");
deba@2040
    64
    }
deba@2040
    65
    
deba@2040
    66
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2040
    67
      int num = 0;
deba@2040
    68
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2040
    69
        if (mm[jt]) ++num;
deba@2051
    70
      }
deba@2040
    71
      check(num <= 1, "INVALID PRIMAL");
deba@2040
    72
    }
deba@2051
    73
    max_cardinality = bpmatch.matchingSize();
deba@2040
    74
  }
deba@2040
    75
deba@2040
    76
  {
deba@2040
    77
    MaxBipartiteMatching<Graph> bpmatch(graph);
deba@2040
    78
deba@2040
    79
    bpmatch.greedyInit();
deba@2040
    80
    bpmatch.start();
deba@2040
    81
deba@2040
    82
    Graph::UEdgeMap<bool> mm(graph);
deba@2040
    83
    Graph::NodeMap<bool> cs(graph);
deba@2040
    84
deba@2040
    85
    check(bpmatch.coverSet(cs) == bpmatch.matching(mm), "INVALID PRIMAL-DUAL");
deba@2040
    86
    
deba@2040
    87
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2040
    88
      check(cs[graph.aNode(it)] || cs[graph.bNode(it)], "INVALID DUAL");
deba@2040
    89
    }
deba@2040
    90
    
deba@2040
    91
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2040
    92
      int num = 0;
deba@2040
    93
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2040
    94
        if (mm[jt]) ++num;
deba@2040
    95
    }
deba@2040
    96
      check(num <= 1, "INVALID PRIMAL");
deba@2040
    97
    }
deba@2040
    98
  }
deba@2040
    99
deba@2040
   100
  {
deba@2040
   101
    MaxBipartiteMatching<Graph> bpmatch(graph);
deba@2040
   102
deba@2040
   103
    bpmatch.greedyInit();
deba@2040
   104
    while (bpmatch.simpleAugment());
deba@2040
   105
    
deba@2040
   106
    Graph::UEdgeMap<bool> mm(graph);
deba@2040
   107
    Graph::NodeMap<bool> cs(graph);
deba@2040
   108
    
deba@2040
   109
    check(bpmatch.coverSet(cs) == bpmatch.matching(mm), "INVALID PRIMAL-DUAL");
deba@2040
   110
    
deba@2040
   111
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2040
   112
      check(cs[graph.aNode(it)] || cs[graph.bNode(it)], "INVALID DUAL");
deba@2040
   113
    }
deba@2040
   114
    
deba@2040
   115
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2040
   116
      int num = 0;
deba@2040
   117
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2040
   118
        if (mm[jt]) ++num;
deba@2040
   119
    }
deba@2040
   120
      check(num <= 1, "INVALID PRIMAL");
deba@2040
   121
    }
deba@2040
   122
  }
deba@2040
   123
deba@2040
   124
  {
deba@2051
   125
    MaxWeightedBipartiteMatching<Graph> bpmatch(graph, weight);
deba@2051
   126
deba@2051
   127
    bpmatch.init();
deba@2051
   128
deba@2051
   129
    max_weight = 0;
deba@2051
   130
    while (bpmatch.augment(true)) {
deba@2051
   131
    
deba@2051
   132
      Graph::UEdgeMap<bool> mm(graph);
deba@2051
   133
      Graph::NodeMap<int> pm(graph);
deba@2051
   134
      
deba@2051
   135
      bpmatch.matching(mm);
deba@2051
   136
      bpmatch.potential(pm);
deba@2051
   137
      
deba@2051
   138
      for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2051
   139
        if (mm[it]) {
deba@2051
   140
          check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] == 0,
deba@2051
   141
                "INVALID DUAL");
deba@2051
   142
        } else {
deba@2051
   143
          check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] >= 0,
deba@2051
   144
                "INVALID DUAL");
deba@2051
   145
        }
deba@2051
   146
      }
deba@2051
   147
deba@2051
   148
      for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2051
   149
        int num = 0;
deba@2051
   150
        for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2051
   151
          if (mm[jt]) ++num;
deba@2051
   152
        }
deba@2051
   153
        check(num <= 1, "INVALID PRIMAL");
deba@2051
   154
      }
deba@2051
   155
      if (bpmatch.matchingValue() > max_weight) {
deba@2051
   156
        max_weight = bpmatch.matchingValue();
deba@2051
   157
      }
deba@2051
   158
    }
deba@2051
   159
  }
deba@2051
   160
deba@2051
   161
  {
deba@2051
   162
    MaxWeightedBipartiteMatching<Graph> bpmatch(graph, weight);
deba@2040
   163
deba@2040
   164
    bpmatch.run();
deba@2051
   165
    
deba@2051
   166
    Graph::UEdgeMap<bool> mm(graph);
deba@2051
   167
    Graph::NodeMap<int> pm(graph);
deba@2040
   168
deba@2051
   169
    bpmatch.matching(mm);
deba@2051
   170
    bpmatch.potential(pm);
deba@2040
   171
    
deba@2040
   172
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2051
   173
      if (mm[it]) {
deba@2051
   174
        check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] == 0,
deba@2051
   175
              "INVALID DUAL");
deba@2051
   176
      } else {
deba@2051
   177
        check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] >= 0,
deba@2051
   178
              "INVALID DUAL");
deba@2051
   179
      }
deba@2040
   180
    }
deba@2051
   181
deba@2040
   182
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2040
   183
      int num = 0;
deba@2040
   184
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2040
   185
        if (mm[jt]) ++num;
deba@2040
   186
    }
deba@2040
   187
      check(num <= 1, "INVALID PRIMAL");
deba@2040
   188
    }
deba@2051
   189
    check(max_weight == bpmatch.matchingValue(), "WRONG WEIGHT");
deba@2051
   190
  }
deba@2051
   191
deba@2051
   192
  {
deba@2051
   193
    MaxWeightedBipartiteMatching<Graph> bpmatch(graph, weight);
deba@2051
   194
deba@2051
   195
    bpmatch.run(true);
deba@2051
   196
    
deba@2051
   197
    Graph::UEdgeMap<bool> mm(graph);
deba@2051
   198
    Graph::NodeMap<int> pm(graph);
deba@2051
   199
deba@2051
   200
    bpmatch.matching(mm);
deba@2051
   201
    bpmatch.potential(pm);
deba@2051
   202
    
deba@2051
   203
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2051
   204
      if (mm[it]) {
deba@2051
   205
        check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] == 0,
deba@2051
   206
              "INVALID DUAL");
deba@2051
   207
      } else {
deba@2051
   208
        check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] >= 0,
deba@2051
   209
              "INVALID DUAL");
deba@2051
   210
      }
deba@2051
   211
    }
deba@2051
   212
deba@2051
   213
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2051
   214
      int num = 0;
deba@2051
   215
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2051
   216
        if (mm[jt]) ++num;
deba@2051
   217
    }
deba@2051
   218
      check(num <= 1, "INVALID PRIMAL");
deba@2051
   219
    }
deba@2051
   220
    check(max_cardinality == bpmatch.matchingSize(), "WRONG SIZE");
deba@2051
   221
    max_cardinality_max_weight = bpmatch.matchingValue();
deba@2051
   222
deba@2051
   223
  }
deba@2051
   224
deba@2051
   225
  {
deba@2051
   226
    Graph::UEdgeMap<int> cost(graph);
deba@2051
   227
deba@2051
   228
    cost = subMap(constMap<UEdge>(c), weight);
deba@2051
   229
deba@2051
   230
    MinCostMaxBipartiteMatching<Graph> bpmatch(graph, cost);
deba@2051
   231
deba@2051
   232
    bpmatch.run();
deba@2051
   233
    
deba@2051
   234
    Graph::UEdgeMap<bool> mm(graph);
deba@2051
   235
    Graph::NodeMap<int> pm(graph);
deba@2051
   236
deba@2051
   237
    bpmatch.matching(mm);
deba@2051
   238
    bpmatch.potential(pm);
deba@2051
   239
    
deba@2051
   240
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2051
   241
      if (mm[it]) {
deba@2051
   242
        check(pm[graph.aNode(it)] + cost[it] - pm[graph.bNode(it)] == 0,
deba@2051
   243
              "INVALID DUAL");
deba@2051
   244
      } else {
deba@2051
   245
        check(pm[graph.aNode(it)] + cost[it] - pm[graph.bNode(it)] >= 0,
deba@2051
   246
              "INVALID DUAL");
deba@2051
   247
      }
deba@2051
   248
    }
deba@2051
   249
deba@2051
   250
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2051
   251
      int num = 0;
deba@2051
   252
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2051
   253
        if (mm[jt]) ++num;
deba@2051
   254
    }
deba@2051
   255
      check(num <= 1, "INVALID PRIMAL");
deba@2051
   256
    }
deba@2051
   257
deba@2051
   258
    check(max_cardinality == bpmatch.matchingSize(), "WRONG SIZE");
deba@2051
   259
    check(max_cardinality * c - max_cardinality_max_weight 
deba@2051
   260
          == bpmatch.matchingCost(), "WRONG SIZE");
deba@2051
   261
deba@2040
   262
  }
deba@2040
   263
deba@2040
   264
  return 0;
deba@2040
   265
}