Lotka-Volterra equations: Difference between revisions
From JSXGraph Wiki
(New page: This example doesn't work by now because it uses Runge-Kutta methods not implemented in the current release of jsxgraph. With the next release this example should work. --~~~~ ---- <js...) |
No edit summary |
||
Line 5: | Line 5: | ||
---- | ---- | ||
The Lotka-Volterra equations, a.k.a. the predator-prey equations, are a pair of non-linear differential equations mainly used to describe interaction of two biological species, one a predator and one a prey. The equations were developed independently by Alfred J. Lotka and Vito Volterra. | |||
==Model== | |||
<math>\frac{dN_1}{dt} = N_1(\epsilon_1 - \gamma_1N_2), \quad \frac{dN_2}{dt} = -N_2(\epsilon_2 - \gamma_2N_1)</math> | |||
Bedeutung der Variablen: | |||
::{| border="1" || | |||
|- | |||
| <math>N_1 = N_1(t)</math> || Number of preys | |||
|- | |||
| <math>\epsilon_1>0</math> || Reproduction rate of prey without distortion and with enough food supply | |||
|- | |||
| <math>N_2 = N_2(t)</math> || Number of predators | |||
|- | |||
| <math>\epsilon_2>0</math> || Death rate of predators if no prey available | |||
|- | |||
| <math>\gamma_1>0</math> || Eating rate of predator per prey (equals death rate of prey per predator) | |||
|- | |||
| <math>\gamma_2>0</math> || Reproduction rate of predator per prey | |||
|} | |||
==Plot== | |||
<jsxgraph width="600" height="600"> | <jsxgraph width="600" height="600"> | ||
Line 57: | Line 80: | ||
} | } | ||
function | var data = ode(); | ||
var t = []; | |||
var dataprey = []; | |||
var datapred = []; | |||
for(var i=0; i<data.length; i++) { | |||
t[i] = data[i][2]; | |||
datapred[i] = data[i][0]; | |||
dataprey[i] = data[i][1]; | |||
} | |||
g3 = board.createElement('curve', [t, datapred], {strokeColor:'red', strokeWidth:'2px'}); | |||
g3.updateDataArray = function() { | |||
var data = ode(); | var data = ode(); | ||
this.dataX = []; | |||
this.dataY = []; | |||
for(var i=0; i<data.length; i++) { | |||
this.dataX[i] = t[i]; | |||
this.dataY[i] = data[i][0]; | |||
} | |||
} | |||
g4 = board.createElement('curve', [t, dataprey], {strokeColor:'blue', strokeWidth:'2px'}); | |||
g4.updateDataArray = function() { | |||
var data = ode(); | |||
this.dataX = []; | |||
this.dataY = []; | |||
for(var i=0; i<data.length; i++) { | |||
this.dataX[i] = t[i]; | |||
this.dataY[i] = data[i][1]; | |||
} | |||
} | |||
</jsxgraph> | |||
==Source code== | |||
<source lang="javascript"> | |||
// Initialise board | |||
board = JXG.JSXGraph.initBoard('jxgbox', {originX: 40, originY: 560, unitX: 20, unitY: 20, axis: false, grid: false}); | |||
// Create axis | |||
xax = board.createElement('axis', [[0,0],[1,0]]); | |||
yax = board.createElement('axis', [[0,0],[0,1]]); | |||
// Define sliders to dynamically change parameters of the equations and create text elements to describe them | |||
s = board.createElement('slider', [[20.0,26.0],[25.0,26.0],[0.0,0.3,1.0]],{name:'ε1'}); | |||
st = board.createElement('text', [20,25, "Birth rate predators"]); | |||
u = board.createElement('slider', [[20.0,24.0],[25.0,24.0],[0.0,0.7,1.0]],{name:'ε2'}); | |||
ut = board.createElement('text', [20,23, "Death rate predators"]); | |||
o = board.createElement('slider', [[10.0,26.0],[15.0,26.0],[0.0,0.1,1.0]],{name:'γ1'}); | |||
ot = board.createElement('text', [10,25, "Death rate preys/per predator"]); | |||
p = board.createElement('slider', [[10.0,24.0],[15.0,24.0],[0.0,0.3,1.0]],{name:'γ2'}); | |||
pt = board.createElement('text', [10,23, "Reproduction rate pred./per prey"]); | |||
// Dynamic initial value as gliders on the y-axis | |||
startpred = board.createElement('glider', [0, 10, yax], {name:'Preys'}); | |||
startprey = board.createElement('glider', [0, 5, yax], {name:'Predators'}); | |||
// Variables for the JXG.Curves | |||
var g3 = null; | |||
var g4 = null; | |||
// Initialise ODE and solve it with JXG.Math.Numerics.rungeKutta() | |||
function ode() { | |||
// evaluation interval | |||
var I = [0, 25]; | |||
// Number of steps. 1000 should be enough | |||
var N = 1000; | |||
// Right hand side of the ODE dx/dt = f(t, x) | |||
var f = function(t, x) { | |||
var bpred = s.Value();//0.3; | |||
var bprey = u.Value();//0.7; | |||
var dpred = o.Value();//0.1; | |||
var dprey = p.Value();//0.3; | |||
var y = []; | |||
y[0] = x[0]*(bpred - dpred*x[1]); | |||
y[1] = -x[1]*(bprey - dprey*x[0]); | |||
return y; | |||
} | |||
// Initial value | |||
var x0 = [startpred.Y(), startprey.Y()]; | |||
// Solve ode | |||
var data = JXG.Math.Numerics.rungeKutta(JXG.Math.Numerics.predefinedButcher.Euler, x0, I, N, f); | |||
// to plot the data against time we need the times where the equations were solved | |||
var t = []; | var t = []; | ||
var | var q = I[0]; | ||
var | var h = (I[1]-I[0])/N; | ||
for(var i=0; i<data.length; i++) { | for(var i=0; i<data.length; i++) { | ||
data[i].push(q); | |||
q += h; | |||
} | } | ||
g3 = board.createElement('curve', [t, datapred], {strokeColor:'red', strokeWidth:'2px'}); | return data; | ||
} | |||
// get data points | |||
var data = ode(); | |||
// copy data to arrays so we can plot it using JXG.Curve | |||
var t = []; | |||
var dataprey = []; | |||
var datapred = []; | |||
for(var i=0; i<data.length; i++) { | |||
t[i] = data[i][2]; | |||
datapred[i] = data[i][0]; | |||
dataprey[i] = data[i][1]; | |||
} | |||
// Plot Predator | |||
g3 = board.createElement('curve', [t, datapred], {strokeColor:'red', strokeWidth:'2px'}); | |||
g3.updateDataArray = function() { | |||
var data = ode(); | |||
this.dataX = []; | |||
this.dataY = []; | |||
for(var i=0; i<data.length; i++) { | |||
this.dataX[i] = t[i]; | |||
this.dataY[i] = data[i][0]; | |||
} | } | ||
} | |||
// Plot Prey | |||
g4 = board.createElement('curve', [t, dataprey], {strokeColor:'blue', strokeWidth:'2px'}); | |||
g4.updateDataArray = function() { | |||
var data = ode(); | |||
this.dataX = []; | |||
this.dataY = []; | |||
for(var i=0; i<data.length; i++) { | |||
this.dataX[i] = t[i]; | |||
this.dataY[i] = data[i][1]; | |||
} | } | ||
} | } | ||
</source> | |||
</ |
Revision as of 18:58, 29 May 2009
This example doesn't work by now because it uses Runge-Kutta methods not implemented in the current release of jsxgraph. With the next release this example should work.
--Michael 18:12, 29 May 2009 (UTC)
The Lotka-Volterra equations, a.k.a. the predator-prey equations, are a pair of non-linear differential equations mainly used to describe interaction of two biological species, one a predator and one a prey. The equations were developed independently by Alfred J. Lotka and Vito Volterra.
Model
[math]\displaystyle{ \frac{dN_1}{dt} = N_1(\epsilon_1 - \gamma_1N_2), \quad \frac{dN_2}{dt} = -N_2(\epsilon_2 - \gamma_2N_1) }[/math]
Bedeutung der Variablen:
[math]\displaystyle{ N_1 = N_1(t) }[/math] Number of preys [math]\displaystyle{ \epsilon_1\gt 0 }[/math] Reproduction rate of prey without distortion and with enough food supply [math]\displaystyle{ N_2 = N_2(t) }[/math] Number of predators [math]\displaystyle{ \epsilon_2\gt 0 }[/math] Death rate of predators if no prey available [math]\displaystyle{ \gamma_1\gt 0 }[/math] Eating rate of predator per prey (equals death rate of prey per predator) [math]\displaystyle{ \gamma_2\gt 0 }[/math] Reproduction rate of predator per prey
Plot
Source code
// Initialise board
board = JXG.JSXGraph.initBoard('jxgbox', {originX: 40, originY: 560, unitX: 20, unitY: 20, axis: false, grid: false});
// Create axis
xax = board.createElement('axis', [[0,0],[1,0]]);
yax = board.createElement('axis', [[0,0],[0,1]]);
// Define sliders to dynamically change parameters of the equations and create text elements to describe them
s = board.createElement('slider', [[20.0,26.0],[25.0,26.0],[0.0,0.3,1.0]],{name:'ε1'});
st = board.createElement('text', [20,25, "Birth rate predators"]);
u = board.createElement('slider', [[20.0,24.0],[25.0,24.0],[0.0,0.7,1.0]],{name:'ε2'});
ut = board.createElement('text', [20,23, "Death rate predators"]);
o = board.createElement('slider', [[10.0,26.0],[15.0,26.0],[0.0,0.1,1.0]],{name:'γ1'});
ot = board.createElement('text', [10,25, "Death rate preys/per predator"]);
p = board.createElement('slider', [[10.0,24.0],[15.0,24.0],[0.0,0.3,1.0]],{name:'γ2'});
pt = board.createElement('text', [10,23, "Reproduction rate pred./per prey"]);
// Dynamic initial value as gliders on the y-axis
startpred = board.createElement('glider', [0, 10, yax], {name:'Preys'});
startprey = board.createElement('glider', [0, 5, yax], {name:'Predators'});
// Variables for the JXG.Curves
var g3 = null;
var g4 = null;
// Initialise ODE and solve it with JXG.Math.Numerics.rungeKutta()
function ode() {
// evaluation interval
var I = [0, 25];
// Number of steps. 1000 should be enough
var N = 1000;
// Right hand side of the ODE dx/dt = f(t, x)
var f = function(t, x) {
var bpred = s.Value();//0.3;
var bprey = u.Value();//0.7;
var dpred = o.Value();//0.1;
var dprey = p.Value();//0.3;
var y = [];
y[0] = x[0]*(bpred - dpred*x[1]);
y[1] = -x[1]*(bprey - dprey*x[0]);
return y;
}
// Initial value
var x0 = [startpred.Y(), startprey.Y()];
// Solve ode
var data = JXG.Math.Numerics.rungeKutta(JXG.Math.Numerics.predefinedButcher.Euler, x0, I, N, f);
// to plot the data against time we need the times where the equations were solved
var t = [];
var q = I[0];
var h = (I[1]-I[0])/N;
for(var i=0; i<data.length; i++) {
data[i].push(q);
q += h;
}
return data;
}
// get data points
var data = ode();
// copy data to arrays so we can plot it using JXG.Curve
var t = [];
var dataprey = [];
var datapred = [];
for(var i=0; i<data.length; i++) {
t[i] = data[i][2];
datapred[i] = data[i][0];
dataprey[i] = data[i][1];
}
// Plot Predator
g3 = board.createElement('curve', [t, datapred], {strokeColor:'red', strokeWidth:'2px'});
g3.updateDataArray = function() {
var data = ode();
this.dataX = [];
this.dataY = [];
for(var i=0; i<data.length; i++) {
this.dataX[i] = t[i];
this.dataY[i] = data[i][0];
}
}
// Plot Prey
g4 = board.createElement('curve', [t, dataprey], {strokeColor:'blue', strokeWidth:'2px'});
g4.updateDataArray = function() {
var data = ode();
this.dataX = [];
this.dataY = [];
for(var i=0; i<data.length; i++) {
this.dataX[i] = t[i];
this.dataY[i] = data[i][1];
}
}