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.
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.
/*
* Copyright 2006 - 2015
* 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.*;
import org.graphstream.algorithm.util.RandomTools;
import org.graphstream.graph.*;
import org.graphstream.stream.GraphReplay;
import org.graphstream.ui.layout.Layout;
import org.graphstream.ui.layout.springbox.implementations.SpringBox;
/**
* Lots of small often used algorithms on graphs.
*
*
* This class contains a lot of very small algorithms that could be often useful
* with a graph. Most methods take a graph as first argument.
*
*
*
Usage
*
*
Degrees
*
*
* The {@link #degreeDistribution(Graph)} method allows to obtain an array where
* each cell index represents the degree, and the value of the cell the number
* of nodes having this degree. Its complexity is O(n) with n the number of
* nodes.
*
*
*
* The {@link #degreeMap(Graph)} returns an array of nodes sorted by degree in
* descending order. The complexity is O(n log(n)) with n the number of nodes.
*
*
*
* The {@link #averageDegree(Graph)} returns the average degree. The complexity
* is O(1).
*
*
*
* The {@link #degreeAverageDeviation(Graph)} returns the deviation of the
* average degree. The complexity is O(n) with n the number of nodes.
*
* *
Density
*
*
* The {@link #density(Graph)} method returns the number of links in the graph
* divided by the total number of possible links. The complexity is O(1).
*
*
*
Diameter
*
*
* The {@link #diameter(Graph)} method computes the diameter of the graph. The
* diameter of the graph is the largest of all the shortest paths from any node
* to any other node.
*
*
*
* The returned diameter is not an integer since some graphs have non-integer
* weights on edges.
*
*
*
* The {@link #diameter(Graph, String, boolean)} method does the same thing, but
* considers that the graph is weighted if the second argument is non-null. The
* second argument is the weight attribute name. The third argument indicates if
* the graph must be considered as directed or not.
*
*
*
* Note that this operation can be quite costly, the algorithm used depends on
* the fact the graph is weighted or not. If unweighted, the algorithm is in
* O(n*(n+m)). If weighted the algorithm is the Floyd-Warshall algorithm whose
* complexity is at worst of O(n^3).
*
*
*
Clustering coefficient
*
*
* The {@link #clusteringCoefficient(Node)} method return the clustering
* coefficient for the given node. The complexity if O(d^2) where d is the
* degree of the node.
*
*
*
* The {@link #clusteringCoefficients(Graph)} method return the clustering
* coefficient of each node of the graph as an array.
*
*
*
* The {@link #averageClusteringCoefficient(Graph)} method return the average
* clustering coefficient for the graph.
*
*
*
Random nodes and edges
*
*
* The {@link #randomNode(Graph)} returns a node chosen at random in the graph.
* You can alternatively pass a ``Random`` instance as parameter with
* {@link #randomNode(Graph, Random)}. The complexity depends on the kind of
* graph.
*
*
*
* The {@link #randomEdge(Graph)} returns an edge chosen at random in the graph.
* You can alternatively pass a ``Random`` instance as parameter with
* {@link #randomEdge(Graph, Random)}. The {@link #randomEdge(Node)} returns an
* edge chosen at random within the edge set of the given node. You can also use
* {@link #randomEdge(Node, Random)}. To chose a random edge of a node inside
* the entering or leaving edge sets only, you can use
* {@link #randomInEdge(Node)} or {@link #randomInEdge(Node, Random)}, or
* {@link #randomOutEdge(Node)} or finally {@link #randomOutEdge(Node, Random)}.
*
*
*
Nodes position
*
*
* Extracting nodes position from attributes can be tricky due to the face the
* positions can be stored either as separate ``x``, ``y`` and ``z`` attributes
* or inside ``xy`` or ``xyz`` attributes.
*
*
*
* To simplify things you can use {@link #nodePosition(Node)} which returns an
* array of three doubles, containing the position of the node. You can also use
* {@link #nodePosition(Graph, String)} with a graph and a node identifier.
*
*
*
* If you already have an array of doubles with at least three cells you can
* also use {@link #nodePosition(Node, double[])} that will store the position
* in the passed array. You can as well use
* {@link #nodePosition(Graph, String, double[])}.
*
*
*
* All these methods can also handle the ``org.graphstream.ui.geom.Point3``
* class instead of arrays of doubles. Methods that use such an array as
* argument are the same. Methods that return a ``Point3`` instead of an array
* are {@link #nodePointPosition(Graph, String)} and
* {@link #nodePointPosition(Node)}.
*
*
*
Cliques
*
*
* A clique C is a subset of the node set of a graph, such that there
* exists an edge between each pair of nodes in C. In other words, the
* subgraph induced by C is complete. A maximal clique is a clique that
* cannot be extended by adding more nodes, that is, there is no node outside
* the clique connected to all the clique nodes.
*
*
*
* This class provides several methods for dealing with cliques. Use
* {@link #isClique(Collection)} or {@link #isMaximalClique(Collection, Graph)}
* to check if a set of nodes is a clique or a maximal clique.
*
*
*
* The methods {@link #getMaximalCliqueIterator(Graph)} and
* {@link #getMaximalCliques(Graph)} enumerate all the maximal cliques in a
* graph. Iterating on all the maximal cliques of a graph can take much time,
* because their number can grow exponentially with the size of the graph. For
* example, the following naive method to find the maximum clique (that is, the
* largest possible clique) in a graph, is practical only for small and sparse
* graphs.
*
*
*
* List<Node> maximumClique = new ArrayList<Node>();
* for (List<Node> clique : Toolkit.getMaximalCliques(g))
* if (clique.size() > maximumClique.size())
* maximumClique = clique;
*
*
*
Example
*
*
* You can use this class with a static import for example:
*
*/
public class Toolkit extends
org.graphstream.ui.graphicGraph.GraphPosLengthUtils {
// Access
/**
* Compute the weighted degree of a given node. For each entering
* and leaving edge the value contained by the 'weightAttribute' is
* considered. If the edge does not have such an attribute, the value
* one is used instead, resolving to a normal degree. Loop edges are counted
* twice. The 'weightAttribute' must contain a number or the default value
* is used.
* @param node The node to consider.
* @param weightAttribute The name of the attribute to look for weights on edges, it must be a number.
* @return The weighted degree.
*/
public static double weightedDegree(Node node, String weightAttribute) {
return weightedDegree(node, weightAttribute, 1);
}
/**
* Compute the weighted degree of a given node. For each entering
* and leaving edge the value contained by the 'weightAttribute' is
* considered. If the edge does not have such an attribute, the value
* `defaultWeightValue` is used instead. Loop edges are counted twice.
* The 'weightAttribute' must contain a number or the default value
* is used.
* @param node The node to consider.
* @param weightAttribute The name of the attribute to look for weights on edges, it must be a number.
* @param defaultWeightValue The default weight value to use if edges do not have the 'weightAttribute'.
* @return The weighted degree.
*/
public static double weightedDegree(Node node, String weightAttribute, double defaultWeightValue) {
double wdegree = 0;
for(Edge edge:node.getEachEdge()) {
if(edge.hasNumber(weightAttribute)) {
if(edge.getSourceNode() == edge.getTargetNode())
wdegree += edge.getNumber(weightAttribute) * 2;
else wdegree += edge.getNumber(weightAttribute);
} else {
if(edge.getSourceNode() == edge.getTargetNode())
wdegree += defaultWeightValue * 2;
else wdegree += defaultWeightValue;
}
}
return wdegree;
}
/**
* Compute the weighted entering degree of a given node. For each
* entering edge the value contained by the 'weightAttribute' is
* considered. If the edge does not have such an attribute, the value
* one is used instead, resolving to a normal degree. Loop edges are counted once
* if directed, but twice if undirected. The 'weightAttribute' must
* contain a number or the default value is used.
* @param node The node to consider.
* @param weightAttribute The name of the attribute to look on edges, it must be a number.
* @param defaultWeightValue The default weight value to use if edges do not have the 'weightAttribute'.
* @return The entering weighted degree.
*/
public static double enteringWeightedDegree(Node node, String weightAttribute) {
return enteringWeightedDegree(node, weightAttribute, 1);
}
/**
* Compute the weighted entering degree of a given node. For each
* entering edge the value contained by the 'weightAttribute' is
* considered. If the edge does not have such an attribute, the value
* 'defaultWeightValue' is used instead. Loop edges are counted once
* if directed, but twice if undirected. The 'weightAttribute' must
* contain a number or the default value is used.
* @param node The node to consider.
* @param weightAttribute The name of the attribute to look on edges, it must be a number.
* @param defaultWeightValue The default weight value to use if edges do not have the 'weightAttribute'.
* @return The entering weighted degree.
*/
public static double enteringWeightedDegree(Node node, String weightAttribute, double defaultWeightValue) {
double wdegree = 0;
for(Edge edge:node.getEnteringEdgeSet()) {
if(edge.hasNumber(weightAttribute)) {
wdegree += edge.getNumber(weightAttribute);
} else {
wdegree += defaultWeightValue;
}
}
return wdegree;
}
/**
* Compute the weighted leaving degree of a given node. For each
* leaving edge the value contained by the 'weightAttribute' is
* considered. If the edge does not have such an attribute, the value
* one is used instead, resolving to a normal degree. Loop edges are counted once
* if directed, but twice if undirected. The 'weightAttribute' must
* contain a number or the default value is used.
* @param node The node to consider.
* @param weightAttribute The name of the attribute to look on edges, it must be a number.
* @param defaultWeightValue The default weight value to use if edges do not have the 'weightAttribute'.
* @return The leaving weighted degree.
*/
public static double leavingWeightedDegree(Node node, String weightAttribute) {
return leavingWeightedDegree(node, weightAttribute, 1);
}
/**
* Compute the weighted leaving degree of a given node. For each
* leaving edge the value contained by the 'weightAttribute' is
* considered. If the edge does not have such an attribute, the value
* 'defaultWeightValue' is used instead. Loop edges are counted once
* if directed, but twice if undirected. The 'weightAttribute' must
* contain a number or the default value is used.
* @param node The node to consider.
* @param weightAttribute The name of the attribute to look on edges, it must be a number.
* @param defaultWeightValue The default weight value to use if edges do not have the 'weightAttribute'.
* @return The leaving weighted degree.
*/
public static double leavingWeightedDegree(Node node, String weightAttribute, double defaultWeightValue) {
double wdegree = 0;
for(Edge edge:node.getLeavingEdgeSet()) {
if(edge.hasNumber(weightAttribute)) {
wdegree += edge.getNumber(weightAttribute);
} else {
wdegree += defaultWeightValue;
}
}
return wdegree;
}
/**
* Compute the degree distribution of this graph. Each cell of the returned
* array contains the number of nodes having degree n where n is the index
* of the cell. For example cell 0 counts how many nodes have zero edges,
* cell 5 counts how many nodes have five edges. The last index indicates
* the maximum degree.
*
* @complexity O(n) where n is the number of nodes.
*/
public static int[] degreeDistribution(Graph graph) {
if (graph.getNodeCount() == 0)
return null;
int max = 0;
int[] dd;
int d;
for (Node node : graph) {
d = node.getDegree();
if (d > max)
max = d;
}
dd = new int[max + 1];
for (Node node : graph) {
d = node.getDegree();
dd[d] += 1;
}
return dd;
}
/**
* Return a list of nodes sorted by degree, the larger first.
*
* @return The degree map.
* @complexity O(n log(n)) where n is the number of nodes.
*/
public static ArrayList degreeMap(Graph graph) {
ArrayList map = new ArrayList();
for (Node node : graph)
map.add(node);
Collections.sort(map, new Comparator() {
public int compare(Node a, Node b) {
return b.getDegree() - a.getDegree();
}
});
return map;
}
/**
* Return a list of nodes sorted by their weighted degree, the larger first.
*
* @param graph The graph to consider.
* @param weightAttribute The name of the attribute to look for weights on edges, it must be a number, or the default value is used.
* @param defaultWeightValue The value to use if the weight attribute is not found on edges.
* @return The degree map.
* @complexity O(n log(n)) where n is the number of nodes.
* @see #weightedDegree(Node, String, double)
*/
public static ArrayList weightedDegreeMap(Graph graph, String weightAttribute, double defaultWeightValue) {
ArrayList map = new ArrayList();
for (Node node : graph)
map.add(node);
Collections.sort(map, new WeightComparator(weightAttribute, defaultWeightValue));
return map;
}
/**
* Return a list of nodes sorted by their weighted degree, the larger first.
*
* @param graph The graph to consider.
* @param weightAttribute The name of the attribute to look for weights on edges, it must be a number, or the default value of one is used.
* @return The degree map.
* @complexity O(n log(n)) where n is the number of nodes.
* @see #weightedDegree(Node, String, double)
*/
public static ArrayList weightedDegreeMap(Graph graph, String weightAttribute) {
return weightedDegreeMap(graph, weightAttribute, 1);
}
/**
* Compare nodes by their weighted degree.
*/
private static class WeightComparator implements Comparator {
private String weightAttribute = "weight";
private double defaultWeightValue = 1;
public WeightComparator(String watt, double dwv) {
this.weightAttribute = watt;
this.defaultWeightValue = dwv;
}
public int compare(Node a, Node b) {
double bw = weightedDegree(b, weightAttribute, defaultWeightValue);
double ba = weightedDegree(a, weightAttribute, defaultWeightValue);
if(bw < ba) return -1;
else if(bw > ba) return 1;
else return 0;
}
}
/**
* Returns the value of the average degree of the graph. A node with a loop
* edge has degree two.
*
* @return The average degree of the graph.
* @complexity O(1).
*/
public static double averageDegree(Graph graph) {
float m = graph.getEdgeCount() * 2;
float n = graph.getNodeCount();
if (n > 0)
return m / n;
return 0;
}
/**
* Returns the value of the degree average deviation of the graph.
*
* @return The degree average deviation.
* @complexity O(n) where n is the number of nodes.
*/
public static double degreeAverageDeviation(Graph graph) {
double average = averageDegree(graph);
double sum = 0;
for (Node node : graph) {
double d = node.getDegree() - average;
sum += d * d;
}
return Math.sqrt(sum / graph.getNodeCount());
}
/**
* The density is the number of links in the graph divided by the total
* number of possible links.
*
* @return The density of the graph.
* @complexity O(1)
*/
public static double density(Graph graph) {
float m = (float) graph.getEdgeCount();
float n = (float) graph.getNodeCount();
if (n > 0)
return ((2 * m) / (n * (n - 1)));
return 0;
}
/**
* Clustering coefficient for each node of the graph.
*
* @return An array whose size correspond to the number of nodes, where each
* element is the clustering coefficient of a node.
* @complexity at worse O(n d^2) where n is the number of nodes and d the
* average or maximum degree of nodes.
*/
public static double[] clusteringCoefficients(Graph graph) {
int n = graph.getNodeCount();
if (n > 0) {
int j = 0;
double[] coefs = new double[n];
for (Node node : graph)
coefs[j++] = clusteringCoefficient(node);
assert (j == n);
return coefs;
}
return new double[0];
}
/**
* Average clustering coefficient of the whole graph. Average of each node
* individual clustering coefficient.
*
* @return The average clustering coefficient.
* @complexity at worse O(n d^2) where n is the number of nodes and d the
* average or maximum degree of nodes.
*/
public static double averageClusteringCoefficient(Graph graph) {
int n = graph.getNodeCount();
if (n > 0) {
double cc = 0;
for (Node node : graph)
cc += clusteringCoefficient(node);
return cc / n;
}
return 0;
}
/**
* Clustering coefficient for one node of the graph. For a node i with
* degree k, if Ni is the neighborhood of i (a set of nodes), clustering
* coefficient of i is defined as the count of edge e_uv with u,v in Ni
* divided by the maximum possible count, ie. k * (k-1) / 2.
*
* This method only works with undirected graphs.
*
* @param node
* The node to compute the clustering coefficient for.
* @return The clustering coefficient for this node.
* @complexity O(d^2) where d is the degree of the given node.
* @reference D. J. Watts and Steven Strogatz (June 1998).
* "Collective dynamics of 'small-world' networks" . Nature 393
* (6684): 440–442
*/
public static double clusteringCoefficient(Node node) {
double coef = 0.0;
int n = node.getDegree();
if (n > 1) {
Node[] nodes = new Node[n];
//
// Collect the neighbor nodes.
//
for (int i = 0; i < n; i++)
nodes[i] = node.getEdge(i).getOpposite(node);
//
// Check all edge possibilities
//
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
if (j != i) {
Edge e = nodes[j].getEdgeToward(nodes[i].getId());
if (e != null && e.getSourceNode() == nodes[j])
coef++;
}
coef /= (n * (n - 1)) / 2.0;
}
return coef;
}
/**
* Choose a node at random.
*
* @return A node chosen at random, null if the graph is empty.
* @complexity O(1).
*/
public static Node randomNode(Graph graph) {
return randomNode(graph, new Random());
}
/**
* Choose a node at random.
*
* @param random
* The random number generator to use.
* @return A node chosen at random, null if the graph is empty.
* @complexity O(1).
*/
public static Node randomNode(Graph graph, Random random) {
int n = graph.getNodeCount();
if (n > 0) {
return graph.getNode(random.nextInt(n));
// int r = random.nextInt(n);
// int i = 0;
//
// for (Node node : graph) {
// if (r == i)
// return node;
// i++;
// }
}
return null;
}
/**
* Choose an edge at random.
*
* @return An edge chosen at random.
* @complexity O(1).
*/
public static Edge randomEdge(Graph graph) {
return randomEdge(graph, new Random());
}
/**
* Choose an edge at random.
*
* @param random
* The random number generator to use.
* @return O(1).
*/
public static Edge randomEdge(Graph graph, Random random) {
int n = graph.getEdgeCount();
if (n > 0) {
return graph.getEdge(random.nextInt(n));
// int r = random.nextInt(n);
// int i = 0;
//
// for (Edge edge : graph.getEachEdge()) {
// if (r == i)
// return edge;
// i++;
// }
}
return null;
}
/**
* Choose an edge at random from the edges connected to the given node.
*
* @return O(1).
*/
public static Edge randomEdge(Node node) {
return randomEdge(node, new Random());
}
/**
* Choose an edge at random from the entering edges connected to the given
* node.
*
* @return O(1).
*/
public static Edge randomInEdge(Node node) {
return randomInEdge(node, new Random());
}
/**
* Choose an edge at random from the leaving edges connected to the given
* node.
*
* @return An edge chosen at random, null if the node has no leaving edges.
* @complexity O(1).
*/
public static Edge randomOutEdge(Node node) {
return randomOutEdge(node, new Random());
}
/**
* Choose an edge at random from the edges connected to the given node.
*
* @param random
* The random number generator to use.
* @return An edge chosen at random, null if the node has no edges.
* @complexity O(1).
*/
public static Edge randomEdge(Node node, Random random) {
int n = node.getDegree();
if (n > 0) {
return node.getEdge(random.nextInt(n));
// int r = random.nextInt(n);
// int i = 0;
//
// for (Edge edge : node.getEdgeSet()) {
// if (r == i)
// return edge;
// i++;
// }
}
return null;
}
/**
* Choose an edge at random from the entering edges connected to the given
* node.
*
* @param random
* The random number generator to use.
* @return An edge chosen at random, null if the node has no entering edges.
* @complexity O(1).
*/
public static Edge randomInEdge(Node node, Random random) {
int n = node.getInDegree();
if (n > 0) {
return node.getEnteringEdge(random.nextInt(n));
// int r = random.nextInt(n);
// int i = 0;
//
// for (Edge edge : node.getEnteringEdgeSet()) {
// if (r == i)
// return edge;
// i++;
// }
}
return null;
}
/**
* Choose an edge at random from the leaving edges connected to the given
* node.
*
* @param random
* The random number generator to use.
* @return An edge chosen at random, null if the node has no leaving edges.
* @complexity O(1).
*/
public static Edge randomOutEdge(Node node, Random random) {
int n = node.getOutDegree();
if (n > 0) {
return node.getLeavingEdge(random.nextInt(n));
// int r = random.nextInt(n);
// int i = 0;
//
// for (Edge edge : node.getLeavingEdgeSet()) {
// if (r == i)
// return edge;
// i += 1;
// }
}
return null;
}
/**
* Return set of nodes grouped by the value of one attribute (the marker).
* For example, if the marker is "color" and in the graph there are nodes
* whose "color" attribute value is "red" and others with value "blue", this
* method will return two sets, one containing all nodes corresponding to
* the nodes whose "color" attribute is red, the other with blue nodes. If
* some nodes do not have the "color" attribute, a third set is returned.
* The returned sets are stored in a hash map whose keys are the values of
* the marker attribute (in our example, the keys would be "red" and "blue",
* and if there are nodes that do not have the "color" attribute, the third
* set will have key "NULL_COMMUNITY").
*
* @param marker
* The attribute that allows to group nodes.
* @return The communities indexed by the value of the marker.
* @complexity O(n) with n the number of nodes.
*/
public static HashMap