1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package p3j.simulation;
17
18 import james.core.math.random.distributions.NormalDistribution;
19 import james.core.math.random.generators.IRandom;
20 import p3j.misc.Misc;
21 import p3j.misc.math.Matrix2D;
22 import p3j.pppm.parameters.ParameterAssignment;
23 import p3j.pppm.parameters.Parameters;
24 import p3j.simulation.calculation.deterministic.Constants;
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 final class DeviationCalculator {
46
47
48
49
50 private DeviationCalculator() {
51 }
52
53
54
55
56
57
58
59
60
61
62
63 static Matrix2D calculateAssignmentDeviation(ParameterAssignment assignment,
64 IRandom random) {
65
66 Matrix2D originalValues = assignment.getMatrixValue();
67 double deviation = assignment.getDeviation();
68
69
70 if (Double.compare(deviation, 0) == 0) {
71 return originalValues;
72 }
73
74 Matrix2D deviatedValues;
75
76
77 if (assignment.getParamInstance().getParameter().getName()
78 .contains(Parameters.SURVIVORS_AGE_X)) {
79 deviatedValues = mortalityDeviation(random, originalValues, deviation);
80 } else {
81 deviatedValues = stochasticDeviation(random, originalValues, deviation);
82 }
83
84 return deviatedValues;
85 }
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 private static Matrix2D mortalityDeviation(IRandom random,
103 Matrix2D originalValues, double deviation) {
104 Matrix2D lnQx = transformMortalityMatrix(originalValues);
105 Matrix2D deviatedValues = stochasticDeviation(random, lnQx, deviation);
106 return reverseTransformation(deviatedValues);
107 }
108
109
110
111
112
113
114
115
116
117
118 private static Matrix2D transformMortalityMatrix(Matrix2D originalValues) {
119
120 Matrix2D lnQx = new Matrix2D(originalValues.rows(),
121 originalValues.columns());
122
123 for (int year = 0; year < originalValues.rows(); year++) {
124 for (int age = 0; age < originalValues.columns() - 1; age++) {
125 double survProb = originalValues.getQuick(year, age + 1)
126 / originalValues.getQuick(year, age);
127 lnQx.setQuick(year, age, Math.log(1 - survProb));
128 }
129 }
130 return lnQx;
131 }
132
133
134
135
136
137
138
139
140
141 private static Matrix2D reverseTransformation(Matrix2D deviatedLnQx) {
142
143 Matrix2D deviatedLx = new Matrix2D(deviatedLnQx.rows(),
144 deviatedLnQx.columns());
145
146 for (int year = 0; year < deviatedLnQx.rows(); year++) {
147 deviatedLx.setQuick(year, 0, Constants.BASELINE_AMOUNT_MORT_MATRICES);
148 for (int age = 1; age < deviatedLnQx.columns(); age++) {
149 double survProb = (1 - Math.exp(deviatedLnQx.getQuick(year, age - 1)));
150 double remainingPop = deviatedLx.getQuick(year, age - 1) * survProb;
151 deviatedLx.setQuick(year, age, remainingPop);
152 }
153 }
154 return deviatedLx;
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 private static Matrix2D stochasticDeviation(IRandom random,
171 Matrix2D originalValues, double deviation) {
172 Matrix2D deviatedValues = originalValues.copy();
173 double[] errors = generateErrors(random, deviation, deviatedValues.rows());
174 applyErrors(deviatedValues, errors);
175 return deviatedValues;
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191 private static double[] generateErrors(IRandom random, double deviation,
192 int years) {
193 double[] errors = new double[years];
194 NormalDistribution normDist = new NormalDistribution(random, 1, deviation);
195 errors[0] = 1.;
196 for (int i = 1; i < years; i++) {
197 errors[i] = errors[i - 1]
198 * Math.max(Misc.EPSILON, normDist.getRandomNumber());
199 }
200 return errors;
201 }
202
203
204
205
206
207
208
209
210
211 private static void applyErrors(Matrix2D deviatedValues, double[] errors) {
212 for (int year = 1; year < deviatedValues.rows(); year++) {
213 for (int age = 0; age < deviatedValues.columns(); age++) {
214 deviatedValues.setQuick(year, age, deviatedValues.getQuick(year, age)
215 * errors[year]);
216 }
217 }
218 }
219 }