求逆矩阵AX=B
#include <eigen/Eigen/Dense>
void test01()
{
Eigen::Matrix3d A;
Eigen::Vector3d b;
A << 4, 7, 2,
3, 5, 1,
6, 8, 9;
b << 1, 2, 3;
if (A.determinant() != 0)
{
Eigen::Matrix3d A_inv = A.inverse();
Eigen::Vector3d x = A_inv * b;
std::cout << "求解的x:" << x << std::endl;
}
else
{
std::cout << "不可逆,无解!" << std::endl;
}
}
梯度下降算法求矩阵AX=B,效果很差
void test02()
{
Eigen::MatrixXd A(3, 3);
A << 4, 7, 2, 3, 5, 1, 6, 8, 9;
Eigen::VectorXd B(3);
B << 1, 2, 3;
Eigen::VectorXd X(3);
X << 1, 1, 1;
double learning_rate = 0.007;
auto objective = [&](const Eigen::MatrixXd& A, const Eigen::VectorXd& X,
const Eigen::VectorXd& B) {
Eigen::VectorXd residual = A * X - B;
return 0.5 * residual.squaredNorm();
};
auto gradient = [&](const Eigen::MatrixXd& A, const Eigen::VectorXd& X,
const Eigen::VectorXd& B) {
return A.transpose() * (A * X - B);
};
int maxIter = 10000;
double tol = 1e-6;
int iter = 0;
while (iter < maxIter)
{
Eigen::VectorXd grad = gradient(A, X, B);
if (grad.norm() < tol)
{
std::cout << "Converged at iteration " << iter << std::endl;
break;
}
X -= learning_rate * grad;
if (iter % 100 == 0)
{
std::cout << "Iteration " << iter
<< ", Objective Value: " << objective(A, X, B)
<< std::endl;
}
iter++;
}
std::cout << "Solution X: " << X.transpose() << std::endl;
}
牛顿法求解AX=B
void test03()
{
Eigen::MatrixXd A(3, 3);
Eigen::Vector3d B(3);
A << 4, 7, 2, 3, 5, 1, 6, 8, 9;
B << 1, 2, 3;
Eigen::Vector3d x = Eigen::Vector3d::Ones();
int max_iterations = 100;
double tolerance = 1e-6;
for (int iteration = 0; iteration < max_iterations; ++iteration)
{
Eigen::Vector3d Ax = A * x;
Eigen::Vector3d error = Ax - B;
Eigen::Vector3d gradient = A.transpose() * error;
Eigen::Matrix3d hessian = A.transpose() * A;
Eigen::Vector3d x_new = x - hessian.inverse() * gradient;
if ((x_new - x).norm() < tolerance)
{
std::cout << "Converged at iteration " << iteration + 1 << std::endl;
break;
}
x = x_new;
}
std::cout << "Final solution x: " << x << std::endl;
}
拟牛顿法BFGS
void test04()
{
Eigen::MatrixXd A(3, 3);
A << 4, 7, 2, 3, 5, 1, 6, 8, 9;
Eigen::VectorXd B(3);
B << 1, 2, 3;
Eigen::VectorXd X(3);
X << 0, 0, 0;
auto objective = [&](const Eigen::MatrixXd& A, const Eigen::VectorXd& X,
const Eigen::VectorXd& B) {
Eigen::VectorXd residual = A * X - B;
return 0.5 * residual.squaredNorm();
};
auto gradient = [&](const Eigen::MatrixXd& A, const Eigen::VectorXd& X,
const Eigen::VectorXd& B) {
return A.transpose() * (A * X - B);
};
int n = A.cols();
Eigen::VectorXd grad = gradient(A, X, B);
Eigen::MatrixXd H = Eigen::MatrixXd::Identity(n, n);
double tol = 1e-6;
int maxIter = 100;
int iter = 0;
while (grad.norm() > tol && iter < maxIter)
{
Eigen::VectorXd p = -H * grad;
double alpha = 1.0;
Eigen::VectorXd X_new = X + alpha * p;
Eigen::VectorXd grad_new = gradient(A, X_new, B);
Eigen::VectorXd s = X_new - X;
Eigen::VectorXd y = grad_new - grad;
double rho = 1.0 / y.dot(s);
Eigen::MatrixXd I = Eigen::MatrixXd::Identity(n, n);
Eigen::MatrixXd term1 = I - rho * s * y.transpose();
Eigen::MatrixXd term2 = I - rho * y * s.transpose();
H = term1 * H * term2 + rho * s * s.transpose();
X = X_new;
grad = grad_new;
iter++;
}
std::cout << "解 X: " << X.transpose() << std::endl;
}
拟牛顿法L-BFGS
void test05()
{
Eigen::MatrixXd A(3, 3);
A << 4, 7, 2, 3, 5, 1, 6, 8, 9;
Eigen::VectorXd B(3);
B << 1, 2, 3;
Eigen::VectorXd X(3);
X << 0, 0, 0;
auto objective = [&](const Eigen::MatrixXd& A, const Eigen::VectorXd& X,
const Eigen::VectorXd& B) {
Eigen::VectorXd residual = A * X - B;
return 0.5 * residual.squaredNorm();
};
auto gradient = [&](const Eigen::MatrixXd& A, const Eigen::VectorXd& X,
const Eigen::VectorXd& B) {
return A.transpose() * (A * X - B);
};
int n = A.cols();
int m = 5;
double tol = 1e-6;
int maxIter = 100;
int iter = 0;
std::vector<Eigen::VectorXd> s_list, y_list;
Eigen::VectorXd grad = gradient(A, X, B);
while (grad.norm() > tol && iter < maxIter)
{
Eigen::VectorXd q = grad;
std::vector<double> alpha_list;
for (int i = s_list.size() - 1; i >= 0; --i)
{
Eigen::VectorXd s = s_list[i];
Eigen::VectorXd y = y_list[i];
double rho = 1.0 / y.dot(s);
double alpha = rho * s.dot(q);
alpha_list.push_back(alpha);
q -= alpha * y;
}
Eigen::VectorXd r = q;
for (int i = 0; i < s_list.size(); ++i)
{
Eigen::VectorXd s = s_list[i];
Eigen::VectorXd y = y_list[i];
double rho = 1.0 / y.dot(s);
double beta = rho * y.dot(r);
r += s * (alpha_list[s_list.size() - 1 - i] - beta);
}
Eigen::VectorXd p = -r;
double alpha = 1.0;
Eigen::VectorXd X_new = X + alpha * p;
Eigen::VectorXd grad_new = gradient(A, X_new, B);
Eigen::VectorXd s = X_new - X;
Eigen::VectorXd y = grad_new - grad;
if (s_list.size() == m)
{
s_list.erase(s_list.begin());
y_list.erase(y_list.begin());
}
s_list.push_back(s);
y_list.push_back(y);
X = X_new;
grad = grad_new;
iter++;
}
std::cout << "解 X: " << X.transpose() << std::endl;
}