Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to simulate exponential growth

Tags:

java

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.

like image 627
Joseph Keane Avatar asked Apr 11 '18 15:04

Joseph Keane


People also ask

How do you calculate exponential growth example?

Therefore, the exponential growth formula we should use is: x(t) = 10,000 * (1 + 0.05)t = 10,000 * 1.05t . Here t is the number of years passed since 2019. In our case, for the year 2030, we should use t = 11, since this is the difference in the number of years between 2030 and the initial year 2019.


3 Answers

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).

like image 102
Jacob G. Avatar answered Sep 24 '22 14:09

Jacob G.


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.

like image 29
GrafWampula Avatar answered Sep 23 '22 14:09

GrafWampula


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);
            }
        }
    }
}
like image 38
vincrichaud Avatar answered Sep 25 '22 14:09

vincrichaud