Введение в Eigen: что это и зачем нужно
Eigen — это высокопроизводительная библиотека для линейной алгебры на языке C++. Она предоставляет широкий спектр возможностей для работы с векторами, матрицами, разреженными матрицами, а также для решения систем линейных уравнений, вычисления собственных значений и сингулярного разложения. Eigen написан на чистом C++ (шаблоны) и не требует внешних зависимостей, что делает его идеальным выбором для встраиваемых систем, научных вычислений, компьютерной графики, машинного обучения и робототехники.
Зачем нужна Eigen? В отличие от многих других библиотек (например, LAPACK или BLAS), Eigen предлагает интуитивно понятный API, который напоминает работу с матрицами в MATLAB или NumPy. Она поддерживает ленивые вычисления (lazy evaluation) и векторизацию (SSE, AVX, NEON), что обеспечивает производительность, близкую к ручной оптимизации на ассемблере. Eigen также полностью совместима с современными стандартами C++ (C++11 и выше) и активно поддерживается сообществом.
Основные возможности:
- Работа с плотными и разреженными матрицами произвольных размеров.
- Операции: сложение, умножение, транспонирование, инвертирование.
- Решение линейных систем (LU, QR, Cholesky, SVD).
- Вычисление собственных значений и собственных векторов.
- Геометрические преобразования (повороты, кватернионы).
- Поддержка произвольных типов данных (float, double, complex, пользовательские типы).
Установка Eigen
Eigen — это библиотека, состоящая только из заголовочных файлов (header-only). Это означает, что вам не нужно компилировать отдельную библиотеку — достаточно подключить нужные заголовки в вашем проекте. Установка зависит от операционной системы и менеджера пакетов.
Установка через менеджеры пакетов
Linux (Ubuntu/Debian):
sudo apt-get install libeigen3-dev
macOS (Homebrew):
brew install eigen
Windows (vcpkg):
vcpkg install eigen3
Windows (Conan):
conan install eigen/3.4.0@
Установка вручную (для всех ОС)
Скачайте последнюю версию с официального сайта или клонируйте репозиторий:
git clone https://gitlab.com/libeigen/eigen.git
Затем укажите путь к папке Eigen в вашем компиляторе. Например, для g++:
g++ -I /path/to/eigen my_program.cpp -o my_program
Примечание: Если вы используете CMake, добавьте в CMakeLists.txt:
find_package(Eigen3 REQUIRED)
target_link_libraries(my_target Eigen3::Eigen)
Быстрый старт с примером кода
Давайте напишем простую программу, которая создает матрицу и вектор, выполняет умножение и выводит результат.
#include <iostream>
#include <Eigen/Dense>
int main() {
// Создаем матрицу 2x2
Eigen::Matrix2d A;
A << 1, 2,
3, 4;
// Создаем вектор 2x1
Eigen::Vector2d b(5, 6);
// Умножаем матрицу на вектор
Eigen::Vector2d x = A * b;
// Выводим результат
std::cout << "A * b =\n" << x << std::endl;
return 0;
}
Компиляция и запуск:
g++ -I /path/to/eigen example.cpp -o example
./example
Вывод:
A * b =
17
39
Этот пример демонстрирует, насколько просто работать с Eigen: синтаксис похож на математические операции, а вывод автоматически форматируется.
Основные методы и функции Eigen
Ниже приведены 10 ключевых методов/функций Eigen с подробным описанием, параметрами и примерами.
1. MatrixXd::Zero() — создание нулевой матрицы
Описание: Создает матрицу или вектор, заполненный нулями. Полезно для инициализации.
Параметры: rows (количество строк), cols (количество столбцов). Для векторов используйте VectorXd::Zero(n).
Пример:
#include <iostream>
#include <Eigen/Dense>
int main() {
Eigen::MatrixXd Z = Eigen::MatrixXd::Zero(3, 4);
std::cout << "Zero matrix 3x4:\n" << Z << std::endl;
return 0;
}
Вывод:
Zero matrix 3x4:
0 0 0 0
0 0 0 0
0 0 0 0
2. .transpose() — транспонирование матрицы
Описание: Возвращает транспонированную матрицу. Исходная матрица не изменяется (если не использовать .transposeInPlace()).
Параметры: Нет (метод вызывается на объекте матрицы).
Пример:
Eigen::Matrix2d A;
A << 1, 2,
3, 4;
Eigen::Matrix2d At = A.transpose();
std::cout << "A transposed:\n" << At << std::endl;
Вывод:
A transposed:
1 3
2 4
3. .inverse() — обратная матрица
Описание: Вычисляет обратную матрицу. Работает только для квадратных матриц. Если матрица вырождена, результат может быть некорректным (проверяйте через .determinant()).
Параметры: Нет.
Пример:
Eigen::Matrix2d A;
A << 1, 2,
3, 4;
Eigen::Matrix2d A_inv = A.inverse();
std::cout << "Inverse of A:\n" << A_inv << std::endl;
Вывод:
Inverse of A:
-2 1
1.5 -0.5
4. .determinant() — определитель матрицы
Описание: Вычисляет определитель квадратной матрицы. Используется для проверки обратимости (если det != 0).
Параметры: Нет.
Пример:
Eigen::Matrix3d A;
A << 1, 2, 3,
4, 5, 6,
7, 8, 10;
double det = A.determinant();
std::cout << "Determinant: " << det << std::endl;
Вывод:
Determinant: -3
5. .eigenvalues() — собственные значения
Описание: Вычисляет собственные значения матрицы. Для этого используется класс EigenSolver (для плотных матриц). Возвращает комплексные числа.
Параметры: Нет (метод вызывается на объекте EigenSolver).
Пример:
Eigen::Matrix2d A;
A << 1, 2,
2, 1;
Eigen::EigenSolver<Eigen::Matrix2d> solver(A);
std::cout << "Eigenvalues:\n" << solver.eigenvalues() << std::endl;
Вывод:
Eigenvalues:
(3,0)
(-1,0)
6. .col(i) и .row(i) — доступ к строкам и столбцам
Описание: Возвращает ссылку на i-й столбец или строку матрицы. Можно читать и изменять значения.
Параметры: i — индекс (начиная с 0).
Пример:
Eigen::Matrix3d A = Eigen::Matrix3d::Random();
std::cout << "Second column:\n" << A.col(1) << std::endl;
A.row(0) = Eigen::Vector3d::Ones(); // Заменяем первую строку на единицы
std::cout << "Modified matrix:\n" << A << std::endl;
7. .block(i, j, p, q) — извлечение подматрицы
Описание: Извлекает блок матрицы размером p x q, начиная с позиции (i, j). Очень удобно для работы с частями матриц.
Параметры: i (строка начала), j (столбец начала), p (количество строк), q (количество столбцов).
Пример:
Eigen::Matrix4d A = Eigen::Matrix4d::Random();
Eigen::Matrix2d B = A.block(1, 1, 2, 2); // Подматрица 2x2 из центра
std::cout << "Block:\n" << B << std::endl;
8. .norm() — норма вектора или матрицы
Описание: Вычисляет евклидову норму (длину) вектора или норму Фробениуса для матрицы.
Параметры: Нет.
Пример:
Eigen::Vector3d v(3, 4, 0);
double n = v.norm();
std::cout << "Norm of v: " << n << std::endl; // 5
9. .solve() — решение системы линейных уравнений
Описание: Решает систему Ax = b. Используется с разложениями (например, LU, QR, LLT). Возвращает вектор x.
Параметры: b — вектор правой части.
Пример:
Eigen::Matrix2d A;
A << 2, 1,
1, 3;
Eigen::Vector2d b(5, 6);
Eigen::Vector2d x = A.colPivHouseholderQr().solve(b);
std::cout << "Solution x:\n" << x << std::endl;
10. .SVD() — сингулярное разложение
Описание: Выполняет сингулярное разложение матрицы (A = U * S * V^T). Используется для решения плохо обусловленных систем и сжатия данных.
Параметры: Нет (используется класс JacobiSVD).
Пример:
Eigen::Matrix3d A;
A << 1, 0, 0,
0, 2