-
Notifications
You must be signed in to change notification settings - Fork 127
/
Copy pathdps_lake_model.py
131 lines (106 loc) · 3.16 KB
/
dps_lake_model.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import math
import numpy as np
from scipy.optimize import brentq
def get_antropogenic_release(xt, c1, c2, r1, r2, w1):
"""
Parameters
----------
xt : ndarray
pollution in lake at time t
c1 : float
center rbf 1
c2 : float
center rbf 2
r1 : float
radius rbf 1
r2 : float
radius rbf 2
w1 : float
weight of rbf 1
Returns
-------
float
note:: w2 = 1 - w1
"""
rule = w1 * (abs(xt - c1) / r1) ** 3 + (1 - w1) * (abs(xt - c2) / r2) ** 3
at = np.clip(rule, 0.01, 0.1)
return at
def lake_model(
b=0.42,
q=2.0,
mean=0.02,
stdev=0.001,
delta=0.98,
alpha=0.4,
nsamples=100,
myears=100,
c1=0.25,
c2=0.25,
r1=0.5,
r2=0.5,
w1=0.5,
seed=None,
):
"""runs the lake model for nsamples stochastic realisation using
specified random seed.
Parameters
----------
b : float
decay rate for P in lake (0.42 = irreversible)
q : float
recycling exponent
mean : float
mean of natural inflows
stdev : float
standard deviation of natural inflows
delta : float
future utility discount rate
alpha : float
utility from pollution
nsamples : int, optional
myears : int, optional
c1 : float
c2 : float
r1 : float
r2 : float
w1 : float
seed : int, optional
seed for the random number generator
Returns
-------
tuple
"""
np.random.seed(seed)
Pcrit = brentq(lambda x: x**q / (1 + x**q) - b * x, 0.01, 1.5)
# Generate natural inflows using lognormal distribution
natural_inflows = np.random.lognormal(
mean=math.log(mean**2 / math.sqrt(stdev**2 + mean**2)),
sigma=math.sqrt(math.log(1.0 + stdev**2 / mean**2)),
size=(nsamples, myears),
)
# Initialize the pollution level array X and the decisions array
X = np.zeros((nsamples, myears))
decisions = np.zeros((myears, myears))
# we assume a decision for T=0
decisions[:, 0] = 0.1
for t in range(1, myears):
# here we use the decision rule
decision = get_antropogenic_release(X[t - 1, :], c1, c2, r1, r2, w1)
decisions[t, :] = decision
X[:, t] = (
(1 - b) * X[:, t - 1]
+ (X[:, t - 1] ** q / (1 + X[:, t - 1] ** q))
+ decisions[:, t - 1]
+ natural_inflows[:, t - 1]
)
# Calculate the average daily pollution for each time step
average_daily_P = np.mean(X, axis=0)
# Calculate the reliability (probability of the pollution level being below Pcrit)
reliability = np.sum(X < Pcrit) / float(nsamples * myears)
# Calculate the maximum pollution level (max_P)
max_P = np.max(average_daily_P)
# Calculate the utility by discounting the decisions using the discount factor (delta)
utility = np.sum(alpha * decisions * np.power(delta, np.arange(myears))) / nsamples
# Calculate the inertia (the fraction of time steps with changes larger than 0.02)
inertia = np.sum(np.abs(np.diff(decisions)) > 0.02) / float(myears * nsamples)
return max_P, utility, inertia, reliability