svZeroDSolver
Loading...
Searching...
No Matches
LevenbergMarquardtOptimizer.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) Stanford University, The Regents of the
2// University of California, and others. SPDX-License-Identifier: BSD-3-Clause
3/**
4 * @file LevenbergMarquardtOptimizer.h
5 * @brief opt::LevenbergMarquardtOptimizer source file
6 */
7#ifndef SVZERODSOLVER_OPTIMIZE_LEVENBERGMARQUARDT_HPP_
8#define SVZERODSOLVER_OPTIMIZE_LEVENBERGMARQUARDT_HPP_
9
10#include <Eigen/Dense>
11#include <Eigen/Sparse>
12
13#include "Model.h"
14#include "SparseSystem.h"
15
16/**
17 * @brief Levenberg-Marquardt optimization class
18 *
19 * The 0D residual (assuming no time-dependency in parameters) is
20 *
21 * \f[
22 * \boldsymbol{r}(\boldsymbol{\alpha}, \boldsymbol{y}, \boldsymbol{\dot{y}}) =
23 * \boldsymbol{E}(\boldsymbol{\alpha}, \boldsymbol{y}) \cdot
24 * \dot{\boldsymbol{y}}+\boldsymbol{F}(\boldsymbol{\alpha}, \boldsymbol{y})
25 * \cdot \boldsymbol{y}+\boldsymbol{c}(\boldsymbol{\alpha}, \boldsymbol{y}) \f]
26 *
27 * with solution vector \f$\boldsymbol{y} \in \mathbb{R}^{N}\f$ (flow and
28 * pressure at nodes), LPN parameters \f$\boldsymbol{\alpha} \in
29 * \mathbb{R}^{P}\f$, system matrices \f$\boldsymbol{E},\boldsymbol{F} \in
30 * \mathbb{R}^{NxN}\f$, and system vector \f$\boldsymbol{c} \in
31 * \mathbb{R}^{N}\f$.
32 *
33 * This residual is identical (up to an overall sign) to the one the solver
34 * assembles in SparseSystem::update_residual. It is therefore reused here
35 * instead of being redefined, and only its Jacobian with respect to the
36 * parameters is assembled by the blocks (see Block::update_gradient). The
37 * overall sign cancels in the normal equations below, so it does not affect
38 * the parameter increment.
39 *
40 * The least squares problem can be formulated as
41 *
42 * \f[
43 * \min _\alpha S, \quad \mathrm { with } \quad S=\sum_i^D
44 * r_i^2\left(\boldsymbol{\alpha}, y_i, \dot{y}_i\right) \f]
45 *
46 * with given solution vectors \f$\boldsymbol{y}\f$, \f$\boldsymbol{\dot{y}}\f$
47 * at all datapoints \f$D\f$. The parameter vector is iteratively improved
48 * according to
49 *
50 * \f[
51 * \boldsymbol{\alpha}^{i+1}=\boldsymbol{\alpha}^{i}+\Delta
52 * \boldsymbol{\alpha}^{i+1} \f]
53 *
54 * wherein the increment \f$\Delta \boldsymbol{\alpha}^{i+1} \f$ is determined
55 * by solving the following system:
56 *
57 * \f[
58 * \left[\mathbf{J}^{\mathrm{T}} \mathbf{J}+\lambda
59 * \operatorname{diag}\left(\mathbf{J}^{\mathrm{T}} \mathbf{J}\right)\right]^{i}
60 * \cdot \Delta \boldsymbol{\alpha}^{i+1}=-\left[\mathbf{J}^{\mathrm{T}}
61 * \mathbf{r}\right]^{i}, \quad \lambda^{i}=\lambda^{i-1}
62 * \cdot\left\|\left[\mathbf{J}^{\mathrm{T}} \mathbf{r}\right]^{i}\right\|_2
63 * /\left\|\left[\mathbf{J}^{\mathrm{T}} \mathbf{r}\right]^{i-1}\right\|_2. \f]
64 *
65 * The algorithm terminates when the following tolerance thresholds are reached
66 *
67 * \f[
68 * \left\|\left[\mathbf{J}^{\mathrm{T}}
69 * \mathbf{r}\right]^{\mathrm{i}}\right\|_2<\operatorname{tol}_{\text {grad
70 * }}^\alpha \text { and }\left\|\Delta
71 * \boldsymbol{\alpha}^{\mathrm{i}+1}\right\|_2<\mathrm{tol}_{\text {inc
72 * }}^\alpha, \f]
73 *
74 * The Jacobian is derived from the residual as
75 *
76 * \f[
77 * J = \frac{\partial \boldsymbol{r}}{\partial \boldsymbol{\alpha}} =
78 * \frac{\partial \mathbf{E}}{\partial \boldsymbol{\alpha}} \cdot
79 * \dot{\mathbf{y}}+\frac{\partial \mathbf{F}}{\partial \boldsymbol{\alpha}}
80 * \cdot \mathbf{y}+\frac{\partial \mathbf{c}}{\partial \boldsymbol{\alpha}} \f]
81 *
82 *
83 */
85 public:
86 /**
87 * @brief Construct a new LevenbergMarquardtOptimizer object
88 *
89 * @param model The 0D model
90 * @param num_obs Number of observations in optimization
91 * @param num_params Total number of parameters in alpha
92 * @param active_param_ids Indices into alpha of parameters that should be
93 * optimized. Parameters not listed are held constant at their initial value.
94 * @param lambda0 Initial damping factor
95 * @param tol_grad Gradient tolerance
96 * @param tol_inc Parameter increment tolerance
97 * @param max_iter Maximum iterations
98 */
99 LevenbergMarquardtOptimizer(Model* model, int num_obs, int num_params,
100 const std::vector<int>& active_param_ids,
101 double lambda0, double tol_grad, double tol_inc,
102 int max_iter);
103
104 /**
105 * @brief Run the optimization algorithm
106 *
107 * @param alpha Initial parameter vector alpha
108 * @param y_obs Matrix (num_obs x n) with all observations for y
109 * @param dy_obs Matrix (num_obs x n) with all observations for dy
110 * @return Eigen::Matrix<double, Eigen::Dynamic, 1> Optimized parameter vector
111 * alpha
112 */
113 Eigen::Matrix<double, Eigen::Dynamic, 1> run(
114 Eigen::Matrix<double, Eigen::Dynamic, 1> alpha,
115 std::vector<std::vector<double>>& y_obs,
116 std::vector<std::vector<double>>& dy_obs);
117
118 private:
119 Eigen::SparseMatrix<double> jacobian;
120 Eigen::Matrix<double, Eigen::Dynamic, 1> residual;
121 Eigen::Matrix<double, Eigen::Dynamic, 1> delta;
122 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> mat;
123 Eigen::Matrix<double, Eigen::Dynamic, 1> vec;
124 std::vector<int> active_param_ids;
125 Model* model;
126 SparseSystem system; ///< Solver system used to reuse the residual assembly
127 double lambda;
128
129 int num_obs;
130 int num_params;
131 int num_active;
132 int num_eqns;
133 int num_vars;
134 int num_dpoints;
135
136 double tol_grad;
137 double tol_inc;
138 int max_iter;
139
140 void update_gradient(Eigen::Matrix<double, Eigen::Dynamic, 1>& alpha,
141 std::vector<std::vector<double>>& y_obs,
142 std::vector<std::vector<double>>& dy_obs);
143
144 void update_delta(bool first_step);
145};
146
147#endif // SVZERODSOLVER_OPTIMIZE_LEVENBERGMARQUARDT_HPP_
model::Model source file
SparseSystem source file.
LevenbergMarquardtOptimizer(Model *model, int num_obs, int num_params, const std::vector< int > &active_param_ids, double lambda0, double tol_grad, double tol_inc, int max_iter)
Construct a new LevenbergMarquardtOptimizer object.
Definition LevenbergMarquardtOptimizer.cpp:7
Eigen::Matrix< double, Eigen::Dynamic, 1 > run(Eigen::Matrix< double, Eigen::Dynamic, 1 > alpha, std::vector< std::vector< double > > &y_obs, std::vector< std::vector< double > > &dy_obs)
Run the optimization algorithm.
Definition LevenbergMarquardtOptimizer.cpp:36
Model of 0D elements.
Definition Model.h:55
Sparse system.
Definition SparseSystem.h:30