/** * Generates a synthetic network for provided vertices in the given graphh such that the provided * expected number of communities are generated with the specified expected number of edges. * * @param graph * @param vertices * @param expectedNumCommunities * @param expectedNumEdges * @return The actual number of edges generated. May be different from the expected number. */ public int generate( Graph graph, Iterable<Vertex> vertices, int expectedNumCommunities, int expectedNumEdges) { if (communitySize == null) throw new IllegalStateException("Need to initialize community size distribution"); if (edgeDegree == null) throw new IllegalStateException("Need to initialize degree distribution"); int numVertices = SizableIterable.sizeOf(vertices); Iterator<Vertex> iter = vertices.iterator(); ArrayList<ArrayList<Vertex>> communities = new ArrayList<ArrayList<Vertex>>(expectedNumCommunities); Distribution communityDist = communitySize.initialize(expectedNumCommunities, numVertices); while (iter.hasNext()) { int nextSize = communityDist.nextValue(random); ArrayList<Vertex> community = new ArrayList<Vertex>(nextSize); for (int i = 0; i < nextSize && iter.hasNext(); i++) { community.add(iter.next()); } if (!community.isEmpty()) communities.add(community); } double inCommunityPercentage = 1.0 - crossCommunityPercentage; Distribution degreeDist = edgeDegree.initialize(numVertices, expectedNumEdges); if (crossCommunityPercentage > 0 && communities.size() < 2) throw new IllegalArgumentException("Cannot have cross links with only one community"); int addedEdges = 0; // System.out.println("Generating links on communities: "+communities.size()); for (ArrayList<Vertex> community : communities) { for (Vertex v : community) { int degree = degreeDist.nextValue(random); degree = Math.min(degree, (int) Math.ceil((community.size() - 1) / inCommunityPercentage) - 1); Set<Vertex> inlinks = new HashSet<Vertex>(); for (int i = 0; i < degree; i++) { Vertex selected = null; if (random.nextDouble() < crossCommunityPercentage || (community.size() - 1 <= inlinks.size())) { // Cross community ArrayList<Vertex> othercomm = null; while (othercomm == null) { othercomm = communities.get(random.nextInt(communities.size())); if (othercomm.equals(community)) othercomm = null; } selected = othercomm.get(random.nextInt(othercomm.size())); } else { // In community while (selected == null) { selected = community.get(random.nextInt(community.size())); if (v.equals(selected) || inlinks.contains(selected)) selected = null; } inlinks.add(selected); } addEdge(graph, v, selected); addedEdges++; } } } return addedEdges; }