MCMC toolbox » Examples » Algae
Algae example
The example uses functions algaesys, algaefun and algaess.
We study the following system
This is a simplified lake algae dynamics model. We consider phytoplankton A, zooplankton Z and nutrition P (eg. phosphorus) available for A in the water. The system is affected by the water outflow/inflow Q, incoming phosphorus load Pin and temperature T. It is described as a simple predator - pray dynamics between A and Z. The growth of A is limited by the availability of P and it depends on the water temperature T. The inflow/outflow Q affects both A and P, but not Z. We use the following equations:
dA/dt = (μ - ρa - Q/V - αZ) A
dZ/dt = αZA-ρz Z
dP/dt = -Q/V (P-Pin)
+ (ρa-μ)A+ρzZ
where the growth rate µ depends on both temperature T and phosphorus P
μ = μmaxθ(T-20)P/(k+P).
The data set is stored in algaedata.mat. First we load and plot the data.
clear model data params options load algaedata.mat figure for i =1:3 subplot(2,3,i) plot(data.xdata(:,1),data.xdata(:,i+1),'-k'); title(data.xlabels(i+1)); xlim([1,120]) end subplot(2,1,2) plot(data.ydata(:,1),data.ydata(:,2:end),'o-'); title('model state variable observations'); legend(data.ylabels(2:end),0); xlabel('days');
The model sum of squares in file algaess.m is given in the model structure.
model.ssfun = @algaess;
All parameters are constrained to be positive. The initial concentrations are also unknown and are treated as extra parameters.
params = { {'mumax', 0.5, 0} {'rhoa', 0.03, 0} {'rhoz', 0.1, 0} {'k', 10, 0} {'alpha', 0.02, 0} {'th', 1.14, 0, Inf, 1.14, 0.2} % N(0.14, 0.2^2)1{th>0} prior % initial values for the model states {'A0', 0.77, 0, Inf, 0.77, 2 } {'Z0', 1.3, 0, Inf, 1.3, 2 } {'P0', 10, 0, Inf, 10, 2 } };
We assume having at least some prior information on the repeatability of the observation and assign rather non informational prior for the residual variances of the observed states. The default prior distribution is sigma2 ~ invchisq(S20,N0), the inverse chi squared distribution (see for example Gelman et al.). The 3 components (A, Z, P) all have separate variances.
model.S20 = [1 1 2]; model.N0 = [4 4 4];
First generate an initial chain.
options.nsimu = 1000; [results, chain, s2chain]= mcmcrun(model,data,params,options);
Sampling these parameters: name start [min,max] N(mu,s^2) mumax: 0.5 [0,Inf] N(0,Inf) rhoa: 0.03 [0,Inf] N(0,Inf) rhoz: 0.1 [0,Inf] N(0,Inf) k: 10 [0,Inf] N(0,Inf) alpha: 0.02 [0,Inf] N(0,Inf) th: 1.14 [0,Inf] N(1.14,0.2^2) A0: 0.77 [0,Inf] N(0.77,2^2) Z0: 1.3 [0,Inf] N(1.3,2^2) P0: 10 [0,Inf] N(10,2^2)
Then re-run starting from the results of the previous run, this will take about 10 minutes.
options.nsimu = 5000; [results, chain, s2chain] = mcmcrun(model,data,params,options, results);
Using values from the previous run Sampling these parameters: name start [min,max] N(mu,s^2) mumax: 0.557412 [0,Inf] N(0,Inf) rhoa: 0.0793868 [0,Inf] N(0,Inf) rhoz: 0.0996645 [0,Inf] N(0,Inf) k: 9.74477 [0,Inf] N(0,Inf) alpha: 0.025318 [0,Inf] N(0,Inf) th: 1.02955 [0,Inf] N(1.14,0.2^2) A0: 1.04487 [0,Inf] N(0.77,2^2) Z0: 1.27712 [0,Inf] N(1.3,2^2) P0: 10.6511 [0,Inf] N(10,2^2)
Chain plots should reveal that the chain has converged and we can use the results for estimation and predictive inference.
figure mcmcplot(chain,[],results,'pairs'); figure mcmcplot(chain,[],results,'denspanel',2);
Function chainstats calculates mean ans std from the chain and estimates the Monte Carlo error of the estimates. Number tau is the integrated autocorrelation time and geweke is a simple test for a null hypothesis that the chain has converged.
chainstats(chain,results)
MCMC statistics, nsimu = 5000 mean std MC_err tau geweke --------------------------------------------------------------------- mumax 0.58295 0.10072 0.0098423 59.983 0.88423 rhoa 0.095294 0.032135 0.0030665 72.198 0.97093 rhoz 0.10071 0.005465 0.00065503 124.01 0.92124 k 11.192 3.6311 0.42752 92.865 0.68367 alpha 0.024053 0.0013425 0.00011572 45.453 0.9596 th 1.0069 0.010952 0.0010679 36.935 0.99297 A0 0.96906 0.28734 0.030465 63.208 0.75098 Z0 1.7996 0.52124 0.037832 30.294 0.87729 P0 9.1803 0.91126 0.1118 147.28 0.82641 ---------------------------------------------------------------------
In order to use the mcmcpred function we need function modelfun with input arguments given as modelfun(xdata,theta). We construct this as an anonymous function.
modelfun = @(d,th) algaefun(d(:,1),th,th(7:9),d);
We sample 500 parameter realizations from chain and s2chain and calculate the predictive plots.
nsample = 500; out = mcmcpred(results,chain,s2chain,data.xdata,modelfun,nsample); figure mcmcpredplot(out); % add the 'y' observations to the plot hold on for i=1:3 subplot(3,1,i) hold on plot(data.ydata(:,1),data.ydata(:,i+1),'s'); ylabel(''); title(data.ylabels(i+1)); hold off end xlabel('days');