test/bipartite_matching_test.cc
author deba
Wed, 28 Jun 2006 16:27:44 +0000
changeset 2114 677ea6c8169a
parent 2051 08652c1763f6
child 2115 4cd528a30ec1
permissions -rw-r--r--
new snapshot
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@2058
    26
  int n = argc > 1 ? atoi(argv[1]) : 10;
deba@2058
    27
  int m = argc > 2 ? atoi(argv[2]) : 10;
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@2058
    36
  int min_cost_matching;
deba@2040
    37
deba@2040
    38
  for (int i = 0; i < n; ++i) {
deba@2040
    39
    Node node = graph.addANode();
deba@2040
    40
    aNodes.push_back(node);
deba@2040
    41
  }
deba@2040
    42
  for (int i = 0; i < m; ++i) {
deba@2040
    43
    Node node = graph.addBNode();
deba@2040
    44
    bNodes.push_back(node);
deba@2040
    45
  }
deba@2040
    46
  for (int i = 0; i < e; ++i) {
deba@2040
    47
    Node aNode = aNodes[urandom(n)];
deba@2040
    48
    Node bNode = bNodes[urandom(m)];
deba@2051
    49
    UEdge uedge = graph.addEdge(aNode, bNode);
deba@2051
    50
    weight[uedge] = urandom(c);
deba@2040
    51
  }
deba@2040
    52
deba@2040
    53
  {
deba@2040
    54
    MaxBipartiteMatching<Graph> bpmatch(graph);
deba@2040
    55
deba@2040
    56
    bpmatch.run();
deba@2040
    57
deba@2040
    58
    Graph::UEdgeMap<bool> mm(graph);
deba@2040
    59
    Graph::NodeMap<bool> cs(graph);
deba@2040
    60
    
deba@2040
    61
    check(bpmatch.coverSet(cs) == bpmatch.matching(mm), "INVALID PRIMAL-DUAL");
deba@2040
    62
    
deba@2040
    63
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2040
    64
      check(cs[graph.aNode(it)] || cs[graph.bNode(it)], "INVALID DUAL");
deba@2040
    65
    }
deba@2040
    66
    
deba@2040
    67
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2040
    68
      int num = 0;
deba@2040
    69
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2040
    70
        if (mm[jt]) ++num;
deba@2051
    71
      }
deba@2040
    72
      check(num <= 1, "INVALID PRIMAL");
deba@2040
    73
    }
deba@2051
    74
    max_cardinality = bpmatch.matchingSize();
deba@2040
    75
  }
deba@2040
    76
deba@2040
    77
  {
deba@2058
    78
    Graph::UEdgeMap<bool> mm(graph);
deba@2058
    79
deba@2058
    80
    check(max_cardinality == maxBipartiteMatching(graph, mm),
deba@2058
    81
          "WRONG MATCHING");
deba@2058
    82
    
deba@2058
    83
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2058
    84
      int num = 0;
deba@2058
    85
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2058
    86
        if (mm[jt]) ++num;
deba@2058
    87
      }
deba@2058
    88
      check(num <= 1, "INVALID PRIMAL");
deba@2058
    89
    }
deba@2058
    90
  }
deba@2058
    91
deba@2058
    92
  {
deba@2040
    93
    MaxBipartiteMatching<Graph> bpmatch(graph);
deba@2040
    94
deba@2040
    95
    bpmatch.greedyInit();
deba@2040
    96
    bpmatch.start();
deba@2040
    97
deba@2040
    98
    Graph::UEdgeMap<bool> mm(graph);
deba@2040
    99
    Graph::NodeMap<bool> cs(graph);
deba@2040
   100
deba@2040
   101
    check(bpmatch.coverSet(cs) == bpmatch.matching(mm), "INVALID PRIMAL-DUAL");
deba@2040
   102
    
deba@2040
   103
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2040
   104
      check(cs[graph.aNode(it)] || cs[graph.bNode(it)], "INVALID DUAL");
deba@2040
   105
    }
deba@2040
   106
    
deba@2040
   107
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2040
   108
      int num = 0;
deba@2040
   109
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2040
   110
        if (mm[jt]) ++num;
deba@2040
   111
    }
deba@2040
   112
      check(num <= 1, "INVALID PRIMAL");
deba@2040
   113
    }
deba@2040
   114
  }
deba@2040
   115
deba@2040
   116
  {
deba@2040
   117
    MaxBipartiteMatching<Graph> bpmatch(graph);
deba@2040
   118
deba@2040
   119
    bpmatch.greedyInit();
deba@2040
   120
    while (bpmatch.simpleAugment());
deba@2040
   121
    
deba@2040
   122
    Graph::UEdgeMap<bool> mm(graph);
deba@2040
   123
    Graph::NodeMap<bool> cs(graph);
deba@2040
   124
    
deba@2040
   125
    check(bpmatch.coverSet(cs) == bpmatch.matching(mm), "INVALID PRIMAL-DUAL");
deba@2040
   126
    
deba@2040
   127
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2040
   128
      check(cs[graph.aNode(it)] || cs[graph.bNode(it)], "INVALID DUAL");
deba@2040
   129
    }
deba@2040
   130
    
deba@2040
   131
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2040
   132
      int num = 0;
deba@2040
   133
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2040
   134
        if (mm[jt]) ++num;
deba@2040
   135
    }
deba@2040
   136
      check(num <= 1, "INVALID PRIMAL");
deba@2040
   137
    }
deba@2040
   138
  }
deba@2040
   139
deba@2040
   140
  {
deba@2051
   141
    MaxWeightedBipartiteMatching<Graph> bpmatch(graph, weight);
deba@2051
   142
deba@2051
   143
    bpmatch.init();
deba@2051
   144
deba@2051
   145
    max_weight = 0;
deba@2051
   146
    while (bpmatch.augment(true)) {
deba@2051
   147
    
deba@2051
   148
      Graph::UEdgeMap<bool> mm(graph);
deba@2051
   149
      Graph::NodeMap<int> pm(graph);
deba@2051
   150
      
deba@2051
   151
      bpmatch.matching(mm);
deba@2051
   152
      bpmatch.potential(pm);
deba@2051
   153
      
deba@2051
   154
      for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2051
   155
        if (mm[it]) {
deba@2058
   156
          check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] == 0,
deba@2051
   157
                "INVALID DUAL");
deba@2051
   158
        } else {
deba@2058
   159
          check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] >= 0,
deba@2051
   160
                "INVALID DUAL");
deba@2051
   161
        }
deba@2051
   162
      }
deba@2051
   163
deba@2051
   164
      for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2051
   165
        int num = 0;
deba@2051
   166
        for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2051
   167
          if (mm[jt]) ++num;
deba@2051
   168
        }
deba@2051
   169
        check(num <= 1, "INVALID PRIMAL");
deba@2051
   170
      }
deba@2051
   171
      if (bpmatch.matchingValue() > max_weight) {
deba@2051
   172
        max_weight = bpmatch.matchingValue();
deba@2051
   173
      }
deba@2051
   174
    }
deba@2051
   175
  }
deba@2051
   176
deba@2051
   177
  {
deba@2058
   178
    Graph::UEdgeMap<bool> mm(graph);
deba@2058
   179
deba@2058
   180
    check(max_weight == maxWeightedBipartiteMatching(graph, weight, mm),
deba@2058
   181
          "WRONG MATCHING");
deba@2058
   182
    
deba@2058
   183
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2058
   184
      int num = 0;
deba@2058
   185
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2058
   186
        if (mm[jt]) ++num;
deba@2058
   187
      }
deba@2058
   188
      check(num <= 1, "INVALID PRIMAL");
deba@2058
   189
    }
deba@2058
   190
  }
deba@2058
   191
deba@2058
   192
  {
deba@2051
   193
    MaxWeightedBipartiteMatching<Graph> bpmatch(graph, weight);
deba@2040
   194
deba@2040
   195
    bpmatch.run();
deba@2051
   196
    
deba@2051
   197
    Graph::UEdgeMap<bool> mm(graph);
deba@2051
   198
    Graph::NodeMap<int> pm(graph);
deba@2040
   199
deba@2051
   200
    bpmatch.matching(mm);
deba@2051
   201
    bpmatch.potential(pm);
deba@2040
   202
    
deba@2040
   203
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2051
   204
      if (mm[it]) {
deba@2058
   205
        check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] == 0,
deba@2051
   206
              "INVALID DUAL");
deba@2051
   207
      } else {
deba@2058
   208
        check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] >= 0,
deba@2051
   209
              "INVALID DUAL");
deba@2051
   210
      }
deba@2040
   211
    }
deba@2051
   212
deba@2040
   213
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2040
   214
      int num = 0;
deba@2040
   215
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2040
   216
        if (mm[jt]) ++num;
deba@2040
   217
    }
deba@2040
   218
      check(num <= 1, "INVALID PRIMAL");
deba@2040
   219
    }
deba@2051
   220
    check(max_weight == bpmatch.matchingValue(), "WRONG WEIGHT");
deba@2051
   221
  }
deba@2051
   222
deba@2051
   223
  {
deba@2051
   224
    MaxWeightedBipartiteMatching<Graph> bpmatch(graph, weight);
deba@2051
   225
deba@2051
   226
    bpmatch.run(true);
deba@2051
   227
    
deba@2051
   228
    Graph::UEdgeMap<bool> mm(graph);
deba@2051
   229
    Graph::NodeMap<int> pm(graph);
deba@2051
   230
deba@2051
   231
    bpmatch.matching(mm);
deba@2051
   232
    bpmatch.potential(pm);
deba@2051
   233
    
deba@2051
   234
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2051
   235
      if (mm[it]) {
deba@2058
   236
        check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] == 0,
deba@2051
   237
              "INVALID DUAL");
deba@2051
   238
      } else {
deba@2058
   239
        check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] >= 0,
deba@2051
   240
              "INVALID DUAL");
deba@2051
   241
      }
deba@2051
   242
    }
deba@2051
   243
deba@2051
   244
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2051
   245
      int num = 0;
deba@2051
   246
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2051
   247
        if (mm[jt]) ++num;
deba@2051
   248
    }
deba@2051
   249
      check(num <= 1, "INVALID PRIMAL");
deba@2051
   250
    }
deba@2051
   251
    check(max_cardinality == bpmatch.matchingSize(), "WRONG SIZE");
deba@2051
   252
    max_cardinality_max_weight = bpmatch.matchingValue();
deba@2051
   253
deba@2051
   254
  }
deba@2051
   255
deba@2051
   256
  {
deba@2058
   257
    Graph::UEdgeMap<bool> mm(graph);
deba@2051
   258
deba@2058
   259
    check(max_cardinality_max_weight == 
deba@2058
   260
          maxWeightedMaxBipartiteMatching(graph, weight, mm),
deba@2058
   261
          "WRONG MATCHING");
deba@2058
   262
    
deba@2058
   263
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2058
   264
      int num = 0;
deba@2058
   265
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2058
   266
        if (mm[jt]) ++num;
deba@2058
   267
      }
deba@2058
   268
      check(num <= 1, "INVALID PRIMAL");
deba@2058
   269
    }
deba@2058
   270
  }
deba@2058
   271
deba@2058
   272
  Graph::UEdgeMap<int> cost(graph);
deba@2058
   273
  cost = subMap(constMap<UEdge>(c), weight);
deba@2058
   274
deba@2058
   275
  {
deba@2051
   276
deba@2051
   277
    MinCostMaxBipartiteMatching<Graph> bpmatch(graph, cost);
deba@2051
   278
deba@2051
   279
    bpmatch.run();
deba@2051
   280
    
deba@2051
   281
    Graph::UEdgeMap<bool> mm(graph);
deba@2051
   282
    Graph::NodeMap<int> pm(graph);
deba@2051
   283
deba@2051
   284
    bpmatch.matching(mm);
deba@2051
   285
    bpmatch.potential(pm);
deba@2051
   286
    
deba@2051
   287
    for (UEdgeIt it(graph); it != INVALID; ++it) {
deba@2051
   288
      if (mm[it]) {
deba@2051
   289
        check(pm[graph.aNode(it)] + cost[it] - pm[graph.bNode(it)] == 0,
deba@2051
   290
              "INVALID DUAL");
deba@2051
   291
      } else {
deba@2051
   292
        check(pm[graph.aNode(it)] + cost[it] - pm[graph.bNode(it)] >= 0,
deba@2051
   293
              "INVALID DUAL");
deba@2051
   294
      }
deba@2051
   295
    }
deba@2051
   296
deba@2051
   297
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2051
   298
      int num = 0;
deba@2051
   299
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2051
   300
        if (mm[jt]) ++num;
deba@2051
   301
    }
deba@2051
   302
      check(num <= 1, "INVALID PRIMAL");
deba@2051
   303
    }
deba@2051
   304
deba@2058
   305
    min_cost_matching = bpmatch.matchingCost();
deba@2051
   306
    check(max_cardinality == bpmatch.matchingSize(), "WRONG SIZE");
deba@2051
   307
    check(max_cardinality * c - max_cardinality_max_weight 
deba@2051
   308
          == bpmatch.matchingCost(), "WRONG SIZE");
deba@2051
   309
deba@2040
   310
  }
deba@2040
   311
deba@2058
   312
  {
deba@2058
   313
    Graph::UEdgeMap<bool> mm(graph);
deba@2058
   314
deba@2058
   315
    check(min_cost_matching == 
deba@2058
   316
          minCostMaxBipartiteMatching(graph, cost, mm),
deba@2058
   317
          "WRONG MATCHING");
deba@2058
   318
    
deba@2058
   319
    for (ANodeIt it(graph); it != INVALID; ++it) {
deba@2058
   320
      int num = 0;
deba@2058
   321
      for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
deba@2058
   322
        if (mm[jt]) ++num;
deba@2058
   323
      }
deba@2058
   324
      check(num <= 1, "INVALID PRIMAL");
deba@2058
   325
    }
deba@2058
   326
  }
deba@2058
   327
deba@2040
   328
  return 0;
deba@2040
   329
}