in gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/algorithm/generator/CommunityGenerator.java [83:158]
public int generate() {
int numVertices = SizableIterable.sizeOf(vertices);
final Iterator<Vertex> iter = vertices.iterator();
final ArrayList<ArrayList<Vertex>> communities = new ArrayList<>(expectedNumCommunities);
final Distribution communityDist = communitySize.initialize(expectedNumCommunities, numVertices);
final Map<String, Object> context = new HashMap<>();
while (iter.hasNext()) {
final int nextSize = communityDist.nextValue(random);
context.put("communityIndex", communities.size());
final ArrayList<Vertex> community = new ArrayList<>(nextSize);
for (int i = 0; i < nextSize && iter.hasNext(); i++) {
community.add(processVertex(iter.next(), context));
}
if (!community.isEmpty()) communities.add(community);
}
final double inCommunityPercentage = 1.0 - crossCommunityPercentage;
final 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) {
final int randomDegree = degreeDist.nextValue(random);
final int degree = Math.min(randomDegree, (int) Math.ceil((community.size() - 1) / inCommunityPercentage) - 1);
final Set<Vertex> inlinks = new HashSet<>();
final Set<Vertex> outlinks = new HashSet<>();
for (int i = 0; i < degree; i++) {
Vertex selected = null;
if (random.nextDouble() < crossCommunityPercentage || (community.size() - 1 <= inlinks.size())) {
//Cross community
int tries = 0;
ArrayList<Vertex> othercomm = null;
// this limit on the number of tries prevents infinite loop where the selected vertex to
// link to doesn't exist given the nature and structure of the graph.
while (null == selected && tries < 100) {
// choose another community to connect to and make sure it's not in the current
// community of the current vertex
while (null == othercomm) {
othercomm = communities.get(random.nextInt(communities.size()));
if (othercomm.equals(community)) othercomm = null;
}
selected = othercomm.get(random.nextInt(othercomm.size()));
if (outlinks.contains(selected)) selected = null;
tries++;
}
// if tries expires then the value of selected is null in which case it should not be added.
if (selected != null) outlinks.add(selected);
} else {
//In community
int tries = 0;
while (selected == null && tries < 100) {
selected = community.get(random.nextInt(community.size()));
if (v.equals(selected) || inlinks.contains(selected)) selected = null;
tries++;
}
if (selected != null) inlinks.add(selected);
}
// only add an edge if the vertex was actually selected.
if (selected != null) {
addEdge(v, selected);
addedEdges++;
}
}
}
}
return addedEdges;
}