forked from ricardo2911/demo-project
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLotkaVolterraClass.py
112 lines (85 loc) · 3.08 KB
/
LotkaVolterraClass.py
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
import numpy as np
class LVM:
""" Simple LotkaVolterraClass with Euler Integration """
def __init__(self, a=1.0, b=0.1, c=1.5, d=0.75, dt=0.1):
self.a = a
self.b = b
self.c = c
self.d = d
self.dt = dt
def update(self, X):
""" Forward Euler method update """
return X + self.dt * np.array(
[
self.a * X[0] - self.b * X[0] * X[1],
-self.c * X[1] + self.d * self.b * X[0] * X[1],
]
)
def dynamics(self, X0, num_iter, saver):
X = X0 # initalize
saver.store_iter(X, 0)
for i in range(num_iter):
X = self.update(X)
saver.store_iter(X, self.dt * i)
class DataSaver:
def __init__(self, instance=None):
# self.a = LVM.a
self.data = {"state_X": [], "state_T": []}
if instance is not None: # to store parameters with the result
self.a = instance.a
self.b = instance.b
self.c = instance.c
self.d = instance.d
self.dt = instance.dt
def reset(self):
self.data = {"state_X": [], "state_T": []}
def store_iter(self, X=None, T=None):
if X is not None:
self.data["state_X"].append(X.copy())
if T is not None:
self.data["state_T"].append(T)
def get_data(self):
return self.data
def LyapunovFunction():
# TODO: https://www.sciencedirect.com/science/article/pii/S1474667017354101
raise NotImplementedError()
if __name__ == "__main__":
# Definition of parameters
a = 1.0 # natural growth rate of rabbits (prey)
b = 0.1 # natural dying rate of rabbits
c = 1.5 # natural dying rate of foxes
d = 0.75 # factor describing growth of foxes based on caught rabbits
numiter = 100
dt = 15 * 1.0 / numiter
lvm = LVM(a, b, c, d, dt)
saver = DataSaver(lvm)
X0 = np.array([10, 5]) # initial conditions: 10 rabbits and 5 foxes
lvm.dynamics(X0, numiter, saver)
# You could also index saver.data['state_T']
T, Xeuler = saver.get_data()["state_T"], np.array(saver.get_data()["state_X"])
rabbits, foxes = Xeuler.T
# from Visualization import evolution
# evolution(tt, XX)
### Alternative method for solving the system
from scipy import integrate
from LotkaVolterraModel import dX_dt
t = np.linspace(0, 15, 1000) # time
X0 = np.array([10, 5]) # initial conditions: 10 rabbits and 5 foxes
X, infodict = integrate.odeint(
lambda x, _: dX_dt(x, a, b, c, d), X0, t, full_output=True
)
r, f = X.T
# Comparing the two methods (overlaid)
import matplotlib.pyplot as plt
fig1 = plt.figure()
plt.plot(T, rabbits, "r-", label="Rabbits")
plt.plot(T, foxes, "b-", label="Foxes")
plt.plot(t, r, "r--", label="Rabbits")
plt.plot(t, f, "b--", label="Foxes")
plt.grid()
plt.legend(loc="best")
plt.xlabel("time")
plt.ylabel("population")
plt.title("Evolution of fox and rabbit populations")
fig1.savefig("rabbits_and_foxes" + str(numiter) + ".png")
plt.show()