Preferential growth with an increasing number of vertices means that older vertices will have far more connections than the newer ones. So we know which vertices will probably be chosen, and we should try to use that in our algorithm. One way to do it is roulette wheel selection:
randomChoice = Compile[{{list, _Real, 1}},
Module[{acc, i = 1, r1 = 0., r2 = 0., i1 = 1, i2 = 1, res},
acc = Accumulate[list];
r1 = RandomReal[{1, Last@acc}];
r2 = RandomReal[{1, Last@acc}];
While[
r1 > acc[[i]] || r2 > acc[[i]],
If[r1 > acc[[i]], i1 = i];
If[r2 > acc[[i]], i2 = i];
i++;
];
{i1, i2}
], CompilationTarget -> "C", RuntimeOptions -> {"Speed"}]
The surrounding code can be left mostly untouched:
m = 1;
w = ConstantArray[0, n] + m;
Table[{i, j} = randomChoice@Take[w, t];
w[[{i, j}]]++; i <-> j, {t, 2, n}]
In the following graph the blue line is the simulation using RandomChoice
and the orange line is the simulation using randomChoice
. Because of the thing that I mentioned I believe that the difference is only going to grow as n
grows. The data points are for n = {10^3, 5 10^3, 10^4, 5 10^4, 10^5}
, the y axis is given in seconds.
A further optimization might be to not use Accumulate
which will sum over all elements. Instead the total sum of vertex degrees can be calculated as t (m + 2)
and the accumulated value can be calculated in the While
loop.
t
and use them as indices. $\endgroup$