1 INTRODUCTION TO ECOLOGICAL MODELLING 3.11. – 12.12.2008 Teachers (e-mail: fistname.lastname@helsinki.fi) Prof. Veijo Kaitala (course leader), Dr. Mike Fowler (coordinator), Doc. Jouni Laakso, M.Sc. Andreas Lindén, M.Sc. Lasse Ruokolainen, M.Sc. Aleksi Lehikoinen, MSc. Minna Pekkonen Schedule (always at 9.15–12 o’clock) Day Mon Wed Fri Date 3.11. 5.11. 7.11. Room 1402 1402 1402 Topic Introduction to ecological modelling Overview of Matlab; a simple population model Population growth models Mon Wed Fri 10.11. 12.11. 14.11. 4403 4403 4403 Tools for population dynamics analyses Parameter space, bifurcation Demographic and environmental stochasticity Mon Wed Fri 17.11. 19.11. 21.11. 1402 4403 4403 Harvesting, maximum sustainable yield Patch dynamics (Spatial models, with Report) Patch dynamics Mon Wed Fri 24.11. 26.11. 28.11. 4403 4403 1402 Predator and prey in continuous time Matrix population models Case studies from Integrative Ecology Unit members Mon Wed Fri 1.12. 3.12. 5.12. 4403 4403 4403 Favourite population model (with Report) Working on assignments Working on assignments Mon Wed Fri 8.12. 10.12. 12.12. 4403 4403 1402 Working on assignments Working on assignments Closing seminar 2 MATLAB – AN OVERVIEW The first exercises are intended for you to get used to the Matlab environment, i.e., assigning parameters with values, handling matrices and vectors. Notation alert! The Matlab code in this compendium is written in Courier font. The symbol ">>" denotes something that can be written to the command line in Matlab. Start Be patient with these exercises, we are practicing things that you will be needed later in the course. Start Matlab from the Start-menu. A command window will open when you start Matlab. You can write commands and perform calculations directly on the command window, but most of the time you will be writing program code (called m-files by their suffix .m) with Matlab editor (starts with the command edit). Getting help Matlab has some help facilities that you should know about and be able to use: demo — demonstration and tutorials, well worth a look helpdesk — opens a graphic help window help command, —help on specified commands, e.g. help rand lookfor topic —finds commands related to a specified topic Useful information is also provided by the developers of Matlab, the Mathworks company (www.mathworks.com). There is also an active newsgroup sci.software-sys.matlab where everything concerning Matlab is discussed. Scalars, vectors and matrices From Matlab's point of view, all data are stored in matrices. Matrices are tables (arrays) of different sizes: Scalar is the most simple of matrices as it has only one row and one column, which makes it a single cell (also called "an element"). Scalars are simple numbers, such as 15.2. Vectors are like tables that have only one row or a column. A row vector has one row and several columns (in Matlab: X(1,:)), while a column vector is a single column with several rows (in Matlab: X(:,1)). Matrix is a table with several rows and columns (in Matlab: Y(i,j), where i and j specify the size of the matrix). It may also be multidimensional, e.g., a three-dimensional matrix can be thought as a stack of several two-dimensional matrices (in Matlab: Y(i,j,k)). There is an important difference between an array and a matrix, which affects how some mathematical operations are performed. Array operations are done element wise, e.g., the array product of two vectors results in a vector where the elements are products of the corresponding elements of the two vectors multiplied with each other. The multiplication of a column vector and row vector results in a scalar and is thus called scalar product. The multiplication of a row vectors by column vector results in a matrix product, and is therefore called a matrix product. Multiplication of a single row vector by column vector is called a dyadic (not allowed in Matlab). This course will not go very deep in matrix algebra, but you should be aware that some mathematical operations are different for arrays and matrices. 3 Practice with scalars, vectors and matrices First create a scalar variable "a" and assign it value 5.2 >> a = 5.2 Variable names can be words and may contain (but not begin with) numbers, but spaces are not allowed. Uppercase and lowercase characters are considered to be different. Matlab commands have to be in lowercase. It is possible to give a variable a name that is also a Matlab command, but should not do that because you will not be able to use that command anymore. Then create a 31 vector ("three-by-one vector", which means three rows and one column) that contains elements 1.4, 3.1 and 4. >> x = [1.4; 3.1; 4] This is called a column vector. Notice that the rows are separated by semicolons (;) and that the dot (.) is used as a decimal separator. A row vector ("one-by-three vector, i.e., one row and three columns) is created by separating columns by spaces (alternatively by commas). >> x = [1.4 3.1 4] Use the apostrophe (') for transposing a vector or a matrix (or function transpose), which means changing rows to columns (or vice versa): >> x = x’ Then create a 33 ("three-by-three", i.e., three rows and three columns) matrix A >> A = [2.1 2.9 3; 4.6 5 6.2; 7.1 8.0 9.4] Notice that the rows of a matrix are separated by semicolons, while the entries on a row are separated by spaces. It is crucial to understand the difference between the index of cell in matrix and the value stored to that cell. The index to the cell (also called an element) is the address and the value is what is stored in that address. Pick the first element of A and call it a (yes, A and a mean different things for Matlab). You do it by referring to the first row and first column of the matrix A as A(1,1) and assigning its value 2.1 to parameter a: >> a = A(1,1) Then pick the last element of A and give its value to parameter b: >> b = A(end,end) You can view the value of a variable simply by writing its name on the command window. Once you have assigned variables with some values you can use the variable names in the calculations, e.g.: >> a+b Pick the first column of A and call it y. Here, you refer to all rows of the matrix A by the colon (:) 4 >> y = A(:,1) Similarly pick the second row of A and call it z: >> z = A(2,:) A useful command is “whos”, which displays the names and types of all variables in the memory space: >> whos If you want to remove variables from your workspace, type clear variable name. Typing clear without variable names removes all variables from the memory. Note that all variables we have are arrays; the “shape'' of the array determines its exact type. The scalar a is a 11 array, the vector x is a 31 array, and A is a 33 array (try the size command for each variable). Standard operations with matrices In addition to matrix operations, multiplications, divisions etc. can be done for each of the elements in an array. .* ./ .^ multiplication by elements division by elements power by elements In Matlab-jargon these may be called "dot-operations" to separate them from matrix operations that do not have a dot. If A and B are arrays, then Matlab can compute A + B and A – B when these operations are defined (i.e. when A and B are equal in size). For example, create the following matrices: >> A = [1 2 3; 4 5 6; 7 8 9]; >> B = [1 1 1; 2 2 2; 3 3 3]; >> C = [1 2; 3 4; 5 6]; Then try to make calculations, like: A+B, A+C, A*C, C*A, A.*C, C.*A, A-1, 3*B, A^B, A.^B which ones worked? Make sure that you understand that there is a difference between an element-wise product A*C and the matrix prouct A.*C. If you are not familiar with the rules of matrix multiplication, don’t worry: you will learn that when we proceed to age and stage structured models (i.e., matrix-models). Matlab has many commands to create special matrices; the following command creates a row vector whose components increase arithmetically: >> t = 1:5 The components can also change by non-unit steps, try typing >> x = 0:.1:1 A negative step is also allowed: >> x = 1:-0.1:0 In Matlab there are several special matrices: zeros(m,n) creates an m n matrix of zeros; ones(m,n) creates an m n matrix of ones; eye(n) creates the n n identity matrix; 5 rand(m,n) creates an m n matrix with random entries Here is a list of useful commands, try them with differently sized matrices and vectors. Create first a 5 1 vector (for example: a = rand(5,1)) and try the following commands. Then create a 4 4 matrix (for example: B = rand(4,4)) and try the commands again. Now the maximums and minimums are calculated separately for each column. If you want the largest entry in the whole matrix, type: max(max(B)), similarly: min(min(B)) gives the smallest element. returns the largest entry of x, if x is a vector; see help max for the result when x is a k-dimensional array; min(x) analogous to max; abs(x) returns an array of the same size as x whose entries are the magnitudes of the entries of x; size(A) returns a vector with the number of rows, columns, etc. of the k-dimensional array A; length(x) returns the ‘’length’’ of the array, i.e. max(size(A)). max(x) Simple calculations with Matlab Matlab can be used as a calculator too. Common scientific functions, such as square root, sine, cosine, tangent, exponential, and logarithm are pre-defined. For example: >> >> >> >> sqrt(11) cos(.5)^2+sin(.5)^2 exp(1) log(5) The result of the last calculation not assigned to a variable is automatically assigned to the variable ans, which can then be used as any other variable in subsequent computations. Here is an example: >> 100^2-4*2*3 ans = 9976 >> sqrt(ans) ans = 99.8799 >> (-100+ans)/4 ans = -0.0300 6 SIMPLE MODELS OF POPULATION DYNAMICS Loops Loops are among the most fundamental parts of all computer programs. Loops allow you to perform calculations and other operations repeatedly. Most simulations build on iterations, where the output from a calculation feeds back to the same calculation as an input. For example, a discrete time population model uses current years population density N(t) as an input for calculating next years population density N(t+1), which is in used as the input for the calculation of population density two years forward, i.e., N(t+2). The population densities are stored in subsequent elements of a vector, where they can be retrieved for plotting and other analyses. Exponential growth The first growth model we will be looking at is exponential growth in discrete time (the same thing as geometric growth). The idea is to calculate the population size at time steps 2, 3, 4, … n when we know the population size at time t = 1. The exponential growth follows the equation: N(t+1) = BN(t) + (1-D) N(t) = RN(t) = N(0)Rt First, open the Matlab editor and create an m-file where the program code will be written: edit expon.m (edit is the command for opening the editor and expon.m is the file name). The m-file is a normal text file that you should save at a known location at your hard disk. Once the file is saved, it can be executed in Matlab by typing the file name without the .m suffix at the command window. Depending on the system, there may also be an active function key (F5) to execute the m-file directly from the editor. In the latest version you can run a code in the “cell-mode”, where you do not have to store any .m -files. First we must decide the simulation time T. Here we can use for example T = 50. Then create a vector N where you will then store the population size at every time step. This can be done using the command N = zeros(T,1). This creates a vector containing zeros and the length of the vector equals the simulation time. Next the initial population size must be inserted to the first element of N, for example N(1) = 10. Then we need to define the growth rate R, for example R = 2. These were the things that had to be defined before we get to actual calculations, which are done in for-loop. In the for-loop Matlab calculates every year the new population size based on the previous one. Each for-loop ends with an end command. Your m-file should contain the rows: % You can write comments on your code after a %-sign. % The comments will not affect how the code functions, % but will help you to remember what each line does. clear % clears all variables in the memory T = 50; % simulation time span R = 2; % population growth rate N(1) = 10; % initial population size for t=1:T-1 % start of a for-loop for simulation time steps N(t+1) = R*N(t); % model for population dynamics end % end of a for-loop plot(1:T,N) % plot population density against time Notice that some of the lines end with a semicolon (;). The calculations at those lines are performed normally, but the results are not shown in the command window. You should use 7 semicolons to limit the output only to those parts that you are interested in. This also speeds up the execution of the code. You have to save the code before you can execute it (not if you prefer using the cell-mode). Do not give a name that is the same as some Matlab function that you are using. Save the file as firstmodel.m and run it in the command window typing firstmodel. With exponential growth it is a good idea to plot the population size on a logarithmic scale (make sure you understand why!). Try replacing the plot-command with semilogy. Run the simulation with different values of T, R and N(1) to see their effect on the results. Try also replasing the growth function with N(1)*R^t (it will run faster, for comparison you can type tic in the bigginning of your code and toc in the end in order to display the time taken to run the code). Is the output the same or different? Why? While-loop The calculations inside a while-loop are repeated as long as the given expression is true. Find out of the use of while loops (use help while) and change the exponential growth model to run as long as population density is smaller than a specified maximum density, e.g., 100 000. Use the "smaller than" (<) operator to compare current population density N(t) to the maximum density. You will also need to add a counter of simulation years. Initiate the counter before the beginning of the while loop as: t = 0; Inside the loop, increase the value of the counter by one at each run of the loop as: t = t+1; It is a good idea to save the new version of the model with a new name. Density dependent growth Once you have a working simulation for the exponential growth you will find it easy to create a similar .m-file which calculates the logistic growth of a population. Change back to a forloop if you have tried the while-loop. The logistic model has an additional parameter for the carrying capacity (K), which you have to define by giving it a numerical value (e.g. K=100). Then replace the growth equation of exponential growth in the firstmodel.m –file with that of logistic and save this new file as logistic.m. N(t+1) = N(t)*exp(R*(1-N(t)/K)); Run the model and see how the outcome differs from exponential growth. Compare the dynamics with different values of population growth rate parameter R and carrying capacity K. What is their qualitative and quantitative effect on the population? 8 BIFURCATION GRAPHS Bifurcation graphs show how the state variable (such as population density) responds to changes in the value of some parameter of the model. Recall the Ricker model for population growth. The following code shows how the dynamics of the system becomes increasingly complicated when the value of population growth rate r is increased. clear tspan = tplot = K = 10; R_min = R_max = R_steps param_R 1000; 100; 1.5; 4; = 201; = linspace(R_min,R_max,R_steps); % % % % % % % % clear memory simulation time span time steps to be plotted carrying capacity smallest value of R largest value of R number of R values R values for bif = 1:R_steps % loop for R values R = param_R(bif); % current R value N = zeros(tspan,1); % initiate population density vector N(1) = rand; % initial population density for t = 1:tspan-1 % loop for simulation year N(t+1) = N(t).*exp(R.*(1-N(t)./K)); % model end R_values(:,bif) = R*ones(tplot,1); % store R values N_values(:,bif) = N(tspan+1-tplot:end); % store densities end figure(1), clf bif = 15; % R step to be plotted as time series subplot(2,1,1) plot(R_values(:), N_values(:),'k.', R_values(:,bif),N_values(:,bif),'r*') xlabel('R (bifurcation parameter)', 'FontSize',16) ylabel('Population density', 'FontSize',16) subplot(2,1,2) plot(1:tplot,N_values(:,bif),'r-') xlabel('Time', 'FontSize',16) ylabel('Population density', 'FontSize',16) Change the population model from Ricker to Maynard Smith-Slatkin: N(t+1) = R*N(t)/(1+(a*N(t))^b). Parameters a and b stand for the strength and type of density dependence, respectively. Draw the bifurcation graph with different values of R and b. What do these parameters to population dynamics? How do they interact? 9 STOCHASTICITY Conditionals In addition to loops, conditionals are another fundamental part of programming languages. Conditionals are used for deciding between different routes the program can proceed depending on the input data. Conditionals can thus be thought as crossroads in the program code. The following examples show you the use of if-else structure. Notice that each if-command has to be terminated by a corresponding end command. Demographic stochasticity Here we model birth and death processes in a population, assuming that both processes are density dependent random events. Each individual has a probability of dying or giving birth to one offspring. At every run of a while-loop, we draw from exponential distribution the indivudal specific times after which either birth or death will take place. The event that actually takes place, is the one (birth or death) that the randomization gives the shortest waiting time. The modelled time is increased by the shortest waiting time, the size of the population is updated with either birth or death of one individual, and the loop is repeated untill the simulation has taken the predefined time-span. The methodological lesson is the use of while-loops and conditionals. The excercise also serves as an example of individual based modelling, where a continuous-time process is modelled as birth and death process taking places at random (but density dependent) time intervals. Your task is to understand how the density independent and dependent parameters of waiting time in birth and death affect (1) population size, (2) the variability of population size, and (3) the difference between contiuous time dynamics and discrete-time dynamics (the Ricker model with the same parameters as the event-based model). clear % give parameter values B = 1; % background time to birth (positive) b = 0; % birth density dependence (zero or negative) D = 2; % background time to death (positive) d = 0.01; % death density dependence (zero or positive) tspan = 30; % simulation time span N(1) = 5; % initial density time = 0; % initiate time between events k = 1; % initiate counter of time steps while sum(time)<tspan k = k+1; % update counter of time steps % draw event times from exponental distribution lambda_birth = B*exp(-b*N(k-1))/N(k-1); % birth rate lambda_death = D*exp(-d*N(k-1))/N(k-1); % death rate bt = -lambda_birth*log(rand); % time to next birth dt = -lambda_death*log(rand); % time to next death % the first of the randomized if bt < dt N(k) = N(k-1)+1; time(k) = bt; else N(k) = N(k-1)-1; events is actualized % if birth occurs before death % add one individual % update counter of time % if death occurs before birth % remove one individual 10 time(k) = dt; % update counter of time end end % simulate Ricker model for a comparison with the individual based model X(1) = N(1); % initial density for t = 1:tspan-1 % loop for time X(t+1) = X(t) * D/B * exp((b-d)*X(t)); % Ricker model end figure(1), clf plot(cumsum(time(1:k)), N(1:k), 'k-', 1:tspan,X,'b-') legend('Event based model', 'Ricker model') ylabel('Population size') xlabel('Time') The take-home message here is that in a small population demographic stochasticity has an important role. This is crucial for conservation of endangered species. Also estimating the birth- and death-rates is very difficult in a small population as the stochasticity plays such an important role. This makes the conservation even more difficult. Another point to understand is that contiuous-time and discrete time dynamics can be qualitatively different, even if the population parameters were exactly same. Clearly, the accumulation of births and deaths and time it takes for the renewal process to respond to changes in population density, is important for population dymamics. Environmental stochasticity Now let’s take a look at exponential growth with environmental stochasticity. We assume that the environment can be either ’good’ or ’bad’, this quality of environment is modeled altering the value of the growth rate, R. It can be either Rgood = 1.25 or Rbad = 0.8. We further assume that each value of R is equally probable (i.e. the probability is 0.5 for both values). clear tspan = 100; % simulation length Rgood = 1.25; % growth rate at good year Rbad = 0.8; % growth rate at bad year N(1) = 100; % initial density for t = 1:tspan-1 quality = rand; % random environmental quality if quality < 1/2 R = Rbad; else R = Rgood; end N(t+1) = R*N(t); end plot(1:tspan,N) How does the environmental stochasticity change the population dynamics? What can you say about the average growth rate? Try repeating the simulation many times to see the influence of stochasticity. Now the geometric average or R’s is 1, try situation in which the arithmetic average is 1 (for example Rgood = 1.2 and Rbad = 0.8). Arithmetic average of a and b = sqrt(a*b). 11 If you have time you can also try a scenario in which there is a very bad year with a very small probability. You can try for example Rgood = 1.05, Rbad = 0.5, P(Rgood) = 0.95, P(Rbad) = 0.05. Try different values or Rgood, Rbad, P(Rgood) and P(Rbad) to see how large catastrophies and how often the population can tolerate. How is this tolerance related to growth rate? If you still have time left, you can try how the environmental stochasticity works with density-dependent growth. Does it differ from what happens with density-independent growth? 12 HARVESTING, MAXIMUM SUSTAINABLE YIELD Recall the model for logistic growth in discrete time and add a parameter H to stand for harvesting (or hunting) N(t+1) = N(t) + R*N(t)*(1-N(t)/K) – H Start the simulation with the initial population density equal to the carrying capacity K. Try different values of H to see what gives the highest annual yield that the population can sustain without going extinct. clear all T = 100; % simulation time span R = 2; % population growth rate K = 100; % carrying capacity H = 10; % harvest = number of killed individuals = Yield N = zeros(T,1); % initiate population density vector N(1) = 100; % initial population size for t=1:T-1 % start of a for-loop for simulation time % steps N(t+1) = N(t) + R*N(t)*(1-N(t)/K) - H; % model end % end of a for-loop MY = H; % max annual Yield clf plot(1:T,N,'b') % plot pop. size axis([0 100 0 100]); xlabel('Time'); ylabel('N') hold on plot(1:T,H,'r') % plot annual yield Add some degree of stochasticity (randomness) in the growth rate or harvesting parameter. How does this affect population persistence? What are the implications to recommended harvesting levels? One way to add stochasticity e.g., in the growth rate (inside the for-loop): Instead of R write: (R-randn*0.3) How does the harvesting of a fixed proportion of the population differ from the harvesting of a fixed quantity? Harvest a proportion: N(t+1) = N(t) + R*N(t)*(1-N(t)/K) – h*N(t); Now you have to collect Yield separately and plot it instead of H. 13 SPATIAL POPULATION DYNAMICS: DISPERSAL AND MORAN-EFFECT When a population is composed of subpopulations inhabiting different patches, each patch needs to be treated as a distinct state variable. Patches may exchange individuals by dispersal, which makes the dynamics in local patches connected to each other. However, patches that are not connected by dispersal may exhibit similar, synchronized population dynamics if they share the same environmental variation and have similar density dependent growth. This is called the "Moran effect" after the famous Australian statistician P.A.P. Moran. Two populations can, e.g., be isolated but affected by same climatic conditions. clear tspan = 200; r = 2.1; % intrinsic growth rate d1 = 0.1; % dispersal, patch 1 d2 = 0.1; % -“patch 2 extinction = 0.01; % extinction threshold x1 = zeros(tspan,1); % memory preallocation x2 = zeros(tspan,1); % memory preallocation x1(1) = rand; % initial population size, patch 1 x2(1) = rand; % initial population size, patch 2 for t = 1:tspan-1 env1(t) = rand+0.5; % random environment for patch 1 env2(t) = rand+0.5; % random environment for patch 2 % density dependent growth x1(t+1) = x1(t)*exp(r*(1-x1(t)))*env1(t); x2(t+1) = x2(t)*exp(r*(1-x2(t)))*env2(t); % dispersal x1disp = d1*x1(t+1); %individuals leaving patch 1 x2disp = d2*x2(t+1); %inds. leaving patch 2 % new population size after growth and dispersal x1(t+1) = x1(t+1) + x2disp - x1disp; x2(t+1) = x2(t+1) + x1disp - x2disp; x1(x1<extinction)=0; %check for extinction events x2(x2<extinction)=0; end figure(1), clf subplot(1,2,1) plot(1:tspan,x1,'b-', 1:tspan,x2,'r-') subplot(1,2,2) plot(x1,x2,'*') Experiment with a) the amount of correlation between environmental impacts, b) the magnitude of environmental stochasticity, and c) the amount of dispersal between patches. You need to develop the code to adjust the correlation between the two environments. To calculate correlation between the environments or the populations, you can use function corrcoef. 14 A CONTINUOUS TIME MODEL ON RESOURCE AND CONSUMER DYNAMICS The following exercise is a deviation from the otherwise discrete-time models used in this course. The code given below simulates a Lotka-Volterra -type resource-consumer (e.g., predator-prey) system. The resource (R) population grows logistically towards a carrying capacity. Resource density is decreased by a consumer (C), which has the saturating Holling's Type II functional response to resource density. R aRC dR rR1 dt K 1 hR dC caRC mC dt 1 hR The parameters are explained in the Matlab-code below. Matlab needs two files to run this simulation. The first file, which should be saved with the name "LVPredPreySys.m", is a user-defined function of the differential equations for predator and prey populations. % -------------------------------------------------------function dy = LVPredPreySys(t,y) global r K h a c m % define global variables % Differential equations dy = zeros(2,1); % initialize a system vector dy(1) = r*y(1)*(1-y(1)/K) - a*y(1)*y(2)/(1+h*y(1));% Prey dy(2) = c*a*y(1)*y(2)/(1+h*y(1)) - m*y(2); % Predator % -------------------------------------------------------- The second file, which should be saved as "LVPredPrey.m", defines values for the parameters of the model and uses 4th and 5th order Runga-Kutta method for the numerical solution (integration) of the predator and prey equations. This file also has the graphing commands for time-series and phase-plane plots. Running this file executes the simulation. % -------------------------------------------------------clear % Parameters for this file and the LVPredPreySys function global r K h a c m % define global variables r = 0.1; % prey intrinsic growth rate K = 1; % prey carrying capacity h = 0.5; % handling time a = 1; % attack rate c = 0.1; % conversion efficiency m = 0.01; % predator mortality rate initstate = [0.1 0.01]; % initial population densities tspan = [0 1000]; % time span of the simulation % Numerial solution of the equations [T,Y] = ode45('LVPredPreySys',tspan,initstate); % Zero growth isoclines x = linspace(0,K,30); prey_zero = r.*(K-x).*(1+h.*x)./(K.*a); pred_zero = m/(c*a-m*h); figure(1), clf 15 fsize = 14; % font size subplot(1,2,1) % Time series plot(T,Y(:,1),'b-', T,Y(:,2),'r-') xlabel('Time', 'FontSize',fsize) ylabel('Population density', 'FontSize',fsize) legend('Prey', 'Predator') subplot(1,2,2) % Phase plane plot(Y(:,1),Y(:,2),'k-', x,prey_zero,'b-', ... [pred_zero pred_zero],[0,1.1*max(Y(:,2))],'r-') axis tight xlabel('Prey density', 'FontSize',fsize) ylabel('Predator density', 'FontSize',fsize) % -------------------------------------------------------- Using this system you may, e.g., study how population sizes and system stability change when: 1. 2. 3. 4. prey growth rate changes, prey carrying capacity changes, predator mortality changes, there is interference competition within the predator population. (Hint: add densitydependence in predator mortality). Notice, that in (4) you should also derive new equations for the zero-growth rate isoclines. You can do this by setting the population equations equal to zero and solving the resource equation for consumer density and consumer equation for resource density. After all the simulations you have done by now, you have ended up using pen and paper (or symbolic mathematics software, but that's another story). 16 MATRIX MODELS Age is a continuous variable, but discrete time models make the census to the modelled population (usually) once a year, and individuals will therefore always be of an age that can be expressed as integer numbers. When individuals are classified in age groups, the age-specific probabilities for individuals to survive to the next age class (survive to next year) and then per capita number of offspring produced can be expressed in a Leslie matrix. When individuals are classified according to their life history stage, such as newborn, juvenile, adult, or seed, vegetative plant, flowering plant, they may spend several years in the same stage. The matrices formed according to the classification to life history stages are called Lefkovitch matrices. The choice between age and stage structured population models should be done according to their relation to the vital rates, such as survival and fecundity. Birds, fish and mammals are usually modelled with age structure, while classification according to life-history stage may be more relevant for plants and invertebrates. The methodological lesson here is that population state can be a vector instead of a scalar. It would be possible to model each state variable (such as age or stage class, species, or ecosystem compartment in element cycling) of the system as a separate equation, but this becomes highly unpractical when the number of state variables is large and impossible when the number of state variables changes during the simulation. The ability to perceive system state as a vector enables you to write compact and easy-to-read code, which helps to keep it free from bugs. The ability to separate system matrix that determines the dynamics, from the system vector enables you to utilize very efficient methods for analysing system dynamics. Becoming accustomed to matrix-vector presentation may feel like major rewiring in your cerebral network, but it is well worth the effort! Age structure population Now we have a population with different age classes. Here we start with 3 classes, but it is easy to add more. Let Px denote the probability that an individual starting in age class x survives through the entire time step (here x = 1, 2 or 3). Similarly let Fx be the fertility of an individual in age group x. Also let nx(t) be the number of individuals in age group x at time t. Now we can calculate the number of new offspring using the sizes of different age classes and fecundities in the age classes: n1t 1 F1n1t F2n1t F3n1t The number of individuals in age class 2 at the next time step is the proportion of individuals that survive the previous time step in age class 1: n2t 1 P1n1t Similarly the age class 3 at next time step is the proportion of individuals in age class 2 that survive: n3t 1 P2n2t Now these three equations can be represented in matrix form. The survival probabilities and fecundities are collected in matrix A, while age-class specific population densities are placed in vector n(t): 17 F1 A P1 0 F2 0 P2 F3 0 0 n1 nt n2 t n3 Using this notation we can write the model as the sum of transition matrix A and system state vector n(t): nt 1 Ant Notice that the product of A and n(t) is a matrix-product, which is different from a product by elements. Let’s try a numerical example. Open the editor and write: clear tspan = 20; % a matrix can be written on several rows A = [0.5 1 0.75 0.666 0 0 0 0.3333 0]; n = zeros(3,tspan); s = zeros(1,tspan); n(:,1) = [2;0;0]; % initial population densities for t = 1:tspan-1 n(:,t+1) = A*n(:,t); % a matrix-vector product! end % If a command does not fit on a single line, % three dots (...) are used for break it: figure(1), clf plot(1:tspan, n(1,:),'b-',1:tspan,n(2,:),'r-', ... 1:tspan,n(3,:),'g-') Save the file as leslie1.m and try running it. The matrix n consists of column vectors containing the sizes of 3 age groups. n(:,1) is the initial distribution of animals belonging to age groups 1, 2 and 3 (first column in the matrix). In the for-loop the program calculates first n(:,2), then n(:,3) etc. Use semilogy for plotting the population size in a logarithmic scale at the y-axis. You should see that after a couple of time steps the population growth becomes exponential. Eigenvalue analysis: sensitivity and elasticity in a plant population The transition matrix of a age or stage structured population model contains all factors intrinsic to the population itself that affect its dynamics. Certain characteristics of the transition matrix can therefore be used in the analysis of population dynamics without simulations. We will concentrate on the measures that indicate the asymptotic dynamics of the population, i.e., the dynamics that the population approaches over time, but other measures are able to provide insight of the transient behaviour of the system as well. The growth rate can be calculated from the time-series, but it is also equals to the dominant eigenvalue of the transition matrix A. The scalar (i.e. number) is an eigenvalue and w is the corresponding eigenvector if Aw = w. Eigenvalue-problems could be devoted a course of their own, but now it is sufficient to understand that a matrix can be replaced by an eigenvalue (i.e., growth rate) when the state of the population n(t) corresponds to the stable state of the system (w). Try: L = eig(A) 18 R = max(L) Try then altering the values of fecundities and survival rates and observe how the population behaves. The following Leslie-matrix describes the red deer population in isle of Rhum, Scotland. The population is being hunted and these fecundities and survivorships are estimated with hunting in presence. The question here is whether the hunting keeps the population in check, i.e. its geometric growth factor R near one. 0 0 .26 .26 .26 .26 .35 .26 .31 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 .94 0 0 0 .80 0 0 0 0 0 0 0 0 0 .67 0 0 0 0 0 red 0 0 0 0 .61 0 0 0 0 0 0 0 .63 0 0 0 0 0 0 0 0 0 .72 0 0 0 0 0 0 0 0 0 0 0 .22 0 Enter the matrix into Matlab. The geometric growth factor is equal to the dominant (i.e. largest real) eigenvalue. Try typing >> [w,L] = eig(red) >> R = max(diag(L)) >> r = log(R) [w,L] = eig(red) calculates the eigenvalues (L) and eigenvectors (w) of matrix red. R is the dominant eigenvalue. What can you conclude about the hunting, is it keeping the population in check? The stable age distribution can be also calculated from the Leslie-matrix. It equals the eigenvector corresponding to the dominant eigenvalue. In this example we have already calculated the eigenvectors (w), so we only have to pick the first one (w(:,1), which corresponds to the dominant eigenvalue) and divide it by its sum to get an age distribution which sums up to one. >> c = w(:,1)/sum(w(:,1)) >> figure >> bar(c) Below is a transition matrix for an imagined plant species. The population is divided into three life-stages: seeds, vegetative individuals and fertile individuals. The transitions between the stages form the matrix A. clear A = [ 0.1 0 10 0.05 0.2 .6 0 0.3 .2] [L,ind] = max(real(eig(A))); lambda = L [W,L] = eig(A); w = W(:,ind); [L,ind] = max(real(eig(A'))); lambda = L; % % % % % % dominant eigenvalue... ...is population growth rate right eigenvectors stable distribution dominant eigenvalue... ...is population growth rate 19 [V,L] = eig(A'); v = V(:,ind); w = w./sum(w) v = v./v(1) sens = v*w'./(v'*w) elast = A./lambda.*sens % % % % % % left eigenvectors reproductive values scaling to sum to unity scaling to first stage sensitivities elasticities The Matlab code below that performs the sensitivity and elasticity analyses for the dominant eigenvalue of matrix A. What can you say about the ecology of the plant in the light of this analysis? What do sensitivity and elasticity analyses tell about the Red deer, when you place matrix red in place of the plant matrix? 20 MY FAVORITE POPULATION MODEL Deadline 18:00, 10.12.2008 Choose an ecological problem or question, formulate the problem as a mathematical model or take a model from literature. Analyse the model using Matlab. Report your work in written form, with the following components Name, student number and course are all vital, then: 1. Introduction – should give some background to your study (including important literature) and state your aim clearly 2. Model and analysis – clearly describe the system you are studying, including any equations that feature in your model. The information here must allow someone reading the report to replicate what you did exactly! 3. Results – Present your model outcomes and results here, using graphs, tables, statistics, equations, whatever communicates your results most clearly to an uninformed reader. 4. Discussion – Relate your results to other work and important concepts. You can be speculative here, but not ridiculous. 5. References – List all literature you have cited in your report, including books, journal articles and web-sites. Beware of websites, though – they are not peer-reviewed and may not all be suitable to back up any arguments you make. 6. Appendix: the Matlab-code to generate any results shown in the report. We are all subjective readers. The way you report your work will be part of our judgment about its quality, so — make it look good!