Ocean
Loading...
Searching...
No Matches
NonLinearUniversalOptimizationSparse.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_GEOMETRY_NON_LINEAR_UNIVERSAL_OPTIMIZATION_SPARSE_H
9#define META_OCEAN_GEOMETRY_NON_LINEAR_UNIVERSAL_OPTIMIZATION_SPARSE_H
10
13
14namespace Ocean
15{
16
17namespace Geometry
18{
19
20/**
21 * This class implements optimizations for universal sparse problems.
22 * @ingroup geometry
23 */
25{
26 public:
27
28 /**
29 * This class implements an optimization for universal sparse problems with one shared model (optimization problem) and concurrently several individual models (optimization problems).
30 * The implementation allows to optimize arbitrary (universal) problems with arbitrary dimensions.
31 * @tparam tSharedModelSize Size of the shared model, the number of model parameters
32 * @tparam tIndividualModelSize Size of the individual model, the number of model parameters
33 * @tparam tResultDimension Number of dimensions that result for each element (measurement) after the model has been applied
34 * @tparam tExternalSharedModelSize Size of the external shared model, the number of model parameters
35 * @tparam tExternalIndividualModelSize Size of the external individual model, the number of model parameters
36 */
37 template <unsigned int tSharedModelSize, unsigned int tIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize = tSharedModelSize, unsigned int tExternalIndividualModelSize = tIndividualModelSize>
39 {
40 public:
41
42 /**
43 * Definition of a shared model.
44 */
46
47 /**
48 * Definition of an external shared model.
49 */
51
52 /**
53 * Definition of an individual model.
54 */
56
57 /**
58 * Definition of an external individual model.
59 */
61
62 /**
63 * Definition of a model result.
64 */
66
67 /**
68 * Definition of a vector holding individual models.
69 */
70 typedef std::vector<IndividualModel> IndividualModels;
71
72 /**
73 * Definition of a callback function for sparse value calculation.
74 * The first parameter provides the shared model that is applied to determine the value.<br>
75 * The second parameter provides the individual model that is applied to determine the value.<br>
76 * The third parameter provides the index of the individual models that is used to determine the value.<br>
77 * The fourth parameter provides the element index for the individual model.<br>
78 * The fifth parameter receives the determined value.
79 */
81
82 /**
83 * Definition of a callback function for sparse error calculation.
84 * The first parameter provides the shared model that is applied to determine the value.<br>
85 * The second parameter provides the individual model that is applied to determine the value.<br>
86 * The third parameter provides the index of the individual models that is used to determine the error.<br>
87 * The fourth parameter provides the element index for the individual model.<br>
88 * The fifth parameter receives the determined error.<br>
89 * The return value provides True if both models provide valid information for the measurement element.<br>
90 */
92
93 /**
94 * Definition of a callback function determining whether a shared model is valid.
95 * The first parameter provides the external shared model for which the decision has to be done
96 * True, if the shared model is valid.<br>
97 */
99
100 /**
101 * Definition of a shared model transformation function.
102 * The transformation function allows to use an external model function for value and error determination while the internal model is used for the internal optimization.<br>
103 * The first parameter provides the internal shared model.<br>
104 * The second parameter receives the external shared model.<br>
105 */
107
108 /**
109 * Definition of an individual model transformation function.
110 * The transformation function allows to use an external model function for value and error determination while the internal model is used for the internal optimization.<br>
111 * The first parameter provides the internal shared model.<br>
112 * The second parameter receives the external shared model.<br>
113 */
115
116 /**
117 * Definition of a model accepted function.
118 * The first parameter provides the internal shared model that has been accepted as improved model.
119 * The second parameter provides the internal individual models that have been accepted as improved model.
120 */
122
123 protected:
124
125 /**
126 * Definition of a vector holding individual models.
127 */
128 typedef std::vector<ExternalIndividualModel> ExternalIndividualModels;
129
130 /**
131 * This class implements a sparse universal optimization provider for universal models and measurement/data values.
132 */
134 {
135 public:
136
137 /**
138 * Creates a new universal optimization object.
139 * @param sharedModel Shared model to be optimized
140 * @param individualModels Individual models to be optimized
141 * @param numberElementsPerIndividualModel Number of elements (measurements) that are used to determine the optimized model
142 * @param valueCallback Callback function that is used to determine the value for an individual element (measurement) by application of the model
143 * @param errorCallback Callback function that is used to determine the error for an individual element (measurement)
144 * @param sharedModelIsValidCallback Optional callback function that allows to decide whether a shared model is valid
145 * @param sharedModelTransformationCallback Callback function allowing to transform the internal shared model into an extern shared model
146 * @param individualModelTransformationCallback Callback function allowing to transform the internal individual model into an external individual model
147 * @param modelAcceptedCallback Optional callback function that allows to be informed whenever the internal models has been improved
148 */
149 inline UniversalOptimizationProvider(SharedModel& sharedModel, IndividualModels& individualModels, const size_t* numberElementsPerIndividualModel, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const SharedModelIsValidCallback& sharedModelIsValidCallback, const SharedModelTransformationCallback& sharedModelTransformationCallback, const IndividualModelTransformationCallback& individualModelTransformationCallback, const ModelAcceptedCallback& modelAcceptedCallback = ModelAcceptedCallback());
150
151 /**
152 * Determines the jacobian matrix for the current model.
153 * @param jacobian Jacobian matrix
154 */
155 void determineJacobian(SparseMatrix& jacobian) const;
156
157 /**
158 * Applies the model correction and stores the new model(s) as candidate.
159 * @param deltas Optimization deltas that define the correction
160 */
161 inline void applyCorrection(const Matrix& deltas);
162
163 /**
164 * Determines the robust error of the current candidate model(s).
165 * @param weightedErrorVector Resulting (weighted - if using a robust estimator) error vector
166 * @param weightVector Vector holding the weights that have already been applied to the error vector
167 * @param invertedCovariances Optional 2x2 inverted covariance matrices
168 * @return The resulting robust error
169 * @tparam tEstimator The type of the estimator that is applied for error determination
170 */
171 template <Estimator::EstimatorType tEstimator>
172 Scalar determineRobustError(Matrix& weightedErrorVector, Matrix& weightVector, const Matrix* invertedCovariances) const;
173
174 /**
175 * Accepts the current model candidate as better model.
176 */
177 inline void acceptCorrection();
178
179 protected:
180
181 /// Universal shared model that will be optimized.
183
184 /// Universal individual model that will be optimized.
186
187 /// Universal shared model that stores the most recent optimization result as candidate.
189
190 /// Universal individual model that stores the most recent optimization result as candidate.
192
193 /// The number of measurement elements that are used to optimize each individual model.
194 const size_t* numberElementsPerIndividualModel_ = nullptr;
195
196 /// The overall number of measurement elements that are used to optimize the models.
198
199 /// The value calculation callback function.
201
202 /// The error calculation callback function.
204
205 /// The callback function determining whether a shared model is valid.
207
208 /// The callback function allowing to transform the shared model into an external model before the value and error callback functions are invoked.
210
211 /// The callback function allowing to transform the individual model into an external model before the value and error callback functions are invoked.
213
214 /// Optional callback function allowing to be informed whenever the model has been improved.
216 };
217
218 public:
219
220 /**
221 * Optimizes a universal model by minimizing the error the model produces.
222 * @param sharedModel Shared model that will be optimized
223 * @param individualModels Individual models that will be optimized
224 * @param numberElementsPerIndividualModel The numbers of measurement elements individually for each individual model
225 * @param valueCallback Callback function that is used to determine the value for an individual element (measurement) by application of the model
226 * @param errorCallback Callback function that is used to determine the error for an individual element (measurement)
227 * @param sharedModelIsValidCallback Optional callback function that allows to decide whether a shared model is valid
228 * @param sharedModelTransformationCallback Callback function allowing to transform the internal shared model into an extern model if intended
229 * @param individualModelTransformationCallback Callback function allowing to transform the internal individual model into an extern model if intended
230 * @param modelAcceptedCallback Optional callback function that allows to be informed whenever the internal models has been improved
231 * @param optimizedSharedModel Resulting optimized shared model
232 * @param optimizedIndividualModels Resulting optimized individual models
233 * @param iterations Number of iterations to be applied at most, if no convergence can be reached
234 * @param estimator Robust error estimator to be used
235 * @param lambda Initial Levenberg-Marquardt damping value which may be changed after each iteration using the damping factor, with range [0, infinity)
236 * @param lambdaFactor Levenberg-Marquardt damping factor to be applied to the damping value, with range [1, infinity)
237 * @param initialError Optional resulting averaged pixel error for the given initial parameters, in relation to the defined estimator
238 * @param finalError Optional resulting averaged error for the final optimized parameters, in relation to the defined estimator
239 * @param intermediateErrors Optional resulting intermediate (improving) errors
240 * @return True, if the model could be optimized
241 */
242 static bool optimizeUniversalModel(const SharedModel& sharedModel, const IndividualModels& individualModels, const size_t* numberElementsPerIndividualModel, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const SharedModelIsValidCallback& sharedModelIsValidCallback, const SharedModelTransformationCallback& sharedModelTransformationCallback, const IndividualModelTransformationCallback& individualModelTransformationCallback, const ModelAcceptedCallback& modelAcceptedCallback, SharedModel& optimizedSharedModel, IndividualModels& optimizedIndividualModels, const unsigned int iterations = 5u, const Estimator::EstimatorType estimator = Estimator::ET_SQUARE, Scalar lambda = Scalar(0.001), const Scalar lambdaFactor = Scalar(5), Scalar* initialError = nullptr, Scalar* finalError = nullptr, Scalars* intermediateErrors = nullptr);
243 };
244
245 /**
246 * This class implements an optimization for universal sparse problems with two types of individual models (optimization problems).
247 * The implementation allows to optimize arbitrary (universal) problems with arbitrary dimensions.<br>
248 * @tparam tFirstModelSize Size of the first model, the number of model parameters
249 * @tparam tSecondModelSize Size of the second model, the number of model parameters
250 * @tparam tResultDimension Number of dimensions that result for each element (measurement) after the model has been applied
251 * @tparam tExternalFirstModelSize Size of the external first model, the number of model parameters
252 * @tparam tExternalSecondModelSize Size of the external second model, the number of model parameters
253 */
254 template <unsigned int tFirstModelSize, unsigned int tSecondModelSize, unsigned int tResultDimension, unsigned int tExternalFirstModelSize = tFirstModelSize, unsigned int tExternalSecondModelSize = tSecondModelSize>
256 {
257 public:
258
259 /**
260 * Definition of the first model.
261 */
263
264 /**
265 * Definition of the external first model.
266 */
268
269 /**
270 * Definition of the second model.
271 */
273
274 /**
275 * Definition of the external second model.
276 */
278
279 /**
280 * Definition of a model result.
281 */
283
284 /**
285 * Definition of a vector holding the first models.
286 */
287 typedef std::vector<FirstModel> FirstModels;
288
289 /**
290 * Definition of a vector holding the external first models.
291 */
292 typedef std::vector<ExternalFirstModel> ExternalFirstModels;
293
294 /**
295 * Definition of a vector holding the first models.
296 */
297 typedef std::vector<SecondModel> SecondModels;
298
299 /**
300 * Definition of a vector holding the external second models.
301 */
302 typedef std::vector<ExternalSecondModel> ExternalSecondModels;
303
304 /**
305 * Definition of a callback function for sparse value calculation.
306 * The first parameter provides the external first models that can be used to determine the value.<br>
307 * The second parameter provides the external second models that can be used to determined the value.<br>
308 * The third parameter provides the index of the second model for which the value needs to be determined.<br>
309 * The fourth parameter provides the element index for the second model for which the value needs to be determined.<br>
310 * The fifth parameter receives the determined value.<br>
311 * The return value provides the index of the corresponding first model.<br>
312 */
314
315 /**
316 * Definition of a callback function for sparse error calculation.
317 * The first parameter provides the external first models that can be used to determine the error.<br>
318 * The second parameter provides the external second models that can be used to determined the error.<br>
319 * The third parameter provides the index of the second model for which the error needs to be determined.<br>
320 * The fourth parameter provides the element index for the second model for which the error needs to be determined.<br>
321 * The fifth parameter receives the determined error.<br>
322 */
324
325 /**
326 * Definition of a first model transformation function.
327 * The transformation function allows to use an external model for value and error determination while the internal model is used for the internal optimization.<br>
328 * The first parameter provides the internal first model.<br>
329 * The second parameter receives the external first model.<br>
330 */
332
333 /**
334 * Definition of a second model transformation function.
335 * The transformation function allows to use an external model for value and error determination while the internal model is used for the internal optimization.<br>
336 * The first parameter provides the internal second model.<br>
337 * The second parameter receives the external second model.<br>
338 */
340
341 /**
342 * Definition of a model accepted function.
343 * The first parameter provides the internal first models that have been accepted as improved models.
344 * The second parameter provides the internal second models that have been accepted as improved model.
345 */
347
348 protected:
349
350 /**
351 * This class implements a sparse universal optimization provider for universal models and measurement/data values.
352 */
354 {
355 public:
356
357 /**
358 * Creates a new universal optimization object.
359 * @param firstModels The first models to be optimized
360 * @param secondModels The second models to be optimized
361 * @param numberElementsPerSecondModel Number of elements (measurements) per second model that are used to determine the optimized models, one number for each second model, with range [1, infinity)
362 * @param valueCallback Callback function that is used to determine the value for an individual element (measurement) by application of the models
363 * @param errorCallback Callback function that is used to determine the error for an individual element (measurement)
364 * @param firstModelTransformationCallback Callback function allowing to transform the internal first model into an extern first model
365 * @param secondModelTransformationCallback Callback function allowing to transform the internal second model into an external second model
366 * @param modelAcceptedCallback Optional callback function that allows to be informed whenever the internal models has been improved
367 */
368 inline UniversalOptimizationProvider(FirstModels& firstModels, SecondModels& secondModels, const size_t* numberElementsPerSecondModel, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const FirstModelTransformationCallback& firstModelTransformationCallback, const SecondModelTransformationCallback& secondModelTransformationCallback, const ModelAcceptedCallback& modelAcceptedCallback = ModelAcceptedCallback());
369
370 /**
371 * Returns that this provider comes with an own equation solver.
372 * @return True, as this provider has an own solver
373 */
374 inline bool hasSolver() const;
375
376 /**
377 * Solves the equation JTJ * deltas = jErrors
378 * @param JTJ The JTJ matrix
379 * @param jErrors The jErrors vector
380 * @param deltas The deltas vector
381 * @return True, if succeeded
382 */
383 inline bool solve(const SparseMatrix& JTJ, const Matrix& jErrors, Matrix& deltas) const;
384
385 /**
386 * Determines the jacobian matrix for the current model.
387 * @param jacobian Jacobian matrix
388 */
389 void determineJacobian(SparseMatrix& jacobian) const;
390
391 /**
392 * Applies the model correction and stores the new model(s) as candidate.
393 * @param deltas Optimization deltas that define the correction
394 */
395 inline void applyCorrection(const Matrix& deltas);
396
397 /**
398 * Determines the robust error of the current candidate model(s).
399 * @param weightedErrorVector Resulting (weighted - if using a robust estimator) error vector
400 * @param weightVector Vector holding the weights that have already been applied to the error vector
401 * @param invertedCovariances Optional 2x2 inverted covariance matrices
402 * @return The resulting robust error
403 * @tparam tEstimator The type of the estimator that is applied for error determination
404 */
405 template <Estimator::EstimatorType tEstimator>
406 Scalar determineRobustError(Matrix& weightedErrorVector, Matrix& weightVector, const Matrix* invertedCovariances) const;
407
408 /**
409 * Accepts the current model candidate as better model.
410 */
411 inline void acceptCorrection();
412
413 protected:
414
415 /// The universal first models that will be optimized.
417
418 /// The universal second models that will be optimized.
420
421 /// The universal first models storing the most recent optimization results as candidates.
423
424 /// The universal second models storing the most recent optimization results as candidates.
426
427 /// The number of measurement elements for each second model.
428 const size_t* numberElementsPerSecondModel_ = nullptr;
429
430 /// The overall number of measurement elements that are used to optimize the models.
432
433 /// The value calculation callback function.
435
436 /// The error calculation callback function.
438
439 /// The callback function allowing to transform the first model into an external model before the value and error callback functions are invoked.
441
442 /// The callback function allowing to transform the second model into an external model before the value and error callback functions are invoked.
444
445 /// Optional callback function allowing to be informed whenever the model has been improved.
447 };
448
449 public:
450
451 /**
452 * Optimizes a universal model by minimizing the error the model produces.
453 * @param firstModels The first models that will be optimized
454 * @param secondModels The second models that will be optimized
455 * @param numberElementsPerSecondModel Number of elements (measurements) per second model that are used to determine the optimized models, one number for each second model, with range [1, infinity)
456 * @param valueCallback Callback function that is used to determine the value for an individual element (measurement) by application of the model(s)
457 * @param errorCallback Callback function that is used to determine the error for an individual element (measurement)
458 * @param firstModelTransformationCallback Callback function allowing to transform the internal first model into an extern model if intended
459 * @param secondModelTransformationCallback Callback function allowing to transform the internal second model into an extern model if intended
460 * @param modelAcceptedCallback Optional callback function that allows to be informed whenever the internal models has been improved
461 * @param optimizedFirstModels Resulting optimized first models
462 * @param optimizedSecondModels Resulting optimized second models
463 * @param iterations Number of iterations to be applied at most, if no convergence can be reached
464 * @param estimator Robust error estimator to be used
465 * @param lambda Initial Levenberg-Marquardt damping value which may be changed after each iteration using the damping factor, with range [0, infinity)
466 * @param lambdaFactor Levenberg-Marquardt damping factor to be applied to the damping value, with range [1, infinity)
467 * @param initialError Optional resulting averaged pixel error for the given initial parameters, in relation to the defined estimator
468 * @param finalError Optional resulting averaged error for the final optimized parameters, in relation to the defined estimator
469 * @param intermediateErrors Optional resulting intermediate (improving) errors
470 * @return True, if the model could be optimized
471 */
472 static bool optimizeUniversalModel(const FirstModels& firstModels, const SecondModels& secondModels, const size_t* numberElementsPerSecondModel, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const FirstModelTransformationCallback& firstModelTransformationCallback, const SecondModelTransformationCallback& secondModelTransformationCallback, const ModelAcceptedCallback& modelAcceptedCallback, FirstModels& optimizedFirstModels, SecondModels& optimizedSecondModels, const unsigned int iterations = 5u, const Estimator::EstimatorType estimator = Estimator::ET_SQUARE, Scalar lambda = Scalar(0.001), const Scalar lambdaFactor = Scalar(5), Scalar* initialError = nullptr, Scalar* finalError = nullptr, Scalars* intermediateErrors = nullptr);
473 };
474
475 /**
476 * This class implements an optimization for universal sparse problems with one common shared model (optimization problem) and two types of individual models (optimization problems).
477 * The implementation allows to optimize arbitrary (universal) problems with arbitrary dimensions.<br>
478 * @tparam tSharedModelSize Size of the shared model, the number of model parameters
479 * @tparam tFirstIndividualModelSize Size of the first individual model, the number of model parameters
480 * @tparam tSecondIndividualModelSize Size of the second individual model, the number of model parameters
481 * @tparam tResultDimension Number of dimensions that result for each element (measurement) after the model has been applied
482 * @tparam tExternalSharedModelSize Size of the external shared model, the number of model parameters
483 * @tparam tExternalFirstIndividualModelSize Size of the external first individual model, the number of model parameters
484 * @tparam tExternalSecondIndividualModelSize Size of the external second individual model, the number of model parameters
485 */
486 template <unsigned int tSharedModelSize, unsigned int tFirstIndividualModelSize, unsigned int tSecondIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize = tSharedModelSize, unsigned int tExternalFirstIndividualModelSize = tFirstIndividualModelSize, unsigned int tExternalSecondIndividualModelSize = tSecondIndividualModelSize>
488 {
489 public:
490
491 /**
492 * Definition of the shared model.
493 */
495
496 /**
497 * Definition of the external shared model.
498 */
500
501 /**
502 * Definition of the first individual model.
503 */
505
506 /**
507 * Definition of the external first individual model.
508 */
510
511 /**
512 * Definition of the second individual model.
513 */
515
516 /**
517 * Definition of the external second individual model.
518 */
520
521 /**
522 * Definition of a model result.
523 */
525
526 /**
527 * Definition of a vector holding the first individual models.
528 */
529 typedef std::vector<FirstIndividualModel> FirstIndividualModels;
530
531 /**
532 * Definition of a vector holding the external first individual models.
533 */
534 typedef std::vector<ExternalFirstIndividualModel> ExternalFirstIndividualModels;
535
536 /**
537 * Definition of a vector holding the first individual models.
538 */
539 typedef std::vector<SecondIndividualModel> SecondIndividualModels;
540
541 /**
542 * Definition of a vector holding the external second individual models.
543 */
544 typedef std::vector<ExternalSecondIndividualModel> ExternalSecondIndividualModels;
545
546 /**
547 * Definition of a callback function for sparse value calculation.
548 * The first parameter provides the external shared model that will be used to determined the value.<br>
549 * The second parameter provides the external first individual models that can be used to determine the value.<br>
550 * The third parameter provides the external second individual models that can be used to determined the value.<br>
551 * The fourth parameter provides the index of the second model for which the value needs to be determined.<br>
552 * The fifth parameter provides the element index for the second model for which the value needs to be determined.<br>
553 * The sixth parameter receives the determined value.<br>
554 * The return value provides the index of the corresponding first model.<br>
555 */
557
558 /**
559 * Definition of a callback function for sparse error calculation.
560 * The first parameter provides the external shared model that will be used to determined the error.<br>
561 * The second parameter provides the external first individual models that can be used to determine the error.<br>
562 * The third parameter provides the external second individual models that can be used to determined the error.<br>
563 * The fourth parameter provides the index of the second model for which the error needs to be determined.<br>
564 * The fifth parameter provides the element index for the second model for which the error needs to be determined.<br>
565 * The sixth parameter receives the determined error.<br>
566 */
568
569 /**
570 * Definition of a callback function determining whether a shared model is valid.
571 * The first parameter provides the external shared model for which the decision has to be done
572 * True, if the shared model is valid.<br>
573 */
575
576 /**
577 * Definition of a transformation function for the shared model.
578 * The transformation function allows to use an external model for value and error determination while the internal model is used for the internal optimization.<br>
579 * The first parameter provides the internal shared model.<br>
580 * The second parameter receives the external shared model.<br>
581 */
583
584 /**
585 * Definition of a transformation function for the first individual models.
586 * The transformation function allows to use an external model for value and error determination while the internal model is used for the internal optimization.<br>
587 * The first parameter provides the internal first individual model.<br>
588 * The second parameter receives the external first individual model.<br>
589 */
591
592 /**
593 * Definition of a transformation function for the second individual models.
594 * The transformation function allows to use an external model for value and error determination while the internal model is used for the internal optimization.<br>
595 * The first parameter provides the internal second individual model.<br>
596 * The second parameter receives the external second individual model.<br>
597 */
599
600 /**
601 * Definition of a model accepted function.
602 * The first parameter provides the internal shared model that have been accepted as improved model.
603 * The second parameter provides the internal first individual models that have been accepted as improved models.
604 * The third parameter provides the internal second individual models that have been accepted as improved model.
605 */
607
608 protected:
609
610 /**
611 * This class implements a sparse universal optimization provider for universal models and measurement/data values.
612 */
614 {
615 public:
616
617 /**
618 * Creates a new universal optimization object.
619 * @param sharedModel The shared model to be optimized
620 * @param firstIndividualModels The first individual models to be optimized
621 * @param secondIndividualModels The second individual models to be optimized
622 * @param numberElementsPerSecondModel Number of elements (measurements) per second model that are used to determine the optimized models, one number for each second model, with range [1, infinity)
623 * @param valueCallback Callback function that is used to determine the value for an individual element (measurement) by application of the models
624 * @param errorCallback Callback function that is used to determine the error for an individual element (measurement)
625 * @param sharedModelIsValidCallback Optional callback function that allows to decide whether a shared model is valid
626 * @param sharedModelTransformationCallback Callback function allowing to transform the internal shared model into an external shared model
627 * @param firstIndividualModelTransformationCallback Callback function allowing to transform the internal first model into an extern first model
628 * @param secondIndividualModelTransformationCallback Callback function allowing to transform the internal second model into an external second model
629 * @param modelAcceptedCallback Optional callback function that allows to be informed whenever the internal models has been improved
630 */
631 inline UniversalOptimizationProvider(SharedModel& sharedModel, FirstIndividualModels& firstIndividualModels, SecondIndividualModels& secondIndividualModels, const size_t* numberElementsPerSecondModel, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const SharedModelIsValidCallback& sharedModelIsValidCallback, const SharedModelTransformationCallback& sharedModelTransformationCallback, const FirstIndividualModelTransformationCallback& firstIndividualModelTransformationCallback, const SecondIndividualModelTransformationCallback& secondIndividualModelTransformationCallback, const ModelAcceptedCallback& modelAcceptedCallback = ModelAcceptedCallback());
632
633 /**
634 * Determines the jacobian matrix for the current model.
635 * @param jacobian Jacobian matrix
636 */
637 void determineJacobian(SparseMatrix& jacobian) const;
638
639 /**
640 * Applies the model correction and stores the new model(s) as candidate.
641 * @param deltas Optimization deltas that define the correction
642 */
643 inline void applyCorrection(const Matrix& deltas);
644
645 /**
646 * Determines the robust error of the current candidate model(s).
647 * @param weightedErrorVector Resulting (weighted - if using a robust estimator) error vector
648 * @param weightVector Vector holding the weights that have already been applied to the error vector
649 * @param invertedCovariances Optional 2x2 inverted covariance matrices
650 * @return The resulting robust error
651 * @tparam tEstimator The type of the estimator that is applied for error determination
652 */
653 template <Estimator::EstimatorType tEstimator>
654 Scalar determineRobustError(Matrix& weightedErrorVector, Matrix& weightVector, const Matrix* invertedCovariances) const;
655
656 /**
657 * Accepts the current model candidate as better model.
658 */
659 inline void acceptCorrection();
660
661 protected:
662
663 /// The universal shared model that will be optimized.
665
666 /// The universal first individual models that will be optimized.
668
669 /// The universal second individual models that will be optimized.
671
672 /// The universal shared model storing the most recent optimization result as candidate.
674
675 /// The universal first individual models storing the most recent optimization results as candidates.
677
678 /// The universal second individual models storing the most recent optimization results as candidates.
680
681 /// The number of measurement elements for each second model.
682 const size_t* numberElementsPerSecondModel_ = nullptr;
683
684 /// The overall number of measurement elements that are used to optimize the models.
686
687 /// The value calculation callback function.
689
690 /// The error calculation callback function.
692
693 /// The callback function determining whether a shared model is valid.
695
696 /// The callback function allowing to transform the shared model into an external model before the value and error callback functions are invoked.
698
699 /// The callback function allowing to transform the first individual model into an external model before the value and error callback functions are invoked.
701
702 /// The callback function allowing to transform the second model into an external model before the value and error callback functions are invoked.
704
705 /// Optional callback function allowing to be informed whenever the model has been improved.
707 };
708
709 public:
710
711 /**
712 * Optimizes a universal model by minimizing the error the model produces.
713 * @param sharedModel The shared model that will be optimized
714 * @param firstIndividualModels The first individual models that will be optimized
715 * @param secondIndividualModels The second individual models that will be optimized
716 * @param numberElementsPerSecondModel Number of elements (measurements) per second model that are used to determine the optimized models, one number for each second model, with range [1, infinity)
717 * @param valueCallback Callback function that is used to determine the value for an individual element (measurement) by application of the model(s)
718 * @param errorCallback Callback function that is used to determine the error for an individual element (measurement)
719 * @param sharedModelIsValidCallback Optional callback function that allows to decide whether a shared model is valid
720 * @param sharedModelTransformationCallback Callback function allowing to transform the internal shared model into an external model if intended
721 * @param firstIndividualModelTransformationCallback Callback function allowing to transform the internal first individual model into an external model if intended
722 * @param secondIndividualModelTransformationCallback Callback function allowing to transform the internal second individual model into an external model if intended
723 * @param modelAcceptedCallback Optional callback function that allows to be informed whenever the internal models has been improved
724 * @param optimizedSharedModel Resulting optimized shared model
725 * @param optimizedFirstIndividualModels Resulting optimized first individual models
726 * @param optimizedSecondIndividualModels Resulting optimized second individual models
727 * @param iterations Number of iterations to be applied at most, if no convergence can be reached
728 * @param estimator Robust error estimator to be used
729 * @param lambda Initial Levenberg-Marquardt damping value which may be changed after each iteration using the damping factor, with range [0, infinity)
730 * @param lambdaFactor Levenberg-Marquardt damping factor to be applied to the damping value, with range [1, infinity)
731 * @param initialError Optional resulting averaged pixel error for the given initial parameters, in relation to the defined estimator
732 * @param finalError Optional resulting averaged error for the final optimized parameters, in relation to the defined estimator
733 * @param intermediateErrors Optional resulting intermediate (improving) errors
734 * @return True, if the model could be optimized
735 */
736 static bool optimizeUniversalModel(const SharedModel& sharedModel, const FirstIndividualModels& firstIndividualModels, const SecondIndividualModels& secondIndividualModels, const size_t* numberElementsPerSecondModel, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const SharedModelIsValidCallback& sharedModelIsValidCallback, const SharedModelTransformationCallback& sharedModelTransformationCallback, const FirstIndividualModelTransformationCallback& firstIndividualModelTransformationCallback, const SecondIndividualModelTransformationCallback& secondIndividualModelTransformationCallback, const ModelAcceptedCallback& modelAcceptedCallback, SharedModel& optimizedSharedModel, FirstIndividualModels& optimizedFirstIndividualModels, SecondIndividualModels& optimizedSecondIndividualModels, const unsigned int iterations = 5u, const Estimator::EstimatorType estimator = Estimator::ET_SQUARE, Scalar lambda = Scalar(0.001), const Scalar lambdaFactor = Scalar(5), Scalar* initialError = nullptr, Scalar* finalError = nullptr, Scalars* intermediateErrors = nullptr);
737 };
738};
739
740template <unsigned int tSharedModelSize, unsigned int tIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalIndividualModelSize>
741inline NonLinearUniversalOptimizationSparse::SharedModelIndividualModels<tSharedModelSize, tIndividualModelSize, tResultDimension, tExternalSharedModelSize, tExternalIndividualModelSize>::UniversalOptimizationProvider::UniversalOptimizationProvider(SharedModel& sharedModel, IndividualModels& individualModels, const size_t* numberElementsPerIndividualModel, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const SharedModelIsValidCallback& sharedModelIsValidCallback, const SharedModelTransformationCallback& sharedModelTransformationCallback, const IndividualModelTransformationCallback& individualModelTransformationCallback, const ModelAcceptedCallback& modelAcceptedCallback) :
742 sharedModel_(sharedModel),
743 individualModels_(individualModels),
744 numberElementsPerIndividualModel_(numberElementsPerIndividualModel),
745 overallNumberElements_(0),
746 valueCallback_(valueCallback),
747 errorCallback_(errorCallback),
748 sharedModelIsValidCallback_(sharedModelIsValidCallback),
749 sharedModelTransformationCallback_(sharedModelTransformationCallback),
750 individualModelTransformationCallback_(individualModelTransformationCallback),
751 modelAcceptedCallback_(modelAcceptedCallback)
752{
753 ocean_assert(valueCallback_);
754 ocean_assert(errorCallback_);
757
758 candidateSharedModel_ = sharedModel;
759 candidateIndividualModels_ = individualModels;
760
761 for (size_t n = 0; n < individualModels.size(); ++n)
762 {
764 }
765};
766
767template <unsigned int tSharedModelSize, unsigned int tIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalIndividualModelSize>
769{
770 ocean_assert(valueCallback_);
771 ocean_assert(sharedModelTransformationCallback_);
772 ocean_assert(individualModelTransformationCallback_);
773
774 ocean_assert(overallNumberElements_ != 0);
775
776 SparseMatrix::Entries jacobianEntries;
777 jacobianEntries.reserve(tResultDimension * overallNumberElements_ * (tSharedModelSize + tIndividualModelSize));
778
779 const Scalar eps = Numeric::weakEps();
780 const Scalar invEps = Scalar(1) / eps;
781
782 // transform the internal shared to the external shared model
783 ExternalSharedModel externalSharedModel;
784 sharedModelTransformationCallback_(sharedModel_, externalSharedModel);
785
786 // stores individual models, each model with one individual epsilon offset
788 for (size_t a = 0; a < tSharedModelSize; ++a)
789 {
790 SharedModel internalModel = sharedModel_;
791 internalModel[a] += eps;
792
793 sharedModelTransformationCallback_(internalModel, externalEpsSharedModels[a]);
794 }
795
796 // transform the internal individual to the external individual models
797 std::vector<ExternalIndividualModel> externalIndividualModels(individualModels_.size());
798 std::vector< StaticBuffer<ExternalIndividualModel, tIndividualModelSize> > externalEpsIndividualModels(individualModels_.size());
799
800 for (size_t i = 0; i < individualModels_.size(); ++i)
801 {
802 individualModelTransformationCallback_(individualModels_[i], externalIndividualModels[i]);
803
804 for (size_t a = 0; a < tIndividualModelSize; ++a)
805 {
806 IndividualModel internalModel = individualModels_[i];
807 internalModel[a] += eps;
808
809 individualModelTransformationCallback_(internalModel, externalEpsIndividualModels[i][a]);
810 }
811 }
812
813 Result result, epsResult;
814 size_t row = 0;
815
818
819 for (size_t i = 0; i < individualModels_.size(); ++i)
820 {
821 const size_t numberElements = numberElementsPerIndividualModel_[i];
822 const size_t columnIndividual = tSharedModelSize + i * tIndividualModelSize;
823
824 for (size_t n = 0; n < numberElements; ++n)
825 {
826 // calculate the value for the current model
827 valueCallback_(externalSharedModel, externalIndividualModels[i], i, n, result);
828
829 // shared model
830 for (size_t m = 0; m < tSharedModelSize; ++m)
831 {
832 // calculate the value for the epsilon model
833 valueCallback_(externalEpsSharedModels[m], externalIndividualModels[i], i, n, epsResult);
834
835 // store the individual results
836 for (size_t d = 0; d < tResultDimension; ++d)
837 {
838 sharedModelResults[d * tSharedModelSize + m] = (epsResult[d] - result[d]) * invEps;
839 }
840 }
841
842 // individual model
843 for (size_t m = 0; m < tIndividualModelSize; ++m)
844 {
845 // calculate the value for the epsilon model
846 valueCallback_(externalSharedModel, externalEpsIndividualModels[i][m], i, n, epsResult);
847
848 // store the individual results
849 for (size_t d = 0; d < tResultDimension; ++d)
850 {
851 individualModelResults[d * tIndividualModelSize + m] = (epsResult[d] - result[d]) * invEps;
852 }
853 }
854
855 for (size_t d = 0; d < tResultDimension; ++d)
856 {
857 // .insert(row, 0u, sharedModelResults.data() + d * tSharedModelSize, tSharedModelSize);
858 for (size_t e = 0; e < tSharedModelSize; ++e)
859 {
860 jacobianEntries.emplace_back(row, e, sharedModelResults.data()[d * tSharedModelSize + e]);
861 }
862
863 // .insertBack(row, columnIndividual, individualModelResults.data() + d * tIndividualModelSize, tIndividualModelSize);
864 for (size_t e = 0; e < tIndividualModelSize; ++e)
865 {
866 jacobianEntries.emplace_back(row, columnIndividual + e, individualModelResults.data()[d * tIndividualModelSize + e]);
867 }
868
869 row++;
870 }
871 }
872 }
873
874 jacobian = SparseMatrix(tResultDimension * overallNumberElements_, tSharedModelSize + tIndividualModelSize * individualModels_.size(), jacobianEntries);
875 ocean_assert(SparseMatrix::Entry::hasOneEntry(jacobian.rows(), jacobian.columns(), jacobianEntries));
876 ocean_assert(row == jacobian.rows());
877}
878
879template <unsigned int tSharedModelSize, unsigned int tIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalIndividualModelSize>
881{
882 ocean_assert(deltas.rows() == tSharedModelSize + tIndividualModelSize * individualModels_.size());
883
884 // shared model
885 for (size_t m = 0; m < tSharedModelSize; ++m)
886 {
887 const Scalar& delta = deltas(m);
888 candidateSharedModel_[m] = sharedModel_[m] - delta;
889 }
890
891 // individual models
892 for (size_t i = 0; i < individualModels_.size(); ++i)
893 {
894 for (size_t m = 0; m < tIndividualModelSize; ++m)
895 {
896 const Scalar& delta = deltas(tSharedModelSize + i * tIndividualModelSize + m);
897 candidateIndividualModels_[i][m] = individualModels_[i][m] - delta;
898 }
899 }
900}
901
902template <unsigned int tSharedModelSize, unsigned int tIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalIndividualModelSize>
903template <Estimator::EstimatorType tEstimator>
905{
906 ocean_assert(valueCallback_);
907 ocean_assert(sharedModelTransformationCallback_);
908 ocean_assert(individualModelTransformationCallback_);
909
910 OCEAN_SUPPRESS_UNUSED_WARNING(invertedCovariances);
911 ocean_assert(invertedCovariances == nullptr);
912 ocean_assert(overallNumberElements_ != 0);
913
914 ExternalSharedModel externalSharedModel;
915 sharedModelTransformationCallback_(candidateSharedModel_, externalSharedModel);
916
917 // check whether we can stop here as we do not have a valid shared model (and the provider supports to decide that)
918 if (sharedModelIsValidCallback_ && !sharedModelIsValidCallback_(externalSharedModel))
919 {
920 return Numeric::maxValue();
921 }
922
923 // set the correct size of the resulting error vector
924 weightedErrorVector.resize(overallNumberElements_ * tResultDimension, 1u);
925 Result* const weightedErrors = (Result*)weightedErrorVector.data();
926
927 ExternalIndividualModels externalIndividualModels(individualModels_.size());
928 for (size_t i = 0; i < individualModels_.size(); ++i)
929 {
930 individualModelTransformationCallback_(candidateIndividualModels_[i], externalIndividualModels[i]);
931 }
932
933 size_t index = 0;
934 Scalar sqrError = 0;
935 Scalars sqrErrors;
936 if constexpr (!Estimator::isStandardEstimator<tEstimator>())
937 {
938 sqrErrors.reserve(overallNumberElements_);
939 }
940
941 for (size_t i = 0; i < individualModels_.size(); ++i)
942 {
943 const size_t numberElements = numberElementsPerIndividualModel_[i];
944
945 for (size_t n = 0; n < numberElements; ++n)
946 {
947 Result& weightedErrorPointer = *((Result*)weightedErrorVector.data() + index);
948
949 if (!errorCallback_(externalSharedModel, externalIndividualModels[i], i, n, weightedErrorPointer))
950 {
951 return Numeric::maxValue();
952 }
953
954 if constexpr (Estimator::isStandardEstimator<tEstimator>())
955 {
956 sqrError += Numeric::summedSqr(weightedErrorPointer.data(), tResultDimension);
957 }
958 else
959 {
960 ocean_assert(!Estimator::isStandardEstimator<tEstimator>());
961 sqrErrors.emplace_back(Numeric::summedSqr(weightedErrorPointer.data(), tResultDimension));
962 }
963
964 index++;
965 }
966 }
967
968 ocean_assert(index == overallNumberElements_);
969 ocean_assert(index * tResultDimension == weightedErrorVector.rows());
970
971 // check whether the standard estimator is used
972 if constexpr (Estimator::isStandardEstimator<tEstimator>())
973 {
974 // the weight vector should be and should stay invalid
975 ocean_assert(!weightVector);
976
977 ocean_assert((overallNumberElements_) > 0);
978 return sqrError /= Scalar(overallNumberElements_);
979 }
980 else
981 {
982 // now we need the weight vector
983 weightVector.resize(tResultDimension * overallNumberElements_, 1u);
984
985 return sqrErrors2robustErrors<tEstimator, tResultDimension>(sqrErrors, tSharedModelSize + tIndividualModelSize * individualModels_.size(), weightedErrors, (StaticBuffer<Scalar, tResultDimension>*)weightVector.data(), nullptr);
986 }
987}
988
989template <unsigned int tSharedModelSize, unsigned int tIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalIndividualModelSize>
991{
992 sharedModel_ = candidateSharedModel_;
993 individualModels_ = candidateIndividualModels_;
994
995 if (modelAcceptedCallback_)
996 {
997 modelAcceptedCallback_(sharedModel_, individualModels_);
998 }
999}
1000
1001template <unsigned int tSharedModelSize, unsigned int tIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalIndividualModelSize>
1002bool NonLinearUniversalOptimizationSparse::SharedModelIndividualModels<tSharedModelSize, tIndividualModelSize, tResultDimension, tExternalSharedModelSize, tExternalIndividualModelSize>::optimizeUniversalModel(const SharedModel& sharedModel, const IndividualModels& individualModels, const size_t* numberElementsPerIndividualModel, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const SharedModelIsValidCallback& sharedModelIsValidCallback, const SharedModelTransformationCallback& sharedModelTransformationCallback, const IndividualModelTransformationCallback& individualModelTransformationCallback, const ModelAcceptedCallback& modelAcceptedCallback, SharedModel& optimizedSharedModel, IndividualModels& optimizedIndividualModels, const unsigned int iterations, const Estimator::EstimatorType estimator, Scalar lambda, const Scalar lambdaFactor, Scalar* initialError, Scalar* finalError, Scalars* intermediateErrors)
1003{
1004 ocean_assert(&sharedModel != &optimizedSharedModel);
1005 ocean_assert(&individualModels != &optimizedIndividualModels);
1006
1007 optimizedSharedModel = sharedModel;
1008 optimizedIndividualModels = individualModels;
1009
1010 if (modelAcceptedCallback)
1011 {
1012 modelAcceptedCallback(sharedModel, individualModels);
1013 }
1014
1015 UniversalOptimizationProvider provider(optimizedSharedModel, optimizedIndividualModels, numberElementsPerIndividualModel, valueCallback, errorCallback, sharedModelIsValidCallback, sharedModelTransformationCallback, individualModelTransformationCallback, modelAcceptedCallback);
1016 return NonLinearOptimization::sparseOptimization<UniversalOptimizationProvider>(provider, iterations, estimator, lambda, lambdaFactor, initialError, finalError, nullptr, intermediateErrors);
1017}
1018
1019template <unsigned int tFirstModelSize, unsigned int tSecondModelSize, unsigned int tResultDimension, unsigned int tExternalFirstModelSize, unsigned int tExternalSecondModelSize>
1021 firstModels_(firstModels),
1022 secondModels_(secondModels),
1023 numberElementsPerSecondModel_(numberElementsPerSecondModel),
1024 overallNumberElements_(0),
1025 valueCallback_(valueCallback),
1026 errorCallback_(errorCallback),
1027 firstModelTransformationCallback_(firstModelTransformationCallback),
1028 secondModelTransformationCallback_(secondModelTransformationCallback),
1029 modelAcceptedCallback_(modelAcceptedCallback)
1030{
1031 ocean_assert(valueCallback_);
1032 ocean_assert(errorCallback_);
1035
1036 candidateFirstModels_ = firstModels;
1037 candidateSecondModels_ = secondModels;
1038
1039 // we need to know how many measurement values are provides as this number determines e.g., the size of the jacobian matrix etc.
1040 for (size_t n = 0; n < secondModels.size(); ++n)
1041 {
1043 }
1044};
1045
1046template <unsigned int tFirstModelSize, unsigned int tSecondModelSize, unsigned int tResultDimension, unsigned int tExternalFirstModelSize, unsigned int tExternalSecondModelSize>
1051
1052template <unsigned int tFirstModelSize, unsigned int tSecondModelSize, unsigned int tResultDimension, unsigned int tExternalFirstModelSize, unsigned int tExternalSecondModelSize>
1054{
1055 static_assert(tFirstModelSize >= 1u, "Invalid model size!");
1056 static_assert(tSecondModelSize >= 1u, "Invalid model size!");
1057
1058 ocean_assert(JTJ.rows() == JTJ.columns());
1059 ocean_assert(JTJ.rows() == jErrors.rows());
1060
1061 ocean_assert(jErrors.columns() == 1);
1062
1063 /**
1064 * here we apply the Schur complement to improve the solve performance:
1065 *
1066 * JTJ * deltas = jErrors
1067 * | A B | | da | | ea |
1068 * | C D | * | db | = | eb |
1069 *
1070 * (A - B D^-1 C ) * da = ea - B D^-1 * eb -> (solve da)
1071 * db = D^-1 (eb - C * da)
1072 *
1073 * or:
1074 * (D - C A^-1 B) * db = eb - C A^-1 * ea -> (solve db)
1075 * da = A^-1 (ea - B * db)
1076 */
1077
1078 // solving da:
1079
1080 const size_t sizeA = firstModels_.size() * tFirstModelSize;
1081 const size_t sizeB = JTJ.rows() - sizeA;
1082 ocean_assert(sizeB % tSecondModelSize == 0);
1083
1084 if (sizeA < sizeB)
1085 {
1086 SparseMatrix D(JTJ.submatrix(sizeA, sizeA, sizeB, sizeB));
1087
1088 switch (tSecondModelSize)
1089 {
1090 case 1u:
1091 if (!D.invertDiagonal())
1092 return false;
1093 break;
1094
1095 case 3u:
1096 if (!D.invertBlockDiagonal3())
1097 return false;
1098 break;
1099
1100 default:
1101 if (!D.invertBlockDiagonal(tSecondModelSize))
1102 return false;
1103 break;
1104 }
1105
1106 const SparseMatrix A(JTJ.submatrix(0, 0, sizeA, sizeA));
1107 const SparseMatrix B(JTJ.submatrix(0, sizeA, sizeA, sizeB));
1108 const SparseMatrix C(JTJ.submatrix(sizeA, 0, sizeB, sizeA));
1109
1110 const Matrix ea(sizeA, 1, jErrors.data());
1111 const Matrix eb(sizeB, 1, jErrors.data() + sizeA);
1112
1113 Matrix da;
1114 if (!(A - B * (D * C)).solve(ea - B * (D * eb), da))
1115 {
1116 return false;
1117 }
1118
1119 const Matrix db = D * (eb - C * da);
1120
1121 deltas.resize(jErrors.rows(), 1);
1122
1123 memcpy(deltas.data(), da.data(), sizeA * sizeof(Scalar));
1124 memcpy(deltas.data() + sizeA, db.data(), sizeB * sizeof(Scalar));
1125 }
1126 else
1127 {
1128 SparseMatrix A(JTJ.submatrix(0, 0, sizeA, sizeA));
1129
1130 switch (tFirstModelSize)
1131 {
1132 case 1u:
1133 if (!A.invertDiagonal())
1134 return false;
1135 break;
1136
1137 case 3u:
1138 if (!A.invertBlockDiagonal3())
1139 return false;
1140 break;
1141
1142 default:
1143 if (!A.invertBlockDiagonal(tFirstModelSize))
1144 return false;
1145 break;
1146 }
1147
1148 const SparseMatrix D(JTJ.submatrix(sizeA, sizeA, sizeB, sizeB));
1149 const SparseMatrix B(JTJ.submatrix(0, sizeA, sizeA, sizeB));
1150 const SparseMatrix C(JTJ.submatrix(sizeA, 0, sizeB, sizeA));
1151
1152 const Matrix ea(sizeA, 1, jErrors.data());
1153 const Matrix eb(sizeB, 1, jErrors.data() + sizeA);
1154
1155 Matrix db;
1156 if (!(D - C * (A * B)).solve(eb - C * (A * ea), db))
1157 {
1158 return false;
1159 }
1160
1161 const Matrix da = A * (ea - B * db);
1162
1163 deltas.resize(jErrors.rows(), 1);
1164
1165 memcpy(deltas.data(), da.data(), sizeA * sizeof(Scalar));
1166 memcpy(deltas.data() + sizeA, db.data(), sizeB * sizeof(Scalar));
1167 }
1168
1169#ifdef OCEAN_INTENSIVE_DEBUG
1170 const Matrix debugJErrors(JTJ * deltas);
1171 Scalars difference(jErrors.rows());
1172
1173 bool allWeakEps = true;
1174 Scalar averageDifference = 0;
1175 for (unsigned int n = 0u; n < jErrors.rows(); ++n)
1176 {
1177 difference[n] = debugJErrors(n, 0) - jErrors(n, 0);
1178
1179 averageDifference += Numeric::abs(difference[n]);
1180 }
1181
1182 ocean_assert(jErrors.rows() != 0);
1183 averageDifference /= Scalar(jErrors.rows());
1184
1185 // sometime event the average difference may not be weak-zero so that we do not check the value by default
1186 // ocean_assert(Numeric::isWeakEqualEps(averageDifference));
1187#endif
1188
1189 return true;
1190}
1191
1192template <unsigned int tFirstModelSize, unsigned int tSecondModelSize, unsigned int tResultDimension, unsigned int tExternalFirstModelSize, unsigned int tExternalSecondModelSize>
1194{
1195 ocean_assert(valueCallback_);
1196 ocean_assert(firstModelTransformationCallback_);
1197 ocean_assert(secondModelTransformationCallback_);
1198
1199 ocean_assert(overallNumberElements_ != 0);
1200
1201 SparseMatrix::Entries jacobianEntries;
1202 jacobianEntries.reserve(tResultDimension * overallNumberElements_ * (tFirstModelSize + tSecondModelSize));
1203
1204 const Scalar eps = Numeric::weakEps();
1205 const Scalar invEps = Scalar(1) / eps;
1206
1207 // for each model (we need to determine a slightly modified epsilon model) so that we can determine the jacobian matrix later
1208 // for each internal model:
1209 // - we determine the corresponding external model (without modifying the individual parameters)
1210 // - we modify each parameter and store the corresponding external sub-models (one external sub-model for each modified internal model parameter)
1211
1212 // the external (first) models (without modified parameters)
1213 ExternalFirstModels externalFirstModels(firstModels_.size());
1214 // the external (first) models (with modified (internal) parameters)
1215 StaticBuffer<ExternalFirstModels, tFirstModelSize> externalEpsFirstModels(tFirstModelSize, ExternalFirstModels(firstModels_.size()));
1216
1217 for (size_t i = 0; i < firstModels_.size(); ++i)
1218 {
1219 firstModelTransformationCallback_(firstModels_[i], externalFirstModels[i]);
1220
1221 for (size_t a = 0; a < tFirstModelSize; ++a)
1222 {
1223 FirstModel firstModel = firstModels_[i];
1224 firstModel[a] += eps;
1225
1226 firstModelTransformationCallback_(firstModel, externalEpsFirstModels[a][i]);
1227 }
1228 }
1229
1230 // the external (second) models (without modified parameters)
1231 ExternalSecondModels externalSecondModels(secondModels_.size());
1232 // the external (second models (with modified (internal) parameters)
1233 StaticBuffer<ExternalSecondModels, tSecondModelSize> externalEpsSecondModels(tSecondModelSize, ExternalSecondModels(secondModels_.size()));
1234
1235 for (size_t i = 0; i < secondModels_.size(); ++i)
1236 {
1237 secondModelTransformationCallback_(secondModels_[i], externalSecondModels[i]);
1238
1239 for (size_t a = 0; a < tSecondModelSize; ++a)
1240 {
1241 SecondModel secondModel = secondModels_[i];
1242 secondModel[a] += eps;
1243
1244 secondModelTransformationCallback_(secondModel, externalEpsSecondModels[a][i]);
1245 }
1246 }
1247
1248 // now we apply the individual external models and their corresponding modified external models to determine the jacobian matrix
1249
1250 Result result, epsResult;
1251 size_t row = 0;
1252
1255
1256 for (size_t i = 0; i < secondModels_.size(); ++i)
1257 {
1258 const size_t numberElements = numberElementsPerSecondModel_[i];
1259 const size_t columnSecond = tFirstModelSize * firstModels_.size() + i * tSecondModelSize;
1260
1261 for (size_t n = 0; n < numberElements; ++n)
1262 {
1263 // calculate the value for the current model
1264 const size_t firstModelIndex = valueCallback_(externalFirstModels, externalSecondModels, i, n, result);
1265 ocean_assert(firstModelIndex <= firstModels_.size());
1266
1267 // first model
1268 for (size_t m = 0; m < tFirstModelSize; ++m)
1269 {
1270 // calculate the value for the epsilon model
1271 const size_t checkModelIndex = valueCallback_(externalEpsFirstModels[m], externalSecondModels, i, n, epsResult);
1272 ocean_assert(checkModelIndex == firstModelIndex);
1273 OCEAN_SUPPRESS_UNUSED_WARNING(checkModelIndex);
1274
1275 // store the individual results
1276 for (size_t d = 0; d < tResultDimension; ++d)
1277 {
1278 firstModelResults[d * tFirstModelSize + m] = (epsResult[d] - result[d]) * invEps;
1279 }
1280 }
1281
1282 // second model
1283 for (size_t m = 0; m < tSecondModelSize; ++m)
1284 {
1285 // calculate the value for the epsilon model
1286 const size_t checkModelIndex = valueCallback_(externalFirstModels, externalEpsSecondModels[m], i, n, epsResult);
1287 ocean_assert(checkModelIndex == firstModelIndex);
1288 OCEAN_SUPPRESS_UNUSED_WARNING(checkModelIndex);
1289
1290 // store the individual results
1291 for (size_t d = 0; d < tResultDimension; ++d)
1292 {
1293 secondModelResults[d * tSecondModelSize + m] = (epsResult[d] - result[d]) * invEps;
1294 }
1295 }
1296
1297 const size_t columnFirst = firstModelIndex * tFirstModelSize;
1298
1299 for (size_t d = 0; d < tResultDimension; ++d)
1300 {
1301 for (size_t e = 0; e < tFirstModelSize; ++e)
1302 {
1303 jacobianEntries.emplace_back(row, columnFirst + e, firstModelResults.data()[d * tFirstModelSize + e]);
1304 }
1305
1306 for (size_t e = 0; e < tSecondModelSize; ++e)
1307 {
1308 jacobianEntries.emplace_back(row, columnSecond + e, secondModelResults.data()[d * tSecondModelSize + e]);
1309 }
1310
1311 row++;
1312 }
1313 }
1314 }
1315
1316 jacobian = SparseMatrix(tResultDimension * overallNumberElements_, tFirstModelSize * firstModels_.size() + tSecondModelSize * secondModels_.size(), jacobianEntries);
1317 ocean_assert(SparseMatrix::Entry::hasOneEntry(jacobian.rows(), jacobian.columns(), jacobianEntries));
1318 ocean_assert(row == jacobian.rows());
1319}
1320
1321template <unsigned int tFirstModelSize, unsigned int tSecondModelSize, unsigned int tResultDimension, unsigned int tExternalFirstModelSize, unsigned int tExternalSecondModelSize>
1323{
1324 ocean_assert(deltas.rows() == tFirstModelSize * firstModels_.size() + tSecondModelSize * secondModels_.size());
1325
1326 size_t index = 0;
1327
1328 // first models
1329 for (size_t i = 0; i < firstModels_.size(); ++i)
1330 {
1331 for (size_t m = 0; m < tFirstModelSize; ++m)
1332 {
1333 const Scalar& delta = deltas(index++);
1334 candidateFirstModels_[i][m] = firstModels_[i][m] - delta;
1335 }
1336 }
1337
1338 // second models
1339 for (size_t i = 0; i < secondModels_.size(); ++i)
1340 {
1341 for (size_t m = 0; m < tSecondModelSize; ++m)
1342 {
1343 const Scalar& delta = deltas(index++);
1344 candidateSecondModels_[i][m] = secondModels_[i][m] - delta;
1345 }
1346 }
1347}
1348
1349template <unsigned int tFirstModelSize, unsigned int tSecondModelSize, unsigned int tResultDimension, unsigned int tExternalFirstModelSize, unsigned int tExternalSecondModelSize>
1350template <Estimator::EstimatorType tEstimator>
1352{
1353 ocean_assert(valueCallback_);
1354 ocean_assert(firstModelTransformationCallback_);
1355 ocean_assert(secondModelTransformationCallback_);
1356
1357 OCEAN_SUPPRESS_UNUSED_WARNING(invertedCovariances);
1358 ocean_assert(invertedCovariances == nullptr);
1359 ocean_assert(overallNumberElements_ != 0);
1360
1361 // set the correct size of the resulting error vector
1362 weightedErrorVector.resize(overallNumberElements_ * tResultDimension, 1u);
1363 Result* const weightedErrors = (Result*)weightedErrorVector.data();
1364
1365 ExternalFirstModels externalFirstModels(firstModels_.size());
1366 for (size_t i = 0; i < firstModels_.size(); ++i)
1367 {
1368 firstModelTransformationCallback_(candidateFirstModels_[i], externalFirstModels[i]);
1369 }
1370
1371 ExternalSecondModels externalSecondModels(secondModels_.size());
1372 for (size_t i = 0; i < secondModels_.size(); ++i)
1373 {
1374 secondModelTransformationCallback_(candidateSecondModels_[i], externalSecondModels[i]);
1375 }
1376
1377 size_t index = 0;
1378 Scalar sqrError = 0;
1379 Scalars sqrErrors;
1380 if constexpr (!Estimator::isStandardEstimator<tEstimator>())
1381 {
1382 sqrErrors.reserve(overallNumberElements_);
1383 }
1384
1385 for (size_t i = 0; i < secondModels_.size(); ++i)
1386 {
1387 const size_t numberElements = numberElementsPerSecondModel_[i];
1388
1389 for (size_t n = 0; n < numberElements; ++n)
1390 {
1391 Result& weightedErrorPointer = *((Result*)weightedErrorVector.data() + index);
1392
1393 if (!errorCallback_(externalFirstModels, externalSecondModels, i, n, weightedErrorPointer))
1394 {
1395 return Numeric::maxValue();
1396 }
1397
1398 if constexpr (Estimator::isStandardEstimator<tEstimator>())
1399 {
1400 sqrError += Numeric::summedSqr(weightedErrorPointer.data(), tResultDimension);
1401 }
1402 else
1403 {
1404 ocean_assert(!Estimator::isStandardEstimator<tEstimator>());
1405 sqrErrors.emplace_back(Numeric::summedSqr(weightedErrorPointer.data(), tResultDimension));
1406 }
1407
1408 index++;
1409 }
1410 }
1411
1412 ocean_assert(index == overallNumberElements_);
1413 ocean_assert(index * 2 == weightedErrorVector.rows());
1414
1415 // check whether the standard estimator is used
1416 if constexpr (Estimator::isStandardEstimator<tEstimator>())
1417 {
1418 // the weight vector should be and should stay invalid
1419 ocean_assert(!weightVector);
1420
1421 ocean_assert((overallNumberElements_) > 0);
1422 return sqrError /= Scalar(overallNumberElements_);
1423 }
1424 else
1425 {
1426 // now we need the weight vector
1427 weightVector.resize(tResultDimension * overallNumberElements_, 1u);
1428
1429 return sqrErrors2robustErrors<tEstimator, tResultDimension>(sqrErrors, tFirstModelSize * firstModels_.size() + tSecondModelSize * secondModels_.size(), weightedErrors, (StaticBuffer<Scalar, tResultDimension>*)weightVector.data(), nullptr);
1430 }
1431}
1432
1433template <unsigned int tFirstModelSize, unsigned int tSecondModelSize, unsigned int tResultDimension, unsigned int tExternalFirstModelSize, unsigned int tExternalSecondModelSize>
1435{
1436 firstModels_ = candidateFirstModels_;
1437 secondModels_ = candidateSecondModels_;
1438
1439 if (modelAcceptedCallback_)
1440 {
1441 modelAcceptedCallback_(firstModels_, secondModels_);
1442 }
1443}
1444
1445template <unsigned int tFirstModelSize, unsigned int tSecondModelSize, unsigned int tResultDimension, unsigned int tExternalFirstModelSize, unsigned int tExternalSecondModelSize>
1446bool NonLinearUniversalOptimizationSparse::IndividualModelsIndividualModels<tFirstModelSize, tSecondModelSize, tResultDimension, tExternalFirstModelSize, tExternalSecondModelSize>::optimizeUniversalModel(const FirstModels& firstModels, const SecondModels& secondModels, const size_t* numberElementsPerSecondModel, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const FirstModelTransformationCallback& firstModelTransformationCallback, const SecondModelTransformationCallback& secondModelTransformationCallback, const ModelAcceptedCallback& modelAcceptedCallback, FirstModels& optimizedFirstModels, SecondModels& optimizedSecondModels, const unsigned int iterations, const Estimator::EstimatorType estimator, Scalar lambda, const Scalar lambdaFactor, Scalar* initialError, Scalar* finalError, Scalars* intermediateErrors)
1447{
1448 ocean_assert(&firstModels != &optimizedFirstModels);
1449 ocean_assert(&secondModels != &optimizedSecondModels);
1450
1451 optimizedFirstModels = firstModels;
1452 optimizedSecondModels = secondModels;
1453
1454 if (modelAcceptedCallback)
1455 {
1456 modelAcceptedCallback(firstModels, secondModels);
1457 }
1458
1459 UniversalOptimizationProvider provider(optimizedFirstModels, optimizedSecondModels, numberElementsPerSecondModel, valueCallback, errorCallback, firstModelTransformationCallback, secondModelTransformationCallback, modelAcceptedCallback);
1460 return NonLinearOptimization::sparseOptimization<UniversalOptimizationProvider>(provider, iterations, estimator, lambda, lambdaFactor, initialError, finalError, nullptr, intermediateErrors);
1461}
1462
1463template <unsigned int tSharedModelSize, unsigned int tFirstIndividualModelSize, unsigned int tSecondIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalFirstIndividualModelSize, unsigned int tExternalSecondIndividualModelSize>
1465 sharedModel_(sharedModel),
1466 firstIndividualModels_(firstIndividualModels),
1467 secondIndividualModels_(secondIndividualModels),
1468 numberElementsPerSecondModel_(numberElementsPerSecondModel),
1469 overallNumberElements_(0),
1470 valueCallback_(valueCallback),
1471 errorCallback_(errorCallback),
1472 sharedModelIsValidCallback_(sharedModelIsValidCallback),
1473 sharedModelTransformationCallback_(sharedModelTransformationCallback),
1474 firstIndividualModelTransformationCallback_(firstIndividualModelTransformationCallback),
1475 secondIndividualModelTransformationCallback_(secondIndividualModelTransformationCallback),
1476 modelAcceptedCallback_(modelAcceptedCallback)
1477{
1478 ocean_assert(valueCallback_);
1479 ocean_assert(errorCallback_);
1483
1484 candidateSharedModel_ = sharedModel;
1485 candidateFirstIndividualModels_ = firstIndividualModels;
1486 candidateSecondIndividualModels_ = secondIndividualModels;
1487
1488 // we need to know how many measurement values are provides as this number determines e.g., the size of the jacobian matrix etc.
1489 for (size_t n = 0; n < secondIndividualModels.size(); ++n)
1490 {
1492 }
1493};
1494
1495template <unsigned int tSharedModelSize, unsigned int tFirstIndividualModelSize, unsigned int tSecondIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalFirstIndividualModelSize, unsigned int tExternalSecondIndividualModelSize>
1497{
1498 ocean_assert(valueCallback_);
1499 ocean_assert(sharedModelTransformationCallback_);
1500 ocean_assert(firstIndividualModelTransformationCallback_);
1501 ocean_assert(secondIndividualModelTransformationCallback_);
1502
1503 ocean_assert(overallNumberElements_ != 0);
1504
1505 SparseMatrix::Entries jacobianEntries;
1506 jacobianEntries.reserve(tResultDimension * overallNumberElements_ * (tSharedModelSize + tFirstIndividualModelSize + tSecondIndividualModelSize));
1507
1508 const Scalar eps = Numeric::weakEps();
1509 const Scalar invEps = Scalar(1) / eps;
1510
1511 // for each model (we need to determine a slightly modified epsilon model) so that we can determine the jacobian matrix later
1512 // for each internal model:
1513 // - we determine the corresponding external model (without modifying the individual parameters)
1514 // - we modify each parameter and store the corresponding external sub-models (one external sub-model for each modified internal model parameter)
1515
1516 // the external shared model (without modified parameter)
1517 ExternalSharedModel externalSharedModel;
1518 // the external shared model (with modified (internal) parameters)
1520
1521 sharedModelTransformationCallback_(sharedModel_, externalSharedModel);
1522 for (size_t a = 0; a < tSharedModelSize; ++a)
1523 {
1524 SharedModel internalModel = sharedModel_;
1525 internalModel[a] += eps;
1526
1527 sharedModelTransformationCallback_(internalModel, externalEpsSharedModels[a]);
1528 }
1529
1530 // the external (first) individual models (without modified parameters)
1531 ExternalFirstIndividualModels externalFirstIndividualModels(firstIndividualModels_.size());
1532 // the external (first) individual models (with modified (internal) parameters)
1533 StaticBuffer<ExternalFirstIndividualModels, tFirstIndividualModelSize> externalEpsFirstIndividualModels(tFirstIndividualModelSize, ExternalFirstIndividualModels(firstIndividualModels_.size()));
1534
1535 for (size_t i = 0; i < firstIndividualModels_.size(); ++i)
1536 {
1537 firstIndividualModelTransformationCallback_(firstIndividualModels_[i], externalFirstIndividualModels[i]);
1538
1539 for (size_t a = 0; a < tFirstIndividualModelSize; ++a)
1540 {
1541 FirstIndividualModel firstIndividualModel = firstIndividualModels_[i];
1542 firstIndividualModel[a] += eps;
1543
1544 firstIndividualModelTransformationCallback_(firstIndividualModel, externalEpsFirstIndividualModels[a][i]);
1545 }
1546 }
1547
1548 // the external (second) individual models (without modified parameters)
1549 ExternalSecondIndividualModels externalSecondIndividualModels(secondIndividualModels_.size());
1550 // the external (second) individual models (with modified (internal) parameters)
1551 StaticBuffer<ExternalSecondIndividualModels, tSecondIndividualModelSize> externalEpsSecondIndividualModels(tSecondIndividualModelSize, ExternalSecondIndividualModels(secondIndividualModels_.size()));
1552
1553 for (size_t i = 0; i < secondIndividualModels_.size(); ++i)
1554 {
1555 secondIndividualModelTransformationCallback_(secondIndividualModels_[i], externalSecondIndividualModels[i]);
1556
1557 for (size_t a = 0; a < tSecondIndividualModelSize; ++a)
1558 {
1559 SecondIndividualModel secondIndividualModel = secondIndividualModels_[i];
1560 secondIndividualModel[a] += eps;
1561
1562 secondIndividualModelTransformationCallback_(secondIndividualModel, externalEpsSecondIndividualModels[a][i]);
1563 }
1564 }
1565
1566 // now we apply the shared external model and the individual external models and their corresponding modified external models to determine the jacobian matrix
1567
1568 Result result, epsResult;
1569 size_t row = 0;
1570
1574
1575 for (size_t i = 0; i < secondIndividualModels_.size(); ++i)
1576 {
1577 const size_t numberElements = numberElementsPerSecondModel_[i];
1578 const size_t columnSecond = tSharedModelSize + tFirstIndividualModelSize * firstIndividualModels_.size() + i * tSecondIndividualModelSize;
1579
1580 for (size_t n = 0; n < numberElements; ++n)
1581 {
1582 // calculate the value for the current model
1583 const size_t firstIndividualModelIndex = valueCallback_(externalSharedModel, externalFirstIndividualModels, externalSecondIndividualModels, i, n, result);
1584 ocean_assert(firstIndividualModelIndex <= firstIndividualModels_.size());
1585
1586 // shared model
1587 for (size_t m = 0; m < tSharedModelSize; ++m)
1588 {
1589 // calculate the value for the epsilon model
1590 const size_t checkModelIndex = valueCallback_(externalEpsSharedModels[m], externalFirstIndividualModels, externalSecondIndividualModels, i, n, epsResult);
1591 ocean_assert(checkModelIndex == firstIndividualModelIndex);
1592 OCEAN_SUPPRESS_UNUSED_WARNING(checkModelIndex);
1593
1594 // store the individual results
1595 for (size_t d = 0; d < tResultDimension; ++d)
1596 {
1597 sharedModelResults[d * tSharedModelSize + m] = (epsResult[d] - result[d]) * invEps;
1598 }
1599 }
1600
1601 // first individual model
1602 for (size_t m = 0; m < tFirstIndividualModelSize; ++m)
1603 {
1604 // calculate the value for the epsilon model
1605 const size_t checkModelIndex = valueCallback_(externalSharedModel, externalEpsFirstIndividualModels[m], externalSecondIndividualModels, i, n, epsResult);
1606 ocean_assert(checkModelIndex == firstIndividualModelIndex);
1607 OCEAN_SUPPRESS_UNUSED_WARNING(checkModelIndex);
1608
1609 // store the individual results
1610 for (size_t d = 0; d < tResultDimension; ++d)
1611 {
1612 firstIndividualModelResults[d * tFirstIndividualModelSize + m] = (epsResult[d] - result[d]) * invEps;
1613 }
1614 }
1615
1616 // second individual model
1617 for (size_t m = 0; m < tSecondIndividualModelSize; ++m)
1618 {
1619 // calculate the value for the epsilon model
1620 const size_t checkModelIndex = valueCallback_(externalSharedModel, externalFirstIndividualModels, externalEpsSecondIndividualModels[m], i, n, epsResult);
1621 ocean_assert(checkModelIndex == firstIndividualModelIndex);
1622 OCEAN_SUPPRESS_UNUSED_WARNING(checkModelIndex);
1623
1624 // store the individual results
1625 for (size_t d = 0; d < tResultDimension; ++d)
1626 {
1627 secondIndividualModelResults[d * tSecondIndividualModelSize + m] = (epsResult[d] - result[d]) * invEps;
1628 }
1629 }
1630
1631 const size_t columnFirst = tSharedModelSize + firstIndividualModelIndex * tFirstIndividualModelSize;
1632
1633 for (size_t d = 0; d < tResultDimension; ++d)
1634 {
1635 for (size_t e = 0; e < tSharedModelSize; ++e)
1636 {
1637 jacobianEntries.emplace_back(row, e, sharedModelResults.data()[d * tSharedModelSize + e]);
1638 }
1639
1640 for (size_t e = 0; e < tFirstIndividualModelSize; ++e)
1641 {
1642 jacobianEntries.emplace_back(row, columnFirst + e, firstIndividualModelResults.data()[d * tFirstIndividualModelSize + e]);
1643 }
1644
1645 for (size_t e = 0; e < tSecondIndividualModelSize; ++e)
1646 {
1647 jacobianEntries.emplace_back(row, columnSecond + e, secondIndividualModelResults.data()[d * tSecondIndividualModelSize + e]);
1648 }
1649
1650 row++;
1651 }
1652 }
1653 }
1654
1655 jacobian = SparseMatrix(tResultDimension * overallNumberElements_, tSharedModelSize + tFirstIndividualModelSize * firstIndividualModels_.size() + tSecondIndividualModelSize * secondIndividualModels_.size(), jacobianEntries);
1656 ocean_assert(SparseMatrix::Entry::hasOneEntry(jacobian.rows(), jacobian.columns(), jacobianEntries));
1657 ocean_assert(row == jacobian.rows());
1658}
1659
1660template <unsigned int tSharedModelSize, unsigned int tFirstIndividualModelSize, unsigned int tSecondIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalFirstIndividualModelSize, unsigned int tExternalSecondIndividualModelSize>
1662{
1663 ocean_assert(deltas.rows() == tSharedModelSize + tFirstIndividualModelSize * firstIndividualModels_.size() + tSecondIndividualModelSize * secondIndividualModels_.size());
1664
1665 size_t index = 0;
1666
1667 // shared model
1668 for (size_t m = 0; m < tSharedModelSize; ++m)
1669 {
1670 const Scalar& delta = deltas(index++);
1671 candidateSharedModel_[m] = sharedModel_[m] - delta;
1672 }
1673
1674 // first individual models
1675 for (size_t i = 0; i < firstIndividualModels_.size(); ++i)
1676 {
1677 for (size_t m = 0; m < tFirstIndividualModelSize; ++m)
1678 {
1679 const Scalar& delta = deltas(index++);
1680 candidateFirstIndividualModels_[i][m] = firstIndividualModels_[i][m] - delta;
1681 }
1682 }
1683
1684 // second individual models
1685 for (size_t i = 0; i < secondIndividualModels_.size(); ++i)
1686 {
1687 for (size_t m = 0; m < tSecondIndividualModelSize; ++m)
1688 {
1689 const Scalar& delta = deltas(index++);
1690 candidateSecondIndividualModels_[i][m] = secondIndividualModels_[i][m] - delta;
1691 }
1692 }
1693}
1694
1695template <unsigned int tSharedModelSize, unsigned int tFirstIndividualModelSize, unsigned int tSecondIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalFirstIndividualModelSize, unsigned int tExternalSecondIndividualModelSize>
1696template <Estimator::EstimatorType tEstimator>
1698{
1699 ocean_assert(valueCallback_);
1700 ocean_assert(sharedModelTransformationCallback_);
1701 ocean_assert(firstIndividualModelTransformationCallback_);
1702 ocean_assert(secondIndividualModelTransformationCallback_);
1703
1704 OCEAN_SUPPRESS_UNUSED_WARNING(invertedCovariances);
1705 ocean_assert(invertedCovariances == nullptr);
1706 ocean_assert(overallNumberElements_ != 0);
1707
1708 ExternalSharedModel externalSharedModel;
1709 sharedModelTransformationCallback_(candidateSharedModel_, externalSharedModel);
1710
1711 // check whether we can stop here as we do not have a valid shared model (and the provider supports to decide that)
1712 if (sharedModelIsValidCallback_ && !sharedModelIsValidCallback_(externalSharedModel))
1713 {
1714 return Numeric::maxValue();
1715 }
1716
1717 // set the correct size of the resulting error vector
1718 weightedErrorVector.resize(overallNumberElements_ * tResultDimension, 1u);
1719 Result* const weightedErrors = (Result*)weightedErrorVector.data();
1720
1721 ExternalFirstIndividualModels externalFirstIndividualModels(firstIndividualModels_.size());
1722 for (size_t i = 0; i < firstIndividualModels_.size(); ++i)
1723 {
1724 firstIndividualModelTransformationCallback_(candidateFirstIndividualModels_[i], externalFirstIndividualModels[i]);
1725 }
1726
1727 ExternalSecondIndividualModels externalSecondIndividualModels(secondIndividualModels_.size());
1728 for (size_t i = 0; i < secondIndividualModels_.size(); ++i)
1729 {
1730 secondIndividualModelTransformationCallback_(candidateSecondIndividualModels_[i], externalSecondIndividualModels[i]);
1731 }
1732
1733 size_t index = 0;
1734 Scalar sqrError = 0;
1735 Scalars sqrErrors;
1736 if constexpr (!Estimator::isStandardEstimator<tEstimator>())
1737 {
1738 sqrErrors.reserve(overallNumberElements_);
1739 }
1740
1741 for (size_t i = 0; i < secondIndividualModels_.size(); ++i)
1742 {
1743 const size_t numberElements = numberElementsPerSecondModel_[i];
1744
1745 for (size_t n = 0; n < numberElements; ++n)
1746 {
1747 Result& weightedErrorPointer = *((Result*)weightedErrorVector.data() + index);
1748
1749 if (!errorCallback_(externalSharedModel, externalFirstIndividualModels, externalSecondIndividualModels, i, n, weightedErrorPointer))
1750 {
1751 return Numeric::maxValue();
1752 }
1753
1754 if constexpr (Estimator::isStandardEstimator<tEstimator>())
1755 {
1756 sqrError += Numeric::summedSqr(weightedErrorPointer.data(), tResultDimension);
1757 }
1758 else
1759 {
1760 ocean_assert(!Estimator::isStandardEstimator<tEstimator>());
1761 sqrErrors.emplace_back(Numeric::summedSqr(weightedErrorPointer.data(), tResultDimension));
1762 }
1763
1764 index++;
1765 }
1766 }
1767
1768 ocean_assert(index == overallNumberElements_);
1769 ocean_assert(index * 2 == weightedErrorVector.rows());
1770
1771 // check whether the standard estimator is used
1772 if constexpr (Estimator::isStandardEstimator<tEstimator>())
1773 {
1774 // the weight vector should be and should stay invalid
1775 ocean_assert(!weightVector);
1776
1777 ocean_assert((overallNumberElements_) > 0);
1778 return sqrError /= Scalar(overallNumberElements_);
1779 }
1780 else
1781 {
1782 // now we need the weight vector
1783 weightVector.resize(tResultDimension * overallNumberElements_, 1u);
1784
1785 return sqrErrors2robustErrors<tEstimator, tResultDimension>(sqrErrors, tSharedModelSize + tFirstIndividualModelSize * firstIndividualModels_.size() + tSecondIndividualModelSize * secondIndividualModels_.size(), weightedErrors, (StaticBuffer<Scalar, tResultDimension>*)weightVector.data(), nullptr);
1786 }
1787}
1788
1789template <unsigned int tSharedModelSize, unsigned int tFirstIndividualModelSize, unsigned int tSecondIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalFirstIndividualModelSize, unsigned int tExternalSecondIndividualModelSize>
1791{
1792 sharedModel_ = candidateSharedModel_;
1793 firstIndividualModels_ = candidateFirstIndividualModels_;
1794 secondIndividualModels_ = candidateSecondIndividualModels_;
1795
1796 if (modelAcceptedCallback_)
1797 {
1798 modelAcceptedCallback_(sharedModel_, firstIndividualModels_, secondIndividualModels_);
1799 }
1800}
1801
1802template <unsigned int tSharedModelSize, unsigned int tFirstIndividualModelSize, unsigned int tSecondIndividualModelSize, unsigned int tResultDimension, unsigned int tExternalSharedModelSize, unsigned int tExternalFirstIndividualModelSize, unsigned int tExternalSecondIndividualModelSize>
1803bool NonLinearUniversalOptimizationSparse::SharedModelIndividualModelsIndividualModels<tSharedModelSize, tFirstIndividualModelSize, tSecondIndividualModelSize, tResultDimension, tExternalSharedModelSize, tExternalFirstIndividualModelSize, tExternalSecondIndividualModelSize>::optimizeUniversalModel(const SharedModel& sharedModel, const FirstIndividualModels& firstIndividualModels, const SecondIndividualModels& secondIndividualModels, const size_t* numberElementsPerSecondModel, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const SharedModelIsValidCallback& sharedModelIsValidCallback, const SharedModelTransformationCallback& sharedModelTransformationCallback, const FirstIndividualModelTransformationCallback& firstIndividualModelTransformationCallback, const SecondIndividualModelTransformationCallback& secondIndividualModelTransformationCallback, const ModelAcceptedCallback& modelAcceptedCallback, SharedModel& optimizedSharedModel, FirstIndividualModels& optimizedFirstIndividualModels, SecondIndividualModels& optimizedSecondIndividualModels, const unsigned int iterations, const Estimator::EstimatorType estimator, Scalar lambda, const Scalar lambdaFactor, Scalar* initialError, Scalar* finalError, Scalars* intermediateErrors)
1804{
1805 ocean_assert(&sharedModel != &optimizedSharedModel);
1806 ocean_assert(&firstIndividualModels != &optimizedFirstIndividualModels);
1807 ocean_assert(&secondIndividualModels != &optimizedSecondIndividualModels);
1808
1809 optimizedSharedModel = sharedModel;
1810 optimizedFirstIndividualModels = firstIndividualModels;
1811 optimizedSecondIndividualModels = secondIndividualModels;
1812
1813 if (modelAcceptedCallback)
1814 {
1815 modelAcceptedCallback(sharedModel, firstIndividualModels, secondIndividualModels);
1816 }
1817
1818 UniversalOptimizationProvider provider(optimizedSharedModel, optimizedFirstIndividualModels, optimizedSecondIndividualModels, numberElementsPerSecondModel, valueCallback, errorCallback, sharedModelIsValidCallback, sharedModelTransformationCallback, firstIndividualModelTransformationCallback, secondIndividualModelTransformationCallback, modelAcceptedCallback);
1819 return NonLinearOptimization::sparseOptimization<UniversalOptimizationProvider>(provider, iterations, estimator, lambda, lambdaFactor, initialError, finalError, nullptr, intermediateErrors);
1820}
1821
1822}
1823
1824}
1825
1826#endif // META_OCEAN_GEOMETRY_NON_LINEAR_UNIVERSAL_OPTIMIZATION_SPARSE_H
This class implements a container for callback functions.
Definition Callback.h:3456
EstimatorType
Definition of individual robust estimator types.
Definition Estimator.h:34
@ ET_SQUARE
The standard square error estimator (L2).
Definition Estimator.h:52
This class implements the base optimization provider.
Definition NonLinearOptimization.h:293
This class implements the basic functions for least square or robust optimization algorithms for non ...
Definition NonLinearOptimization.h:34
This class implements a sparse universal optimization provider for universal models and measurement/d...
Definition NonLinearUniversalOptimizationSparse.h:354
void determineJacobian(SparseMatrix &jacobian) const
Determines the jacobian matrix for the current model.
Definition NonLinearUniversalOptimizationSparse.h:1193
FirstModels candidateFirstModels_
The universal first models storing the most recent optimization results as candidates.
Definition NonLinearUniversalOptimizationSparse.h:422
const ModelAcceptedCallback modelAcceptedCallback_
Optional callback function allowing to be informed whenever the model has been improved.
Definition NonLinearUniversalOptimizationSparse.h:446
size_t overallNumberElements_
The overall number of measurement elements that are used to optimize the models.
Definition NonLinearUniversalOptimizationSparse.h:431
SecondModels & secondModels_
The universal second models that will be optimized.
Definition NonLinearUniversalOptimizationSparse.h:419
const size_t * numberElementsPerSecondModel_
The number of measurement elements for each second model.
Definition NonLinearUniversalOptimizationSparse.h:428
const FirstModelTransformationCallback firstModelTransformationCallback_
The callback function allowing to transform the first model into an external model before the value a...
Definition NonLinearUniversalOptimizationSparse.h:440
void applyCorrection(const Matrix &deltas)
Applies the model correction and stores the new model(s) as candidate.
Definition NonLinearUniversalOptimizationSparse.h:1322
Scalar determineRobustError(Matrix &weightedErrorVector, Matrix &weightVector, const Matrix *invertedCovariances) const
Determines the robust error of the current candidate model(s).
Definition NonLinearUniversalOptimizationSparse.h:1351
FirstModels & firstModels_
The universal first models that will be optimized.
Definition NonLinearUniversalOptimizationSparse.h:416
bool solve(const SparseMatrix &JTJ, const Matrix &jErrors, Matrix &deltas) const
Solves the equation JTJ * deltas = jErrors.
Definition NonLinearUniversalOptimizationSparse.h:1053
void acceptCorrection()
Accepts the current model candidate as better model.
Definition NonLinearUniversalOptimizationSparse.h:1434
UniversalOptimizationProvider(FirstModels &firstModels, SecondModels &secondModels, const size_t *numberElementsPerSecondModel, const ValueCallback &valueCallback, const ErrorCallback &errorCallback, const FirstModelTransformationCallback &firstModelTransformationCallback, const SecondModelTransformationCallback &secondModelTransformationCallback, const ModelAcceptedCallback &modelAcceptedCallback=ModelAcceptedCallback())
Creates a new universal optimization object.
Definition NonLinearUniversalOptimizationSparse.h:1020
bool hasSolver() const
Returns that this provider comes with an own equation solver.
Definition NonLinearUniversalOptimizationSparse.h:1047
const ErrorCallback errorCallback_
The error calculation callback function.
Definition NonLinearUniversalOptimizationSparse.h:437
const ValueCallback valueCallback_
The value calculation callback function.
Definition NonLinearUniversalOptimizationSparse.h:434
const SecondModelTransformationCallback secondModelTransformationCallback_
The callback function allowing to transform the second model into an external model before the value ...
Definition NonLinearUniversalOptimizationSparse.h:443
SecondModels candidateSecondModels_
The universal second models storing the most recent optimization results as candidates.
Definition NonLinearUniversalOptimizationSparse.h:425
This class implements an optimization for universal sparse problems with two types of individual mode...
Definition NonLinearUniversalOptimizationSparse.h:256
StaticBuffer< Scalar, tExternalFirstModelSize > ExternalFirstModel
Definition of the external first model.
Definition NonLinearUniversalOptimizationSparse.h:267
std::vector< FirstModel > FirstModels
Definition of a vector holding the first models.
Definition NonLinearUniversalOptimizationSparse.h:287
Callback< void, SecondModel &, ExternalSecondModel & > SecondModelTransformationCallback
Definition of a second model transformation function.
Definition NonLinearUniversalOptimizationSparse.h:339
StaticBuffer< Scalar, tExternalSecondModelSize > ExternalSecondModel
Definition of the external second model.
Definition NonLinearUniversalOptimizationSparse.h:277
static bool optimizeUniversalModel(const FirstModels &firstModels, const SecondModels &secondModels, const size_t *numberElementsPerSecondModel, const ValueCallback &valueCallback, const ErrorCallback &errorCallback, const FirstModelTransformationCallback &firstModelTransformationCallback, const SecondModelTransformationCallback &secondModelTransformationCallback, const ModelAcceptedCallback &modelAcceptedCallback, FirstModels &optimizedFirstModels, SecondModels &optimizedSecondModels, const unsigned int iterations=5u, const Estimator::EstimatorType estimator=Estimator::ET_SQUARE, Scalar lambda=Scalar(0.001), const Scalar lambdaFactor=Scalar(5), Scalar *initialError=nullptr, Scalar *finalError=nullptr, Scalars *intermediateErrors=nullptr)
Optimizes a universal model by minimizing the error the model produces.
Definition NonLinearUniversalOptimizationSparse.h:1446
StaticBuffer< Scalar, tFirstModelSize > FirstModel
Definition of the first model.
Definition NonLinearUniversalOptimizationSparse.h:262
std::vector< ExternalSecondModel > ExternalSecondModels
Definition of a vector holding the external second models.
Definition NonLinearUniversalOptimizationSparse.h:302
std::vector< ExternalFirstModel > ExternalFirstModels
Definition of a vector holding the external first models.
Definition NonLinearUniversalOptimizationSparse.h:292
Callback< bool, const ExternalFirstModels &, const ExternalSecondModels &, const size_t, const size_t, Result & > ErrorCallback
Definition of a callback function for sparse error calculation.
Definition NonLinearUniversalOptimizationSparse.h:323
Callback< void, const FirstModels &, const SecondModels & > ModelAcceptedCallback
Definition of a model accepted function.
Definition NonLinearUniversalOptimizationSparse.h:346
Callback< void, FirstModel &, ExternalFirstModel & > FirstModelTransformationCallback
Definition of a first model transformation function.
Definition NonLinearUniversalOptimizationSparse.h:331
StaticBuffer< Scalar, tSecondModelSize > SecondModel
Definition of the second model.
Definition NonLinearUniversalOptimizationSparse.h:272
StaticBuffer< Scalar, tResultDimension > Result
Definition of a model result.
Definition NonLinearUniversalOptimizationSparse.h:282
Callback< size_t, const ExternalFirstModels &, const ExternalSecondModels &, const size_t, const size_t, Result & > ValueCallback
Definition of a callback function for sparse value calculation.
Definition NonLinearUniversalOptimizationSparse.h:313
std::vector< SecondModel > SecondModels
Definition of a vector holding the first models.
Definition NonLinearUniversalOptimizationSparse.h:297
This class implements a sparse universal optimization provider for universal models and measurement/d...
Definition NonLinearUniversalOptimizationSparse.h:614
const SharedModelIsValidCallback sharedModelIsValidCallback_
The callback function determining whether a shared model is valid.
Definition NonLinearUniversalOptimizationSparse.h:694
SharedModel & sharedModel_
The universal shared model that will be optimized.
Definition NonLinearUniversalOptimizationSparse.h:664
const ValueCallback valueCallback_
The value calculation callback function.
Definition NonLinearUniversalOptimizationSparse.h:688
SecondIndividualModels & secondIndividualModels_
The universal second individual models that will be optimized.
Definition NonLinearUniversalOptimizationSparse.h:670
const ModelAcceptedCallback modelAcceptedCallback_
Optional callback function allowing to be informed whenever the model has been improved.
Definition NonLinearUniversalOptimizationSparse.h:706
Scalar determineRobustError(Matrix &weightedErrorVector, Matrix &weightVector, const Matrix *invertedCovariances) const
Determines the robust error of the current candidate model(s).
Definition NonLinearUniversalOptimizationSparse.h:1697
void acceptCorrection()
Accepts the current model candidate as better model.
Definition NonLinearUniversalOptimizationSparse.h:1790
const SharedModelTransformationCallback sharedModelTransformationCallback_
The callback function allowing to transform the shared model into an external model before the value ...
Definition NonLinearUniversalOptimizationSparse.h:697
SecondIndividualModels candidateSecondIndividualModels_
The universal second individual models storing the most recent optimization results as candidates.
Definition NonLinearUniversalOptimizationSparse.h:679
void applyCorrection(const Matrix &deltas)
Applies the model correction and stores the new model(s) as candidate.
Definition NonLinearUniversalOptimizationSparse.h:1661
FirstIndividualModels & firstIndividualModels_
The universal first individual models that will be optimized.
Definition NonLinearUniversalOptimizationSparse.h:667
const SecondIndividualModelTransformationCallback secondIndividualModelTransformationCallback_
The callback function allowing to transform the second model into an external model before the value ...
Definition NonLinearUniversalOptimizationSparse.h:703
const ErrorCallback errorCallback_
The error calculation callback function.
Definition NonLinearUniversalOptimizationSparse.h:691
UniversalOptimizationProvider(SharedModel &sharedModel, FirstIndividualModels &firstIndividualModels, SecondIndividualModels &secondIndividualModels, const size_t *numberElementsPerSecondModel, const ValueCallback &valueCallback, const ErrorCallback &errorCallback, const SharedModelIsValidCallback &sharedModelIsValidCallback, const SharedModelTransformationCallback &sharedModelTransformationCallback, const FirstIndividualModelTransformationCallback &firstIndividualModelTransformationCallback, const SecondIndividualModelTransformationCallback &secondIndividualModelTransformationCallback, const ModelAcceptedCallback &modelAcceptedCallback=ModelAcceptedCallback())
Creates a new universal optimization object.
Definition NonLinearUniversalOptimizationSparse.h:1464
const size_t * numberElementsPerSecondModel_
The number of measurement elements for each second model.
Definition NonLinearUniversalOptimizationSparse.h:682
SharedModel candidateSharedModel_
The universal shared model storing the most recent optimization result as candidate.
Definition NonLinearUniversalOptimizationSparse.h:673
void determineJacobian(SparseMatrix &jacobian) const
Determines the jacobian matrix for the current model.
Definition NonLinearUniversalOptimizationSparse.h:1496
const FirstIndividualModelTransformationCallback firstIndividualModelTransformationCallback_
The callback function allowing to transform the first individual model into an external model before ...
Definition NonLinearUniversalOptimizationSparse.h:700
FirstIndividualModels candidateFirstIndividualModels_
The universal first individual models storing the most recent optimization results as candidates.
Definition NonLinearUniversalOptimizationSparse.h:676
size_t overallNumberElements_
The overall number of measurement elements that are used to optimize the models.
Definition NonLinearUniversalOptimizationSparse.h:685
This class implements a sparse universal optimization provider for universal models and measurement/d...
Definition NonLinearUniversalOptimizationSparse.h:134
SharedModel candidateSharedModel_
Universal shared model that stores the most recent optimization result as candidate.
Definition NonLinearUniversalOptimizationSparse.h:188
IndividualModels candidateIndividualModels_
Universal individual model that stores the most recent optimization result as candidate.
Definition NonLinearUniversalOptimizationSparse.h:191
size_t overallNumberElements_
The overall number of measurement elements that are used to optimize the models.
Definition NonLinearUniversalOptimizationSparse.h:197
const ModelAcceptedCallback modelAcceptedCallback_
Optional callback function allowing to be informed whenever the model has been improved.
Definition NonLinearUniversalOptimizationSparse.h:215
IndividualModels & individualModels_
Universal individual model that will be optimized.
Definition NonLinearUniversalOptimizationSparse.h:185
Scalar determineRobustError(Matrix &weightedErrorVector, Matrix &weightVector, const Matrix *invertedCovariances) const
Determines the robust error of the current candidate model(s).
Definition NonLinearUniversalOptimizationSparse.h:904
void determineJacobian(SparseMatrix &jacobian) const
Determines the jacobian matrix for the current model.
Definition NonLinearUniversalOptimizationSparse.h:768
void applyCorrection(const Matrix &deltas)
Applies the model correction and stores the new model(s) as candidate.
Definition NonLinearUniversalOptimizationSparse.h:880
const IndividualModelTransformationCallback individualModelTransformationCallback_
The callback function allowing to transform the individual model into an external model before the va...
Definition NonLinearUniversalOptimizationSparse.h:212
const size_t * numberElementsPerIndividualModel_
The number of measurement elements that are used to optimize each individual model.
Definition NonLinearUniversalOptimizationSparse.h:194
const SharedModelTransformationCallback sharedModelTransformationCallback_
The callback function allowing to transform the shared model into an external model before the value ...
Definition NonLinearUniversalOptimizationSparse.h:209
SharedModel & sharedModel_
Universal shared model that will be optimized.
Definition NonLinearUniversalOptimizationSparse.h:182
const ValueCallback valueCallback_
The value calculation callback function.
Definition NonLinearUniversalOptimizationSparse.h:200
const ErrorCallback errorCallback_
The error calculation callback function.
Definition NonLinearUniversalOptimizationSparse.h:203
void acceptCorrection()
Accepts the current model candidate as better model.
Definition NonLinearUniversalOptimizationSparse.h:990
const SharedModelIsValidCallback sharedModelIsValidCallback_
The callback function determining whether a shared model is valid.
Definition NonLinearUniversalOptimizationSparse.h:206
UniversalOptimizationProvider(SharedModel &sharedModel, IndividualModels &individualModels, const size_t *numberElementsPerIndividualModel, const ValueCallback &valueCallback, const ErrorCallback &errorCallback, const SharedModelIsValidCallback &sharedModelIsValidCallback, const SharedModelTransformationCallback &sharedModelTransformationCallback, const IndividualModelTransformationCallback &individualModelTransformationCallback, const ModelAcceptedCallback &modelAcceptedCallback=ModelAcceptedCallback())
Creates a new universal optimization object.
Definition NonLinearUniversalOptimizationSparse.h:741
This class implements an optimization for universal sparse problems with one shared model (optimizati...
Definition NonLinearUniversalOptimizationSparse.h:39
Callback< bool, const ExternalSharedModel &, const ExternalIndividualModel &, const size_t, const size_t, Result & > ErrorCallback
Definition of a callback function for sparse error calculation.
Definition NonLinearUniversalOptimizationSparse.h:91
StaticBuffer< Scalar, tExternalIndividualModelSize > ExternalIndividualModel
Definition of an external individual model.
Definition NonLinearUniversalOptimizationSparse.h:60
StaticBuffer< Scalar, tIndividualModelSize > IndividualModel
Definition of an individual model.
Definition NonLinearUniversalOptimizationSparse.h:55
StaticBuffer< Scalar, tExternalSharedModelSize > ExternalSharedModel
Definition of an external shared model.
Definition NonLinearUniversalOptimizationSparse.h:50
std::vector< IndividualModel > IndividualModels
Definition of a vector holding individual models.
Definition NonLinearUniversalOptimizationSparse.h:70
std::vector< ExternalIndividualModel > ExternalIndividualModels
Definition of a vector holding individual models.
Definition NonLinearUniversalOptimizationSparse.h:128
Callback< void, const SharedModel &, const IndividualModels & > ModelAcceptedCallback
Definition of a model accepted function.
Definition NonLinearUniversalOptimizationSparse.h:121
Callback< bool, const ExternalSharedModel & > SharedModelIsValidCallback
Definition of a callback function determining whether a shared model is valid.
Definition NonLinearUniversalOptimizationSparse.h:98
Callback< void, const ExternalSharedModel &, const ExternalIndividualModel &, const size_t, const size_t, Result & > ValueCallback
Definition of a callback function for sparse value calculation.
Definition NonLinearUniversalOptimizationSparse.h:80
Callback< void, IndividualModel &, ExternalIndividualModel & > IndividualModelTransformationCallback
Definition of an individual model transformation function.
Definition NonLinearUniversalOptimizationSparse.h:114
StaticBuffer< Scalar, tResultDimension > Result
Definition of a model result.
Definition NonLinearUniversalOptimizationSparse.h:65
static bool optimizeUniversalModel(const SharedModel &sharedModel, const IndividualModels &individualModels, const size_t *numberElementsPerIndividualModel, const ValueCallback &valueCallback, const ErrorCallback &errorCallback, const SharedModelIsValidCallback &sharedModelIsValidCallback, const SharedModelTransformationCallback &sharedModelTransformationCallback, const IndividualModelTransformationCallback &individualModelTransformationCallback, const ModelAcceptedCallback &modelAcceptedCallback, SharedModel &optimizedSharedModel, IndividualModels &optimizedIndividualModels, const unsigned int iterations=5u, const Estimator::EstimatorType estimator=Estimator::ET_SQUARE, Scalar lambda=Scalar(0.001), const Scalar lambdaFactor=Scalar(5), Scalar *initialError=nullptr, Scalar *finalError=nullptr, Scalars *intermediateErrors=nullptr)
Optimizes a universal model by minimizing the error the model produces.
Definition NonLinearUniversalOptimizationSparse.h:1002
Callback< void, SharedModel &, ExternalSharedModel & > SharedModelTransformationCallback
Definition of a shared model transformation function.
Definition NonLinearUniversalOptimizationSparse.h:106
StaticBuffer< Scalar, tSharedModelSize > SharedModel
Definition of a shared model.
Definition NonLinearUniversalOptimizationSparse.h:45
This class implements an optimization for universal sparse problems with one common shared model (opt...
Definition NonLinearUniversalOptimizationSparse.h:488
StaticBuffer< Scalar, tFirstIndividualModelSize > FirstIndividualModel
Definition of the first individual model.
Definition NonLinearUniversalOptimizationSparse.h:504
Callback< void, FirstIndividualModel &, ExternalFirstIndividualModel & > FirstIndividualModelTransformationCallback
Definition of a transformation function for the first individual models.
Definition NonLinearUniversalOptimizationSparse.h:590
StaticBuffer< Scalar, tSecondIndividualModelSize > SecondIndividualModel
Definition of the second individual model.
Definition NonLinearUniversalOptimizationSparse.h:514
Callback< bool, const ExternalSharedModel & > SharedModelIsValidCallback
Definition of a callback function determining whether a shared model is valid.
Definition NonLinearUniversalOptimizationSparse.h:574
StaticBuffer< Scalar, tSharedModelSize > SharedModel
Definition of the shared model.
Definition NonLinearUniversalOptimizationSparse.h:494
Callback< size_t, const ExternalSharedModel &, const ExternalFirstIndividualModels &, const ExternalSecondIndividualModels &, const size_t, const size_t, Result & > ValueCallback
Definition of a callback function for sparse value calculation.
Definition NonLinearUniversalOptimizationSparse.h:556
StaticBuffer< Scalar, tExternalFirstIndividualModelSize > ExternalFirstIndividualModel
Definition of the external first individual model.
Definition NonLinearUniversalOptimizationSparse.h:509
StaticBuffer< Scalar, tExternalSharedModelSize > ExternalSharedModel
Definition of the external shared model.
Definition NonLinearUniversalOptimizationSparse.h:499
static bool optimizeUniversalModel(const SharedModel &sharedModel, const FirstIndividualModels &firstIndividualModels, const SecondIndividualModels &secondIndividualModels, const size_t *numberElementsPerSecondModel, const ValueCallback &valueCallback, const ErrorCallback &errorCallback, const SharedModelIsValidCallback &sharedModelIsValidCallback, const SharedModelTransformationCallback &sharedModelTransformationCallback, const FirstIndividualModelTransformationCallback &firstIndividualModelTransformationCallback, const SecondIndividualModelTransformationCallback &secondIndividualModelTransformationCallback, const ModelAcceptedCallback &modelAcceptedCallback, SharedModel &optimizedSharedModel, FirstIndividualModels &optimizedFirstIndividualModels, SecondIndividualModels &optimizedSecondIndividualModels, const unsigned int iterations=5u, const Estimator::EstimatorType estimator=Estimator::ET_SQUARE, Scalar lambda=Scalar(0.001), const Scalar lambdaFactor=Scalar(5), Scalar *initialError=nullptr, Scalar *finalError=nullptr, Scalars *intermediateErrors=nullptr)
Optimizes a universal model by minimizing the error the model produces.
Definition NonLinearUniversalOptimizationSparse.h:1803
std::vector< ExternalFirstIndividualModel > ExternalFirstIndividualModels
Definition of a vector holding the external first individual models.
Definition NonLinearUniversalOptimizationSparse.h:534
StaticBuffer< Scalar, tResultDimension > Result
Definition of a model result.
Definition NonLinearUniversalOptimizationSparse.h:524
std::vector< FirstIndividualModel > FirstIndividualModels
Definition of a vector holding the first individual models.
Definition NonLinearUniversalOptimizationSparse.h:529
std::vector< ExternalSecondIndividualModel > ExternalSecondIndividualModels
Definition of a vector holding the external second individual models.
Definition NonLinearUniversalOptimizationSparse.h:544
StaticBuffer< Scalar, tExternalSecondIndividualModelSize > ExternalSecondIndividualModel
Definition of the external second individual model.
Definition NonLinearUniversalOptimizationSparse.h:519
Callback< void, SecondIndividualModel &, ExternalSecondIndividualModel & > SecondIndividualModelTransformationCallback
Definition of a transformation function for the second individual models.
Definition NonLinearUniversalOptimizationSparse.h:598
std::vector< SecondIndividualModel > SecondIndividualModels
Definition of a vector holding the first individual models.
Definition NonLinearUniversalOptimizationSparse.h:539
Callback< void, SharedModel &, ExternalSharedModel & > SharedModelTransformationCallback
Definition of a transformation function for the shared model.
Definition NonLinearUniversalOptimizationSparse.h:582
Callback< void, const SharedModel &, const FirstIndividualModels &, const SecondIndividualModels & > ModelAcceptedCallback
Definition of a model accepted function.
Definition NonLinearUniversalOptimizationSparse.h:606
Callback< bool, const ExternalSharedModel &, const ExternalFirstIndividualModels &, const ExternalSecondIndividualModels &, const size_t, const size_t, Result & > ErrorCallback
Definition of a callback function for sparse error calculation.
Definition NonLinearUniversalOptimizationSparse.h:567
This class implements optimizations for universal sparse problems.
Definition NonLinearUniversalOptimizationSparse.h:25
size_t columns() const
Returns the count of columns.
Definition Matrix.h:698
const T * data() const
Returns a pointer to the internal values.
Definition Matrix.h:798
size_t rows() const
Returns the count of rows.
Definition Matrix.h:692
void resize(const size_t rows, const size_t columns)
Resizes this matrix.
static constexpr T weakEps()
Returns a weak epsilon.
static T abs(const T value)
Returns the absolute value of a given value.
Definition Numeric.h:1220
static T summedSqr(const T *values, const size_t number)
Returns the summed squares of a given values.
Definition Numeric.h:1514
static constexpr T maxValue()
Returns the max scalar value.
Definition Numeric.h:3244
This class implements a sparse matrix using a float type for its elements that is specified by T.
Definition SparseMatrix.h:61
bool invertBlockDiagonal3()
Inverts this square block diagonal matrix with 3x3 block size.
size_t rows() const
Returns the number of rows this matrix has.
std::vector< Entry > Entries
Definition of a vector holding entries.
Definition SparseMatrix.h:70
size_t columns() const
Returns the number of columns this matrix has.
bool invertDiagonal()
Inverts this square diagonal matrix.
bool invertBlockDiagonal(const size_t size)
Inverts this square block diagonal matrix with size x size block size.
SparseMatrixT< T > submatrix(const size_t row, const size_t column, const size_t rows, const size_t columns) const
Returns a submatrix of this matrix.
This class implements a static buffer that has a fixed capacity.
Definition StaticBuffer.h:24
const T * data() const
Returns the buffer data pointer.
Definition StaticBuffer.h:240
SparseMatrixT< Scalar > SparseMatrix
Definition of the SparseMatrix object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with s...
Definition SparseMatrix.h:30
float Scalar
Definition of a scalar type.
Definition Math.h:129
std::vector< Scalar > Scalars
Definition of a vector holding Scalar objects.
Definition Math.h:145
The namespace covering the entire Ocean framework.
Definition Accessor.h:15