
org.dishevelled.analysis.GraphGenerators Maven / Gradle / Ivy
/*
dsh-analysis Data analysis.
Copyright (c) 2011-2014 held jointly by the individual authors.
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 3 of the License, or (at
your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; with out 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 library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> http://www.fsf.org/licensing/licenses/lgpl.html
> http://www.opensource.org/licenses/lgpl-license.php
*/
package org.dishevelled.analysis;
import java.util.List;
import org.apache.commons.math.random.JDKRandomGenerator;
import org.apache.commons.math.random.RandomGenerator;
import org.dishevelled.collect.Lists;
import org.dishevelled.functor.BinaryFunction;
import org.dishevelled.graph.Edge;
import org.dishevelled.graph.Graph;
import org.dishevelled.graph.Node;
import org.dishevelled.graph.impl.GraphUtils;
import org.dishevelled.multimap.BinaryKeyMap;
import org.dishevelled.multimap.impl.BinaryKeyMaps;
import org.dishevelled.weighted.WeightedMap;
import org.dishevelled.weighted.WeightedMaps;
/**
* Graph generators.
*
* @author Michael Heuer
*/
public final class GraphGenerators
{
/** Default unconnected node weight, 0.1d
. */
private static final double DEFAULT_UNCONNECTED_NODE_WEIGHT = 0.1d;
/**
* Private no-arg constructor.
*/
private GraphGenerators()
{
// empty
}
/**
* Connect the specified graph completely with the specified value on all added edges.
*
* @param graph node type
* @param graph edge type
* @param graph graph to connect, must not be null
* @param edgeValue edge value
* @return the specified graph connected completely with the specified value on all added edges
*/
public static Graph connectCompletely(final Graph graph, final E edgeValue)
{
return connectCompletely(graph, new Scalar(edgeValue));
}
/**
* Connect the specified graph completely with values provided by the specified function on edges.
*
* @param graph node type
* @param graph edge type
* @param graph graph to connect, must not be null
* @param edgeValues edge values, must not be null
* @return the specified graph connected completely with values provided by the specified function on edges
*/
public static Graph connectCompletely(final Graph graph,
final BinaryFunction edgeValues)
{
if (graph == null)
{
throw new IllegalArgumentException("graph must not be null");
}
if (edgeValues == null)
{
throw new IllegalArgumentException("edgeValues must not be null");
}
int n = graph.nodeCount();
List> nodes = Lists.asImmutableList(graph.nodes());
BinaryKeyMap, Node, Edge> edges = BinaryKeyMaps.createBinaryKeyMap(n * n);
for (Edge edge : graph.edges())
{
edges.put(edge.source(), edge.target(), edge);
}
for (int i = 0; i < n; i++)
{
Node source = nodes.get(i);
for (int j = 0; j < n; j++)
{
Node target = nodes.get(j);
if (!source.equals(target) && !edges.containsKey(source, target))
{
E edgeValue = edgeValues.evaluate(source.getValue(), target.getValue());
graph.createEdge(source, target, edgeValue);
}
}
}
return graph;
}
/**
* Create and return a new completely connected graph with the specified nodes values
* on nodes and the specified edge value on all added edges.
*
* @param graph node type
* @param graph edge type
* @param nodeValues list of node values, must not be null
* @param edgeValue edge value
* @return a new completely connected graph with the specified nodes values
* on nodes and the specified edge value on all added edges
*/
public static Graph connectCompletely(final List nodeValues,
final E edgeValue)
{
return connectCompletely(nodeValues, new Scalar(edgeValue));
}
/**
* Create and return a new completely connected graph with the specified nodes values
* on nodes and values provided by the specified function on edges.
*
* @param graph node type
* @param graph edge type
* @param nodeValues list of node values, must not be null
* @param edgeValues edge values, must not be null
* @return a new completely connected graph with the specified nodes values
* on nodes and the specified edge value on all added edges
*/
public static Graph connectCompletely(final List nodeValues,
final BinaryFunction edgeValues)
{
if (nodeValues == null)
{
throw new IllegalArgumentException("nodeValues must not be null");
}
if (edgeValues == null)
{
throw new IllegalArgumentException("edgeValues must not be null");
}
int n = nodeValues.size();
Graph graph = GraphUtils.createGraph(n, n * n);
List> nodes = Lists.createList(n);
for (N nodeValue : nodeValues)
{
nodes.add(graph.createNode(nodeValue));
}
for (int i = 0; i < n; i++)
{
Node source = nodes.get(i);
for (int j = 0; j < n; j++)
{
Node target = nodes.get(j);
if (!source.equals(target))
{
E edgeValue = edgeValues.evaluate(source.getValue(), target.getValue());
graph.createEdge(source, target, edgeValue);
}
}
}
return graph;
}
/**
* Connect the specified graph randomly with the specified value on all added edges.
*
* @param graph node type
* @param graph edge type
* @param graph graph to connect, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValue edge value
* @return the specified graph connected randomly with the specified value on all added edges
*/
public static Graph connectRandomly(final Graph graph,
final int edgeCount,
final E edgeValue)
{
return connectRandomly(graph, edgeCount, new Scalar(edgeValue));
}
/**
* Connect the specified graph randomly with the specified value on all added edges.
*
* @param graph node type
* @param graph edge type
* @param graph graph to connect, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValue edge value
* @param random source of randomness, must not be null
* @return the specified graph connected randomly with the specified value on all added edges
*/
public static Graph connectRandomly(final Graph graph,
final int edgeCount,
final E edgeValue,
final RandomGenerator random)
{
return connectRandomly(graph, edgeCount, new Scalar(edgeValue), random);
}
/**
* Connect the specified graph randomly with the specified value on all added edges.
*
* @param graph node type
* @param graph edge type
* @param graph graph to connect, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValues edge values, must not be null
* @return the specified graph connected randomly with the specified value on all added edges
*/
public static Graph connectRandomly(final Graph graph,
final int edgeCount,
final BinaryFunction edgeValues)
{
return connectRandomly(graph, edgeCount, edgeValues, new JDKRandomGenerator());
}
/**
* Connect the specified graph randomly with the specified value on all added edges.
*
* @param graph node type
* @param graph edge type
* @param graph graph to connect, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValues edge values, must not be null
* @param random source of randomness, must not be null
* @return the specified graph connected randomly with the specified value on all added edges
*/
public static Graph connectRandomly(final Graph graph,
final int edgeCount,
final BinaryFunction edgeValues,
final RandomGenerator random)
{
if (graph == null)
{
throw new IllegalArgumentException("graph must not be null");
}
if (edgeCount < 0)
{
throw new IllegalArgumentException("edgeCount must be at least zero");
}
if (edgeValues == null)
{
throw new IllegalArgumentException("edgeValues must not be null");
}
if (random == null)
{
throw new IllegalArgumentException("random must not be null");
}
List> nodes = Lists.asImmutableList(graph.nodes());
for (int i = graph.edgeCount(); i < edgeCount; i++)
{
Node source = nodes.get(random.nextInt(nodes.size()));
Node target = nodes.get(random.nextInt(nodes.size()));
E edgeValue = edgeValues.evaluate(source.getValue(), target.getValue());
graph.createEdge(source, target, edgeValue);
}
return graph;
}
/**
* Create and return a new randomly connected graph with the specified nodes values
* on nodes and the specified edge value on all added edges.
*
* @param graph node type
* @param graph edge type
* @param nodeValues list of node values, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValue edge value
* @return a new randomly connected graph with the specified nodes values
* on nodes and the specified edge value on all added edges
*/
public static Graph connectRandomly(final List nodeValues,
final int edgeCount,
final E edgeValue)
{
return connectRandomly(nodeValues, edgeCount, new Scalar(edgeValue));
}
/**
* Create and return a new randomly connected graph with the specified nodes values
* on nodes and the specified edge value on all added edges.
*
* @param graph node type
* @param graph edge type
* @param nodeValues list of node values, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValue edge value
* @param random source of randomness, must not be null
* @return a new randomly connected graph with the specified nodes values
* on nodes and the specified edge value on all added edges
*/
public static Graph connectRandomly(final List nodeValues,
final int edgeCount,
final E edgeValue,
final RandomGenerator random)
{
return connectRandomly(nodeValues, edgeCount, new Scalar(edgeValue), random);
}
/**
* Create and return a new randomly connected graph with the specified nodes values
* on nodes and values provided by the specified function on edges.
*
* @param graph node type
* @param graph edge type
* @param nodeValues list of node values, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValues edge values, must not be null
* @return a new randomly connected graph with the specified nodes values
* on nodes and the specified edge value on all added edges
*/
public static Graph connectRandomly(final List nodeValues,
final int edgeCount,
final BinaryFunction edgeValues)
{
return connectRandomly(nodeValues, edgeCount, edgeValues, new JDKRandomGenerator());
}
/**
* Create and return a new randomly connected graph with the specified nodes values
* on nodes and values provided by the specified function on edges.
*
* @param graph node type
* @param graph edge type
* @param nodeValues list of node values, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValues edge values, must not be null
* @param random source of randomness, must not be null
* @return a new randomly connected graph with the specified nodes values
* on nodes and the specified edge value on all added edges
*/
public static Graph connectRandomly(final List nodeValues,
final int edgeCount,
final BinaryFunction edgeValues,
final RandomGenerator random)
{
if (nodeValues == null)
{
throw new IllegalArgumentException("nodeValues must not be null");
}
if (edgeCount < 0)
{
throw new IllegalArgumentException("edgeCount must be at least zero");
}
if (edgeValues == null)
{
throw new IllegalArgumentException("edgeValues must not be null");
}
if (random == null)
{
throw new IllegalArgumentException("random must not be null");
}
int n = nodeValues.size();
Graph graph = GraphUtils.createGraph(n, edgeCount);
List> nodes = Lists.createList(n);
for (N nodeValue : nodeValues)
{
nodes.add(graph.createNode(nodeValue));
}
for (int i = 0; i < edgeCount; i++)
{
Node source = nodes.get(random.nextInt(n));
Node target = nodes.get(random.nextInt(n));
E edgeValue = edgeValues.evaluate(source.getValue(), target.getValue());
graph.createEdge(source, target, edgeValue);
}
return graph;
}
/**
* Connect the specified graph preferentially with the specified value on all added edges.
*
* @param graph node type
* @param graph edge type
* @param graph graph to connect, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValue edge value
* @return the specified graph connected preferentially with the specified value on all added edges
*/
public static Graph connectPreferentially(final Graph graph,
final int edgeCount,
final E edgeValue)
{
return connectPreferentially(graph, edgeCount, new Scalar(edgeValue));
}
/**
* Connect the specified graph preferentially with the specified value on all added edges.
*
* @param graph node type
* @param graph edge type
* @param graph graph to connect, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValues edge values, must not be null
* @return the specified graph connected preferentially with the specified value on all added edges
*/
public static Graph connectPreferentially(final Graph graph,
final int edgeCount,
final BinaryFunction edgeValues)
{
if (graph == null)
{
throw new IllegalArgumentException("graph must not be null");
}
if (edgeCount < 0)
{
throw new IllegalArgumentException("edgeCount must be at least zero");
}
if (edgeValues == null)
{
throw new IllegalArgumentException("edgeValues must not be null");
}
// weight nodes by degree
WeightedMap> weightedNodes = WeightedMaps.createWeightedMap(graph.nodeCount());
for (Node node : graph.nodes())
{
weightedNodes.put(node, Double.valueOf(node.degree() + DEFAULT_UNCONNECTED_NODE_WEIGHT));
}
// store existing edges to prevent creating duplicates
BinaryKeyMap, Node, Edge> edges = BinaryKeyMaps.createBinaryKeyMap(edgeCount);
for (Edge edge : graph.edges())
{
edges.put(edge.source(), edge.target(), edge);
}
// connect preferentially until edgeCount is reached
while (edges.size() < edgeCount)
{
Node source = weightedNodes.sample();
Node target = weightedNodes.sample();
// avoid self-edges
if (!source.equals(target) && !edges.containsKey(source, target))
{
E edgeValue = edgeValues.evaluate(source.getValue(), target.getValue());
edges.put(source, target, graph.createEdge(source, target, edgeValue));
// update weights
weightedNodes.put(source, Double.valueOf(source.degree()));
weightedNodes.put(target, Double.valueOf(target.degree()));
}
}
return graph;
}
/**
* Create and return a new preferentially connected graph with the specified nodes values
* on nodes and the specified edge value on all added edges.
*
* @param graph node type
* @param graph edge type
* @param nodeValues list of node values, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValue edge value
* @return a new randomly connected graph with the specified nodes values
* on nodes and the specified edge value on all added edges
*/
public static Graph connectPreferentially(final List nodeValues,
final int edgeCount,
final E edgeValue)
{
return connectPreferentially(nodeValues, edgeCount, new Scalar(edgeValue));
}
/**
* Create and return a new preferentially connected graph with the specified nodes values
* on nodes and values provided by the specified function on edges.
*
* @param graph node type
* @param graph edge type
* @param nodeValues list of node values, must not be null
* @param edgeCount edge count, must be at least zero
* @param edgeValues edge values, must not be null
* @return a new randomly connected graph with the specified nodes values
* on nodes and values provided by the specified function on edges
*/
public static Graph connectPreferentially(final List nodeValues,
final int edgeCount,
final BinaryFunction edgeValues)
{
if (nodeValues == null)
{
throw new IllegalArgumentException("nodeValues must not be null");
}
if (edgeCount < 0)
{
throw new IllegalArgumentException("edgeCount must be at least zero");
}
if (edgeValues == null)
{
throw new IllegalArgumentException("edgeValues must not be null");
}
int n = nodeValues.size();
Graph graph = GraphUtils.createGraph(n, edgeCount);
List> nodes = Lists.createList(n);
for (N nodeValue : nodeValues)
{
nodes.add(graph.createNode(nodeValue));
}
// weight nodes by degree
WeightedMap> weightedNodes = WeightedMaps.createWeightedMap(n);
for (Node node : graph.nodes())
{
weightedNodes.put(node, Double.valueOf(node.degree() + DEFAULT_UNCONNECTED_NODE_WEIGHT));
}
// store existing edges to prevent creating duplicates
BinaryKeyMap, Node, Edge> edges = BinaryKeyMaps.createBinaryKeyMap(edgeCount);
// connect preferentially until edgeCount is reached
while (edges.size() < edgeCount)
{
Node source = weightedNodes.sample();
Node target = weightedNodes.sample();
if (!source.equals(target) && !edges.containsKey(source, target))
{
E edgeValue = edgeValues.evaluate(source.getValue(), target.getValue());
edges.put(source, target, graph.createEdge(source, target, edgeValue));
weightedNodes.put(source, Double.valueOf(source.degree()));
weightedNodes.put(target, Double.valueOf(target.degree()));
}
}
return graph;
}
/**
* Scalar function.
*
* @param graph node type
* @param graph edge type
*/
private static final class Scalar implements BinaryFunction
{
/** Value. */
private final E value;
/**
* Create a new scalar function with the specified value.
*
* @param value value
*/
private Scalar(final E value)
{
this.value = value;
}
@Override
public E evaluate(final N ignore0, final N ignore1)
{
return value;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy