We are going to look at two models for
population growth of a species. The
first is a standard exponential growth/decay model that describes quite well
the population of a species becoming extinct, or the short-term behavior of a
population growing in an unchecked fashion.
The second, more realistic model, describes the growth of a species
subject to constraints of space, food supply, and competitors/predators.
We assume that the species starts with
an initial population P0. The population after n time units is denoted Pn. Suppose that in each time interval, the
population increases or decreases by a fixed proportion of its value at the
beginning of the interval. Thus Pn = Pn-1
+ r Pn-1, n
³ 1. The constant r
represents the difference between the birth rate and the death rate. The population increases if r is positive, decreases if r is negative, and remains fixed if r = 0.
Here is a simple M-file that will
compute the population at stage n,
given the population at the previous stage and the rate r.
function X =
itseq(f,Xinit,n,r)
% computing an iterative
sequence of values
X = zeros(n + 1, 1);
X(1) = Xinit;
for i = 1:n
X(i + 1) = f(X(i), r);
end
In fact, this is a simple program for
computing iteratively the values of a sequence
an = f(an-1),
n ³ 1, provided you have previously entered the formula for the function f and the initial value of the sequence a0. Note the extra parameter r
is built into the algorithm.
Now let's use the program to compute
two populations at five year intervals for different values of r:
r = 0.1; Xinit = 100; f = inline('x*(1 + r)', 'x', 'r');
1.0e+006 *
0.00010000000000
0.00016105100000
0.00025937424601
0.00041772481694
0.00067274999493
0.00108347059434
0.00174494022689
0.00281024368481
0.00452592555682
0.00728904836851
0.01173908528797
0.01890591424713
0.03044816395414
0.04903707252979
0.07897469567994
0.12718953713951
0.20484002145855
0.32989690295921
0.53130226118483
0.85566760466078
1.37806123398224
r = -0.1; X = itseq(f, Xinit, 100, r);
1.0e+002 *
1.00000000000000
0.59049000000000
0.34867844010000
0.20589113209465
0.12157665459057
0.07178979876919
0.04239115827522
0.02503155504993
0.01478088294143
0.00872796356809
0.00515377520732
0.00304325272217
0.00179701029991
0.00106111661200
0.00062657874822
0.00036998848504
0.00021847450053
0.00012900700782
0.00007617734805
0.00004498196225
0.00002656139889
In the first case, the population is
growing rapidly; in the second, decaying rapidly. In fact, it is clear from the model that, for any n, the quotient Pn/Pn+1 = (1 + r), and therefore it follows that Pn = P0(1 + r)n, n ³ 0. This accounts for the expression exponential growth/decay. The model predicts a population growth
without bound (for growing populations), and is therefore not realistic. Our next model allows for a check on the
population caused by limited space, limited food supply, competitors, and
predators.
The previous model assumes that the
relative change in population is constant, that is
(Pn+1 – Pn)/Pn = r.
Now let's build in a term that holds
down the growth, namely
(Pn+1 – Pn)/Pn = r –
uPn.
We shall simplify matters by assuming
that u = 1 + r
, so that our recursion relation becomes
Pn+1 = u Pn(1
– Pn),
where u is a positive constant.
In this model, the population P
is constrained to lie between 0 and 1, and should be interpreted as a
percentage of a maximum possible population in the environment in
question. So let us set up the function
we will use in the iterative procedure:
clear f; f = inline('u*x*(1 - x)', 'x', 'u');
Now let's compute a few examples; and
use plot to display
the results.
u = 0.5; Xinit = 0.5; X = itseq(f, Xinit, 20, u); plot(X)
u = 1; X = itseq(f, Xinit, 20, u); plot(X)
u = 1.5; X =
itseq(f, Xinit, 20, u); plot(X)
u = 3.4; X =
itseq(f, Xinit, 20, u); plot(X)
In the first computation, we have used
our iterative program to compute the population density for 20 time intervals,
assuming a logistic growth constant u
= 0.5, and an initial population density of 50%. The population seems to be dying out. In the remaining examples, we kept the initial population density
at 50%; the only thing we varied was the logistic growth constant. In the second example, with a growth
constant u = 1, once again the
population is dying out—although more slowly.
In the third example, with a growth constant of 1.5 the population seems
to be stabilizing at 33.3...%. Finally,
in the last example, with a constant of 3.4 the population seems to oscillate
between densities of approximately 45% and 84%.
These examples illustrate the
remarkable features of the logistic population dynamics model. This model has been studied for more than
150 years, its origins lying in an analysis by the Belgian mathematician
Verhulst. Here are some of the facts
associated with this model. We will
corroborate some of them with MATLAB.
In particular, we shall use bar as well as plot to display some of the data.
(1)
The logistic constant cannot be larger than 4.
In order for the model to work, the
output at any point must be between 0 and 1.
But the parabola ux(1 - x), for 0 £ x £ 1, has its maximum height when x =
1/2, where its value is u/4. To keep that number between 0 and 1, we must
restrict u £ 4.
Here is what happens if u is
bigger than 4:
u = 4.5; Xinit = 0.9; X = itseq(f, Xinit, 10, u)
1.0e+072 *
0.00000000000000
0.00000000000000
0.00000000000000
-0.00000000000000
-0.00000000000000
-0.00000000000000
-0.00000000000000
-0.00000000000000
-0.00000000000000
-0.00000000000000
-3.49103403458070
(2)
If 0 £ u
£ 1, the population density tends to
zero for any initial configuration.
X = itseq(f, 0.99, 100, 0.8); X(101)
1.939524024691387e-012
bar(X)
(3)
If 1 < u £ 3, the population will stabilize at density 1 -1/u for any initial density
other than zero.
The third of the original four
examples corroborates the assertion (with u
= 1.5 and 1 -1/u = 1/3). In the following
examples, we set u = 2, 2.5 and 3
respectively, so that 1 -1/u equals 0.5, 0.6 and
0.666..., respectively. The convergence
in the last computation is rather slow (as one might expect from a boundary
case—or bifurcation point).
X = itseq(f, 0.25, 100, 2); X(101)
0.50000000000000
X = itseq(f,
0.75, 100, 2); X(101)
0.50000000000000
bar(X); axis([0 100 0 0.8])
(4)
If 3 < u < 3.56994..., then there is a periodic cycle.
The theory is quite subtle. For a fuller explanation, the reader may
consult Encounters with Chaos, by
Denny Gulick (McGraw-Hill), section 1.5.
In fact there is a sequence
u0 = 3 < u1 = 1 + Ö6 < u2 < u3
< ... < 4,
such that: between u0 and u1 there is a cycle of period 2; between u1 and u2 there is cycle of period 4; and in general, between uk and uk+1 there is a cycle of period 2k+1. In fact one knows that, at least for small k, one has the approximation uk+1 » 1 + Ö(3+uk). So
3.44948974278318
3.53958456106175
This explains the oscillatory behavior
we saw in the last of the original four examples (with u0 < u =
3.4 < u1). Here is the behavior for u1 < u = 3.5 < u2. The command bar is
particularly effective here for spotting the cycle of order 4.
bar(X); axis([0 100 0 0.9])
(5) There is a value u < 4 beyond which—chaos!
It is possible to prove that the
sequence uk tends to a
limit u¥. The value of u¥, sometimes called the Feigenbaum parameter, is aproximately
3.56994... Let's see what happens if we
use a value of u between the
Feigenbaum parameter and 4.
X = itseq(f,
0.75, 100, 3.7); plot(X)
This is an example of what
mathematicians call a chaotic
phenomenon! It is not random—the sequence was generated by a precise, fixed
mathematical procedure, but the results manifest no discernible pattern. Chaotic phenomena are unpredictable, but
with modern methods (including computer analysis), mathematicians have been
able to identify certain patterns of behavior in chaotic phenomena. For example, the last figure suggests the
possibility of unstable periodic cycles and other recurring phenomena. Indeed a great deal of information is
known. The aforementioned book by Gulick
is a fine reference, as well as the source of an excellent bibliography on the
subject.
The logistic growth model that we have been exploring lends itself particularly well to simulation using SIMULINK. Here is a simple SIMULINK model that corresponds to the above calculations:
Let's briefly explain how this
works. If you ignore the Discrete Pulse
Generator block and the Sum block in the lower left for a moment, this model
implements the equation
x at next
time = u x (1 – x) at old time,
which is the equation for the logistic
model. The Scope block displays a plot
of x as a function of (discrete)
time. However, we need somehow to build
in the initial condition for x. The simplest way to do this is as
illustrated here: we add to the right-hand side a discrete pulse that is the
initial value of x at time t = 0 and is 0 thereafter. Since the model is discrete, you can achieve
this by setting the period of the Discrete Pulse Generator block to something
longer than the length of the simulation, and setting the width of the pulse to
1 and the amplitude of the pulse to the initial value of x. The outputs from the
model in the two interesting cases of u = 3.4 and u = 3.7 are shown here:
Output with u = 3.4
Output with u = 3.7
In the first case of u = 3.4, the periodic behavior is clearly
visible. On the other hand, when u = 3.7, we get chaotic behavior.