Commit a99a213d authored by sbalev's avatar sbalev

* Added new package org.graphstream.algorithm.util

* Moved FibonacciHeap there
* Added a class RandomTools with methods generating random stuff
* On the fly, added in Toolkit several useful methods for picking random
  subsets of nodes/edges
parent 369ce4d2
......@@ -35,6 +35,7 @@ import java.util.List;
import java.util.NoSuchElementException;
import java.util.Stack;
import org.graphstream.algorithm.util.FibonacciHeap;
import org.graphstream.graph.Edge;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
......
......@@ -31,6 +31,7 @@ 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;
......@@ -1347,9 +1348,9 @@ public class Toolkit extends
* The adjacency matrix of a graph is a <i>n</i> times <i>n</i> matrix
* {@code a}, where <i>n</i> is the number of nodes of the graph. The
* element {@code a[i][j]} of this matrix is equal to the number of edges
* from the node {@code graph.getNode(i)} to the node {@code
* graph.getNode(j)}. An undirected edge between i-th and j-th node is
* counted twice: in {@code a[i][j]} and in {@code a[j][i]}.
* from the node {@code graph.getNode(i)} to the node
* {@code graph.getNode(j)}. An undirected edge between i-th and j-th node
* is counted twice: in {@code a[i][j]} and in {@code a[j][i]}.
*
* @param graph
* A graph.
......@@ -1381,9 +1382,9 @@ public class Toolkit extends
* The adjacency matrix of a graph is a <i>n</i> times <i>n</i> matrix
* {@code a}, where <i>n</i> is the number of nodes of the graph. The
* element {@code a[i][j]} of this matrix is equal to the number of edges
* from the node {@code graph.getNode(i)} to the node {@code
* graph.getNode(j)}. An undirected edge between i-th and j-th node is
* counted twice: in {@code a[i][j]} and in {@code a[j][i]}.
* from the node {@code graph.getNode(i)} to the node
* {@code graph.getNode(j)}. An undirected edge between i-th and j-th node
* is counted twice: in {@code a[i][j]} and in {@code a[j][i]}.
*
* @param graph
* A graph
......@@ -1407,12 +1408,12 @@ public class Toolkit extends
* number of edges of the graph. The coefficients {@code a[i][j]} of this
* matrix have the following values:
* <ul>
* <li>-1 if {@code graph.getEdge(j)} is directed and {@code
* graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getEdge(j)} is undirected and {@code
* graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getNode(i)} is the target of {@code
* graph.getEdge(j)}.</li>
* <li>-1 if {@code graph.getEdge(j)} is directed and
* {@code graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getEdge(j)} is undirected and
* {@code graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getNode(i)} is the target of
* {@code graph.getEdge(j)}.</li>
* <li>0 otherwise.
* </ul>
* In the special case when the j-th edge is a loop connecting the i-th node
......@@ -1450,12 +1451,12 @@ public class Toolkit extends
* number of edges of the graph. The coefficients {@code a[i][j]} of this
* matrix have the following values:
* <ul>
* <li>-1 if {@code graph.getEdge(j)} is directed and {@code
* graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getEdge(j)} is undirected and {@code
* graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getNode(i)} is the target of {@code
* graph.getEdge(j)}.</li>
* <li>-1 if {@code graph.getEdge(j)} is directed and
* {@code graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getEdge(j)} is undirected and
* {@code graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getNode(i)} is the target of
* {@code graph.getEdge(j)}.</li>
* <li>0 otherwise.</li>
* </ul>
* In the special case when the j-th edge is a loop connecting the i-th node
......@@ -1523,4 +1524,190 @@ public class Toolkit extends
public static void computeLayout(Graph g) {
computeLayout(g, new SpringBox(), 0.99);
}
/**
* Returns a random subset of nodes of fixed size. Each node has the same
* chance to be chosen.
*
* @param graph
* A graph.
* @param k
* The size of the subset.
* @return A random subset of nodes of size <code>k</code>.
* @throws IllegalArgumentException
* If <code>k</code> is negative or greater than the number of
* nodes.
* @complexity O(<code>k</code>)
*/
public static <T extends Node> List<T> randomNodeSet(Graph graph, int k) {
return randomNodeSet(graph, k, new Random());
}
/**
* Returns a random subset of nodes of fixed size. Each node has the same
* chance to be chosen.
*
* @param graph
* A graph.
* @param k
* The size of the subset.
* @param random
* A source of randomness.
* @return A random subset of nodes of size <code>k</code>.
* @throws IllegalArgumentException
* If <code>k</code> is negative or greater than the number of
* nodes.
* @complexity O(<code>k</code>)
*/
public static <T extends Node> List<T> randomNodeSet(Graph graph, int k,
Random random) {
if (k < 0 || k > graph.getNodeCount())
throw new IllegalArgumentException("k must be between 0 and "
+ graph.getNodeCount());
Set<Integer> subset = RandomTools.randomKsubset(graph.getNodeCount(),
k, null, random);
List<T> result = new ArrayList<T>(subset.size());
for (int i : subset)
result.add(graph.<T> getNode(i));
return result;
}
/**
* Returns a random subset of nodes. Each node is chosen with given
* probability.
*
* @param graph
* A graph.
* @param p
* The probability to choose each node.
* @return A random subset of nodes.
* @throws IllegalArgumentException
* If <code>p</code> is negative or greater than one.
* @complexity In average O(<code>n * p<code>), where <code>n</code> is the
* number of nodes.
*/
public static <T extends Node> List<T> randomNodeSet(Graph graph, double p) {
return randomNodeSet(graph, p, new Random());
}
/**
* Returns a random subset of nodes. Each node is chosen with given
* probability.
*
* @param graph
* A graph.
* @param p
* The probability to choose each node.
* @param random
* A source of randomness.
* @return A random subset of nodes.
* @throws IllegalArgumentException
* If <code>p</code> is negative or greater than one.
* @complexity In average O(<code>n * p<code>), where <code>n</code> is the
* number of nodes.
*/
public static <T extends Node> List<T> randomNodeSet(Graph graph, double p,
Random random) {
if (p < 0 || p > 1)
throw new IllegalArgumentException("p must be between 0 and 1");
Set<Integer> subset = RandomTools.randomPsubset(graph.getNodeCount(),
p, null, random);
List<T> result = new ArrayList<T>(subset.size());
for (int i : subset)
result.add(graph.<T> getNode(i));
return result;
}
/**
* Returns a random subset of edges of fixed size. Each edge has the same
* chance to be chosen.
*
* @param graph
* A graph.
* @param k
* The size of the subset.
* @return A random subset of edges of size <code>k</code>.
* @throws IllegalArgumentException
* If <code>k</code> is negative or greater than the number of
* edges.
* @complexity O(<code>k</code>)
*/
public static <T extends Edge> List<T> randomEdgeSet(Graph graph, int k) {
return randomEdgeSet(graph, k, new Random());
}
/**
* Returns a random subset of edges of fixed size. Each edge has the same
* chance to be chosen.
*
* @param graph
* A graph.
* @param k
* The size of the subset.
* @param random
* A source of randomness.
* @return A random subset of edges of size <code>k</code>.
* @throws IllegalArgumentException
* If <code>k</code> is negative or greater than the number of
* edges.
* @complexity O(<code>k</code>)
*/
public static <T extends Edge> List<T> randomEdgeSet(Graph graph, int k,
Random random) {
if (k < 0 || k > graph.getEdgeCount())
throw new IllegalArgumentException("k must be between 0 and "
+ graph.getEdgeCount());
Set<Integer> subset = RandomTools.randomKsubset(graph.getEdgeCount(),
k, null, random);
List<T> result = new ArrayList<T>(subset.size());
for (int i : subset)
result.add(graph.<T> getEdge(i));
return result;
}
/**
* Returns a random subset of edges. Each edge is chosen with given
* probability.
*
* @param graph
* A graph.
* @param p
* The probability to choose each edge.
* @return A random subset of edges.
* @throws IllegalArgumentException
* If <code>p</code> is negative or greater than one.
* @complexity In average O(<code>m * p<code>), where <code>m</code> is the
* number of edges.
*/
public static <T extends Edge> List<T> randomEdgeSet(Graph graph, double p) {
return randomEdgeSet(graph, p, new Random());
}
/**
* Returns a random subset of edges. Each edge is chosen with given
* probability.
*
* @param graph
* A graph.
* @param p
* The probability to choose each edge.
* @param random
* A source of randomness.
* @return A random subset of edges.
* @throws IllegalArgumentException
* If <code>p</code> is negative or greater than one.
* @complexity In average O(<code>m * p<code>), where <code>m</code> is the
* number of edges.
*/
public static <T extends Edge> List<T> randomEdgeSet(Graph graph, double p,
Random random) {
if (p < 0 || p > 1)
throw new IllegalArgumentException("p must be between 0 and 1");
Set<Integer> subset = RandomTools.randomPsubset(graph.getEdgeCount(),
p, null, random);
List<T> result = new ArrayList<T>(subset.size());
for (int i : subset)
result.add(graph.<T> getEdge(i));
return result;
}
}
......@@ -27,7 +27,7 @@
* 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;
package org.graphstream.algorithm.util;
import java.util.ArrayList;
......
package org.graphstream.algorithm.util;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
/**
* This class provides several static methods for generating random numbers and
* sets
*/
public class RandomTools {
/**
* Returns a pseudorandom number drawn from exponential distribution with
* mean 1.
*
* Uses the von Neumann's exponential generator.
*
* @param rnd
* source of randomness
* @return a pseudorandom number drawn from exponential distribution with
* mean 1.
* @complexity O(1) average complexity. The expected number of uniformly
* distributed numbers used is e^2 / (e - 1)
*
*/
public static double exponential(Random rnd) {
double y, w, u;
int z, k;
z = -1;
do {
w = y = rnd.nextDouble();
k = 1;
while (true) {
u = rnd.nextDouble();
if (u > w)
break;
w = u;
k++;
}
z++;
} while ((k & 1) == 0);
return z + y;
}
/**
* Returns a pseudorandom number drawn from binomial distribution B(n, p).
*
* Uses a simple waiting time method based on exponential distribution.
*
* @param n
* number of tries
* @param p
* success probability
* @param rnd
* source of randomness
* @return a pseudorandom number drawn from binomial distribution
* @complexity Average complexity O(np)
*/
public static int binomial(int n, double p, Random rnd) {
double q = -Math.log(1 - p);
int x = 0;
double s = 0;
do {
s += exponential(rnd) / (n - x);
x++;
} while (s <= q);
return x - 1;
}
/**
* Generates a pseudorandom subset of size k of the set {0, 1,...,n - 1}.
* Each element has the same chance to be chosen.
*
* Uses Floyd's method of subset generation with only k iterations. Note
* that the quality of this generator is limited by Java's random generator.
* Java stores the internal state in 48 bits, so in the best case we can
* only generate 2^48 different subsets.
*
* @param n
* the size of the initial set
* @param k
* the size of the generated set
* @param subset
* if not null, this set is cleared and the result is stored
* here. This avoids creations of sets at each call of this
* method
* @param rnd
* source of randomness
* @return a pseudorandom subset of size k of the set {0, 1,...,n}
* @complexity Depends on the set implementation. If add and lookup
* operations take constant time, the complexity is O(k)
*/
public static Set<Integer> randomKsubset(int n, int k, Set<Integer> subset,
Random rnd) {
if (subset == null)
subset = new HashSet<Integer>(4 * k / 3 + 1);
else
subset.clear();
for (int i = n - k; i < n; i++) {
int j = rnd.nextInt(i + 1);
subset.add(subset.contains(j) ? i : j);
}
return subset;
}
/**
* Generates a pseudorandom subset of the set {0, 1,...,n - 1}. Each element
* is chosen with probability p.
*
* @param n
* the size of the initial set
* @param p
* the probability to choose each element
* @param subset
* if not null, this set is cleared and the result is stored
* here. This avoids creations of sets at each call of this
* method
* @param rnd
* source of randomness
* @return a pseudorandom subset of the set {0, 1,...,n}.
* @complexity Depends on the set implementation. If add and lookup
* operations take constant time, the complexity is O(np)
*/
public static Set<Integer> randomPsubset(int n, double p,
Set<Integer> subset, Random rnd) {
return randomKsubset(n, binomial(n, p, rnd), subset, rnd);
}
}
/*
* Copyright 2006 - 2012
* Stefan Balev <stefan.balev@graphstream-project.org>
* Julien Baudry <julien.baudry@graphstream-project.org>
* Antoine Dutot <antoine.dutot@graphstream-project.org>
* Yoann Pigné <yoann.pigne@graphstream-project.org>
* Guilhelm Savin <guilhelm.savin@graphstream-project.org>
*
* 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 <http://www.cecill.info> 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 <http://www.gnu.org/licenses/>.
*
* 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.util;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment