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.
/* ==========================================
* JGraphT : a free Java graph-theory library
* ==========================================
*
* Project Info: http://jgrapht.sourceforge.net/
* Project Creator: Barak Naveh (http://sourceforge.net/users/barak_naveh)
*
* (C) Copyright 2003-2011, by Barak Naveh and Contributors.
*
* 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.
*/
/* ----------------
* StoerWagnerMinimumCut.java
* ----------------
* (C) Copyright 2011-2011, by Robby McKilliam and Contributors.
*
* Original Author: Robby McKilliam
* Contributor(s): Ernst de Ridder
*
* $Id: StoerWagnerMinimumCut.java $
*
* Changes
* -------
*
*/
package org.jgrapht.alg;
import java.util.*;
import org.jgrapht.*;
import org.jgrapht.graph.*;
import org.jgrapht.util.*;
/**
* Implements the Stoer and
* Wagner minimum cut algorithm. Deterministically computes the minimum cut
* in O(|V||E| + |V|log|V|) time. This implementation uses Java's PriorityQueue
* and requires O(|V||E|log|E|) time. M. Stoer and F. Wagner, "A Simple Min-Cut
* Algorithm", Journal of the ACM, volume 44, number 4. pp 585-591, 1997.
*
* @author Robby McKilliam, Ernst de Ridder
*/
public class StoerWagnerMinimumCut
{
final WeightedGraph, DefaultWeightedEdge> workingGraph;
protected double bestCutWeight = Double.POSITIVE_INFINITY;
protected Set bestCut;
/**
* Will compute the minimum cut in graph.
*
* @param graph graph over which to run algorithm
*
* @throws IllegalArgumentException if a negative weight edge is found
* @throws IllegalArgumentException if graph has less than 2 vertices
*/
public StoerWagnerMinimumCut(UndirectedGraph graph)
{
if (graph.vertexSet().size() < 2) {
throw new IllegalArgumentException(
"Graph has less than 2 vertices");
}
//get a version of this graph where each vertex is wrapped with a list
workingGraph =
new SimpleWeightedGraph, DefaultWeightedEdge>(
DefaultWeightedEdge.class);
Map> vertexMap = new HashMap>();
for (V v : graph.vertexSet()) {
Set list = new HashSet();
list.add(v);
vertexMap.put(v, list);
workingGraph.addVertex(list);
}
for (E e : graph.edgeSet()) {
if (graph.getEdgeWeight(e) < 0.0) {
throw new IllegalArgumentException(
"Negative edge weights not allowed");
}
V s = graph.getEdgeSource(e);
Set sNew = vertexMap.get(s);
V t = graph.getEdgeTarget(e);
Set tNew = vertexMap.get(t);
// For multigraphs, we sum the edge weights (either all are
// contained in a cut, or none)
DefaultWeightedEdge eNew = workingGraph.getEdge(sNew, tNew);
if (eNew == null) {
eNew = workingGraph.addEdge(sNew, tNew);
workingGraph.setEdgeWeight(eNew, graph.getEdgeWeight(e));
} else {
workingGraph.setEdgeWeight(
eNew,
workingGraph.getEdgeWeight(eNew) + graph.getEdgeWeight(e));
}
}
//arbitrary vertex used to seed the algorithm.
Set a = workingGraph.vertexSet().iterator().next();
while (workingGraph.vertexSet().size() > 1) {
minimumCutPhase(a);
}
}
/**
* Implements the MinimumCutPhase function of Stoer and Wagner
*/
protected void minimumCutPhase(Set a)
{
// The last and before last vertices added to A.
Set last = a, beforelast = null;
// queue contains vertices not in A ordered by max weight of edges to A.
PriorityQueue queue =
new PriorityQueue();
// Maps vertices to elements of queue
Map, VertexAndWeight> dmap =
new HashMap, VertexAndWeight>();
// Initialize queue
for (Set v : workingGraph.vertexSet()) {
if (v == a) {
continue;
}
DefaultWeightedEdge e = workingGraph.getEdge(v, a);
Double w = (e == null) ? 0.0 : workingGraph.getEdgeWeight(e);
VertexAndWeight vandw = new VertexAndWeight(v, w, e != null);
queue.add(vandw);
dmap.put(v, vandw);
}
// Now iteratively update the queue to get the required vertex ordering
while (!queue.isEmpty()) {
Set v = queue.poll().vertex;
dmap.remove(v);
beforelast = last;
last = v;
for (DefaultWeightedEdge e : workingGraph.edgesOf(v)) {
Set vc = Graphs.getOppositeVertex(workingGraph, e, v);
VertexAndWeight vcandw = dmap.get(vc);
if (vcandw != null) {
queue.remove(vcandw); //this is O(logn) but could be O(1)?
vcandw.active = true;
vcandw.weight += workingGraph.getEdgeWeight(e);
queue.add(vcandw); //this is O(logn) but could be O(1)?
}
}
}
// Update the best cut
double w = vertexWeight(last);
if (w < bestCutWeight) {
bestCutWeight = w;
bestCut = last;
}
//merge the last added vertices
mergeVertices(beforelast, last);
}
/**
* Return the weight of the minimum cut
*/
public double minCutWeight()
{
return bestCutWeight;
}
/**
* Return a set of vertices on one side of the cut
*/
public Set minCut()
{
return bestCut;
}
/**
* Merges vertex t into vertex s, summing the weights as required. Returns
* the merged vertex and the sum of its weights
*/
protected VertexAndWeight mergeVertices(Set s, Set t)
{
//construct the new combinedvertex
Set set = new HashSet();
set.addAll(s);
set.addAll(t);
workingGraph.addVertex(set);
//add edges and weights to the combined vertex
double wsum = 0.0;
for (Set v : workingGraph.vertexSet()) {
if ((s != v) && (t != v)) {
double neww = 0.0;
DefaultWeightedEdge etv = workingGraph.getEdge(t, v);
DefaultWeightedEdge esv = workingGraph.getEdge(s, v);
if (etv != null) {
neww += workingGraph.getEdgeWeight(etv);
}
if (esv != null) {
neww += workingGraph.getEdgeWeight(esv);
}
if ((etv != null) || (esv != null)) {
wsum += neww;
workingGraph.setEdgeWeight(
workingGraph.addEdge(set, v),
neww);
}
}
}
//remove original vertices
workingGraph.removeVertex(t);
workingGraph.removeVertex(s);
return new VertexAndWeight(set, wsum, false);
}
/**
* Compute the sum of the weights entering a vertex
*/
public double vertexWeight(Set v)
{
double wsum = 0.0;
for (DefaultWeightedEdge e : workingGraph.edgesOf(v)) {
wsum += workingGraph.getEdgeWeight(e);
}
return wsum;
}
/**
* Class for weighted vertices
*/
protected class VertexAndWeight
implements Comparable
{
public Set vertex;
public Double weight;
public boolean active; // active == neighbour in A
public VertexAndWeight(Set v, double w, boolean active)
{
this.vertex = v;
this.weight = w;
this.active = active;
}
/**
* compareTo that sorts in reverse order because we need extract-max and
* queue provides extract-min.
*/
@Override public int compareTo(VertexAndWeight that)
{
if (this.active && that.active) {
return -Double.compare(weight, that.weight);
}
if (this.active && !that.active) {
return -1;
}
if (!this.active && that.active) {
return +1;
}
// both inactive
return 0;
}
@Override public String toString()
{
return "(" + vertex + ", " + weight + ")";
}
}
}
// End StoerWagnerMinimumCut.java