31 const Eigen::MatrixXd& Hessian,
34 Eigen::VectorXd freestep = Hessian.colPivHouseholderQr().solve(-gradient);
36 if (freestep.norm() < delta) {
41 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> es(Hessian);
42 const Eigen::VectorXd factor =
43 (es.eigenvectors().transpose() * gradient).cwiseAbs2();
46 if (std::abs(factor[0]) < 1
e-18) {
47 std::vector<Index> index;
48 Eigen::VectorXd diag = Eigen::VectorXd::Zero(factor.size());
50 for (
Index i = 0; i < factor.size(); i++) {
51 double entry = es.eigenvalues()(i) - es.eigenvalues()(0);
52 if (std::abs(entry) < 1
e-14) {
59 Eigen::MatrixXd pseudo_inv =
60 es.eigenvectors() * diag.asDiagonal() * es.eigenvectors().transpose();
61 Eigen::VectorXd step = -pseudo_inv * gradient;
62 if (step.norm() < delta) {
63 double tau = std::sqrt(delta * delta - step.squaredNorm());
64 step += tau * es.eigenvectors().col(index[0]);
69 Index start_index = 0;
70 for (; start_index < factor.size(); start_index++) {
71 if (factor[start_index] < 1
e-18) {
77 if (start_index == factor.size()) {
78 throw std::runtime_error(
79 "trustregion.cc: all the factors are close to zero trust region method "
80 "will not converge further.");
85 -es.eigenvalues()(start_index) + std::sqrt(factor(start_index)) / delta;
87 for (
Index iter = 0; iter < 100; iter++) {
88 std::pair<double, double> result = TRF.
Evaluate(lambda);
89 double func_value = result.first;
90 double update = result.second;
92 if (update < 1
e-14 || std::abs(func_value) < 1
e-12) {
100 Eigen::VectorXd new_delta_pos = Eigen::VectorXd::Zero(gradient.size());
101 for (
Index i = start_index; i < gradient.size(); i++) {
102 new_delta_pos -= es.eigenvectors().col(i) *
103 (es.eigenvectors().col(i).transpose() * gradient) /
104 (es.eigenvalues()(i) + lambda);
108 if (new_delta_pos.norm() > delta) {
109 new_delta_pos *= (delta / new_delta_pos.norm());
111 return new_delta_pos;