[Lemon-commits] [lemon_svn] deba: r2702 - in hugo/trunk: lemon test
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:54:36 CET 2006
Author: deba
Date: Tue Apr 18 09:01:55 2006
New Revision: 2702
Modified:
hugo/trunk/lemon/bipartite_matching.h
hugo/trunk/test/bipartite_matching_test.cc
Log:
Refinements in bipartite matching algorithms
Modified: hugo/trunk/lemon/bipartite_matching.h
==============================================================================
--- hugo/trunk/lemon/bipartite_matching.h (original)
+++ hugo/trunk/lemon/bipartite_matching.h Tue Apr 18 09:01:55 2006
@@ -328,7 +328,7 @@
///
/// It just initalize the algorithm and then start it.
void run() {
- init();
+ greedyInit();
start();
}
@@ -349,7 +349,7 @@
/// problem what is proof of the optimality of the matching.
/// \return The size of the cover set.
template <typename CoverMap>
- int coverSet(CoverMap& covering) {
+ int coverSet(CoverMap& covering) const {
typename Graph::template ANodeMap<bool> areached(*graph, false);
typename Graph::template BNodeMap<bool> breached(*graph, false);
@@ -403,7 +403,7 @@
/// value mapped to the other uedges.
/// \return The number of the matching edges.
template <typename MatchingMap>
- int quickMatching(MatchingMap& matching) {
+ int quickMatching(MatchingMap& matching) const {
for (ANodeIt it(*graph); it != INVALID; ++it) {
if (anode_matching[it] != INVALID) {
matching[anode_matching[it]] = true;
@@ -417,7 +417,7 @@
/// Set true all matching uedge in the map and the others to false.
/// \return The number of the matching edges.
template <typename MatchingMap>
- int matching(MatchingMap& matching) {
+ int matching(MatchingMap& matching) const {
for (UEdgeIt it(*graph); it != INVALID; ++it) {
matching[it] = it == anode_matching[graph->aNode(it)];
}
@@ -428,7 +428,7 @@
/// \brief Return true if the given uedge is in the matching.
///
/// It returns true if the given uedge is in the matching.
- bool matchingEdge(const UEdge& edge) {
+ bool matchingEdge(const UEdge& edge) const {
return anode_matching[graph->aNode(edge)] == edge;
}
@@ -436,7 +436,7 @@
///
/// Returns the matching edge from the node. If there is not such
/// edge it gives back \c INVALID.
- UEdge matchingEdge(const Node& node) {
+ UEdge matchingEdge(const Node& node) const {
if (graph->aNode(node)) {
return anode_matching[node];
} else {
@@ -463,6 +463,26 @@
};
+ /// \ingroup matching
+ ///
+ /// \brief Maximum cardinality bipartite matching
+ ///
+ /// This function calculates the maximum cardinality matching
+ /// in a bipartite graph. It gives back the matching in an undirected
+ /// edge map.
+ ///
+ /// \param graph The bipartite graph.
+ /// \retval matching The undirected edge map which will be set to
+ /// the matching.
+ /// \return The size of the matching.
+ template <typename BpUGraph, typename MatchingMap>
+ int maxBipartiteMatching(const BpUGraph& graph, MatchingMap& matching) {
+ MaxBipartiteMatching<BpUGraph> bpmatching(graph);
+ bpmatching.run();
+ bpmatching.matching(matching);
+ return bpmatching.matchingSize();
+ }
+
/// \brief Default traits class for weighted bipartite matching algoritms.
///
/// Default traits class for weighted bipartite matching algoritms.
@@ -701,8 +721,8 @@
bnode_matching[it] = INVALID;
bnode_potential[it] = 0;
for (IncEdgeIt jt(*graph, it); jt != INVALID; ++jt) {
- if (-(*weight)[jt] <= bnode_potential[it]) {
- bnode_potential[it] = -(*weight)[jt];
+ if ((*weight)[jt] > bnode_potential[it]) {
+ bnode_potential[it] = (*weight)[jt];
}
}
}
@@ -753,8 +773,8 @@
for (IncEdgeIt jt(*graph, anode); jt != INVALID; ++jt) {
if (jt == anode_matching[anode]) continue;
Node bnode = graph->bNode(jt);
- Value bvalue = avalue + anode_potential[anode] -
- bnode_potential[bnode] - (*weight)[jt];
+ Value bvalue = avalue - (*weight)[jt] +
+ anode_potential[anode] + bnode_potential[bnode];
if (bpred[bnode] == INVALID || bvalue < bdist[bnode]) {
bdist[bnode] = bvalue;
bpred[bnode] = jt;
@@ -778,8 +798,8 @@
}
} else {
if (bestNode == INVALID ||
- - bvalue - bnode_potential[bnode] > bestValue) {
- bestValue = - bvalue - bnode_potential[bnode];
+ bnode_potential[bnode] - bvalue > bestValue) {
+ bestValue = bnode_potential[bnode] - bvalue;
bestNode = bnode;
}
}
@@ -795,9 +815,9 @@
for (BNodeIt it(*graph); it != INVALID; ++it) {
if (bpred[it] != INVALID) {
- bnode_potential[it] += bdist[it];
+ bnode_potential[it] -= bdist[it];
} else {
- bnode_potential[it] += bdistMax;
+ bnode_potential[it] -= bdistMax;
}
}
for (ANodeIt it(*graph); it != INVALID; ++it) {
@@ -864,12 +884,12 @@
/// \brief Gives back the potential in the NodeMap
///
- /// Gives back the potential in the NodeMap. The potential
- /// is feasible if \f$ \pi(a) - \pi(b) - w(ab) = 0 \f$ for
- /// each matching edges and \f$ \pi(a) - \pi(b) - w(ab) \ge 0 \f$
- /// for each edges.
+ /// Gives back the potential in the NodeMap. The matching is optimal
+ /// with the current number of edges if \f$ \pi(a) + \pi(b) - w(ab) = 0 \f$
+ /// for each matching edges and \f$ \pi(a) + \pi(b) - w(ab) \ge 0 \f$
+ /// for each edges.
template <typename PotentialMap>
- void potential(PotentialMap& potential) {
+ void potential(PotentialMap& potential) const {
for (ANodeIt it(*graph); it != INVALID; ++it) {
potential[it] = anode_potential[it];
}
@@ -884,7 +904,7 @@
/// value mapped to the other uedges.
/// \return The number of the matching edges.
template <typename MatchingMap>
- int quickMatching(MatchingMap& matching) {
+ int quickMatching(MatchingMap& matching) const {
for (ANodeIt it(*graph); it != INVALID; ++it) {
if (anode_matching[it] != INVALID) {
matching[anode_matching[it]] = true;
@@ -898,7 +918,7 @@
/// Set true all matching uedge in the map and the others to false.
/// \return The number of the matching edges.
template <typename MatchingMap>
- int matching(MatchingMap& matching) {
+ int matching(MatchingMap& matching) const {
for (UEdgeIt it(*graph); it != INVALID; ++it) {
matching[it] = it == anode_matching[graph->aNode(it)];
}
@@ -909,7 +929,7 @@
/// \brief Return true if the given uedge is in the matching.
///
/// It returns true if the given uedge is in the matching.
- bool matchingEdge(const UEdge& edge) {
+ bool matchingEdge(const UEdge& edge) const {
return anode_matching[graph->aNode(edge)] == edge;
}
@@ -917,7 +937,7 @@
///
/// Returns the matching edge from the node. If there is not such
/// edge it gives back \c INVALID.
- UEdge matchingEdge(const Node& node) {
+ UEdge matchingEdge(const Node& node) const {
if (graph->aNode(node)) {
return anode_matching[node];
} else {
@@ -982,6 +1002,55 @@
};
+ /// \ingroup matching
+ ///
+ /// \brief Maximum weighted bipartite matching
+ ///
+ /// This function calculates the maximum weighted matching
+ /// in a bipartite graph. It gives back the matching in an undirected
+ /// edge map.
+ ///
+ /// \param graph The bipartite graph.
+ /// \param weight The undirected edge map which contains the weights.
+ /// \retval matching The undirected edge map which will be set to
+ /// the matching.
+ /// \return The value of the matching.
+ template <typename BpUGraph, typename WeightMap, typename MatchingMap>
+ typename WeightMap::Value
+ maxWeightedBipartiteMatching(const BpUGraph& graph, const WeightMap& weight,
+ MatchingMap& matching) {
+ MaxWeightedBipartiteMatching<BpUGraph, WeightMap>
+ bpmatching(graph, weight);
+ bpmatching.run();
+ bpmatching.matching(matching);
+ return bpmatching.matchingValue();
+ }
+
+ /// \ingroup matching
+ ///
+ /// \brief Maximum weighted maximum cardinality bipartite matching
+ ///
+ /// This function calculates the maximum weighted of the maximum cardinality
+ /// matchings of a bipartite graph. It gives back the matching in an
+ /// undirected edge map.
+ ///
+ /// \param graph The bipartite graph.
+ /// \param weight The undirected edge map which contains the weights.
+ /// \retval matching The undirected edge map which will be set to
+ /// the matching.
+ /// \return The value of the matching.
+ template <typename BpUGraph, typename WeightMap, typename MatchingMap>
+ typename WeightMap::Value
+ maxWeightedMaxBipartiteMatching(const BpUGraph& graph,
+ const WeightMap& weight,
+ MatchingMap& matching) {
+ MaxWeightedBipartiteMatching<BpUGraph, WeightMap>
+ bpmatching(graph, weight);
+ bpmatching.run(true);
+ bpmatching.matching(matching);
+ return bpmatching.matchingValue();
+ }
+
/// \brief Default traits class for minimum cost bipartite matching
/// algoritms.
///
@@ -1360,12 +1429,12 @@
/// \brief Gives back the potential in the NodeMap
///
- /// Gives back the potential in the NodeMap. The potential
- /// is feasible if \f$ \pi(a) - \pi(b) + w(ab) = 0 \f$ for
+ /// Gives back the potential in the NodeMap. The potential is optimal with
+ /// the current number of edges if \f$ \pi(a) - \pi(b) + w(ab) = 0 \f$ for
/// each matching edges and \f$ \pi(a) - \pi(b) + w(ab) \ge 0 \f$
/// for each edges.
template <typename PotentialMap>
- void potential(PotentialMap& potential) {
+ void potential(PotentialMap& potential) const {
for (ANodeIt it(*graph); it != INVALID; ++it) {
potential[it] = anode_potential[it];
}
@@ -1380,7 +1449,7 @@
/// value mapped to the other uedges.
/// \return The number of the matching edges.
template <typename MatchingMap>
- int quickMatching(MatchingMap& matching) {
+ int quickMatching(MatchingMap& matching) const {
for (ANodeIt it(*graph); it != INVALID; ++it) {
if (anode_matching[it] != INVALID) {
matching[anode_matching[it]] = true;
@@ -1394,7 +1463,7 @@
/// Set true all matching uedge in the map and the others to false.
/// \return The number of the matching edges.
template <typename MatchingMap>
- int matching(MatchingMap& matching) {
+ int matching(MatchingMap& matching) const {
for (UEdgeIt it(*graph); it != INVALID; ++it) {
matching[it] = it == anode_matching[graph->aNode(it)];
}
@@ -1405,7 +1474,7 @@
/// \brief Return true if the given uedge is in the matching.
///
/// It returns true if the given uedge is in the matching.
- bool matchingEdge(const UEdge& edge) {
+ bool matchingEdge(const UEdge& edge) const {
return anode_matching[graph->aNode(edge)] == edge;
}
@@ -1413,7 +1482,7 @@
///
/// Returns the matching edge from the node. If there is not such
/// edge it gives back \c INVALID.
- UEdge matchingEdge(const Node& node) {
+ UEdge matchingEdge(const Node& node) const {
if (graph->aNode(node)) {
return anode_matching[node];
} else {
@@ -1478,6 +1547,31 @@
};
+ /// \ingroup matching
+ ///
+ /// \brief Minimum cost maximum cardinality bipartite matching
+ ///
+ /// This function calculates the minimum cost matching of the maximum
+ /// cardinality matchings of a bipartite graph. It gives back the matching
+ /// in an undirected edge map.
+ ///
+ /// \param graph The bipartite graph.
+ /// \param cost The undirected edge map which contains the costs.
+ /// \retval matching The undirected edge map which will be set to
+ /// the matching.
+ /// \return The cost of the matching.
+ template <typename BpUGraph, typename CostMap, typename MatchingMap>
+ typename CostMap::Value
+ minCostMaxBipartiteMatching(const BpUGraph& graph,
+ const CostMap& cost,
+ MatchingMap& matching) {
+ MinCostMaxBipartiteMatching<BpUGraph, CostMap>
+ bpmatching(graph, cost);
+ bpmatching.run();
+ bpmatching.matching(matching);
+ return bpmatching.matchingCost();
+ }
+
}
#endif
Modified: hugo/trunk/test/bipartite_matching_test.cc
==============================================================================
--- hugo/trunk/test/bipartite_matching_test.cc (original)
+++ hugo/trunk/test/bipartite_matching_test.cc Tue Apr 18 09:01:55 2006
@@ -23,8 +23,8 @@
Graph graph;
vector<Node> aNodes;
vector<Node> bNodes;
- int n = argc > 1 ? atoi(argv[1]) : 100;
- int m = argc > 2 ? atoi(argv[2]) : 100;
+ int n = argc > 1 ? atoi(argv[1]) : 10;
+ int m = argc > 2 ? atoi(argv[2]) : 10;
int e = argc > 3 ? atoi(argv[3]) : (int)((n+m) * log(n+m));
int c = argc > 4 ? atoi(argv[4]) : 100;
@@ -33,6 +33,7 @@
int max_cardinality;
int max_weight;
int max_cardinality_max_weight;
+ int min_cost_matching;
for (int i = 0; i < n; ++i) {
Node node = graph.addANode();
@@ -74,6 +75,21 @@
}
{
+ Graph::UEdgeMap<bool> mm(graph);
+
+ check(max_cardinality == maxBipartiteMatching(graph, mm),
+ "WRONG MATCHING");
+
+ for (ANodeIt it(graph); it != INVALID; ++it) {
+ int num = 0;
+ for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
+ if (mm[jt]) ++num;
+ }
+ check(num <= 1, "INVALID PRIMAL");
+ }
+ }
+
+ {
MaxBipartiteMatching<Graph> bpmatch(graph);
bpmatch.greedyInit();
@@ -137,10 +153,10 @@
for (UEdgeIt it(graph); it != INVALID; ++it) {
if (mm[it]) {
- check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] == 0,
+ check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] == 0,
"INVALID DUAL");
} else {
- check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] >= 0,
+ check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] >= 0,
"INVALID DUAL");
}
}
@@ -159,6 +175,21 @@
}
{
+ Graph::UEdgeMap<bool> mm(graph);
+
+ check(max_weight == maxWeightedBipartiteMatching(graph, weight, mm),
+ "WRONG MATCHING");
+
+ for (ANodeIt it(graph); it != INVALID; ++it) {
+ int num = 0;
+ for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
+ if (mm[jt]) ++num;
+ }
+ check(num <= 1, "INVALID PRIMAL");
+ }
+ }
+
+ {
MaxWeightedBipartiteMatching<Graph> bpmatch(graph, weight);
bpmatch.run();
@@ -171,10 +202,10 @@
for (UEdgeIt it(graph); it != INVALID; ++it) {
if (mm[it]) {
- check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] == 0,
+ check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] == 0,
"INVALID DUAL");
} else {
- check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] >= 0,
+ check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] >= 0,
"INVALID DUAL");
}
}
@@ -202,10 +233,10 @@
for (UEdgeIt it(graph); it != INVALID; ++it) {
if (mm[it]) {
- check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] == 0,
+ check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] == 0,
"INVALID DUAL");
} else {
- check(pm[graph.aNode(it)] - weight[it] - pm[graph.bNode(it)] >= 0,
+ check(pm[graph.aNode(it)] + pm[graph.bNode(it)] - weight[it] >= 0,
"INVALID DUAL");
}
}
@@ -223,9 +254,25 @@
}
{
- Graph::UEdgeMap<int> cost(graph);
+ Graph::UEdgeMap<bool> mm(graph);
- cost = subMap(constMap<UEdge>(c), weight);
+ check(max_cardinality_max_weight ==
+ maxWeightedMaxBipartiteMatching(graph, weight, mm),
+ "WRONG MATCHING");
+
+ for (ANodeIt it(graph); it != INVALID; ++it) {
+ int num = 0;
+ for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
+ if (mm[jt]) ++num;
+ }
+ check(num <= 1, "INVALID PRIMAL");
+ }
+ }
+
+ Graph::UEdgeMap<int> cost(graph);
+ cost = subMap(constMap<UEdge>(c), weight);
+
+ {
MinCostMaxBipartiteMatching<Graph> bpmatch(graph, cost);
@@ -255,11 +302,28 @@
check(num <= 1, "INVALID PRIMAL");
}
+ min_cost_matching = bpmatch.matchingCost();
check(max_cardinality == bpmatch.matchingSize(), "WRONG SIZE");
check(max_cardinality * c - max_cardinality_max_weight
== bpmatch.matchingCost(), "WRONG SIZE");
}
+ {
+ Graph::UEdgeMap<bool> mm(graph);
+
+ check(min_cost_matching ==
+ minCostMaxBipartiteMatching(graph, cost, mm),
+ "WRONG MATCHING");
+
+ for (ANodeIt it(graph); it != INVALID; ++it) {
+ int num = 0;
+ for (IncEdgeIt jt(graph, it); jt != INVALID; ++jt) {
+ if (mm[jt]) ++num;
+ }
+ check(num <= 1, "INVALID PRIMAL");
+ }
+ }
+
return 0;
}
More information about the Lemon-commits
mailing list