3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2007
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
23 #include <lemon/smart_graph.h>
25 #include <lemon/bpugraph_adaptor.h>
26 #include <lemon/bipartite_matching.h>
28 #include <lemon/graph_utils.h>
30 #include <lemon/maps.h>
32 #include "test_tools.h"
35 using namespace lemon;
37 typedef SmartBpUGraph Graph;
38 BPUGRAPH_TYPEDEFS(Graph);
45 const int sa[E] = { 6, 5, 6, 4, 1, 0, 9, 5, 2, 4, 4, 3, 5,
46 2, 3, 8, 3, 4, 9, 6, 9, 4, 3, 1, 5, 8,
47 4, 8, 9, 2, 2, 3, 0, 5, 2, 3, 6, 3, 8,
48 8, 4, 0, 9, 9, 6, 2, 1, 2, 7, 1, 9, 4};
50 const int ta[E] = { 2, 7, 4, 8, 6, 3, 4, 1, 7, 7, 0, 1, 6,
51 3, 2, 6, 8, 3, 5, 6, 3, 1, 8, 7, 2, 0,
52 6, 9, 6, 7, 8, 3, 3, 4, 5, 8, 6, 4, 1,
53 4, 3, 3, 8, 7, 7, 3, 7, 7, 3, 5, 1, 6};
55 const int wa[E] = { 3, 99, 85, 16, 79, 52, 83, 99, 62, 6, 42, 6, 95,
56 13, 34, 9, 5, 38, 39, 75, 99, 12, 73, 35, 93, 43,
57 54, 91, 45, 26, 77, 47, 11, 22, 50, 74, 37, 64, 91,
58 60, 6, 92, 29, 46, 34, 84, 67, 34, 45, 0, 39, 47};
66 Graph::UEdgeMap<int> weight(graph);
70 int max_cardinality_max_weight;
71 int min_cost_matching;
73 for (int i = 0; i < N; ++i) {
74 Node node = graph.addANode();
75 aNodes.push_back(node);
77 for (int i = 0; i < M; ++i) {
78 Node node = graph.addBNode();
79 bNodes.push_back(node);
81 for (int i = 0; i < E; ++i) {
82 Node aNode = aNodes[sa[i]];
83 Node bNode = bNodes[ta[i]];
84 UEdge uedge = graph.addEdge(aNode, bNode);
85 weight[uedge] = wa[i];
90 MaxBipartiteMatching<Graph> bpmatch(graph);
94 Graph::UEdgeMap<bool> mm(graph);
95 Graph::NodeMap<bool> cs(graph);
97 check(bpmatch.coverSet(cs) == bpmatch.matching(mm), "INVALID PRIMAL-DUAL");
99 for (UEdgeIt it(graph); it != INVALID; ++it) {
100 check(cs[graph.aNode(it)] || cs[graph.bNode(it)], "INVALID DUAL");
103 for (ANodeIt it(graph); it != INVALID; ++it) {
105 for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
108 check(num <= 1, "INVALID PRIMAL");
110 max_cardinality = bpmatch.matchingSize();
114 Graph::UEdgeMap<bool> mm(graph);
116 check(max_cardinality == maxBipartiteMatching(graph, mm),
119 for (ANodeIt it(graph); it != INVALID; ++it) {
121 for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
124 check(num <= 1, "INVALID PRIMAL");
129 MaxBipartiteMatching<Graph> bpmatch(graph);
131 bpmatch.greedyInit();
134 Graph::UEdgeMap<bool> mm(graph);
135 Graph::NodeMap<bool> cs(graph);
137 check(bpmatch.coverSet(cs) == bpmatch.matching(mm), "INVALID PRIMAL-DUAL");
139 for (UEdgeIt it(graph); it != INVALID; ++it) {
140 check(cs[graph.aNode(it)] || cs[graph.bNode(it)], "INVALID DUAL");
143 for (ANodeIt it(graph); it != INVALID; ++it) {
145 for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
148 check(num <= 1, "INVALID PRIMAL");
153 MaxBipartiteMatching<Graph> bpmatch(graph);
155 bpmatch.greedyInit();
156 while (bpmatch.simpleAugment());
158 Graph::UEdgeMap<bool> mm(graph);
159 Graph::NodeMap<bool> cs(graph);
161 check(bpmatch.coverSet(cs) == bpmatch.matching(mm), "INVALID PRIMAL-DUAL");
163 for (UEdgeIt it(graph); it != INVALID; ++it) {
164 check(cs[graph.aNode(it)] || cs[graph.bNode(it)], "INVALID DUAL");
167 for (ANodeIt it(graph); it != INVALID; ++it) {
169 for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
172 check(num <= 1, "INVALID PRIMAL");
177 MaxWeightedBipartiteMatching<Graph> bpmatch(graph, weight);
182 while (bpmatch.augment(true)) {
184 Graph::UEdgeMap<bool> mm(graph);
185 Graph::NodeMap<int> pm(graph);
187 bpmatch.matching(mm);
188 bpmatch.potential(pm);
190 for (UEdgeIt it(graph); it != INVALID; ++it) {
192 check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] == 0,
195 check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] >= 0,
200 for (ANodeIt it(graph); it != INVALID; ++it) {
202 for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
205 check(num <= 1, "INVALID PRIMAL");
207 if (bpmatch.matchingValue() > max_weight) {
208 max_weight = bpmatch.matchingValue();
214 Graph::UEdgeMap<bool> mm(graph);
216 check(max_weight == maxWeightedBipartiteMatching(graph, weight, mm),
219 for (ANodeIt it(graph); it != INVALID; ++it) {
221 for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
224 check(num <= 1, "INVALID PRIMAL");
229 MaxWeightedBipartiteMatching<Graph> bpmatch(graph, weight);
233 Graph::UEdgeMap<bool> mm(graph);
234 Graph::NodeMap<int> pm(graph);
236 bpmatch.matching(mm);
237 bpmatch.potential(pm);
239 for (UEdgeIt it(graph); it != INVALID; ++it) {
241 check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] == 0,
244 check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] >= 0,
249 for (ANodeIt it(graph); it != INVALID; ++it) {
251 for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
254 check(num <= 1, "INVALID PRIMAL");
256 check(max_weight == bpmatch.matchingValue(), "WRONG WEIGHT");
260 MaxWeightedBipartiteMatching<Graph> bpmatch(graph, weight);
264 Graph::UEdgeMap<bool> mm(graph);
265 Graph::NodeMap<int> pm(graph);
267 bpmatch.matching(mm);
268 bpmatch.potential(pm);
270 for (UEdgeIt it(graph); it != INVALID; ++it) {
272 check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] == 0,
275 check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] >= 0,
280 for (ANodeIt it(graph); it != INVALID; ++it) {
282 for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
285 check(num <= 1, "INVALID PRIMAL");
287 check(max_cardinality == bpmatch.matchingSize(), "WRONG SIZE");
288 max_cardinality_max_weight = bpmatch.matchingValue();
293 Graph::UEdgeMap<bool> mm(graph);
295 check(max_cardinality_max_weight ==
296 maxWeightedMaxBipartiteMatching(graph, weight, mm),
299 for (ANodeIt it(graph); it != INVALID; ++it) {
301 for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
304 check(num <= 1, "INVALID PRIMAL");
308 Graph::UEdgeMap<int> cost(graph);
309 cost = subMap(constMap<UEdge>(C), weight);
312 MinCostMaxBipartiteMatching<Graph> bpmatch(graph, cost);
316 Graph::UEdgeMap<bool> mm(graph);
317 Graph::NodeMap<int> pm(graph);
319 bpmatch.matching(mm);
320 bpmatch.potential(pm);
322 min_cost_matching = bpmatch.matchingCost();
323 check(max_cardinality == bpmatch.matchingSize(), "WRONG SIZE");
324 check(max_cardinality * C - max_cardinality_max_weight
325 == bpmatch.matchingCost(), "WRONG SIZE");
327 for (UEdgeIt it(graph); it != INVALID; ++it) {
329 check(pm[graph.aNode(it)] + cost[it] - pm[graph.bNode(it)] == 0,
332 check(pm[graph.aNode(it)] + cost[it] - pm[graph.bNode(it)] >= 0,
337 for (ANodeIt it(graph); it != INVALID; ++it) {
339 for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
342 check(num <= 1, "INVALID PRIMAL");
345 min_cost_matching = bpmatch.matchingCost();
346 check(max_cardinality == bpmatch.matchingSize(), "WRONG SIZE");
347 check(max_cardinality * C - max_cardinality_max_weight
348 == bpmatch.matchingCost(), "WRONG SIZE");
353 Graph::UEdgeMap<bool> mm(graph);
355 check(min_cost_matching ==
356 minCostMaxBipartiteMatching(graph, cost, mm),
359 for (ANodeIt it(graph); it != INVALID; ++it) {
361 for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
364 check(num <= 1, "INVALID PRIMAL");