class BarabasiAlbertGraphGenerator implements GraphGenerator<V, E, V> {

    @Override
    public void generateGraph(
        Graph<V, E> target, VertexFactory<V> vertexFactory, Map<String, V> resultMap)
    {
        /*
         * Create complete graph with m0 nodes
         */
        Set<V> oldNodes = new HashSet<>(target.vertexSet());
        Set<V> newNodes = new HashSet<>();
        new CompleteGraphGenerator<V, E>(m0).generateGraph(target, vertexFactory, resultMap);
        target.vertexSet().stream().filter(v -> !oldNodes.contains(v)).forEach(newNodes::add);

        List<V> nodes = new ArrayList<>(n * m);
        nodes.addAll(newNodes);
        /*
         * Augment node list to have node multiplicity equal to min(1,m0-1).
         */
        for (int i = 0; i < m0 - 2; i++) {
            nodes.addAll(newNodes);
        }

        /*
         * Grow network with preferential attachment
         */
        for (int i = m0; i < n; i++) {
            V v = vertexFactory.createVertex();
            if (!target.addVertex(v)) {
                throw new IllegalArgumentException("Invalid vertex factory");
            }

            List<V> newEndpoints = new ArrayList<>();
            int added = 0;
            while (added < m) {
                V u = nodes.get(rng.nextInt(nodes.size()));
                if (!target.containsEdge(v, u)) {
                    target.addEdge(v, u);
                    added++;
                    newEndpoints.add(v);
                    if (i > 1) {
                        newEndpoints.add(u);
                    }
                }
            }
            nodes.addAll(newEndpoints);
        }

    }

    public  BarabasiAlbertGraphGenerator(int m0, int m, int n);
    public  BarabasiAlbertGraphGenerator(int m0, int m, int n, long seed);
    public  BarabasiAlbertGraphGenerator(int m0, int m, int n, Random rng);

}