11 #include <Eigen/Dense>
25 using AmulFunc = std::function<Eigen::VectorXd(
const Eigen::Ref<const Eigen::VectorXd> &)>;
28 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
42 inline void solve(
const Eigen::Ref<const Eigen::MatrixXd> & A,
43 const Eigen::Ref<const Eigen::VectorXd> & b,
44 Eigen::Ref<Eigen::VectorXd> x,
48 assert(A.rows() == b.size());
49 AmulFunc Amul_func = [&](
const Eigen::Ref<const Eigen::VectorXd> & vec) {
return A * vec; };
50 solve(Amul_func, b, x, k_max, eps);
68 const Eigen::Ref<const Eigen::VectorXd> & b,
69 Eigen::Ref<Eigen::VectorXd> x,
73 k_max = std::min(k_max,
static_cast<int>(x.size()));
79 Eigen::VectorXd r = b - Amul_func(x);
80 basis_.push_back(r.normalized());
81 double rho = r.norm();
83 g_.setZero(k_max + 1);
86 double b_norm = b.norm();
87 H_.setZero(k_max + 1, k_max);
92 std::vector<double> c_list;
93 std::vector<double> s_list;
94 while(rho > eps * b_norm && k < k_max)
102 Eigen::VectorXd Avk = Amul_func(
basis_.back());
103 Eigen::VectorXd new_basis = Avk;
104 for(
int j = 0; j < k; j++)
107 H_(j, k - 1) = new_basis.dot(
basis_[j]);
109 new_basis = new_basis -
H_(j, k - 1) *
basis_[j];
113 double new_basis_norm = new_basis.norm();
114 H_(k, k - 1) = new_basis_norm;
119 double Avk_norm = Avk.norm();
120 if(Avk_norm + 1e-3 * new_basis_norm == Avk_norm)
123 for(
int j = 0; j < k; j++)
125 double h_tmp = new_basis.dot(
basis_[j]);
126 H_(j, k - 1) += h_tmp;
127 new_basis -= h_tmp *
basis_[j];
133 basis_.push_back(new_basis.normalized());
139 for(
int i = 0; i < k - 1; i++)
141 double h0 =
H_(i, k - 1);
142 double h1 =
H_(i + 1, k - 1);
143 double c = c_list[i];
144 double s = s_list[i];
145 H_(i, k - 1) = c * h0 - s * h1;
146 H_(i + 1, k - 1) = s * h0 + c * h1;
150 double nu = std::sqrt(std::pow(
H_(k - 1, k - 1), 2) + std::pow(
H_(k, k - 1), 2));
153 double c_k =
H_(k - 1, k - 1) / nu;
154 double s_k = -
H_(k, k - 1) / nu;
155 c_list.push_back(c_k);
156 s_list.push_back(s_k);
157 H_(k - 1, k - 1) = c_k *
H_(k - 1, k - 1) - s_k *
H_(k, k - 1);
161 double g0 =
g_(k - 1);
163 g_(k - 1) = c_k * g0 - s_k * g1;
164 g_(k) = s_k * g0 + c_k * g1;
167 rho = std::abs(
g_(k));
172 y_k =
H_.topLeftCorner(k + 1, k).householderQr().solve(
g_.head(k + 1));
175 rho = (
g_.head(k + 1) -
H_.topLeftCorner(k + 1, k) * y_k).norm();
184 y_k =
H_.topLeftCorner(k, k).triangularView<Eigen::Upper>().
solve(
g_.head(k));
188 for(
int i = 0; i < k; i++)