Joseph Keane
Joseph Keane

Reputation: 321

How to simulate exponential growth

I'm working on a game, and in it I want growth to happen exponentially - so, for example, getting from 2 to 3 people might take around the same time as getting from 2 million to 3 million people. However, I would like this growth to be random if possible to make it more realistic. So far I have a method that works well:

if (buildingCount > populationCount && foodCount > populationCount)
    for(int i=1;i<populationCount;i++) {
        int randomInt = random.nextInt(1000);
        if (randomInt == 42) {
            Data.main.setPopulationCount(populationCount+1);
        }
    }
if ((buildingCount < populationCount || foodCount < populationCount)&&populationCount>2)
    for(int i=1;i<populationCount;i++) {
        int randomInt = random.nextInt(1000);
        if (randomInt == 888) {
            Data.main.setPopulationCount(populationCount-1);
        }

However, I realise this will not be sustainable. It runs approximately 60 times a second (on that magnitude), and once it reaches levels of millions, it may end up running billions of operations per second - a bit much for such a simple check. I'll put it on an interval if I have to, but I'd rather keep it random.

I tried to find an equation for the probability but ended up with:

Σ(99^r/1000^(r+1)) from r=0 to p (where p = probability)

Is there any easy way to change that probability to a test, or a simpler method in Java to accomplish such a purpose.

If it helps I'm using LibGdx as an engine.

Upvotes: 6

Views: 2236

Answers (4)

GrafWampula
GrafWampula

Reputation: 241

The explicit formula for exponential growth is: x_t=x_0*(1+r)^t where t is your interval (in your case there are 60 intervals per second) and r is your growth rate. So the formula for the increase in one interval is:

x_1=x_0*(1+r)

with x_0 being the previous population.

So basically, instead of looping over your whole population count on every interval, you can just this (with a growth rate of 0.1%):

Data.main.setPopulationCount(populationCount + Math.floor(populationCount * 0.001f));

For population decrease just subtract instead of adding.

Data.main.setPopulationCount(populationCount - Math.floor(populationCount * 0.001f));

In order to integrate randomness you could do something like this:

Data.main.setPopulationCount(populationCount + Math.floor(populationCount * 0.001f * random.nextFloat()));

That way your growth rate would fluctuate between 0% and 100% on each increment.

Then it would only be a matter of experimenting with the growth rate.

This strategy should only be employed though as soon as the population exceeds about 5 * (1 / growth rate), for otherwise Math.floor will render it too inaccurate or even diminish any growth.

Upvotes: 1

Jacob G.
Jacob G.

Reputation: 29730

It seems that, assuming the distribution of random numbers is uniform, you'll increase the population count by n / 1000, on average, for a population count of n.

To emulate this, it might be a good idea to just divide populationCount by 500 and use ThreadLocalRandom#nextGaussian to determine how much to increment populationCount by, allowing you to rid yourself of the for-loop:

if (buildingCount > populationCount && foodCount > populationCount) {
    if (populationCount > 1000) {
        int randomNum = (int) ((ThreadLocalRandom.current().nextGaussian() / 2 + 0.5) * populationCount / 500);

        Data.main.setPopulationCount(populationCount + randomNum);
    } else {
        // Original for-loop here for populations less than 1000.
    }
}

For a population of 10,000, this would increase the population by an average of 10 (ranges from 0 to 20 in this case, but favors a mean of 10 due to the use of nextGaussian).

Upvotes: 4

vincrichaud
vincrichaud

Reputation: 2208

Currently what you are doing is : for every person it has a chance of 1 over 1000 to produce a new person. Your code is going crazy on big numbers cause you check everyone.

For big numbers your algorithm is equivalent as multiplying your population by 1.001 (1+1/1000). The random aspect will disappear for big numbers (as explain here)

But for small number the random is really important. I think the best way to handle this is to define a population level over which you use a multiplication and under which you use your method.

if (buildingCount > populationCount && foodCount > populationCount)
    if(populationCount > 10000) { //I use 10000 has population level but do what you want
        for(int i=1;i<populationCount;i++) {
            int randomInt = random.nextInt(1000);
            if (randomInt == 42) {
                Data.main.setPopulationCount(populationCount+1);
            }
        }
    }
}

Upvotes: 1

Lio
Lio

Reputation: 51

Here

with your exemple 2-3 2M to 3M i would say use a *1.5 operator

exemple: every 60S --> people=people*1.5

pearps i'am don't understand clearly your need

lio

Upvotes: -1

Related Questions