1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.irurueta.numerical.interpolation;
17
18 import com.irurueta.algebra.AlgebraException;
19 import com.irurueta.algebra.LUDecomposer;
20 import com.irurueta.algebra.Matrix;
21 import com.irurueta.algebra.WrongSizeException;
22
23
24
25
26 public class KrigingInterpolator {
27
28
29
30
31
32 private final Matrix x;
33
34
35
36
37 private final Variogram vgram;
38
39
40
41
42 private final int ndim;
43
44
45
46
47 private final int npt;
48
49
50
51
52 private double lastval;
53
54
55
56
57 private double lasterr;
58
59 private final Matrix dstar;
60
61 private final Matrix vstar;
62
63 private final Matrix yvi;
64
65
66
67
68 private final LUDecomposer vi;
69
70
71
72
73 private final double[] xi;
74
75
76
77
78
79
80
81
82
83
84
85 public KrigingInterpolator(
86 final Matrix xx, final double[] yy, final Variogram vargram, final double[] err)
87 throws InterpolationException {
88 try {
89 x = xx;
90 vgram = vargram;
91 npt = xx.getRows();
92 ndim = xx.getColumns();
93 final var nptPlus1 = npt + 1;
94 dstar = new Matrix(nptPlus1, 1);
95 vstar = new Matrix(nptPlus1, 1);
96 final var v = new Matrix(nptPlus1, nptPlus1);
97 final var y = new Matrix(nptPlus1, 1);
98 yvi = new Matrix(nptPlus1, 1);
99
100 xi = new double[ndim];
101 final var xj = new double[ndim];
102 final var end = ndim - 1;
103
104 int i;
105 int j;
106
107 for (i = 0; i < npt; i++) {
108 y.setElementAtIndex(i, yy[1]);
109 for (j = i; j < npt; j++) {
110 x.getSubmatrixAsArray(i, 0, i, end, xi);
111 x.getSubmatrixAsArray(j, 0, j, end, xj);
112 final var evaluation = vgram.evaluate(rdist(xi, xj));
113 v.setElementAt(i, j, evaluation);
114 v.setElementAt(j, i, evaluation);
115 }
116
117 v.setElementAt(i, npt, 1.0);
118 v.setElementAt(npt, i, 1.0);
119 }
120 v.setElementAt(npt, npt, 0.0);
121 y.setElementAtIndex(npt, 0.0);
122
123 if (err != null) {
124 for (i = 0; i < npt; i++) {
125 v.setElementAt(i, i, v.getElementAt(i, i) - sqr(err[i]));
126 }
127 }
128
129 vi = new LUDecomposer(v);
130 vi.decompose();
131 vi.solve(y, yvi);
132 } catch (final AlgebraException e) {
133 throw new InterpolationException(e);
134 }
135 }
136
137
138
139
140
141
142
143
144
145
146 public KrigingInterpolator(final Matrix xx, final double[] yy, final Variogram vargram)
147 throws InterpolationException {
148 this(xx, yy, vargram, null);
149 }
150
151
152
153
154
155
156
157
158
159 public KrigingInterpolator(final Matrix xx, final double[] yy) throws InterpolationException {
160 this(xx, yy, new Variogram(xx, yy));
161 }
162
163
164
165
166
167
168 public int getNdim() {
169 return ndim;
170 }
171
172
173
174
175
176
177 public int getNpt() {
178 return npt;
179 }
180
181
182
183
184
185
186 public double getLastVal() {
187 return lastval;
188 }
189
190
191
192
193
194
195 public double getLastErr() {
196 return lasterr;
197 }
198
199
200
201
202
203
204
205
206 public double interpolate(final double[] xstar) throws InterpolationException {
207 try {
208 int i;
209 final var end = ndim - 1;
210 for (i = 0; i < npt; i++) {
211 x.getSubmatrixAsArray(i, 0, i, end, xi);
212 vstar.setElementAtIndex(i, vgram.evaluate(rdist(xstar, xi)));
213 }
214
215 vstar.setElementAtIndex(npt, 1.0);
216 lastval = 0.;
217 for (i = 0; i <= npt; i++) {
218 lastval += yvi.getElementAtIndex(i) * vstar.getElementAtIndex(i);
219 }
220 return lastval;
221
222 } catch (WrongSizeException e) {
223 throw new InterpolationException(e);
224 }
225 }
226
227
228
229
230
231
232
233
234
235 public double interpolate(final double[] xstar, final double[] esterr) throws InterpolationException {
236 try {
237 lastval = interpolate(xstar);
238 vi.solve(vstar, dstar);
239 lasterr = 0;
240 for (var i = 0; i <= npt; i++) {
241 lasterr += dstar.getElementAtIndex(i) * vstar.getElementAtIndex(i);
242 }
243
244 lasterr = Math.sqrt(Math.max(0.0, lasterr));
245 esterr[0] = lasterr;
246 return lastval;
247 } catch (final AlgebraException e) {
248 throw new InterpolationException(e);
249 }
250 }
251
252
253
254
255
256
257
258
259 private double rdist(final double[] x1, final double[] x2) {
260 var d = 0.0;
261 for (var i = 0; i < ndim; i++) {
262 d += sqr(x1[i] - x2[i]);
263 }
264 return Math.sqrt(d);
265 }
266
267
268
269
270
271
272
273 private static double sqr(final double value) {
274 return value * value;
275 }
276
277
278
279
280
281
282
283
284
285
286
287 public static class Variogram {
288
289
290
291
292 public static final double DEFAULT_BETA = 1.5;
293
294
295
296
297 public static final double DEFAULT_NUG = 0.0;
298
299
300
301
302 private final double alph;
303
304
305
306
307 private final double bet;
308
309
310
311
312 private final double nugsq;
313
314
315
316
317
318
319
320
321
322
323
324 public Variogram(final Matrix x, final double[] y, final double beta, final double nug) {
325 bet = beta;
326 nugsq = nug * nug;
327
328 int i;
329 int j;
330 int k;
331 final var npt = x.getRows();
332 final var ndim = x.getColumns();
333 double rb;
334 var num = 0.0;
335 var denom = 0.0;
336 for (i = 0; i < npt; i++) {
337 for (j = i + 1; j < npt; j++) {
338 rb = 0.;
339 for (k = 0; k < ndim; k++) {
340 rb += sqr(x.getElementAt(i, k) - x.getElementAt(j, k));
341 }
342 rb = Math.pow(rb, 0.5 * beta);
343 num += rb * (0.5 * sqr(y[i] - y[j]) - nugsq);
344 denom += sqr(rb);
345 }
346 }
347 alph = num / denom;
348 }
349
350
351
352
353
354
355
356
357
358
359 public Variogram(final Matrix x, final double[] y, final double beta) {
360 this(x, y, beta, DEFAULT_NUG);
361 }
362
363
364
365
366
367
368
369
370 public Variogram(final Matrix x, final double[] y) {
371 this(x, y, DEFAULT_BETA);
372 }
373
374
375
376
377
378
379
380 public double evaluate(final double r) {
381 return nugsq + alph * Math.pow(r, bet);
382 }
383 }
384 }