public void initAsErdosRenyi(final List<Integer> clusterSizes, final List<Double> pInValues,
		final double pOut)
	{
		this.pOut = pOut;
		// node count
		final int n = (int) ListUtils.sumUp(ListUtils.mapType(clusterSizes, Double.class));

		/*
		 * Create clusters
		 */
		for (int index = 0; index < pInValues.size(); ++index)
		{
			final double pIn = pInValues.get(index);
			final int clSize = clusterSizes.get(index);

			final OrdinaryCluster cluster = new OrdinaryCluster(this, pIn, clSize);
			this.addCluster(cluster);
		}

		final int clusterCount = this.getClusterCount();
		assert clusterCount == pInValues.size();

		/*
		 * Distribute nodes:
		 * At first make sure, that every cluster has at least size one.
		 */
		// insert one node into every cluster
		for (int c = 0; c < clusterCount; ++c)
		{
			final OrdinaryCluster home = this.groundTruth.getCluster(c);
			final Node node = new Node();
			this.addNode(node, home);
		}

		// distribute remaining nodes
		for (int c = clusterCount; c < n; ++c)
		{
			final OrdinaryCluster home = this.groundTruth.proposeClusterForNewNode();
			final Node node = new Node();
			this.addNode(node, home);
		}

		/*
		 * Create intra-cluster edges
		 * using the geometric method
		 */
		for (int c = 0; c < clusterCount; ++c)
		{
			final OrdinaryCluster cluster = this.groundTruth.getCluster(c);
			final long maxEdgeCount = Edge.maxEdgeCount(cluster.getNodeCount());

			final List<Long> edges = Sequences.binomialSequence(cluster.getPIn(), maxEdgeCount);

			for (final long edge : edges)
			{
				final Pair<Integer> localNodeIDs = Edge.nodeIndices(edge);
				final Pair<Node> nodes = cluster.getNodes(localNodeIDs);

				assert Edge.createEdge(nodes).isIntraClusterEdge() : "nodes: " + nodes;
				this.addEdge(nodes);
			}
		}

		/*
		 * Create inter-cluster edges
		 * (also using geometric method)
		 * The 'indices' of all edges are created at once.
		 * Due to the irregular structure of inter-cluster edges,
		 * these indices need to be transformed first.
		 * We procede as follows:
		 *
		 * 1. iterate over all nodes (source node/source cluster)
		 * 2. For each source node:
		 * iterate over all nodes within clusters having a larger
		 * cluster index than the source cluster (destination
		 * node/destination
		 * cluster)
		 */
		assert this.getInterClusterEdgeCount() == 0;

		for (int srcClusterIdx = 0; srcClusterIdx < this.groundTruth.getClusterCount(); ++srcClusterIdx)
		{
			final OrdinaryCluster srcCluster = this.groundTruth.getCluster(srcClusterIdx);
			for (int targetClusterIdx = srcClusterIdx + 1; targetClusterIdx < this.groundTruth
				.getClusterCount(); ++targetClusterIdx)
			{
				final OrdinaryCluster targetCluster = this.groundTruth.getCluster(targetClusterIdx);
				final int targetNodeCount = targetCluster.getNodeCount();
				final int srcNodeCount = srcCluster.getNodeCount();
				final long maxEdgeCount = srcNodeCount * targetNodeCount;

				final List<Long> edgeIndices = Sequences.binomialSequence(pOut, maxEdgeCount);

				for (final Long edge : edgeIndices)
				{
					long srcNodeIdx = 0;
					long targetNodeIdx = edge;
					while (!targetCluster.isValidNodeIndex(targetNodeIdx))
					{
						++srcNodeIdx;
						targetNodeIdx = targetNodeIdx - targetNodeCount;
					}

					assert srcCluster.isValidNodeIndex(srcNodeIdx);

					final Node srcNode = srcCluster.getNode((int) srcNodeIdx);
					final Node otherNode = targetCluster.getNode((int)
						targetNodeIdx);

					final Pair<Node> nonEdge = new Pair<Node>(srcNode, otherNode);

					this.addEdge(nonEdge);
				}

			}
		}
	}