@Override
    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;
    }
Generates a synthetic network for provided vertices in the given graph such that the provided expected number
of communities are generated with the specified expected number of edges.

@return The actual number of edges generated. May be different from the expected number.
gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/algorithm/generator/CommunityGenerator.java