13
$\begingroup$

I have a rather strange question (for this Stack Exchange anyway). It felt too mathematical to ask elsewhere. If this is out of place here, please let me know.

A chicken in Minecraft lays eggs; the time between layings is uniformly distributed between 5 and 10 minutes in intervals of 0.05 seconds. An egg, when thrown, produces one chick with probability $\frac3{32}$ or four chicks with probability $\frac1{32}$, and is destroyed afterwards regardless. A chick matures into an egg-laying chicken in 20 minutes.

Assuming eggs are immediately thrown upon laying, how can I estimate the number of chickens after $X$ minutes starting with 1 chicken (that is at the start of its egg-laying cycle)? Chickens are immortal.

I can figure most of it out myself, but the thing that's giving me the most trouble is the last bit. I don't know how to take into account the time delay between an egg hatching and the chick growing up.

$\endgroup$
19
  • 3
    $\begingroup$ The notion of branching process (Galton-Watson process, equivalently) is obviously relevant but, to give quantitative estimates, the assumption "every 5-10 minutes" should be made more precise. $\endgroup$
    – Did
    Sep 10, 2016 at 6:24
  • 2
    $\begingroup$ You are describing a cycle with an expected time of $27.5$ minutes that produces $(3/32)*1+(1/32)4 = 7/32$ chicken per cycle. Now factor in a little slop between eggs being laid and harvested, and whatever other work you have to do... lets call it 0.1 chickens / hour. And as time increases it starts to become an exponential distribution. $\endgroup$
    – user317176
    Sep 10, 2016 at 6:50
  • 2
    $\begingroup$ The unconventional features of the model are the inter-laying times, uniform on the interval $(u,v)=(5,10)$, and the delay to maturity, deterministic and equal to $m=20$ (we measure everything in minutes). To simplify the computations, assume that the inter-laying times are actually exponentially distributed with the same mean inter-laying time, that is, exponential with parameter $\lambda=\frac2{u+v}$, and that the delays to maturity are exponentially distributed with mean the (true) delay to maturity, that is, exponential with parameter $\mu=1/m$. Note also that each laying ... $\endgroup$
    – Did
    Sep 10, 2016 at 12:07
  • 2
    $\begingroup$ ... produces $\beta=1\cdot\frac{3}{32}+4\cdot\frac{1}{32}+0\cdot\frac{28}{32}=\frac{7}{32}$ (immature) chicken in the mean. Then, the numbers of mature chicken and of immature chicken at time $t$ are described by a bivariate branching process and the mean numbers $x(t)$ of mature chicken and $y(t)$ of immature chicken at time $t$ are such that $$x(t+dt)=x(t)+y(t)\mu dt\qquad y(t+dt)=(1-\mu dt)y(t)+\beta x(t)\lambda dt$$ that is, $$x'(t)=\mu y(t)\qquad y'(t)=\beta\lambda x(t)-\mu y(t)$$ The positive eigenvalue $\alpha$ of the matrix $$\begin{pmatrix}0&\mu\\\beta\lambda&-\mu\end{pmatrix}$$ $\endgroup$
    – Did
    Sep 10, 2016 at 12:08
  • 3
    $\begingroup$ @did very interesting! You might want to make that an answer. $\endgroup$
    – Daffy
    Sep 10, 2016 at 15:05

1 Answer 1

1
$\begingroup$

Well, this is well above my capabilities to solve the problem analytically but I can do a nice simulation using the following code:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

public class Chicken {
    public static final int STARTING_CHICKENS = 1;
    public static final int TOTAL_MINUTES = 400;
    public static final int REPORTING_PERIOD = 5; // minutes

    public static final int LAYING_START = 5; // minutes
    public static final int LAYING_END = 10; // minutes
    public static final int MATURING_PERIOD = 20; // minutes

    public static final int TICKS_PER_SECOND = 20; // 0.05 seconds
    public static final int TICKS_PER_MINUTE = 60 * TICKS_PER_SECOND;

    public static final int LAYING_START_TICKS = LAYING_START * TICKS_PER_MINUTE;
    public static final int LAYING_END_TICKS = LAYING_END * TICKS_PER_MINUTE;
    public static final int MATURING_TICKS = MATURING_PERIOD * TICKS_PER_MINUTE;
    public static final int TOTAL_TICKS = TOTAL_MINUTES * TICKS_PER_MINUTE;
    public static final int REPORTING_TICKS = REPORTING_PERIOD * TICKS_PER_MINUTE;

    public static final double ONE_CHICK_PROBABILITY = 3D / 32D;
    public static final double FOUR_CHICKS_PROBABILITY = 1D / 32D;

    private static Random rnd = new Random();

    private int ticks;
    private int nextEggTick;

    public Chicken() {
        this.ticks = 0;
        this.nextEggTick = MATURING_TICKS;
    }

    public List<Chicken> tick() {
        ticks++;
        if(ticks == nextEggTick) {
            // update next egg time
            nextEggTick = ticks + LAYING_START_TICKS + rnd.nextInt(LAYING_END_TICKS - LAYING_START_TICKS + 1);
            // lay an egg
            double r = rnd.nextDouble();
            if (r < FOUR_CHICKS_PROBABILITY) {
                return Arrays.asList(new Chicken(), new Chicken(), new Chicken(), new Chicken());
            }
            else if (r < FOUR_CHICKS_PROBABILITY + ONE_CHICK_PROBABILITY) {
                return Arrays.asList(new Chicken());
            }
        }
        return Arrays.asList();
    }

    public static void main(String[]  args) {
        StringBuffer output = new StringBuffer("{");
        List<Chicken> chickens = new ArrayList<>();
        for(int i = 0; i < STARTING_CHICKENS; i++) {
            chickens.add(new Chicken());
        }
        int ticks = 0;
        while(ticks <= TOTAL_TICKS) {
            if(ticks % REPORTING_TICKS == 0) {
                report(output, ticks, chickens);
            }
            ticks++;
            List<Chicken> newChickens = new ArrayList<>();
            for(Chicken chicken: chickens) {
                newChickens.addAll(chicken.tick());
            }
            chickens.addAll(newChickens);
        }
        output.append("}");
        System.out.println(output.toString());
    }

    private static void report(StringBuffer output, int ticks, List<Chicken> chickens) {
        int minutes = ticks / TICKS_PER_MINUTE;
        String msg = String.format("{%d, %d}", minutes, chickens.size());
        System.out.println(msg);
        if(output.length() > 1) {
            output.append(", ");
        }
        output.append(msg);
    }
}

I did run 10 simulations and got exponential growth of chickens:

enter image description here

...which becomes perfectly clear when you use logarithmic scale:

enter image description here

Actually, it looks like the process "struggles" in the beginning. With a small number number of chickens it might take considerable time for population to reach, say, 10 chickens. After that, the population is big enough and reproduction starts to go smoothly, always at the same exponential rate.

It can be stated empirically that, for a big enough number of minutes $X$, the number of chickens $Y$ changes according to:

$$\ln Y=\ln (\text{const}) + 0.021 X$$

$$Y = \text{const}\cdot e^{0.021 X}$$

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .