Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* (C) Copyright 2015-2017, by Graeme Ahokas and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* This program and the accompanying materials are dual-licensed under
* either
*
* (a) the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation, or (at your option) any
* later version.
*
* or (per the licensee's choosing)
*
* (b) the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation.
*/
package org.jgrapht.alg;
import java.util.*;
import org.jgrapht.*;
import org.jgrapht.alg.interfaces.*;
/**
* This class finds a maximum weight matching of a simple undirected weighted bipartite graph. The
* algorithm runs in O(V|E|^2). The algorithm is described in The LEDA Platform of Combinatorial and
* Geometric Computing, Cambridge University Press, 1999.
* https://people.mpi-inf.mpg.de/~mehlhorn/LEDAbook.html Note: the input graph must be bipartite
* with positive integer edge weights
*
* @param the graph vertex type
* @param the graph edge type
*
* @author Graeme Ahokas
* @deprecated Use {@link org.jgrapht.alg.matching.MaximumWeightBipartiteMatching} instead.
*/
@Deprecated
public class MaximumWeightBipartiteMatching
implements WeightedMatchingAlgorithm
{
private final WeightedGraph graph;
private final Set partition1;
private final Set partition2;
private Map vertexWeights;
private Map hasVertexBeenProcessed;
private Map isEdgeMatched;
private Set bipartiteMatching;
/**
* Creates a new MaximumWeightBipartiteMatching algorithm instance. The union of
* vertexPartition1 and vertexParition2 should be equal to the vertex set of the graph Every
* edge in the graph must connect a vertex in vertexPartition1 with a vertex in vertexPartition2
*
* @param graph simple undirected weighted bipartite graph to find matching in, with positive
* integer edge weights
* @param vertexPartition1 first vertex partition of the bipartite graph, disjoint from
* vertexPartition2
* @param vertexPartition2 second vertex partition of the bipartite graph, disjoint from
* vertexPartition1
*/
public MaximumWeightBipartiteMatching(
final WeightedGraph graph, Set vertexPartition1, Set vertexPartition2)
{
this.graph = graph;
partition1 = vertexPartition1;
partition2 = vertexPartition2;
vertexWeights = new HashMap<>();
hasVertexBeenProcessed = new HashMap<>();
isEdgeMatched = new HashMap<>();
initializeVerticesAndEdges();
}
@Override
public Set getMatching()
{
if (bipartiteMatching == null) {
bipartiteMatching = maximumWeightBipartiteMatching();
}
return bipartiteMatching;
}
@Override
public double getMatchingWeight()
{
if (bipartiteMatching == null) {
getMatching();
}
long weight = 0;
for (E edge : bipartiteMatching) {
weight += graph.getEdgeWeight(edge);
}
return weight;
}
/**
* {@inheritDoc}
*/
@Override
public Matching computeMatching()
{
Set m = getMatching();
double w = 0d;
for (E e : m) {
w += graph.getEdgeWeight(e);
}
return new MatchingImpl(m, w);
}
private void initializeVerticesAndEdges()
{
for (V vertex : graph.vertexSet()) {
if (isTargetVertex(vertex)) {
hasVertexBeenProcessed.put(vertex, true);
setVertexWeight(vertex, (long) 0);
} else {
hasVertexBeenProcessed.put(vertex, false);
setVertexWeight(vertex, maximumWeightOfEdgeIncidentToVertex(vertex));
}
}
for (E edge : graph.edgeSet()) {
isEdgeMatched.put(edge, false);
}
}
private long maximumWeightOfEdgeIncidentToVertex(V vertex)
{
long maxWeight = 0;
for (E edge : graph.edgesOf(vertex)) {
if (graph.getEdgeWeight(edge) > maxWeight) {
maxWeight = (long) graph.getEdgeWeight(edge);
}
}
return maxWeight;
}
private boolean isSourceVertex(V vertex)
{
return partition1.contains(vertex);
}
private boolean isTargetVertex(V vertex)
{
return partition2.contains(vertex);
}
private long vertexWeight(V vertex)
{
return vertexWeights.get(vertex);
}
private void setVertexWeight(V vertex, Long weight)
{
vertexWeights.put(vertex, weight);
}
private long reducedWeight(E edge)
{
return (long) (vertexWeight(graph.getEdgeSource(edge))
+ vertexWeight(graph.getEdgeTarget(edge)) - graph.getEdgeWeight(edge));
}
private boolean isVertexMatched(V vertex, Set matchings)
{
for (E edge : matchings) {
if (graph.getEdgeSource(edge).equals(vertex)
|| graph.getEdgeTarget(edge).equals(vertex))
{
return true;
}
}
return false;
}
private void addPathToMatchings(List path, Set matchings)
{
for (int i = 0; i < path.size(); i++) {
E edge = path.get(i);
if ((i % 2) == 0) {
isEdgeMatched.put(edge, true);
matchings.add(edge);
} else {
isEdgeMatched.put(edge, false);
matchings.remove(edge);
}
}
}
private void adjustVertexWeights(Map> reachableVertices)
{
long alpha = Long.MAX_VALUE;
for (V vertex : reachableVertices.keySet()) {
if (isSourceVertex(vertex) && (vertexWeights.get(vertex) < alpha)) {
alpha = vertexWeights.get(vertex);
}
}
long beta = Long.MAX_VALUE;
for (V vertex : reachableVertices.keySet()) {
if (isTargetVertex(vertex)) {
continue;
}
for (E edge : graph.edgesOf(vertex)) {
if (hasVertexBeenProcessed.get(Graphs.getOppositeVertex(graph, edge, vertex))
&& !reachableVertices
.keySet().contains(Graphs.getOppositeVertex(graph, edge, vertex))
&& (reducedWeight(edge) < beta))
{
beta = reducedWeight(edge);
}
}
}
assert ((alpha > 0) && (beta > 0));
long minValue = Math.min(alpha, beta);
for (V vertex : reachableVertices.keySet()) {
if (isSourceVertex(vertex)) {
vertexWeights.put(vertex, vertexWeights.get(vertex) - minValue);
} else {
vertexWeights.put(vertex, vertexWeights.get(vertex) + minValue);
}
}
}
private Map> verticesReachableByTightAlternatingEdgesFromVertex(V vertex)
{
Map> pathsToVertices = new HashMap<>();
pathsToVertices.put(vertex, new ArrayList<>());
findPathsToVerticesFromVertices(Collections.singletonList(vertex), false, pathsToVertices);
return pathsToVertices;
}
private void findPathsToVerticesFromVertices(
List verticesToProcess, boolean needMatchedEdge, Map> pathsToVertices)
{
if (verticesToProcess.size() == 0) {
return;
}
List nextVerticesToProcess = new ArrayList<>();
for (V vertex : verticesToProcess) {
for (E edge : graph.edgesOf(vertex)) {
V adjacentVertex = Graphs.getOppositeVertex(graph, edge, vertex);
if (hasVertexBeenProcessed.get(adjacentVertex) && (reducedWeight(edge) == 0)
&& !pathsToVertices.keySet().contains(adjacentVertex))
{
if ((needMatchedEdge && isEdgeMatched.get(edge))
|| (!needMatchedEdge && !isEdgeMatched.get(edge)))
{
nextVerticesToProcess.add(adjacentVertex);
List pathToAdjacentVertex = new ArrayList<>(pathsToVertices.get(vertex));
pathToAdjacentVertex.add(edge);
pathsToVertices.put(adjacentVertex, pathToAdjacentVertex);
}
}
}
}
findPathsToVerticesFromVertices(nextVerticesToProcess, !needMatchedEdge, pathsToVertices);
}
private Set maximumWeightBipartiteMatching()
{
Set matchings = new HashSet<>();
for (V vertex : partition1) {
hasVertexBeenProcessed.put(vertex, true);
while (true) {
Map> reachableVertices =
verticesReachableByTightAlternatingEdgesFromVertex(vertex);
boolean successful = false;
for (V reachableVertex : reachableVertices.keySet()) {
if (isSourceVertex(reachableVertex) && (vertexWeight(reachableVertex) == 0)) {
addPathToMatchings(reachableVertices.get(reachableVertex), matchings);
successful = true;
break;
}
if (isTargetVertex(reachableVertex)
&& !isVertexMatched(reachableVertex, matchings))
{
addPathToMatchings(reachableVertices.get(reachableVertex), matchings);
successful = true;
break;
}
}
if (successful) {
break;
}
adjustVertexWeights(reachableVertices);
}
}
return matchings;
}
}
// End MaximumWeightBipartiteMatching.java