+++ /dev/null
-package edu.uci.ics.jung.algorithms.shortestpath;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.collections15.Factory;
-import org.apache.commons.collections15.functors.ConstantTransformer;
-import org.apache.commons.collections15.map.LazyMap;
-
-import edu.uci.ics.jung.graph.Forest;
-import edu.uci.ics.jung.graph.Graph;
-import edu.uci.ics.jung.graph.util.EdgeType;
-import edu.uci.ics.jung.graph.util.Pair;
-
-/**
- * For the input Graph, creates a MinimumSpanningTree
- * using a variation of Prim's algorithm.
- *
- * @author Tom Nelson - tomnelson@dev.java.net
- *
- * @param <V>
- * @param <E>
- */
-public class MinimumSpanningForest<V,E> {
-
- protected Graph<V,E> graph;
- protected Forest<V,E> forest;
- protected Map<E,Double> weights;
-
- /**
- * Creates a Forest from the supplied Graph and supplied Factory, which
- * is used to create a new, empty Forest. If non-null, the supplied root
- * will be used as the root of the tree/forest. If the supplied root is
- * null, or not present in the Graph, then an arbitrary Graph vertex
- * will be selected as the root.
- * If the Minimum Spanning Tree does not include all vertices of the
- * Graph, then a leftover vertex is selected as a root, and another
- * tree is created.
- * @param graph the input graph
- * @param factory the factory to use to create the new forest
- * @param root the vertex of the graph to be used as the root of the forest
- * @param weights edge weights
- */
- public MinimumSpanningForest(Graph<V, E> graph, Factory<Forest<V,E>> factory,
- V root, Map<E, Double> weights) {
- this(graph, factory.create(), root, weights);
- }
-
- /**
- * Creates a minimum spanning forest from the supplied graph, populating the
- * supplied Forest, which must be empty.
- * If the supplied root is null, or not present in the Graph,
- * then an arbitrary Graph vertex will be selected as the root.
- * If the Minimum Spanning Tree does not include all vertices of the
- * Graph, then a leftover vertex is selected as a root, and another
- * tree is created
- * @param graph the Graph to find MST in
- * @param forest the Forest to populate. Must be empty
- * @param root first Tree root, may be null
- * @param weights edge weights, may be null
- */
- public MinimumSpanningForest(Graph<V, E> graph, Forest<V,E> forest,
- V root, Map<E, Double> weights) {
-
- if(forest.getVertexCount() != 0) {
- throw new IllegalArgumentException("Supplied Forest must be empty");
- }
- this.graph = graph;
- this.forest = forest;
- if(weights != null) {
- this.weights = weights;
- }
- Set<E> unfinishedEdges = new HashSet<E>(graph.getEdges());
- if(graph.getVertices().contains(root)) {
- this.forest.addVertex(root);
- }
- updateForest(forest.getVertices(), unfinishedEdges);
- }
-
- /**
- * Creates a minimum spanning forest from the supplied graph, populating the
- * supplied Forest, which must be empty.
- * If the supplied root is null, or not present in the Graph,
- * then an arbitrary Graph vertex will be selected as the root.
- * If the Minimum Spanning Tree does not include all vertices of the
- * Graph, then a leftover vertex is selected as a root, and another
- * tree is created
- * @param graph the Graph to find MST in
- * @param forest the Forest to populate. Must be empty
- * @param root first Tree root, may be null
- */
- @SuppressWarnings("unchecked")
- public MinimumSpanningForest(Graph<V, E> graph, Forest<V,E> forest,
- V root) {
-
- if(forest.getVertexCount() != 0) {
- throw new IllegalArgumentException("Supplied Forest must be empty");
- }
- this.graph = graph;
- this.forest = forest;
- this.weights = LazyMap.decorate(new HashMap<E,Double>(),
- new ConstantTransformer(1.0));
- Set<E> unfinishedEdges = new HashSet<E>(graph.getEdges());
- if(graph.getVertices().contains(root)) {
- this.forest.addVertex(root);
- }
- updateForest(forest.getVertices(), unfinishedEdges);
- }
-
- /**
- * Returns the generated forest.
- */
- public Forest<V,E> getForest() {
- return forest;
- }
-
- protected void updateForest(Collection<V> tv, Collection<E> unfinishedEdges) {
- double minCost = Double.MAX_VALUE;
- E nextEdge = null;
- V nextVertex = null;
- V currentVertex = null;
- for(E e : unfinishedEdges) {
-
- if(forest.getEdges().contains(e)) continue;
- // find the lowest cost edge, get its opposite endpoint,
- // and then update forest from its Successors
- Pair<V> endpoints = graph.getEndpoints(e);
- V first = endpoints.getFirst();
- V second = endpoints.getSecond();
- if(tv.contains(first) == true && tv.contains(second) == false) {
- if(weights.get(e) < minCost) {
- minCost = weights.get(e);
- nextEdge = e;
- currentVertex = first;
- nextVertex = second;
- }
- }
- if(graph.getEdgeType(e) == EdgeType.UNDIRECTED &&
- tv.contains(second) == true && tv.contains(first) == false) {
- if(weights.get(e) < minCost) {
- minCost = weights.get(e);
- nextEdge = e;
- currentVertex = second;
- nextVertex = first;
- }
- }
- }
-
- if(nextVertex != null && nextEdge != null) {
- unfinishedEdges.remove(nextEdge);
- forest.addEdge(nextEdge, currentVertex, nextVertex);
- updateForest(forest.getVertices(), unfinishedEdges);
- }
- Collection<V> leftovers = new HashSet<V>(graph.getVertices());
- leftovers.removeAll(forest.getVertices());
- if(leftovers.size() > 0) {
- V anotherRoot = leftovers.iterator().next();
- forest.addVertex(anotherRoot);
- updateForest(forest.getVertices(), unfinishedEdges);
- }
- }
-}