-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlotkavolterra.html
139 lines (124 loc) · 5.51 KB
/
lotkavolterra.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://api.fonts.coollabs.io">
<title>Lotka Volterra</title>
<meta name="description" content="Numerical solutions of the Lotka Volterra population model in JavaScript">
<link rel="stylesheet" href="css/ode.css">
<link rel="stylesheet" href="https://api.fonts.coollabs.io/css2?family=Raleway:wght@300;400;600&display=swap">
<link rel="preload" href="css/uplot.min.css" as="style">
<link rel="preload" href="scripts/ode.js" as="script">
<link rel="preload" href="scripts/uplot.min.js" as="script">
</head>
<body> <a class="homeLink" href="./"><svg width="40" height="40" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M11.9481 14.8285L10.5339 16.2427L6.29126 12L10.5339 7.7574L11.9481 9.17161L10.1197 11H17.6568V13H10.1197L11.9481 14.8285Z"
fill="currentColor" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M23 19C23 21.2091 21.2091 23 19 23H5C2.79086 23 1 21.2091 1 19V5C1 2.79086 2.79086 1 5 1H19C21.2091 1 23 2.79086 23 5V19ZM19 21H5C3.89543 21 3 20.1046 3 19V5C3 3.89543 3.89543 3 5 3H19C20.1046 3 21 3.89543 21 5V19C21 20.1046 20.1046 21 19 21Z"
fill="currentColor" />
</svg></a>
<h1>Lotka Volterra</h1>
<p>
The Lotka Volterra equations are a pair of first order differential equations that model predator prey populations.
Without a predator, we would expect the prey population to grow exponentially. The increasing prey population means
lots of food for our predator population, leading to a positive growth rate. At some point, the predator food demand
surpasses the available resources, leading to a rapid fall in prey population. Due to the lack of prey, the
predators starve to death and their population decreases as well. This concludes a cycle. The equations can easily
be adapted for a model with multiple predators, which will produce to more complex periodic solutions. As you can
see, the model is heavily simplified, in reality there are many other limiting factors, like food and space.
Nonetheless, the Lotka Volterra model produces useful results that can for example be observed in nature and
market economies.
</p>
<object style="width: 100%; max-height: 6.7em;" data="images/lotkavolt.svg" type="image/svg+xml">Lotka Volterra
equations</object>
<p>
The parameters describe natural birth and deathrates of both species. Slight modifications of the Lotka Volterra
ODEs can also be used to model how viruses spread when hosts get immunity for some time after an infection. Since
immune individuals aren't available as hosts, this can be treated as "prey dying". The longer the immunity lasts,
the longer the "birth rate". If you want to learn more, here's the
<a href="https://en.wikipedia.org/wiki/Lotka%E2%80%93Volterra_equations">wikipedia article</a>.
</p>
<div style="display: flex; justify-content: space-between;">
<div class="sliderscont">
<input type="range" oninput="updateSim()" value="1.5" min="0.1" max="5" step="any" name="resolution slider"
id="alphaSlid">
<label for="alphaSlid">birth rate prey</label>
<input type="range" oninput="updateSim()" value="1" min="0.1" max="5" step="any" name="resolution slider"
id="betaSlid">
<label for="betaSlid">death rate prey</label>
</div>
<div class="sliderscont">
<input type="range" oninput="updateSim()" value="3" min="0.1" max="5" step="any" name="resolution slider"
id="deltaSlid">
<label for="deltaSlid">birth rate predator</label>
<input type="range" oninput="updateSim()" value="2" min="0.1" max="5" step="any" name="resolution slider"
id="gammaSlid">
<label for="gammaSlid">death rate predator</label>
</div>
</div>
<noscript>
<p>
Please enable JavaScript for a live demo. I promise it's not for tracking.
</p>
</noscript>
<div id="plot"></div>
</body>
<link rel="stylesheet" href="css/uplot.min.css">
<script src="scripts/uplot.min.js"></script>
<script src="scripts/ode.js"></script>
<script async>
var plotElem = document.getElementById("plot")
function getSliderValue(id) {
return parseFloat(document.getElementById(id).value)
}
var LotkaVolterraVAR = (t, y) => {
var alpha = getSliderValue("alphaSlid")
var beta = getSliderValue("betaSlid")
var delta = getSliderValue("deltaSlid")
var gamma = getSliderValue("gammaSlid")
return [alpha * y[0] - beta * y[0] * y[1], delta * y[0] * y[1] - gamma * y[1]]
}
var solver = new ODEsolver(LotkaVolterraVAR, [1, 2], 0, 20)
function calcOde(resolution) {
const eres = solver.rk4(~~resolution)
data = [
eres.ts,
eres.ys.map((t) => t[0]),
eres.ys.map((t) => t[1]),
]
return data
}
function updateSim() {
u.setData(calcOde(2000))
}
const opts = {
width: 900,
height: 900,
title: "Lotka Volterra population model",
scales: {
x: { time: false },
},
series: [
{ label: "t" },
{
label: "Prey",
stroke: "#D32F2F",
},
{
label: "Predator",
stroke: "#12B02F",
},
],
}
var u = new uPlot(opts, calcOde(100), plotElem)
u.setData(calcOde(1000))
u.setSize({ width: plotElem.clientWidth, height: plotElem.clientWidth });
window.addEventListener("resize", e => {
u.setSize({ width: plotElem.clientWidth, height: plotElem.clientWidth });
})
</script>
</html>