package org.egonet.graph; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; public class Graph<N> { private Map<N,Set<N>> connections; public Graph() { this(new HashMap<N,Set<N>>()); } public Graph(Map<N,Set<N>> connections) { this.connections = new HashMap<N,Set<N>>(); for(N node : connections.keySet()) { Set<N> set = Sets.newHashSet(); set.addAll(connections.get(node)); this.connections.put(node, set); } } public static Graph<Integer> random(Integer numNodes, Double density) { Random rand = new Random(); Map<Integer,Set<Integer>> connections = Maps.newHashMap(); List<Integer> nodes = Lists.newArrayList(); for(Integer i = 0; i < numNodes; i++) { nodes.add(i); } for(Integer i = 0; i < numNodes; i++) { Collections.shuffle(nodes,rand); Integer expectedConnections = (int) Math.round(density * (numNodes - 1)); Integer spread = Math.min(expectedConnections, numNodes-1-expectedConnections); Integer actual = rand.nextInt(2*spread+1) + expectedConnections - spread; Set<Integer> connectionsForThisNode = Sets.newHashSet(); for(Integer j = 0; j < actual && j < nodes.size(); j++) { if(nodes.get(j).equals(j)) { actual++; } else { connectionsForThisNode.add(nodes.get(j)); } } connections.put(i, connectionsForThisNode); } return new Graph<Integer>(connections); } public Double density() { Integer numNodes = connections.keySet().size(); if(numNodes < 2) { return 1.0; } Integer maxConnectionsTimesTwo = numNodes * (numNodes-1); Integer actualConnectionsTimesTwo = 0; for(N node : connections.keySet()) { actualConnectionsTimesTwo += connections.get(node).size(); } return actualConnectionsTimesTwo < 1 ? 0.0 : (actualConnectionsTimesTwo * 1.0 / maxConnectionsTimesTwo); } public Set<N> nodes() { return connections.keySet(); } public boolean connected(N n1, N n2) { return connections.get(n1).contains(n2); } // TODO: Double distance(N n1, N n2) public boolean equals(Object o) { if(o == null || ! (o instanceof Graph)) { return false; } return connections.equals(((Graph) o).connections); } public int hashCode() { return connections.hashCode(); } }