All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graphstream.algorithm.Kruskal Maven / Gradle / Ivy

Go to download

The GraphStream library. With GraphStream you deal with graphs. Static and Dynamic. You create them from scratch, from a file or any source. You display and render them. This package contains algorithms and generators.

There is a newer version: 2.0
Show newest version
/*
 * Copyright 2006 - 2013
 *     Stefan Balev     
 *     Julien Baudry    
 *     Antoine Dutot    
 *     Yoann Pigné      
 *     Guilhelm Savin   
 * 
 * This file is part of GraphStream .
 * 
 * GraphStream is a library whose purpose is to handle static or dynamic
 * graph, create them from scratch, file or any source and display them.
 * 
 * This program is free software distributed under the terms of two licenses, the
 * CeCILL-C license that fits European law, and the GNU Lesser General Public
 * License. You can  use, modify and/ or redistribute the software under the terms
 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
 * URL  or under the terms of the GNU LGPL as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 * 
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
 */
package org.graphstream.algorithm;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.graphstream.algorithm.util.DisjointSets;
import org.graphstream.graph.Edge;
import org.graphstream.graph.Node;

/**
 * Compute a spanning tree using the Kruskal algorithm.
 * 
 * 

* Kruskal's algorithm is a greedy algorithm which allows to find a minimal * spanning tree in a weighted connected graph. More informations on Wikipedia. *

* *

Example

* * The following example generates a graph with the Dorogovtsev-Mendes generator * and then computes a spanning-tree using the Kruskal algorithm. The generator * creates random weights for edges that will be used by the Kruskal algorithm. * * If no weight is present, algorithm considers that all weights are set to 1. * * When an edge is in the spanning tree, the algorithm will set its "ui.class" * attribute to "intree", else the attribute is set to "notintree". According to * the css stylesheet that is defined, spanning will be displayed with thick * black lines while edges not in the spanning tree will be displayed with thin * gray lines. * *
 * import org.graphstream.graph.Graph;
 * import org.graphstream.graph.implementations.DefaultGraph;
 * 
 * import org.graphstream.algorithm.Kruskal;
 * import org.graphstream.algorithm.generator.DorogovtsevMendesGenerator;
 * 
 * public class KruskalTest {
 *  
 * 	public static void main(String .. args) {
 * 		DorogovtsevMendesGenerator gen = new DorogovtsevMendesGenerator();
 * 		Graph graph = new DefaultGraph("Kruskal Test");
 * 
 *  	String css = "edge .notintree {size:1px;fill-color:gray;} " +
 *  				 "edge .intree {size:3px;fill-color:black;}";
 *  
 * 		graph.addAttribute("ui.stylesheet", css);
 * 		graph.display();
 * 
 * 		gen.addEdgeAttribute("weight");
 * 		gen.setEdgeAttributesRange(1, 100);
 * 		gen.addSink(graph);
 * 		gen.begin();
 * 		for (int i = 0; i < 100 && gen.nextEvents(); i++)
 * 			;
 * 		gen.end();
 * 
 * 		Kruskal kruskal = new Kruskal("ui.class", "intree", "notintree");
 * 
 * 		kruskal.init(g);
 * 		kruskal.compute();
 *  }
 * }
 * 
* * @complexity O(m log n) where m is the number of edges and n is the number of * nodes of the graph * @reference Joseph. B. Kruskal: On the Shortest Spanning Subtree of a Graph * and the Traveling Salesman Problem. In: Proceedings of the * American Mathematical Society, Vol 7, No. 1 (Feb, 1956), pp. 48–50 * @see org.graphstream.algorithm.AbstractSpanningTree * */ public class Kruskal extends AbstractSpanningTree { /** * Default weight attribute */ public static final String DEFAULT_WEIGHT_ATTRIBUTE = "weight"; /** * Attribute where the weights of the edges are stored */ protected String weightAttribute; /** * List of the tree edges. Used by the iterator. */ protected List treeEdges; /** * The weight of the spanning tree */ protected double treeWeight; /** * Create a new Kruskal's algorithm. Uses the default weight attribute and * does not tag the edges. */ public Kruskal() { this(DEFAULT_WEIGHT_ATTRIBUTE, null); } /** * Create a new Kruskal's algorithm. The value of the flag attribute is * {@code true} for the tree edges and false for the non-tree edges. * * @param weightAttribute * attribute used to compare edges * @param flagAttribute * attribute used to set if an edge is in the spanning tree */ public Kruskal(String weightAttribute, String flagAttribute) { this(weightAttribute, flagAttribute, true, false); } /** * Create a new Kruskal's algorithm. Uses the default weight attribute. * * @param flagAttribute * attribute used to set if an edge is in the spanning tree * @param flagOn * value of the flagAttribute if edge is in the spanning * tree * @param flagOff * value of the flagAttribute if edge is not in the * spanning tree */ public Kruskal(String flagAttribute, Object flagOn, Object flagOff) { this(DEFAULT_WEIGHT_ATTRIBUTE, flagAttribute, flagOn, flagOff); } /** * Create a new Kruskal's algorithm. * * @param weightAttribute * attribute used to compare edges * @param flagAttribute * attribute used to set if an edge is in the spanning tree * @param flagOn * value of the flagAttribute if edge is in the spanning * tree * @param flagOff * value of the flagAttribute if edge is not in the * spanning tree */ public Kruskal(String weightAttribute, String flagAttribute, Object flagOn, Object flagOff) { super(flagAttribute, flagOn, flagOff); this.weightAttribute = weightAttribute; } /** * Get weight attribute used to compare edges. * * @return weight attribute */ public String getWeightAttribute() { return weightAttribute; } /** * Set the weight attribute. * * @param newWeightAttribute * new attribute used */ public void setWeightAttribute(String newWeightAttribute) { this.weightAttribute = newWeightAttribute; } @Override protected void makeTree() { if (treeEdges == null) treeEdges = new LinkedList(); else treeEdges.clear(); List sortedEdges = new ArrayList(graph.getEdgeSet()); Collections.sort(sortedEdges, new EdgeComparator()); DisjointSets components = new DisjointSets( graph.getNodeCount()); for (Node node : graph) components.add(node); treeWeight = 0; for (Edge edge : sortedEdges) if (components.union(edge.getNode0(), edge.getNode1())) { treeEdges.add(edge); edgeOn(edge); treeWeight += getWeight(edge); if (treeEdges.size() == graph.getNodeCount() - 1) break; } sortedEdges.clear(); components.clear(); } @Override public Iterator getTreeEdgesIterator() { return new TreeIterator(); } @Override public void clear() { super.clear(); treeEdges.clear(); } /** * Returns the total weight of the minimum spanning tree * * @return The sum of the weights of the edges in the spanning tree */ public double getTreeWeight() { return treeWeight; } // helpers protected double getWeight(Edge e) { if (weightAttribute == null) return 1.0; double w = e.getNumber(weightAttribute); if (Double.isNaN(w)) return 1; return w; } protected class EdgeComparator implements Comparator { public int compare(Edge arg0, Edge arg1) { double w0 = getWeight(arg0); double w1 = getWeight(arg1); if (w0 < w1) return -1; if (w0 > w1) return 1; return 0; } } protected class TreeIterator implements Iterator { protected Iterator it = treeEdges.iterator(); public boolean hasNext() { return it.hasNext(); } @SuppressWarnings("unchecked") public T next() { return (T) it.next(); } public void remove() { throw new UnsupportedOperationException( "This iterator does not support remove."); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy