1"""A resource scarcity model in vensim.
2
3This is a slightly more sophisticated example where we translate some of the uncertainties
4on the python side, prior to running the vensim model.
5
6"""
7
8from math import exp
9
10from ema_workbench.connectors.vensim import VensimModel
11from ema_workbench.em_framework import (
12 CategoricalParameter,
13 RealParameter,
14 TimeSeriesOutcome,
15 perform_experiments,
16)
17from ema_workbench.util import ema_logging
18
19# Created on 8 mrt. 2011
20#
21# .. codeauthor:: jhkwakkel <j.h.kwakkel (at) tudelft (dot) nl>
22# epruyt <e.pruyt (at) tudelft (dot) nl>
23
24
25class ScarcityModel(VensimModel):
26 """Scarcity model."""
27
28 def returns_to_scale(self, x, speed, scale):
29 """Translate uncertainties to lookup."""
30 return (x * 1000, scale * 1 / (1 + exp(-1 * speed * (x - 50))))
31
32 def approx_learning(self, x, speed, scale, start):
33 """Translate uncertainties to lookup."""
34 x = x - start
35 loc = 1 - scale
36 a = (x * 10000, scale * 1 / (1 + exp(speed * x)) + loc)
37 return a
38
39 def f(self, x, speed, loc):
40 """Translate uncertainties to lookup."""
41 return (x / 10, loc * 1 / (1 + exp(speed * x)))
42
43 def price_substite(self, x, speed, begin, end):
44 """Translate uncertainties to lookup."""
45 scale = 2 * end
46 start = begin - scale / 2
47
48 return (x + 2000, scale * 1 / (1 + exp(-1 * speed * x)) + start)
49
50 def run_model(self, scenario, policy, constants):
51 """Method for running an instantiated model structure."""
52 kwargs = scenario
53 loc = kwargs.pop("lookup_shortage_loc")
54 speed = kwargs.pop("lookup_shortage_speed")
55 lookup = [self.f(x / 10, speed, loc) for x in range(100)]
56 kwargs["shortage price effect lookup"] = lookup
57
58 speed = kwargs.pop("lookup_price_substitute_speed")
59 begin = kwargs.pop("lookup_price_substitute_begin")
60 end = kwargs.pop("lookup_price_substitute_end")
61 lookup = [self.price_substite(x, speed, begin, end) for x in range(0, 100, 10)]
62 kwargs["relative price substitute lookup"] = lookup
63
64 scale = kwargs.pop("lookup_returns_to_scale_speed")
65 speed = kwargs.pop("lookup_returns_to_scale_scale")
66 lookup = [self.returns_to_scale(x, speed, scale) for x in range(0, 101, 10)]
67 kwargs["returns to scale lookup"] = lookup
68
69 scale = kwargs.pop("lookup_approximated_learning_speed")
70 speed = kwargs.pop("lookup_approximated_learning_scale")
71 start = kwargs.pop("lookup_approximated_learning_start")
72 lookup = [
73 self.approx_learning(x, speed, scale, start) for x in range(0, 101, 10)
74 ]
75 kwargs["approximated learning effect lookup"] = lookup
76
77 super().run_model(kwargs, policy, constants)
78
79
80if __name__ == "__main__":
81 ema_logging.log_to_stderr(ema_logging.DEBUG)
82
83 model = ScarcityModel(
84 "scarcity", wd="./models/scarcity", model_file="MetalsEMA.vpm"
85 )
86
87 model.outcomes = [
88 TimeSeriesOutcome(
89 "relative_market_price", variable_name="relative market price"
90 ),
91 TimeSeriesOutcome("supply_demand_ratio", variable_name="supply demand ratio"),
92 TimeSeriesOutcome("real_annual_demand", variable_name="real annual demand"),
93 TimeSeriesOutcome(
94 "produced_of_intrinsically_demanded",
95 variable_name="produced of intrinsically demanded",
96 ),
97 TimeSeriesOutcome("supply", variable_name="supply"),
98 TimeSeriesOutcome(
99 "Installed_Recycling_Capacity", variable_name="Installed Recycling Capacity"
100 ),
101 TimeSeriesOutcome(
102 "Installed_Extraction_Capacity",
103 variable_name="Installed Extraction Capacity",
104 ),
105 ]
106
107 model.uncertainties = [
108 RealParameter(
109 "price_elasticity_of_demand",
110 0,
111 0.5,
112 variable_name="price elasticity of demand",
113 ),
114 RealParameter(
115 "fraction_of_maximum_extraction_capacity_used",
116 0.6,
117 1.2,
118 variable_name="fraction of maximum extraction capacity used",
119 ),
120 RealParameter(
121 "initial_average_recycling_cost",
122 1,
123 4,
124 variable_name="initial average recycling cost",
125 ),
126 RealParameter(
127 "exogenously_planned_extraction_capacity",
128 0,
129 15000,
130 variable_name="exogenously planned extraction capacity",
131 ),
132 RealParameter(
133 "absolute_recycling_loss_fraction",
134 0.1,
135 0.5,
136 variable_name="absolute recycling loss fraction",
137 ),
138 RealParameter(
139 "normal_profit_margin", 0, 0.4, variable_name="normal profit margin"
140 ),
141 RealParameter(
142 "initial_annual_supply",
143 100000,
144 120000,
145 variable_name="initial annual supply",
146 ),
147 RealParameter(
148 "initial_in_goods", 1500000, 2500000, variable_name="initial in goods"
149 ),
150 RealParameter(
151 "average_construction_time_extraction_capacity",
152 1,
153 10,
154 variable_name="average construction time extraction capacity",
155 ),
156 RealParameter(
157 "average_lifetime_extraction_capacity",
158 20,
159 40,
160 variable_name="average lifetime extraction capacity",
161 ),
162 RealParameter(
163 "average_lifetime_recycling_capacity",
164 20,
165 40,
166 variable_name="average lifetime recycling capacity",
167 ),
168 RealParameter(
169 "initial_extraction_capacity_under_construction",
170 5000,
171 20000,
172 variable_name="initial extraction capacity under construction",
173 ),
174 RealParameter(
175 "initial_recycling_capacity_under_construction",
176 5000,
177 20000,
178 variable_name="initial recycling capacity under construction",
179 ),
180 RealParameter(
181 "initial_recycling_infrastructure",
182 5000,
183 20000,
184 variable_name="initial recycling infrastructure",
185 ),
186 # order of delay
187 CategoricalParameter(
188 "order_in_goods_delay",
189 (1, 4, 10, 1000),
190 variable_name="order in goods delay",
191 ),
192 CategoricalParameter(
193 "order_recycling_capacity_delay",
194 (1, 4, 10),
195 variable_name="order recycling capacity delay",
196 ),
197 CategoricalParameter(
198 "order_extraction_capacity_delay",
199 (1, 4, 10),
200 variable_name="order extraction capacity delay",
201 ),
202 # uncertainties associated with lookups
203 RealParameter(
204 "lookup_shortage_loc", 20, 50, variable_name="lookup shortage loc"
205 ),
206 RealParameter(
207 "lookup_shortage_speed", 1, 5, variable_name="lookup shortage speed"
208 ),
209 RealParameter(
210 "lookup_price_substitute_speed",
211 0.1,
212 0.5,
213 variable_name="lookup price substitute speed",
214 ),
215 RealParameter(
216 "lookup_price_substitute_begin",
217 3,
218 7,
219 variable_name="lookup price substitute begin",
220 ),
221 RealParameter(
222 "lookup_price_substitute_end",
223 15,
224 25,
225 variable_name="lookup price substitute end",
226 ),
227 RealParameter(
228 "lookup_returns_to_scale_speed",
229 0.01,
230 0.2,
231 variable_name="lookup returns to scale speed",
232 ),
233 RealParameter(
234 "lookup_returns_to_scale_scale",
235 0.3,
236 0.7,
237 variable_name="lookup returns to scale scale",
238 ),
239 RealParameter(
240 "lookup_approximated_learning_speed",
241 0.01,
242 0.2,
243 variable_name="lookup approximated learning speed",
244 ),
245 RealParameter(
246 "lookup_approximated_learning_scale",
247 0.3,
248 0.6,
249 variable_name="lookup approximated learning scale",
250 ),
251 RealParameter(
252 "lookup_approximated_learning_start",
253 30,
254 60,
255 variable_name="lookup approximated learning start",
256 ),
257 ]
258
259 results = perform_experiments(model, 1000)