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