aiphoria 0.0.1__py3-none-any.whl → 0.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. aiphoria/__init__.py +59 -0
  2. aiphoria/core/__init__.py +55 -0
  3. aiphoria/core/builder.py +305 -0
  4. aiphoria/core/datachecker.py +1808 -0
  5. aiphoria/core/dataprovider.py +806 -0
  6. aiphoria/core/datastructures.py +1686 -0
  7. aiphoria/core/datavisualizer.py +431 -0
  8. aiphoria/core/datavisualizer_data/LICENSE +21 -0
  9. aiphoria/core/datavisualizer_data/datavisualizer_plotly.html +5561 -0
  10. aiphoria/core/datavisualizer_data/pako.min.js +2 -0
  11. aiphoria/core/datavisualizer_data/plotly-3.0.0.min.js +3879 -0
  12. aiphoria/core/flowmodifiersolver.py +1754 -0
  13. aiphoria/core/flowsolver.py +1472 -0
  14. aiphoria/core/logger.py +113 -0
  15. aiphoria/core/network_graph.py +136 -0
  16. aiphoria/core/network_graph_data/ECHARTS_LICENSE +202 -0
  17. aiphoria/core/network_graph_data/echarts_min.js +45 -0
  18. aiphoria/core/network_graph_data/network_graph.html +76 -0
  19. aiphoria/core/network_graph_data/network_graph.js +1391 -0
  20. aiphoria/core/parameters.py +269 -0
  21. aiphoria/core/types.py +20 -0
  22. aiphoria/core/utils.py +362 -0
  23. aiphoria/core/visualizer_parameters.py +7 -0
  24. aiphoria/data/example_scenario.xlsx +0 -0
  25. aiphoria/example.py +66 -0
  26. aiphoria/lib/docs/dynamic_stock.py +124 -0
  27. aiphoria/lib/odym/modules/ODYM_Classes.py +362 -0
  28. aiphoria/lib/odym/modules/ODYM_Functions.py +1299 -0
  29. aiphoria/lib/odym/modules/__init__.py +1 -0
  30. aiphoria/lib/odym/modules/dynamic_stock_model.py +808 -0
  31. aiphoria/lib/odym/modules/test/DSM_test_known_results.py +762 -0
  32. aiphoria/lib/odym/modules/test/ODYM_Classes_test_known_results.py +107 -0
  33. aiphoria/lib/odym/modules/test/ODYM_Functions_test_known_results.py +136 -0
  34. aiphoria/lib/odym/modules/test/__init__.py +2 -0
  35. aiphoria/runner.py +678 -0
  36. aiphoria-0.8.0.dist-info/METADATA +119 -0
  37. aiphoria-0.8.0.dist-info/RECORD +40 -0
  38. {aiphoria-0.0.1.dist-info → aiphoria-0.8.0.dist-info}/WHEEL +1 -1
  39. aiphoria-0.8.0.dist-info/licenses/LICENSE +21 -0
  40. aiphoria-0.0.1.dist-info/METADATA +0 -5
  41. aiphoria-0.0.1.dist-info/RECORD +0 -5
  42. {aiphoria-0.0.1.dist-info → aiphoria-0.8.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,762 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Mon Aug 11 16:19:39 2014
4
+
5
+ """
6
+ import os
7
+ import sys
8
+ import imp
9
+ # Put location of
10
+ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..\\..')) + '\\modules') # add ODYM module directory to system path
11
+ #NOTE: Hidden variable __file__ must be know to script for the directory structure to work.
12
+ # Therefore: When first using the model, run the entire script with F5 so that the __file__ variable can be created.
13
+
14
+ import dynamic_stock_model as dsm # remove and import the class manually if this unit test is run as standalone script
15
+ imp.reload(dsm)
16
+
17
+ import numpy as np
18
+ import unittest
19
+ import scipy
20
+
21
+
22
+ ###############################################################################
23
+ """My Input for fixed lifetime"""
24
+ Time_T_FixedLT = np.arange(0,10)
25
+ Time_T_30 = np.arange(0,30)
26
+ Inflow_T_FixedLT = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
27
+ lifetime_FixedLT = {'Type': 'Fixed', 'Mean': np.array([5])}
28
+ lifetime_FixedLT0 = {'Type': 'Fixed', 'Mean': np.array([0])}
29
+ #lifetime_FixedLT = {'Type': 'Fixed', 'Mean': np.array([5,5,5,5,5,5,5,5,5,5])}
30
+ lifetime_NormLT = {'Type': 'Normal', 'Mean': np.array([5]), 'StdDev': np.array([1.5])}
31
+ lifetime_NormLT0 = {'Type': 'Normal', 'Mean': np.array([0]), 'StdDev': np.array([1.5])}
32
+ lifetime_NormLT8 = {'Type': 'Normal', 'Mean': np.array([8]), 'StdDev': np.array([3])}
33
+ ###############################################################################
34
+ """My Output for fixed lifetime"""
35
+ Outflow_T_FixedLT = np.array([0, 0, 0, 0, 0, 1, 2, 3, 4, 5])
36
+
37
+ Outflow_TC_FixedLT = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
38
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
39
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
40
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
41
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
42
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
43
+ [0, 2, 0, 0, 0, 0, 0, 0, 0, 0],
44
+ [0, 0, 3, 0, 0, 0, 0, 0, 0, 0],
45
+ [0, 0, 0, 4, 0, 0, 0, 0, 0, 0],
46
+ [0, 0, 0, 0, 5, 0, 0, 0, 0, 0]])
47
+
48
+ Stock_T_FixedLT = np.array([1, 3, 6, 10, 15, 20, 25, 30, 35, 40])
49
+
50
+ StockChange_T_FixedLT = np.array([1, 2, 3, 4, 5, 5, 5, 5, 5, 5])
51
+
52
+ Stock_TC_FixedLT = np.array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
53
+ [1, 2, 0, 0, 0, 0, 0, 0, 0, 0],
54
+ [1, 2, 3, 0, 0, 0, 0, 0, 0, 0],
55
+ [1, 2, 3, 4, 0, 0, 0, 0, 0, 0],
56
+ [1, 2, 3, 4, 5, 0, 0, 0, 0, 0],
57
+ [0, 2, 3, 4, 5, 6, 0, 0, 0, 0],
58
+ [0, 0, 3, 4, 5, 6, 7, 0, 0, 0],
59
+ [0, 0, 0, 4, 5, 6, 7, 8, 0, 0],
60
+ [0, 0, 0, 0, 5, 6, 7, 8, 9, 0],
61
+ [0, 0, 0, 0, 0, 6, 7, 8, 9, 10]])
62
+
63
+ Bal = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
64
+ Bal9 = np.zeros((9))
65
+ Bal30 = np.zeros((30))
66
+ """My Output for normally distributed lifetime"""
67
+
68
+ Stock_TC_NormLT = np.array([[ 9.99570940e-01, 0.00000000e+00, 0.00000000e+00,
69
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
70
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
71
+ 0.00000000e+00],
72
+ [ 9.96169619e-01, 1.99914188e+00, 0.00000000e+00,
73
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
74
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
75
+ 0.00000000e+00],
76
+ [ 9.77249868e-01, 1.99233924e+00, 2.99871282e+00,
77
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
78
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
79
+ 0.00000000e+00],
80
+ [ 9.08788780e-01, 1.95449974e+00, 2.98850886e+00,
81
+ 3.99828376e+00, 0.00000000e+00, 0.00000000e+00,
82
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
83
+ 0.00000000e+00],
84
+ [ 7.47507462e-01, 1.81757756e+00, 2.93174960e+00,
85
+ 3.98467848e+00, 4.99785470e+00, 0.00000000e+00,
86
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
87
+ 0.00000000e+00],
88
+ [ 5.00000000e-01, 1.49501492e+00, 2.72636634e+00,
89
+ 3.90899947e+00, 4.98084810e+00, 5.99742564e+00,
90
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
91
+ 0.00000000e+00],
92
+ [ 2.52492538e-01, 1.00000000e+00, 2.24252239e+00,
93
+ 3.63515512e+00, 4.88624934e+00, 5.97701772e+00,
94
+ 6.99699658e+00, 0.00000000e+00, 0.00000000e+00,
95
+ 0.00000000e+00],
96
+ [ 9.12112197e-02, 5.04985075e-01, 1.50000000e+00,
97
+ 2.99002985e+00, 4.54394390e+00, 5.86349921e+00,
98
+ 6.97318734e+00, 7.99656752e+00, 0.00000000e+00,
99
+ 0.00000000e+00],
100
+ [ 2.27501319e-02, 1.82422439e-01, 7.57477613e-01,
101
+ 2.00000000e+00, 3.73753731e+00, 5.45273268e+00,
102
+ 6.84074908e+00, 7.96935696e+00, 8.99613846e+00,
103
+ 0.00000000e+00],
104
+ [ 3.83038057e-03, 4.55002639e-02, 2.73633659e-01,
105
+ 1.00997015e+00, 2.50000000e+00, 4.48504477e+00,
106
+ 6.36152146e+00, 7.81799894e+00, 8.96552657e+00,
107
+ 9.99570940e+00]])
108
+
109
+ Stock_T_NormLT = np.array([ 0.99957094, 2.9953115 , 5.96830193, 9.85008113,
110
+ 14.4793678 , 19.60865447, 24.99043368, 30.46342411,
111
+ 35.95916467, 41.45873561])
112
+
113
+ Stock_SDM_NegInflow_NormLT = np.array([0.0,0,1,2,3,5,6,8,8,6,6,6,6,6,8,8,8,9,10,12,9,9,9,9,9,9,9,9.0,9,9])
114
+ Stock_SDM_NegInflow_NormLTNeg = np.array([0.0,0,0,0,0,0,0,0,8,6,6,6,6,6,3,3,3,3,4,5,6,7,8,9,9,9,7.1,8,8.0,8])
115
+ Stock_SDM_PosInflow_NormLTNeg = np.array([0.0,0,0,0,0,0,0,0,8,8,8,8.2,9,9,8.5,8,7.5,7,6.5,6,5.5,7,8,9,8.8,8.5,8.1,8,8.0,8])
116
+
117
+ Outflow_T_NormLT = np.array([ 4.29060333e-04, 4.25944090e-03, 2.70095728e-02,
118
+ 1.18220793e-01, 3.70713330e-01, 8.70713330e-01,
119
+ 1.61822079e+00, 2.52700957e+00, 3.50425944e+00,
120
+ 4.50042906e+00])
121
+
122
+ Outflow_TC_NormLT = np.array([[ 4.29060333e-04, 0.00000000e+00, 0.00000000e+00,
123
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
124
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
125
+ 0.00000000e+00],
126
+ [ 3.40132023e-03, 8.58120666e-04, -0.00000000e+00,
127
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
128
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
129
+ -0.00000000e+00],
130
+ [ 1.89197514e-02, 6.80264047e-03, 1.28718100e-03,
131
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
132
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
133
+ -0.00000000e+00],
134
+ [ 6.84610878e-02, 3.78395028e-02, 1.02039607e-02,
135
+ 1.71624133e-03, -0.00000000e+00, -0.00000000e+00,
136
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
137
+ -0.00000000e+00],
138
+ [ 1.61281318e-01, 1.36922176e-01, 5.67592541e-02,
139
+ 1.36052809e-02, 2.14530167e-03, -0.00000000e+00,
140
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
141
+ -0.00000000e+00],
142
+ [ 2.47507462e-01, 3.22562636e-01, 2.05383263e-01,
143
+ 7.56790055e-02, 1.70066012e-02, 2.57436200e-03,
144
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
145
+ -0.00000000e+00],
146
+ [ 2.47507462e-01, 4.95014925e-01, 4.83843953e-01,
147
+ 2.73844351e-01, 9.45987569e-02, 2.04079214e-02,
148
+ 3.00342233e-03, -0.00000000e+00, -0.00000000e+00,
149
+ -0.00000000e+00],
150
+ [ 1.61281318e-01, 4.95014925e-01, 7.42522387e-01,
151
+ 6.45125271e-01, 3.42305439e-01, 1.13518508e-01,
152
+ 2.38092416e-02, 3.43248267e-03, -0.00000000e+00,
153
+ -0.00000000e+00],
154
+ [ 6.84610878e-02, 3.22562636e-01, 7.42522387e-01,
155
+ 9.90029850e-01, 8.06406589e-01, 4.10766527e-01,
156
+ 1.32438260e-01, 2.72105619e-02, 3.86154300e-03,
157
+ -0.00000000e+00],
158
+ [ 1.89197514e-02, 1.36922176e-01, 4.83843953e-01,
159
+ 9.90029850e-01, 1.23753731e+00, 9.67687907e-01,
160
+ 4.79227614e-01, 1.51358011e-01, 3.06118821e-02,
161
+ 4.29060333e-03]])
162
+
163
+ StockChange_T_NormLT = np.array([ 0.99957094, 1.99574056, 2.97299043, 3.88177921, 4.62928667,
164
+ 5.12928667, 5.38177921, 5.47299043, 5.49574056, 5.49957094])
165
+
166
+ """My Output for Weibull-distributed lifetime"""
167
+
168
+ Stock_TC_WeibullLT = np.array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], # computed with Excel and taken from there
169
+ [0.367879441, 2, 0, 0, 0, 0, 0, 0, 0, 0],
170
+ [0.100520187, 0.735758882, 3, 0, 0, 0, 0, 0, 0, 0],
171
+ [0.023820879, 0.201040373, 1.103638324, 4, 0, 0, 0, 0, 0, 0],
172
+ [0.005102464, 0.047641758, 0.30156056, 1.471517765,5, 0, 0, 0, 0, 0],
173
+ [0.001009149, 0.010204929, 0.071462637, 0.402080746,1.839397206, 6, 0, 0, 0, 0],
174
+ [0.000186736, 0.002018297, 0.015307393, 0.095283516, 0.502600933, 2.207276647, 7, 0, 0, 0],
175
+ [3.26256E-05, 0.000373472, 0.003027446, 0.020409858, 0.119104394, 0.60312112, 2.575156088, 8, 0, 0],
176
+ [5.41828E-06, 6.52513E-05, 0.000560208, 0.004036594, 0.025512322, 0.142925273, 0.703641306, 2.943035529, 9, 0],
177
+ [8.59762E-07, 1.08366E-05, 9.78769E-05, 0.000746944, 0.005045743, 0.030614786, 0.166746152, 0.804161493, 3.310914971, 10]])
178
+
179
+ Stock_T_WeibullLT = np.array([1,2.367879441,3.836279069,5.328499576,6.825822547,8.324154666,9.822673522,11.321225,12.8197819,14.31833966])
180
+
181
+ Outflow_T_WeibullLT = np.array([0,0.632120559,1.531600372,2.507779493,3.502677029,4.50166788,5.501481144,6.501448519,7.5014431,8.501442241])
182
+
183
+ Outflow_TC_WeibullLT = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
184
+ [0.632120559, 0, 0, 0, 0, 0, 0, 0, 0, 0],
185
+ [0.267359255, 1.264241118, 0, 0, 0, 0, 0, 0, 0, 0],
186
+ [0.076699308, 0.534718509, 1.896361676, 0, 0, 0, 0, 0, 0, 0],
187
+ [0.018718414, 0.153398615, 0.802077764, 2.528482235, 0, 0, 0, 0, 0, 0],
188
+ [0.004093316, 0.037436829, 0.230097923, 1.069437018, 3.160602794, 0, 0, 0, 0, 0],
189
+ [0.000822413, 0.008186632, 0.056155243, 0.306797231, 1.336796273, 3.792723353, 0, 0, 0, 0],
190
+ [0.00015411, 0.001644825, 0.012279947, 0.074873658, 0.383496539, 1.604155527, 4.424843912, 0, 0, 0],
191
+ [2.72074E-05, 0.000308221, 0.002467238, 0.016373263, 0.093592072, 0.460195846, 1.871514782, 5.056964471, 0, 0],
192
+ [4.55852E-06, 5.44147E-05 , 0.000462331 , 0.00328965, 0.020466579, 0.112310487, 0.536895154, 2.138874037, 5.689085029, 0]])
193
+
194
+ StockChange_T_WeibullLT = np.array([1,1.367879441,1.468399628,1.492220507,1.497322971,1.49833212,1.498518856,1.498551481,1.4985569,1.498557759])
195
+
196
+ lifetime_WeibullLT = {'Type': 'Weibull', 'Shape': np.array([1.2]), 'Scale': np.array([1])}
197
+ InitialStock_WB = np.array([0.01, 0.01, 0.08, 0.2, 0.2, 2, 2, 3, 4, 7.50])
198
+ Inflow_WB = np.array([11631.1250671964, 1845.6048709861, 2452.0593141014, 1071.0305279511, 198.1868742385, 391.9674590243, 83.9599583940, 29.8447516023, 10.8731273138, 7.5000000000])
199
+ # We need 10 digits AFTER the . to get a 9 digits after the . overlap with np.testing.
200
+ # The total number of counting digits is higher, because there are up to 5 digits before the .
201
+
202
+ # For the stock-driven model with initial stock, colculated with Excel
203
+ Sc_InitialStock_2_Ref = np.array([[ 3.29968072, 0. , 0. , 0. , 0. ,
204
+ 0. , 0. , 0. , 0. ],
205
+ [ 3.28845263, 5.1142035 , 0. , 0. , 0. ,
206
+ 0. , 0. , 0. , 0. ],
207
+ [ 3.2259967 , 5.09680099, 2.0068288 , 0. , 0. ,
208
+ 0. , 0. , 0. , 0. ],
209
+ [ 3. , 5. , 2. , 4. , 0. ,
210
+ 0. , 0. , 0. , 0. ],
211
+ [ 2.46759471, 4.64972578, 1.962015 , 3.98638888, 4.93427563,
212
+ 0. , 0. , 0. , 0. ],
213
+ [ 1.65054855, 3.82454624, 1.82456634, 3.91067739, 4.91748538,
214
+ 3.8721761 , 0. , 0. , 0. ],
215
+ [ 0.83350238, 2.55819937, 1.50076342, 3.63671549, 4.82409004,
216
+ 3.85899993, 2.78772936, 0. , 0. ],
217
+ [ 0.30109709, 1.2918525 , 1.00384511, 2.9913133 , 4.48613916,
218
+ 3.78570788, 2.77824333, 3.36180162, 0. ],
219
+ [ 0.07510039, 0.46667297, 0.5069268 , 2.00085849, 3.68999109,
220
+ 3.5205007 , 2.72547754, 3.35036215, 3.66410986]])
221
+
222
+ Sc_InitialStock_2_Ref_Sum = np.array([ 3.29968072, 8.40265614, 10.32962649, 14. ,
223
+ 18. , 20. , 20. , 20. , 20. ])
224
+
225
+ Oc_InitialStock_2_Ref = np.array([[ 1.41636982e-03, 0.00000000e+00, 0.00000000e+00,
226
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
227
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
228
+ [ 1.12280883e-02, 2.19524375e-03, -0.00000000e+00,
229
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
230
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00],
231
+ [ 6.24559363e-02, 1.74025106e-02, 8.61420234e-04,
232
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00,
233
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00],
234
+ [ 2.25996698e-01, 9.68009922e-02, 6.82879736e-03,
235
+ 1.71697802e-03, -0.00000000e+00, -0.00000000e+00,
236
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00],
237
+ [ 5.32405289e-01, 3.50274224e-01, 3.79849998e-02,
238
+ 1.36111209e-02, 2.11801070e-03, -0.00000000e+00,
239
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00],
240
+ [ 8.17046165e-01, 8.25179532e-01, 1.37448656e-01,
241
+ 7.57114903e-02, 1.67902556e-02, 1.66211031e-03,
242
+ -0.00000000e+00, -0.00000000e+00, -0.00000000e+00],
243
+ [ 8.17046165e-01, 1.26634687e+00, 3.23802924e-01,
244
+ 2.73961897e-01, 9.33953405e-02, 1.31761643e-02,
245
+ 1.19661751e-03, -0.00000000e+00, -0.00000000e+00],
246
+ [ 5.32405289e-01, 1.26634687e+00, 4.96918311e-01,
247
+ 6.45402188e-01, 3.37950879e-01, 7.32920558e-02,
248
+ 9.48603036e-03, 1.44303487e-03, -0.00000000e+00],
249
+ [ 2.25996698e-01, 8.25179532e-01, 4.96918311e-01,
250
+ 9.90454815e-01, 7.96148072e-01, 2.65207178e-01,
251
+ 5.27657861e-02, 1.14394721e-02, 1.57279902e-03]])
252
+
253
+ I_InitialStock_2_Ref = np.array([ 3.30109709, 5.11639875, 2.00769022, 4.00171698, 4.93639364, 3.87383821, 2.78892598, 3.36324466, 3.66568266])
254
+
255
+ """ Test case with fixed lifetime for initial stock"""
256
+ Time_T_FixedLT_X = np.arange(1, 9, 1)
257
+ lifetime_FixedLT_X = {'Type': 'Fixed', 'Mean': np.array([5])}
258
+ InitialStock_X = np.array([0, 0, 0, 7, 5, 4, 3, 2])
259
+ Inflow_X = np.array([0, 0, 0, 7, 5, 4, 3, 2])
260
+
261
+ Time_T_FixedLT_XX = np.arange(1, 11, 1)
262
+ lifetime_NormLT_X = {'Type': 'Normal', 'Mean': np.array([5]), 'StdDev': np.array([1.5])}
263
+ InitialStock_XX = np.array([0.01, 0.01, 0.08, 0.2, 0.2, 2, 2, 3, 4, 7.50])
264
+ Inflow_XX = np.array([ 2.61070664, 0.43955789, 0.87708508, 0.79210262, 0.4,
265
+ 2.67555857, 2.20073139, 3.06983925, 4.01538044, 7.50321933])
266
+
267
+ """ Test case with normally distributed lifetime for initial stock and stock-driven model"""
268
+ Time_T_FixedLT_2 = np.arange(1, 10, 1)
269
+ Time_T_FixedLT_3 = np.arange(0, 30, 1)
270
+ lifetime_NormLT_2 = {'Type': 'Normal', 'Mean': np.array([5]), 'StdDev': np.array([1.5])}
271
+ lifetime_NormLT_3 = {'Type': 'LogNormal', 'Mean': np.array([6]), 'StdDev': np.array([3])}
272
+ lifetime_NormLT_4 = {'Type': 'Normal', 'Mean': np.array([7]), 'StdDev': np.array([2])}
273
+ InitialStock_2 = np.array([3,5,2,4])
274
+ InitialStock_8 = np.array([0.5,0.5,0.2,0.4,1,1,1,1])
275
+ FutureStock_2 = np.array([0.0,0.0,0.0,0.0,18.0,20,20,20,20.0])
276
+ ThisSwitchTime = 5 # First year with future stock curve, start counting from 1.
277
+ Inflow_2 = np.array([3.541625588, 5.227890554,2.01531097,4])
278
+
279
+ """ Test case with lognormally distributed lifetime for inflow-driven model"""
280
+ # NOTE: for dynamic MFA the parameters average lifetime and standard deviation refer to the pdf curve as plotted,
281
+ # whereas in the scipy and Excel functions, the parameters mu and sigma
282
+ # refer to the parameters of the underlying normal distribution.
283
+ # The parameters need to be converted as follows:
284
+ # for single (fixed) lifetime
285
+ Time_T_LN = np.arange(0, 300, 1)
286
+ mu = 20
287
+ sg = 20
288
+ LT_LN = np.log(mu / np.sqrt(1 + mu * mu / (sg * sg))) # calculate parameter mu of underlying normal distribution
289
+ SG_LN = np.sqrt(np.log(1 + mu * mu / (sg * sg))) # calculate parameter sigma of underlying normal distribution
290
+ lifetime_LogNorm = {'Type': 'LogNormal', 'Mean': np.array([mu]), 'StdDev': np.array([sg])} # call with ACTUAL mu and sigma of curve,
291
+ # dsm makes conversion
292
+ SF = scipy.stats.lognorm.sf(x=Time_T_LN, s=SG_LN, loc = 0, scale=np.exp(LT_LN)) # values chosen according to description on
293
+ # https://docs.scipy.org/doc/scipy-0.13.0/reference/generated/scipy.stats.lognorm.html
294
+ # Same result as EXCEL function "=LOGNORM.VERT(x;LT_LN;SG_LN;TRUE)"
295
+ Inflow_LN = np.zeros((300))
296
+ Inflow_LN[0:20] = np.array([1,2,3,4,5,6,7,8,2,3,5,6,7,1,2,4,5,6,7,3])
297
+ LN_Stock_Reference_2060 = 5.8693165260386 # calculated independently with Excel
298
+
299
+ """ Test case with folded normally distributed lifetime for inflow-driven model"""
300
+ Time_T_FN = np.arange(0, 100, 1)
301
+ mu = 20
302
+ sg = 20
303
+ lifetime_FoldNorm = {'Type': 'FoldedNormal', 'Mean': np.array([mu]), 'StdDev': np.array([sg])} # call with mu and sigma of curve BEFORE folding,
304
+ # dsm makes conversion
305
+ Inflow_FN = np.zeros((100))
306
+ Inflow_FN[0:20] = np.array([1,2,3,4,5,6,7,8,2,3,5,6,7,1,2,4,5,6,7,3])
307
+ FN_Stock_Reference_2060 = 6.5004904790008300000
308
+ # calculated independently with Excel
309
+
310
+ # Inflow for quick declines in stock, with negative entries, no correction of negative inflows
311
+ InflowNeg_NoCorr = np.array([0,0,1.003845108798,1.009876170898,1.022946871294,2.052181974193,1.098597211758,2.178632487261,0.2864589383765,
312
+ -1.57838035116,0.5823071731028,0.7368688072826,0.8609818446092,0.9303172472582,2.940380920226,0.8868056550348,0.8077321288789,1.74261978268,
313
+ 1.72284735601,2.770808172213,-2.13996861954,0.9927014953087,1.118058099656,1.211591711403,1.256322506739,1.248773108954,1.197964611415,
314
+ 1.122904133751,1.047910488113,0.9952110047915])
315
+ InflowNeg_WithCorr = np.array([0,0,1.003845108797608,1.009876170898179,1.022946871293978,2.052181974192771,1.09859721175781,2.178632487260613,
316
+ 0.2864589383765391,0,0.468909567774503,0.600148064601485,0.7138380402455925,0.7922474677487478,2.832866490884595,0.8262270093751778,0.7986846781384966,
317
+ 1.775290769026188,1.776531605001062,2.822224969997677,0,0.82099326892646,0.9183009967181216,1.007417665416504,1.076751857993922,1.119633273700667,
318
+ 1.134233884697729,1.123750382153023,1.096483322433279,1.064262457376682])
319
+
320
+ StockChange_WithCorr = np.array([0,0,1,1,1,2,1,2,0,-2,0,0,0,0,2,0,0,1,1,2,-3,0,0,0,0,0,0,0,0,0])
321
+
322
+ InitialStockInflowNegNoCorrect = np.array([0.7929476381216127,0.6688896434012339,0.2377146834690121,0.4401462789619187,1.050188897357724,
323
+ 1.023279749316858,1.00991262429366,1.003845108797608,2.734512232505172,-1.576179715364555,0.5270786116039677,0.6253099746885178,
324
+ 0.7133245646541703,0.7808737550728377,-2.193761739572536,0.8006372758619281,0.7486059179704083,0.6628542885032971,1.562532671694373,
325
+ 1.463347346524538,1.385763022717013,1.346937342733784,1.360199865992007,1.431582763055532,0.5522778871344547,0.7074660291917115,
326
+ -1.038359636072531,1.901306859994554,1.088965343251684,1.121312374405391])
327
+
328
+ InitialStockInflowNoNegCorrect = np.array([0.7929476381216127,0.6688896434012339,0.2377146834690121,0.4401462789619187,1.050188897357724,
329
+ 1.023279749316858,1.00991262429366,1.003845108797608,2.734512232505172,0.431510502230662,0.5391407358051091,0.8522203972396362,
330
+ 1.568386852314742,0.8767713133566062,0.4696866483782957,0.5372828546582809,0.5715642400086977,0.571388710240865,0.5417776639498378,
331
+ 0.4910906219746665,0.4275448257791661,2.365060643030991,1.802882915501588,1.755204649624293,0.5284632857607936,0.4360513595181573,
332
+ 0.3800804006621792,0.755755759275017,0.9453763220611762,1.024955581556197])
333
+
334
+ InitialStockInflowNegCorrect = np.array([0.7929476381216127,0.6688896434012339,0.2377146834690121,0.4401462789619187,
335
+ 1.050188897357724,1.023279749316858,1.00991262429366,1.003845108797608,2.734512232505172,0,0.4252614122673855,0.5118790151618888,
336
+ 0.5969693316522457,0.6739530024236163,0,0.4358419187951329,0.4372674850950349,0.4227905939406414,1.401739961117737,1.38013886282689,
337
+ 1.370084205085089,1.381499862452395,1.422069169849336,1.495945462462685,0.5985535082458745,0.7251533575497293,0,1.756743048425328,
338
+ 0.9375744022016721,0.984738434681199])
339
+
340
+ # Parameters for stock-driven model with initial stock:
341
+ FutureStock1 = np.array([2.8,3,3.5,4,5,5])
342
+ FutureStock1a = np.array([0,0,0,2.8,3,3.5,4,5,5])
343
+ FutureStock2 = np.array([2.8,3,3.5,2.2,2.3,2.5])
344
+ FutureStock2a = np.array([0,0,0,2.8,3,3.5,2.2,2.3,2.5])
345
+ InitialStock1 = np.array([[0.4,0.2,0.5,0,0,0,0,0,0],[0.1,0.5,1.0,0,0,0,0,0,0]]).transpose()
346
+ InitialStock2 = np.array([[0.4,0.2,0.5,0.1,0.25,0.3,0.1,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
347
+ [0.1,0.5,1.0,0.7,0.2,0.3,0.45,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]).transpose()
348
+ TypeSplit1 = np.array([[0.5,0.5,0.1,0.5,0.8,0.5],[0.5,0.5,0.9,0.5,0.2,0.5]]).transpose()
349
+ TypeSplit1a = np.array([[0,0,0,0.5,0.5,0.1,0.5,0.8,0.5],[0,0,0,0.5,0.5,0.9,0.5,0.2,0.5]]).transpose()
350
+ TypeSplit2a = np.array([[0,0,0,0,0,0,0,0,0.5,0.5,0.1,0.5,0.8,0.5,0.5,0.1,0.5,0.8,0.5,0.5,0.1,0.5,0.8,0.5,0.5,0.1,0.5,0.8,0.5,0.33],
351
+ [0,0,0,0,0,0,0,0,0.5,0.5,0.9,0.5,0.2,0.5,0.5,0.9,0.5,0.2,0.5,0.5,0.9,0.5,0.2,0.5,0.5,0.9,0.5,0.2,0.5,0.67]]).transpose()
352
+
353
+ TypeSplitStockCheckType1=np.array([0.1520464589202331,0.06727086112098983,0.1559267249296865,0.1326551318262058,0.1923019570573063,
354
+ 0.06734416832144496,0.4795521109040651,1.459402923878064,0])
355
+
356
+ TypeSplitStockCheckType2=np.array([0.03801161473005826,0.1681771528024746,0.311853449859373,0.1326551318262058,0.1923019570573063,
357
+ 0.6060975148930047,0.4795521109040651,0.3648507309695161,0])
358
+
359
+ TypeSplitInflowCheckType=np.array([[0.6761333517696461,0.1690333379424115],
360
+ [0.2558444008518857,0.6396110021297141],
361
+ [0.5,1],
362
+ [0.3523465342883199,0.3523465342883199],
363
+ [0.4135884347844512,0.4135884347844512],
364
+ [0.1138340956232945,1.02450686060965],
365
+ [0.6134536124575378,0.6134536124575378],
366
+ [1.459402923878064,0.3648507309695161],
367
+ [0.5136958913485281,0.5136958913485281]])
368
+
369
+ TypeSplitInitialStockInflowCorrect1StockCheck = np.array([[0,0],
370
+ [0,0],
371
+ [0.5,1],
372
+ [0.3908625698550751,0.7817251397101502],
373
+ [0.2957996369747763,0.5915992739495526],
374
+ [0.2324798530180466,0.4649597060360933],
375
+ [0.1882452627129519,0.3764905254259038],
376
+ [0.1559267249296865,0.311853449859373],
377
+ [0.1314683082705697,0.2629366165411394]])
378
+
379
+ TypeSplitInitialStockInflowCorrect2StockCheck = np.array([[0,0],
380
+ [0,0],
381
+ [0.5,1],
382
+ [0.3908625698550751,0.7817251397101502],
383
+ [0.2957996369747763,0.5915992739495526],
384
+ [0.2324798530180466,0.4649597060360933],
385
+ [0.1882452627129519,0.3764905254259038],
386
+ [0.1559267249296865,0.311853449859373],
387
+ [0.1314683082705697,0.2629366165411394]])
388
+
389
+ TypeSplitInitialStockInflowCorrect3StockCheck = np.array([[0,0],
390
+ [0,0],
391
+ [0.5,1],
392
+ [0.3908625698550751,0.7817251397101502],
393
+ [0.2957996369747763,0.5915992739495526],
394
+ [0.2324798530180466,0.4649597060360933],
395
+ [0.1493421286476113,0.2986842572952226],
396
+ [0.123702603074578,0.247405206149156],
397
+ [0.1042988106254021,0.2085976212508043]])
398
+
399
+ ###############################################################################
400
+ """Create Dynamic Stock Models and hand over the pre-defined values."""
401
+ # For zero lifetime: border case
402
+ myDSM0 = dsm.DynamicStockModel(t=Time_T_FixedLT, i=Inflow_T_FixedLT, lt=lifetime_FixedLT0)
403
+
404
+ # For fixed LT
405
+ myDSM = dsm.DynamicStockModel(t=Time_T_FixedLT, i=Inflow_T_FixedLT, lt=lifetime_FixedLT)
406
+
407
+ myDSM2 = dsm.DynamicStockModel(t=Time_T_FixedLT, s=Stock_T_FixedLT, lt=lifetime_FixedLT)
408
+
409
+ myDSMx = dsm.DynamicStockModel(t=Time_T_FixedLT_X, lt=lifetime_FixedLT_X)
410
+ TestInflow_X = myDSMx.compute_i_from_s(InitialStock=InitialStock_X)
411
+
412
+ myDSMxy = dsm.DynamicStockModel(t=Time_T_FixedLT_X, i=TestInflow_X, lt=lifetime_FixedLT_X)
413
+
414
+ # For zero normally distributed lifetime: border case
415
+ myDSM0n = dsm.DynamicStockModel(t=Time_T_FixedLT, i=Inflow_T_FixedLT, lt=lifetime_NormLT0)
416
+
417
+ # For normally distributed Lt
418
+ myDSM3 = dsm.DynamicStockModel(t=Time_T_FixedLT, i=Inflow_T_FixedLT, lt=lifetime_NormLT)
419
+
420
+ myDSM4 = dsm.DynamicStockModel(t=Time_T_FixedLT, s=Stock_T_NormLT, lt=lifetime_NormLT)
421
+ myDSM4a= dsm.DynamicStockModel(t=Time_T_FixedLT, s=Stock_T_NormLT, lt=lifetime_NormLT)
422
+
423
+ myDSMX = dsm.DynamicStockModel(t=Time_T_FixedLT_XX, lt=lifetime_NormLT_X)
424
+ TestInflow_XX = myDSMX.compute_i_from_s(InitialStock=InitialStock_XX)
425
+
426
+ myDSMXY = dsm.DynamicStockModel(t=Time_T_FixedLT_XX, i=TestInflow_XX, lt=lifetime_NormLT_X)
427
+
428
+ #For negatative inflow correction
429
+ myDSM_ICF = dsm.DynamicStockModel(t=Time_T_30, s=Stock_SDM_NegInflow_NormLT, lt=lifetime_NormLT8)
430
+ [SC1,OC1,I1] = myDSM_ICF.compute_stock_driven_model(NegativeInflowCorrect = False)
431
+ myDSM_ICT = dsm.DynamicStockModel(t=Time_T_30, s=Stock_SDM_NegInflow_NormLT, lt=lifetime_NormLT8)
432
+ [SC2,OC2,I2] = myDSM_ICT.compute_stock_driven_model(NegativeInflowCorrect = True)
433
+ OT2 = myDSM_ICT.compute_outflow_total()
434
+ SCh2= myDSM_ICT.compute_stock_change()
435
+ Bal2= myDSM_ICT.check_stock_balance()
436
+
437
+ #For negatative inflow correction with initial stock
438
+ #a) Neg inflow, Correction Flag is False:
439
+ myDSM_ICFIS = dsm.DynamicStockModel(t=Time_T_30, s=Stock_SDM_NegInflow_NormLTNeg.copy(), lt=lifetime_NormLT8)
440
+ [SC1IS,OC1IS,I1IS] = myDSM_ICFIS.compute_stock_driven_model_initialstock(InitialStock = InitialStock_8, SwitchTime = 9, NegativeInflowCorrect = False)
441
+ OT1IS = myDSM_ICFIS.compute_outflow_total()
442
+ SCh1IS= myDSM_ICFIS.compute_stock_change()
443
+ Bal1IS= myDSM_ICFIS.check_stock_balance()
444
+ #b) No neg. inflow, correction flag is True:
445
+ myDSM_ICTIST = dsm.DynamicStockModel(t=Time_T_30, s=Stock_SDM_PosInflow_NormLTNeg.copy(), lt=lifetime_NormLT8)
446
+ [SC3IS,OC3IS,I3IS] = myDSM_ICTIST.compute_stock_driven_model_initialstock(InitialStock = InitialStock_8, SwitchTime = 9, NegativeInflowCorrect = True)
447
+ OT3IS = myDSM_ICTIST.compute_outflow_total()
448
+ SCh3IS= myDSM_ICTIST.compute_stock_change()
449
+ Bal3IS= myDSM_ICTIST.check_stock_balance()
450
+ #c) Neg. inflow: Correction flag is True and neg. inflow occurs.
451
+ myDSM_ICTIS = dsm.DynamicStockModel(t=Time_T_30, s=Stock_SDM_NegInflow_NormLTNeg.copy(), lt=lifetime_NormLT8)
452
+ [SC2IS,OC2IS,I2IS] = myDSM_ICTIS.compute_stock_driven_model_initialstock(InitialStock = InitialStock_8, SwitchTime = 9, NegativeInflowCorrect = True)
453
+ OT2IS = myDSM_ICTIS.compute_outflow_total()
454
+ SCh2IS= myDSM_ICTIS.compute_stock_change()
455
+ Bal2IS= myDSM_ICTIS.check_stock_balance()
456
+
457
+ # Test compute_stock_driven_model_initialstock:
458
+ TestDSM_IntitialStock = dsm.DynamicStockModel(t=Time_T_FixedLT_2, s=FutureStock_2, lt=lifetime_NormLT_2)
459
+ Sc_InitialStock_2,Oc_InitialStock_2,I_InitialStock_2 = TestDSM_IntitialStock.compute_stock_driven_model_initialstock(InitialStock = InitialStock_2, SwitchTime = ThisSwitchTime)
460
+ OT3 = TestDSM_IntitialStock.compute_outflow_total()
461
+ #TestDSM_IntitialStock.compute_stock_total()
462
+ SCh3= TestDSM_IntitialStock.compute_stock_change()
463
+ Bal3= TestDSM_IntitialStock.check_stock_balance()
464
+
465
+ # Test stock-driven model with initialstock and type split
466
+ TestDSM_IntitialStockTypeSplit = dsm.DynamicStockModel(t=Time_T_FixedLT_2, s=FutureStock1, lt=lifetime_NormLT_3)
467
+ SFArrayCombined = TestDSM_IntitialStockTypeSplit.compute_sf().copy()
468
+ [SC_IS_TS,OC_IS_TS,I_IS_TS] = TestDSM_IntitialStockTypeSplit.compute_stock_driven_model_initialstock_typesplit(FutureStock=FutureStock1,InitialStock=InitialStock1,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombined,np.ones(2)),TypeSplit=TypeSplit1)
469
+ OT_IS_TS = TestDSM_IntitialStockTypeSplit.compute_outflow_total()
470
+ SCh_IS_TS = TestDSM_IntitialStockTypeSplit.compute_stock_change()
471
+ Bal_IS_TS = TestDSM_IntitialStockTypeSplit.check_stock_balance()
472
+
473
+ # Test stock-driven model with initialstock and type split and NegativeInflowCorrect, lognormal lifetime
474
+ # 1) NegativeInflowCorrect on but does not occur
475
+ TestDSM_IntitialStockTypeSplit1 = dsm.DynamicStockModel(t=Time_T_FixedLT_2, s=FutureStock1a.copy(), lt=lifetime_NormLT_3)
476
+ SFArrayCombined = TestDSM_IntitialStockTypeSplit1.compute_sf().copy()
477
+ [SC_IS_TS1,OC_IS_TS1,I_IS_TS1,Flags1] = TestDSM_IntitialStockTypeSplit1.compute_stock_driven_model_initialstock_typesplit_negativeinflowcorrect(SwitchTime=3,InitialStock=InitialStock1,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombined,np.ones(2)),TypeSplit=TypeSplit1a,NegativeInflowCorrect=True)
478
+ OT_IS_TS1 = TestDSM_IntitialStockTypeSplit1.compute_outflow_total()
479
+ SCh_IS_TS1 = TestDSM_IntitialStockTypeSplit1.compute_stock_change()
480
+ Bal_IS_TS1 = TestDSM_IntitialStockTypeSplit1.check_stock_balance()
481
+
482
+ # 2) NegativeInflowCorrect on but is not fixed
483
+ TestDSM_IntitialStockTypeSplit2 = dsm.DynamicStockModel(t=Time_T_FixedLT_2, s=FutureStock2a.copy(), lt=lifetime_NormLT_3)
484
+ SFArrayCombined = TestDSM_IntitialStockTypeSplit2.compute_sf().copy()
485
+ [SC_IS_TS2,OC_IS_TS2,I_IS_TS2,Flags2] = TestDSM_IntitialStockTypeSplit2.compute_stock_driven_model_initialstock_typesplit_negativeinflowcorrect(SwitchTime=3,InitialStock=InitialStock1,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombined,np.ones(2)),TypeSplit=TypeSplit1a,NegativeInflowCorrect=False)
486
+ OT_IS_TS2 = TestDSM_IntitialStockTypeSplit2.compute_outflow_total()
487
+ SCh_IS_TS2 = TestDSM_IntitialStockTypeSplit2.compute_stock_change()
488
+ Bal_IS_TS2 = TestDSM_IntitialStockTypeSplit2.check_stock_balance()
489
+
490
+ # 3) NegativeInflowCorrect on and fixed
491
+ TestDSM_IntitialStockTypeSplit3 = dsm.DynamicStockModel(t=Time_T_FixedLT_2, s=FutureStock2a.copy(), lt=lifetime_NormLT_3)
492
+ SFArrayCombined = TestDSM_IntitialStockTypeSplit3.compute_sf().copy()
493
+ [SC_IS_TS3,OC_IS_TS3,I_IS_TS3,Flags3] = TestDSM_IntitialStockTypeSplit3.compute_stock_driven_model_initialstock_typesplit_negativeinflowcorrect(SwitchTime=3,InitialStock=InitialStock1,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombined,np.ones(2)),TypeSplit=TypeSplit1a,NegativeInflowCorrect=True)
494
+ OT_IS_TS3 = TestDSM_IntitialStockTypeSplit3.compute_outflow_total()
495
+ SCh_IS_TS3 = TestDSM_IntitialStockTypeSplit3.compute_stock_change()
496
+ Bal_IS_TS3 = TestDSM_IntitialStockTypeSplit3.check_stock_balance()
497
+
498
+ # Test stock-driven model with initialstock and type split and NegativeInflowCorrect, normal lifetime
499
+ # 1) NegativeInflowCorrect on but does not occur
500
+ TestDSM_IntitialStockTypeSplit1a = dsm.DynamicStockModel(t=Time_T_FixedLT_3, s=Stock_SDM_PosInflow_NormLTNeg.copy(), lt=lifetime_NormLT_4)
501
+ SFArrayCombineda = TestDSM_IntitialStockTypeSplit1a.compute_sf().copy()
502
+ [SC_IS_TS1a,OC_IS_TS1a,I_IS_TS1a,Flags1a] = TestDSM_IntitialStockTypeSplit1a.compute_stock_driven_model_initialstock_typesplit_negativeinflowcorrect(SwitchTime=8,InitialStock=InitialStock2,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombineda,np.ones(2)),TypeSplit=TypeSplit2a,NegativeInflowCorrect=True)
503
+ OT_IS_TS1a = TestDSM_IntitialStockTypeSplit1a.compute_outflow_total()
504
+ SCh_IS_TS1a = TestDSM_IntitialStockTypeSplit1a.compute_stock_change()
505
+ Bal_IS_TS1a = TestDSM_IntitialStockTypeSplit1a.check_stock_balance()
506
+
507
+ # 2) NegativeInflowCorrect on but is not fixed
508
+ TestDSM_IntitialStockTypeSplit2a = dsm.DynamicStockModel(t=Time_T_FixedLT_3, s=Stock_SDM_NegInflow_NormLTNeg.copy(), lt=lifetime_NormLT_4)
509
+ SFArrayCombineda = TestDSM_IntitialStockTypeSplit2a.compute_sf().copy()
510
+ [SC_IS_TS2a,OC_IS_TS2a,I_IS_TS2a,Flags2a] = TestDSM_IntitialStockTypeSplit2a.compute_stock_driven_model_initialstock_typesplit_negativeinflowcorrect(SwitchTime=8,InitialStock=InitialStock2,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombineda,np.ones(2)),TypeSplit=TypeSplit2a,NegativeInflowCorrect=False)
511
+ OT_IS_TS2a = TestDSM_IntitialStockTypeSplit2a.compute_outflow_total()
512
+ SCh_IS_TS2a = TestDSM_IntitialStockTypeSplit2a.compute_stock_change()
513
+ Bal_IS_TS2a = TestDSM_IntitialStockTypeSplit2a.check_stock_balance()
514
+
515
+ # 3) NegativeInflowCorrect on and fixed
516
+ TestDSM_IntitialStockTypeSplit3a = dsm.DynamicStockModel(t=Time_T_FixedLT_3, s=Stock_SDM_NegInflow_NormLTNeg.copy(), lt=lifetime_NormLT_4)
517
+ SFArrayCombineda = TestDSM_IntitialStockTypeSplit3a.compute_sf().copy()
518
+ [SC_IS_TS3a,OC_IS_TS3a,I_IS_TS3a,Flags3a] = TestDSM_IntitialStockTypeSplit3a.compute_stock_driven_model_initialstock_typesplit_negativeinflowcorrect(SwitchTime=8,InitialStock=InitialStock2,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombineda,np.ones(2)),TypeSplit=TypeSplit2a,NegativeInflowCorrect=True)
519
+ OT_IS_TS3a = TestDSM_IntitialStockTypeSplit3a.compute_outflow_total()
520
+ SCh_IS_TS3a = TestDSM_IntitialStockTypeSplit3a.compute_stock_change()
521
+ Bal_IS_TS3a = TestDSM_IntitialStockTypeSplit3a.check_stock_balance()
522
+
523
+ # Compute stock back from inflow
524
+ TestDSM_IntitialStock_Verify = dsm.DynamicStockModel(t=Time_T_FixedLT_2, i=I_InitialStock_2, lt=lifetime_NormLT_2)
525
+ Sc_Stock_2 = TestDSM_IntitialStock_Verify.compute_s_c_inflow_driven()
526
+ Sc_Stock_2_Sum = Sc_Stock_2.sum(axis =1)
527
+ Sc_Stock_Sum = TestDSM_IntitialStock_Verify.compute_stock_total()
528
+ Sc_Outflow_t_c = TestDSM_IntitialStock_Verify.compute_o_c_from_s_c()
529
+
530
+ # For Weibull-distributed Lt
531
+ myDSMWB1 = dsm.DynamicStockModel(t=Time_T_FixedLT, i=Inflow_T_FixedLT, lt=lifetime_WeibullLT)
532
+
533
+ myDSMWB2 = dsm.DynamicStockModel(t=Time_T_FixedLT, s=Stock_T_WeibullLT, lt=lifetime_WeibullLT)
534
+
535
+ myDSMWB3 = dsm.DynamicStockModel(t=Time_T_FixedLT_XX, lt=lifetime_WeibullLT)
536
+ TestInflow_WB = myDSMWB3.compute_i_from_s(InitialStock=InitialStock_XX)
537
+
538
+ myDSMWB4 = dsm.DynamicStockModel(t=Time_T_FixedLT_XX, i=TestInflow_WB, lt=lifetime_WeibullLT)
539
+ # Compute full stock model in correct order
540
+
541
+ # Test lognormal lifetime dist.
542
+ myDSM_LN = dsm.DynamicStockModel(t=Time_T_LN, i=Inflow_LN, lt=lifetime_LogNorm)
543
+ LN_Stock = myDSM_LN.compute_s_c_inflow_driven()
544
+ LN_Stock_60 = LN_Stock.sum(axis =1)
545
+
546
+ # Test folded normal lifetime dist.
547
+ myDSM_FN = dsm.DynamicStockModel(t=Time_T_FN, i=Inflow_FN, lt=lifetime_FoldNorm)
548
+ FN_Stock = myDSM_FN.compute_s_c_inflow_driven()
549
+ FN_Stock_60 = FN_Stock.sum(axis =1)
550
+
551
+
552
+ # Test that ouflow computed with pdf from compute_outflow_pdf() yields same result as the one calculated directly from the sf via compute_s_c_inflow_driven() and compute_o_c_from_s_c()
553
+ lt_pdf = {'Type': 'Normal', 'Mean': np.array([8]), 'StdDev': np.array([3])}
554
+ ifl_pdf = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5]
555
+
556
+ DSM_pdf = dsm.DynamicStockModel(t=np.arange(0, 25, 1),i=ifl_pdf, lt=lt_pdf)
557
+ SF_pdf = DSM_pdf.compute_sf()
558
+ PDF_pdf = DSM_pdf.compute_outflow_pdf()
559
+ SC_pdf = DSM_pdf.compute_s_c_inflow_driven()
560
+ OC_pdf = DSM_pdf.compute_o_c_from_s_c()
561
+ OC_alt = np.einsum('c,tc->tc',np.array(ifl_pdf),PDF_pdf)
562
+ Bal_pdf = (np.abs(OC_pdf-OC_alt)).sum()
563
+ ###############################################################################
564
+ """Unit Test Class"""
565
+
566
+
567
+ class KnownResultsTestCase(unittest.TestCase):
568
+
569
+ def test_inflow_driven_model_fixedLifetime_0(self):
570
+ """Test Inflow Driven Model with Fixed product lifetime of 0."""
571
+ np.testing.assert_array_equal(myDSM0.compute_s_c_inflow_driven(), np.zeros(Stock_TC_FixedLT.shape))
572
+ np.testing.assert_array_equal(myDSM0.compute_stock_total(), np.zeros((Stock_TC_FixedLT.shape[0])))
573
+ np.testing.assert_array_equal(myDSM0.compute_stock_change(), np.zeros((Stock_TC_FixedLT.shape[0])))
574
+ np.testing.assert_array_equal(myDSM0.compute_outflow_mb(), Inflow_T_FixedLT)
575
+ np.testing.assert_array_equal(myDSM0.check_stock_balance(), Bal.transpose())
576
+
577
+
578
+ def test_inflow_driven_model_fixedLifetime(self):
579
+ """Test Inflow Driven Model with Fixed product lifetime."""
580
+ np.testing.assert_array_equal(myDSM.compute_s_c_inflow_driven(), Stock_TC_FixedLT)
581
+ np.testing.assert_array_equal(myDSM.compute_stock_total(),Stock_T_FixedLT)
582
+ np.testing.assert_array_equal(myDSM.compute_o_c_from_s_c(), Outflow_TC_FixedLT)
583
+ np.testing.assert_array_equal(myDSM.compute_outflow_total(), Outflow_T_FixedLT)
584
+ np.testing.assert_array_equal(myDSM.compute_stock_change(), StockChange_T_FixedLT)
585
+ np.testing.assert_array_equal(myDSM.check_stock_balance(), Bal.transpose())
586
+
587
+ def test_stock_driven_model_fixedLifetime(self):
588
+ """Test Stock Driven Model with Fixed product lifetime."""
589
+ np.testing.assert_array_equal(myDSM2.compute_stock_driven_model()[0], Stock_TC_FixedLT)
590
+ np.testing.assert_array_equal(myDSM2.compute_stock_driven_model()[1], Outflow_TC_FixedLT)
591
+ np.testing.assert_array_equal(myDSM2.compute_stock_driven_model()[2], Inflow_T_FixedLT)
592
+ np.testing.assert_array_equal(myDSM2.compute_outflow_total(), Outflow_T_FixedLT)
593
+ np.testing.assert_array_equal(myDSM2.compute_stock_change(), StockChange_T_FixedLT)
594
+ np.testing.assert_array_equal(myDSM2.check_stock_balance(), Bal.transpose())
595
+
596
+ def test_inflow_driven_model_normallyDistrLifetime_0(self):
597
+ """Test Inflow Driven Model with Fixed product lifetime of 0."""
598
+ np.testing.assert_array_equal(myDSM0n.compute_s_c_inflow_driven(), np.zeros(Stock_TC_FixedLT.shape))
599
+ np.testing.assert_array_equal(myDSM0n.compute_stock_total(), np.zeros((Stock_TC_FixedLT.shape[0])))
600
+ np.testing.assert_array_equal(myDSM0n.compute_stock_change(), np.zeros((Stock_TC_FixedLT.shape[0])))
601
+ np.testing.assert_array_equal(myDSM0n.compute_outflow_mb(), Inflow_T_FixedLT)
602
+ np.testing.assert_array_equal(myDSM0n.check_stock_balance(), Bal.transpose())
603
+
604
+ def test_inflow_driven_model_normallyDistLifetime(self):
605
+ """Test Inflow Driven Model with normally distributed product lifetime."""
606
+ np.testing.assert_array_almost_equal(myDSM3.compute_s_c_inflow_driven(), Stock_TC_NormLT, 8)
607
+ np.testing.assert_array_almost_equal(myDSM3.compute_stock_total(), Stock_T_NormLT, 8)
608
+ np.testing.assert_array_almost_equal(myDSM3.compute_o_c_from_s_c(), Outflow_TC_NormLT, 8)
609
+ np.testing.assert_array_almost_equal(myDSM3.compute_outflow_total(), Outflow_T_NormLT, 8)
610
+ np.testing.assert_array_almost_equal(myDSM3.compute_stock_change(), StockChange_T_NormLT, 8)
611
+ np.testing.assert_array_almost_equal(myDSM3.check_stock_balance(), Bal.transpose(), 12)
612
+
613
+ def test_stock_driven_model_normallyDistLifetime(self):
614
+ """Test Stock Driven Model with normally distributed product lifetime."""
615
+ np.testing.assert_array_almost_equal(
616
+ myDSM4.compute_stock_driven_model()[0], Stock_TC_NormLT, 8)
617
+ np.testing.assert_array_almost_equal(
618
+ myDSM4.compute_stock_driven_model()[1], Outflow_TC_NormLT, 8)
619
+ np.testing.assert_array_almost_equal(
620
+ myDSM4.compute_stock_driven_model()[2], Inflow_T_FixedLT, 8)
621
+ np.testing.assert_array_almost_equal(myDSM4.compute_outflow_total(), Outflow_T_NormLT, 8)
622
+ np.testing.assert_array_almost_equal(
623
+ myDSM4.compute_stock_change(), StockChange_T_NormLT, 8)
624
+ np.testing.assert_array_almost_equal(myDSM4.check_stock_balance(), Bal.transpose(), 12)
625
+
626
+ def test_stock_driven_model_normallyDistLifetime_NegInflowFlagTrue(self):
627
+ """Test Stock Driven Model with normally distributed product lifetime.
628
+ Set the NegativeInflowCorrect flag as True but use a test case without negative inflows."""
629
+ np.testing.assert_array_almost_equal(
630
+ myDSM4a.compute_stock_driven_model(NegativeInflowCorrect = True)[0], Stock_TC_NormLT, 8)
631
+ np.testing.assert_array_almost_equal(
632
+ myDSM4a.compute_stock_driven_model(NegativeInflowCorrect = True)[1], Outflow_TC_NormLT, 8)
633
+ np.testing.assert_array_almost_equal(
634
+ myDSM4a.compute_stock_driven_model(NegativeInflowCorrect = True)[2], Inflow_T_FixedLT, 8)
635
+ np.testing.assert_array_almost_equal(myDSM4a.compute_outflow_total(), Outflow_T_NormLT, 8)
636
+ np.testing.assert_array_almost_equal(
637
+ myDSM4a.compute_stock_change(), StockChange_T_NormLT, 8)
638
+ np.testing.assert_array_almost_equal(myDSM4a.check_stock_balance(), Bal.transpose(), 12)
639
+
640
+ def test_stock_driven_model_normallyDistLifetime_NegInflow(self):
641
+ """Test Stock Driven Model with normally distributed product lifetime, with negative inflow."""
642
+ np.testing.assert_array_almost_equal(
643
+ myDSM_ICF.compute_stock_driven_model(NegativeInflowCorrect = False)[2], InflowNeg_NoCorr, 12)
644
+ np.testing.assert_array_almost_equal(
645
+ myDSM_ICT.compute_stock_driven_model(NegativeInflowCorrect = True)[2], InflowNeg_WithCorr, 12)
646
+ np.testing.assert_array_almost_equal(
647
+ myDSM_ICT.compute_stock_change(), StockChange_WithCorr, 12)
648
+ np.testing.assert_array_almost_equal(myDSM_ICT.check_stock_balance(), Bal30.transpose(), 12)
649
+
650
+ def test_stock_driven_model_Initialstock_NegInflow(self):
651
+ """Test Stock Driven Model with normally distributed product lifetime, initial stock, with negative inflow and no negative inflow correction."""
652
+ np.testing.assert_array_almost_equal(myDSM_ICFIS.check_stock_balance(), Bal30.transpose(), 12)
653
+ np.testing.assert_array_almost_equal(myDSM_ICFIS.compute_stock_driven_model_initialstock(InitialStock = InitialStock_8, SwitchTime = 9, NegativeInflowCorrect = False)[2], InitialStockInflowNegNoCorrect, 12)
654
+
655
+ def test_stock_driven_model_Initialstock_NegInflowNotUsed(self):
656
+ """Test Stock Driven Model with normally distributed product lifetime, initial stock, with no negative inflow and no negative inflow correction."""
657
+ np.testing.assert_array_almost_equal(myDSM_ICTIST.check_stock_balance(), Bal30.transpose(), 12)
658
+ np.testing.assert_array_almost_equal(myDSM_ICTIST.compute_stock_driven_model_initialstock(InitialStock = InitialStock_8, SwitchTime = 9, NegativeInflowCorrect = False)[2], InitialStockInflowNoNegCorrect, 12)
659
+
660
+ def test_stock_driven_model_Initialstock_NegInflowFixed(self):
661
+ """Test Stock Driven Model with normally distributed product lifetime, initial stock, with negative inflow and negative inflow correction."""
662
+ np.testing.assert_array_almost_equal(myDSM_ICTIS.check_stock_balance(), Bal30.transpose(), 12)
663
+ np.testing.assert_array_almost_equal(myDSM_ICTIS.compute_stock_driven_model_initialstock(InitialStock = InitialStock_8, SwitchTime = 9, NegativeInflowCorrect = True)[2], InitialStockInflowNegCorrect, 12)
664
+
665
+ def test_stock_driven_model_Initialstock_NegInflow_TypeSplit_NotUsed(self):
666
+ """Test Stock Driven Model with lognormally distributed product lifetime, initial stock, typesplit, with negative inflow correction but no negative inflow occurring."""
667
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit1.check_stock_balance(), Bal9.transpose(), 12)
668
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit1.compute_stock_driven_model_initialstock_typesplit_negativeinflowcorrect(SwitchTime=3,InitialStock=InitialStock1,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombined,np.ones(2)),TypeSplit=TypeSplit1a,NegativeInflowCorrect=True)[0][:,2,:], TypeSplitInitialStockInflowCorrect1StockCheck, 12)
669
+
670
+ def test_stock_driven_model_Initialstock_NegInflow_TypeSplit_NoCorr(self):
671
+ """Test Stock Driven Model with lognormally distributed product lifetime, initial stock, typesplit, with negative inflow correction of but negative inflow occurring."""
672
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit2.check_stock_balance(), Bal9.transpose(), 12)
673
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit2.compute_stock_driven_model_initialstock_typesplit_negativeinflowcorrect(SwitchTime=3,InitialStock=InitialStock1,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombined,np.ones(2)),TypeSplit=TypeSplit1a,NegativeInflowCorrect=False)[0][:,2,:], TypeSplitInitialStockInflowCorrect2StockCheck, 12)
674
+
675
+ def test_stock_driven_model_Initialstock_NegInflow_TypeSplit_Corr(self):
676
+ """Test Stock Driven Model with lognormally distributed product lifetime, initial stock, typesplit, with negative inflow correction on and negative inflow occurring and corrected."""
677
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit3.check_stock_balance(), Bal9.transpose(), 12)
678
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit3.compute_stock_driven_model_initialstock_typesplit_negativeinflowcorrect(SwitchTime=3,InitialStock=InitialStock1,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombined,np.ones(2)),TypeSplit=TypeSplit1a,NegativeInflowCorrect=True)[0][:,2,:], TypeSplitInitialStockInflowCorrect3StockCheck, 12)
679
+
680
+ def test_stock_driven_model_Initialstock_NegInflow_TypeSplit_NotUsed_NormalLT(self):
681
+ """Test Stock Driven Model with normally distributed product lifetime, initial stock, typesplit, with negative inflow correction but no negative inflow occurring."""
682
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit1a.check_stock_balance(), Bal30.transpose(), 12)
683
+
684
+ def test_stock_driven_model_Initialstock_NegInflow_TypeSplit_NoCorr_NormalLT(self):
685
+ """Test Stock Driven Model with normally distributed product lifetime, initial stock, typesplit, with negative inflow correction of but negative inflow occurring."""
686
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit2a.check_stock_balance(), Bal30.transpose(), 12)
687
+
688
+ def test_stock_driven_model_Initialstock_NegInflow_TypeSplit_Corr_NormalLT(self):
689
+ """Test Stock Driven Model with normally distributed product lifetime, initial stock, typesplit, with negative inflow correction on and negative inflow occurring and corrected."""
690
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit3a.check_stock_balance(), Bal30.transpose(), 12)
691
+
692
+ def test_stock_driven_model_Initialstock_TypeSplit(self):
693
+ """Test Stock Driven Model with lognormally distributed product lifetime, initial stock, and type split."""
694
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit.check_stock_balance()[1::], np.zeros((5)), 12)
695
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit.compute_stock_driven_model_initialstock_typesplit(FutureStock=FutureStock1,InitialStock=InitialStock1,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombined,np.ones(2)),TypeSplit=TypeSplit1)[0][4,:,0], TypeSplitStockCheckType1, 12)
696
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit.compute_stock_driven_model_initialstock_typesplit(FutureStock=FutureStock1,InitialStock=InitialStock1,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombined,np.ones(2)),TypeSplit=TypeSplit1)[0][4,:,1], TypeSplitStockCheckType2, 12)
697
+ np.testing.assert_array_almost_equal(TestDSM_IntitialStockTypeSplit.compute_stock_driven_model_initialstock_typesplit(FutureStock=FutureStock1,InitialStock=InitialStock1,SFArrayCombined=np.einsum('tc,g->tcg',SFArrayCombined,np.ones(2)),TypeSplit=TypeSplit1)[2], TypeSplitInflowCheckType, 12)
698
+
699
+ def test_inflow_driven_model_WeibullDistLifetime(self):
700
+ """Test Inflow Driven Model with Weibull-distributed product lifetime."""
701
+ np.testing.assert_array_almost_equal(
702
+ myDSMWB1.compute_s_c_inflow_driven(), Stock_TC_WeibullLT, 9)
703
+ np.testing.assert_array_almost_equal(myDSMWB1.compute_stock_total(), Stock_T_WeibullLT, 8)
704
+ np.testing.assert_array_almost_equal(myDSMWB1.compute_o_c_from_s_c(), Outflow_TC_WeibullLT, 9)
705
+ np.testing.assert_array_almost_equal(myDSMWB1.compute_outflow_total(), Outflow_T_WeibullLT, 9)
706
+ np.testing.assert_array_almost_equal(
707
+ myDSMWB1.compute_stock_change(), StockChange_T_WeibullLT, 9)
708
+ np.testing.assert_array_almost_equal(myDSMWB1.check_stock_balance(), Bal.transpose(), 12)
709
+
710
+ def test_stock_driven_model_WeibullDistLifetime(self):
711
+ """Test Stock Driven Model with Weibull-distributed product lifetime."""
712
+ np.testing.assert_array_almost_equal(
713
+ myDSMWB1.compute_stock_driven_model()[0], Stock_TC_WeibullLT, 8)
714
+ np.testing.assert_array_almost_equal(
715
+ myDSMWB1.compute_stock_driven_model()[1], Outflow_TC_WeibullLT, 8)
716
+ np.testing.assert_array_almost_equal(
717
+ myDSMWB1.compute_stock_driven_model()[2], Inflow_T_FixedLT, 8)
718
+ np.testing.assert_array_almost_equal(myDSMWB1.compute_outflow_total(), Outflow_T_WeibullLT, 9)
719
+ np.testing.assert_array_almost_equal(
720
+ myDSMWB1.compute_stock_change(), StockChange_T_WeibullLT, 8)
721
+ np.testing.assert_array_almost_equal(myDSMWB1.check_stock_balance(), Bal.transpose(), 12)
722
+
723
+
724
+ def test_inflow_from_stock_fixedLifetime(self):
725
+ """Test computation of inflow from stock with Fixed product lifetime."""
726
+ np.testing.assert_array_equal(TestInflow_X, Inflow_X)
727
+ np.testing.assert_array_equal(myDSMxy.compute_s_c_inflow_driven()[-1, :], InitialStock_X)
728
+
729
+ def test_inflow_from_stock_normallyDistLifetime(self):
730
+ """Test computation of inflow from stock with normally distributed product lifetime."""
731
+ np.testing.assert_array_almost_equal(TestInflow_XX, Inflow_XX, 8)
732
+ np.testing.assert_array_almost_equal(myDSMXY.compute_s_c_inflow_driven()[-1, :], InitialStock_XX, 9)
733
+
734
+ def test_inflow_from_stock_WeibullDistLifetime(self):
735
+ """Test computation of inflow from stock with Weibull-distributed product lifetime."""
736
+ np.testing.assert_array_almost_equal(TestInflow_WB, Inflow_WB, 6)
737
+ np.testing.assert_array_almost_equal(myDSMWB4.compute_s_c_inflow_driven()[-1, :], InitialStock_WB, 8)
738
+
739
+ def test_compute_stock_driven_model_initialstock(self):
740
+ """Test stock-driven model with initial stock given."""
741
+ np.testing.assert_array_almost_equal(I_InitialStock_2, I_InitialStock_2_Ref, 8)
742
+ np.testing.assert_array_almost_equal(Sc_InitialStock_2, Sc_InitialStock_2_Ref, 8)
743
+ np.testing.assert_array_almost_equal(Sc_InitialStock_2.sum(axis =1), Sc_InitialStock_2_Ref_Sum, 8)
744
+ np.testing.assert_array_almost_equal(Oc_InitialStock_2, Oc_InitialStock_2_Ref, 8)
745
+
746
+ def test_stock_from_inflow_LogNormalDistLifetime(self):
747
+ """Test computation of stock from inflow for lognormally distributed product lifetime."""
748
+ np.testing.assert_array_almost_equal(LN_Stock_Reference_2060, LN_Stock_60[60], 9)
749
+
750
+ def test_stock_from_inflow_FoldedNormalDistLifetime(self):
751
+ """Test computation of stock from inflow for folded normally distributed product lifetime."""
752
+ np.testing.assert_array_almost_equal(FN_Stock_Reference_2060, FN_Stock_60[60], 12)
753
+
754
+ def test_compute_outflow_pdf(self):
755
+ """Test wether outflow by cohort is the same if computed with pdf from compute_outflow_pdf vs. the standard routines."""
756
+ np.testing.assert_array_almost_equal(OC_pdf, OC_alt, 14)
757
+ np.testing.assert_array_almost_equal(Bal_pdf, 0, 12)
758
+
759
+
760
+ if __name__ == '__main__':
761
+ unittest.main()
762
+