From a99a213de39e9c6a15862cfccab8681801e409fa Mon Sep 17 00:00:00 2001
From: sbalev
Date: Thu, 19 Apr 2012 11:21:30 +0200
Subject: [PATCH] * 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
---
src/org/graphstream/algorithm/Dijkstra.java | 1 +
src/org/graphstream/algorithm/Toolkit.java | 223 ++++++++++++++++--
.../algorithm/{ => util}/FibonacciHeap.java | 2 +-
.../algorithm/util/RandomTools.java | 129 ++++++++++
.../algorithm/util/package-info.java | 30 +++
5 files changed, 366 insertions(+), 19 deletions(-)
rename src/org/graphstream/algorithm/{ => util}/FibonacciHeap.java (99%)
create mode 100644 src/org/graphstream/algorithm/util/RandomTools.java
create mode 100644 src/org/graphstream/algorithm/util/package-info.java
diff --git a/src/org/graphstream/algorithm/Dijkstra.java b/src/org/graphstream/algorithm/Dijkstra.java
index cab457d..6ac8a9c 100644
--- a/src/org/graphstream/algorithm/Dijkstra.java
+++ b/src/org/graphstream/algorithm/Dijkstra.java
@@ -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;
diff --git a/src/org/graphstream/algorithm/Toolkit.java b/src/org/graphstream/algorithm/Toolkit.java
index 9dc0d3f..3284e1a 100644
--- a/src/org/graphstream/algorithm/Toolkit.java
+++ b/src/org/graphstream/algorithm/Toolkit.java
@@ -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 n times n matrix
* {@code a}, where n 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 n times n matrix
* {@code a}, where n 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:
*
- * - -1 if {@code graph.getEdge(j)} is directed and {@code
- * graph.getNode(i)} is its source.
- * - 1 if {@code graph.getEdge(j)} is undirected and {@code
- * graph.getNode(i)} is its source.
- * - 1 if {@code graph.getNode(i)} is the target of {@code
- * graph.getEdge(j)}.
+ * - -1 if {@code graph.getEdge(j)} is directed and
+ * {@code graph.getNode(i)} is its source.
+ * - 1 if {@code graph.getEdge(j)} is undirected and
+ * {@code graph.getNode(i)} is its source.
+ * - 1 if {@code graph.getNode(i)} is the target of
+ * {@code graph.getEdge(j)}.
* - 0 otherwise.
*
* 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:
*
- * - -1 if {@code graph.getEdge(j)} is directed and {@code
- * graph.getNode(i)} is its source.
- * - 1 if {@code graph.getEdge(j)} is undirected and {@code
- * graph.getNode(i)} is its source.
- * - 1 if {@code graph.getNode(i)} is the target of {@code
- * graph.getEdge(j)}.
+ * - -1 if {@code graph.getEdge(j)} is directed and
+ * {@code graph.getNode(i)} is its source.
+ * - 1 if {@code graph.getEdge(j)} is undirected and
+ * {@code graph.getNode(i)} is its source.
+ * - 1 if {@code graph.getNode(i)} is the target of
+ * {@code graph.getEdge(j)}.
* - 0 otherwise.
*
* 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 k
.
+ * @throws IllegalArgumentException
+ * If k
is negative or greater than the number of
+ * nodes.
+ * @complexity O(k
)
+ */
+ public static List 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 k
.
+ * @throws IllegalArgumentException
+ * If k
is negative or greater than the number of
+ * nodes.
+ * @complexity O(k
)
+ */
+ public static List 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 subset = RandomTools.randomKsubset(graph.getNodeCount(),
+ k, null, random);
+ List result = new ArrayList(subset.size());
+ for (int i : subset)
+ result.add(graph. 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 p
is negative or greater than one.
+ * @complexity In average O(n * p), where n
is the
+ * number of nodes.
+ */
+ public static List 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 p
is negative or greater than one.
+ * @complexity In average O(n * p), where n
is the
+ * number of nodes.
+ */
+ public static List randomNodeSet(Graph graph, double p,
+ Random random) {
+ if (p < 0 || p > 1)
+ throw new IllegalArgumentException("p must be between 0 and 1");
+ Set subset = RandomTools.randomPsubset(graph.getNodeCount(),
+ p, null, random);
+ List result = new ArrayList(subset.size());
+ for (int i : subset)
+ result.add(graph. 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 k
.
+ * @throws IllegalArgumentException
+ * If k
is negative or greater than the number of
+ * edges.
+ * @complexity O(k
)
+ */
+ public static List 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 k
.
+ * @throws IllegalArgumentException
+ * If k
is negative or greater than the number of
+ * edges.
+ * @complexity O(k
)
+ */
+ public static List 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 subset = RandomTools.randomKsubset(graph.getEdgeCount(),
+ k, null, random);
+ List result = new ArrayList(subset.size());
+ for (int i : subset)
+ result.add(graph. 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 p
is negative or greater than one.
+ * @complexity In average O(m * p), where m
is the
+ * number of edges.
+ */
+ public static List 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 p
is negative or greater than one.
+ * @complexity In average O(m * p), where m
is the
+ * number of edges.
+ */
+ public static List randomEdgeSet(Graph graph, double p,
+ Random random) {
+ if (p < 0 || p > 1)
+ throw new IllegalArgumentException("p must be between 0 and 1");
+ Set subset = RandomTools.randomPsubset(graph.getEdgeCount(),
+ p, null, random);
+ List result = new ArrayList(subset.size());
+ for (int i : subset)
+ result.add(graph. getEdge(i));
+ return result;
+ }
}
diff --git a/src/org/graphstream/algorithm/FibonacciHeap.java b/src/org/graphstream/algorithm/util/FibonacciHeap.java
similarity index 99%
rename from src/org/graphstream/algorithm/FibonacciHeap.java
rename to src/org/graphstream/algorithm/util/FibonacciHeap.java
index f58f475..7e62024 100644
--- a/src/org/graphstream/algorithm/FibonacciHeap.java
+++ b/src/org/graphstream/algorithm/util/FibonacciHeap.java
@@ -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;
diff --git a/src/org/graphstream/algorithm/util/RandomTools.java b/src/org/graphstream/algorithm/util/RandomTools.java
new file mode 100644
index 0000000..4460d0f
--- /dev/null
+++ b/src/org/graphstream/algorithm/util/RandomTools.java
@@ -0,0 +1,129 @@
+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 randomKsubset(int n, int k, Set subset,
+ Random rnd) {
+ if (subset == null)
+ subset = new HashSet(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 randomPsubset(int n, double p,
+ Set subset, Random rnd) {
+ return randomKsubset(n, binomial(n, p, rnd), subset, rnd);
+ }
+}
diff --git a/src/org/graphstream/algorithm/util/package-info.java b/src/org/graphstream/algorithm/util/package-info.java
new file mode 100644
index 0000000..63279cd
--- /dev/null
+++ b/src/org/graphstream/algorithm/util/package-info.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2006 - 2012
+ * Stefan Balev
+ * Julien Baudry
+ * Antoine Dutot
+ * Yoann PignÃ©
+ * Guilhelm Savin
+ *
+ * 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.util;
--
GitLab