Spec-Zone.ru › Eigen3

Расширенная инициализация

На этой странице рассматриваются несколько расширенных методов инициализации матриц. Она предоставляет более подробную информацию о инициализаторе с запятыми, который был введён ранее. Также объясняется, как получить специальные матрицы, такие как единичная матрица и нулевая матрица.

Инициализатор с запятыми

Eigen предлагает синтаксис инициализатора с запятыми, который позволяет пользователю легко установить все коэффициенты матрицы, вектора или массива. Просто перечислите коэффициенты, начиная с верхнего левого угла и двигаясь слева направо и сверху вниз. Размер объекта необходимо указать предварительно. Если вы перечислите слишком мало или слишком много коэффициентов, Eigen сообщит об ошибке.

Пример: Результат:
Matrix3f m;
m << 1, 2, 3,
     4, 5, 6,
     7, 8, 9;
std::cout << m;
1 2 3
4 5 6
7 8 9

Кроме того, элементы списка инициализации могут сами быть векторами или матрицами. Распространённое применение — объединение векторов или матриц. Например, вот как объединить два строчных вектора. Помните, что вам нужно установить размер перед использованием инициализатора с запятыми.

Пример: Результат:
RowVectorXd vec1(3);
vec1 << 1, 2, 3;
std::cout << "vec1 = " << vec1 << std::endl;
 
RowVectorXd vec2(4);
vec2 << 1, 4, 9, 16;
std::cout << "vec2 = " << vec2 << std::endl;
 
RowVectorXd joined(7);
joined << vec1, vec2;
std::cout << "joined = " << joined << std::endl;
vec1 = 1 2 3
vec2 =  1  4  9 16
joined =  1  2  3  1  4  9 16

Мы можем использовать ту же технику для инициализации матриц с блочной структурой.

Пример: Результат:
MatrixXf matA(2, 2);
matA << 1, 2, 3, 4;
MatrixXf matB(4, 4);
matB << matA, matA/10, matA/10, matA;
std::cout << matB << std::endl;
  1   2 0.1 0.2
  3   4 0.3 0.4
0.1 0.2   1   2
0.3 0.4   3   4

Инициализатор с запятыми также может использоваться для заполнения блочных выражений, таких как m.row(i). Вот более сложный способ получить тот же результат, что и в первом примере выше:

Пример: Результат:
Matrix3f m;
m.row(0) << 1, 2, 3;
m.block(1,0,2,2) << 4, 5, 7, 8;
m.col(2).tail(2) << 6, 9;                   
std::cout << m;
1 2 3
4 5 6
7 8 9

Специальные матрицы и массивы

Классы Matrix и Array имеют статические методы, такие как Zero(), которые можно использовать для инициализации всех коэффициентов нулём. Существует три варианта. Первый вариант не принимает аргументов и может использоваться только для объектов фиксированного размера. Если вы хотите инициализировать объект динамического размера нулём, вам нужно указать размер. Таким образом, второй вариант требует один аргумент и может использоваться для одномерных объектов динамического размера, а третий вариант требует два аргумента и может использоваться для двумерных объектов. Все три варианта проиллюстрированы в следующем примере:

Пример: Результат:
std::cout << "A fixed-size array:\n";
Array33f a1 = Array33f::Zero();
std::cout << a1 << "\n\n";
 
 
std::cout << "A one-dimensional dynamic-size array:\n";
ArrayXf a2 = ArrayXf::Zero(3);
std::cout << a2 << "\n\n";
 
 
std::cout << "A two-dimensional dynamic-size array:\n";
ArrayXXf a3 = ArrayXXf::Zero(3, 4);
std::cout << a3 << "\n";
A fixed-size array:
0 0 0
0 0 0
0 0 0

A one-dimensional dynamic-size array:
0
0
0

A two-dimensional dynamic-size array:
0 0 0 0
0 0 0 0
0 0 0 0

Аналогично, статический метод Constant(значение) устанавливает все коэффициенты в value. Если размер объекта необходимо указать, дополнительные аргументы идут перед аргументом value, как в MatrixXd::Constant(rows, cols, value). Метод Random() заполняет матрицу или массив случайными коэффициентами. Единичную матрицу можно получить, вызвав Identity(); этот метод доступен только для Matrix, а не для Array, потому что «единичная матрица» — это понятие линейной алгебры. Метод LinSpaced(размер, низкое, высокое) доступен только для векторов и одномерных массивов; он возвращает вектор заданного размера, чьи коэффициенты равномерно распределены между low и high. Метод LinSpaced() проиллюстрирован в следующем примере, который выводит таблицу с углами в градусах, соответствующим углом в радианах и их синусом и косинусом.

Пример: Результат:
ArrayXXf table(10, 4);
table.col(0) = ArrayXf::LinSpaced(10, 0, 90);
table.col(1) = M_PI / 180 * table.col(0);
table.col(2) = table.col(1).sin();
table.col(3) = table.col(1).cos();
std::cout << "  Degrees   Radians      Sine    Cosine\n";
std::cout << table << std::endl;
  Degrees   Radians      Sine    Cosine
        0         0         0         1
       10     0.175     0.174     0.985
       20     0.349     0.342      0.94
       30     0.524       0.5     0.866
       40     0.698     0.643     0.766
       50     0.873     0.766     0.643
       60      1.05     0.866       0.5
       70      1.22      0.94     0.342
       80       1.4     0.985     0.174
       90      1.57         1 -4.37e-08

Этот пример показывает, что объекты, возвращаемые LinSpaced(), могут быть присвоены переменным (и выражениям). Eigen определяет вспомогательные функции, такие как setZero(), MatrixBase::setIdentity() и DenseBase::setLinSpaced() для удобства. Следующий пример сравнивает три способа построения матрицы \( J = \bigl[ \begin{smallmatrix} O & I \\ I & O \end{smallmatrix} \bigr] \): использование статических методов и присваивания, использование статических методов и инициализатора с запятыми или использование методов setXxx().

Пример: Результат:
const int size = 6;
MatrixXd mat1(size, size);
mat1.topLeftCorner(size/2, size/2)     = MatrixXd::Zero(size/2, size/2);
mat1.topRightCorner(size/2, size/2)    = MatrixXd::Identity(size/2, size/2);
mat1.bottomLeftCorner(size/2, size/2)  = MatrixXd::Identity(size/2, size/2);
mat1.bottomRightCorner(size/2, size/2) = MatrixXd::Zero(size/2, size/2);
std::cout << mat1 << std::endl << std::endl;
 
MatrixXd mat2(size, size);
mat2.topLeftCorner(size/2, size/2).setZero();
mat2.topRightCorner(size/2, size/2).setIdentity();
mat2.bottomLeftCorner(size/2, size/2).setIdentity();
mat2.bottomRightCorner(size/2, size/2).setZero();
std::cout << mat2 << std::endl << std::endl;
 
MatrixXd mat3(size, size);
mat3 << MatrixXd::Zero(size/2, size/2), MatrixXd::Identity(size/2, size/2),
        MatrixXd::Identity(size/2, size/2), MatrixXd::Zero(size/2, size/2);
std::cout << mat3 << std::endl;
 
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0

0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0

0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0

Полный список предопределённых матриц, векторов и массивов можно найти в кратком справочнике.

Использование в качестве временных объектов

Как показано выше, статические методы, такие как Zero() и Constant(), можно использовать для инициализации переменных во время объявления или в правой части оператора присваивания. Можно представить эти методы как возвращающие матрицу или массив; на самом деле они возвращают так называемые объекты выражений, которые оцениваются как матрица или массив при необходимости, поэтому этот синтаксис не несёт никаких накладных расходов.

Эти выражения также могут использоваться как временный объект. Второй пример в руководстве Начало работы, который мы воспроизводим здесь, уже иллюстрирует это.

Пример: Результат:
#include <iostream>
#include <Eigen/Dense>
 
using namespace Eigen;
using namespace std;
 
int main()
{
  MatrixXd m = MatrixXd::Random(3,3);
  m = (m + MatrixXd::Constant(3,3,1.2)) * 50;
  cout << "m =" << endl << m << endl;
  VectorXd v(3);
  v << 1, 2, 3;
  cout << "m * v =" << endl << m * v << endl;
}
m =
  94 89.8 43.5
49.4  101 86.8
88.3 29.8 37.8
m * v =
404
512
261

Выражение m + MatrixXf::Constant(3,3,1.2) строит выражение матрицы 3x3 со всеми коэффициентами, равными 1,2 плюс соответствующему коэффициенту m.

Инициализатор с запятыми также может использоваться для создания временных объектов. Следующий пример создаёт случайную матрицу размером 2x3, а затем умножает эту матрицу слева на \( \bigl[ \begin{smallmatrix} 0 & 1 \\ 1 & 0 \end{smallmatrix} \bigr] \).

Пример: Результат:
MatrixXf mat = MatrixXf::Random(2, 3);
std::cout << mat << std::endl << std::endl;
mat = (MatrixXf(2,2) << 0, 1, 1, 0).finished() * mat;
std::cout << mat << std::endl;
  0.68  0.566  0.823
-0.211  0.597 -0.605

-0.211  0.597 -0.605
  0.68  0.566  0.823

Метод finished() необходим здесь, чтобы получить фактический объект матрицы после завершения инициализации временной подматрицы с помощью инициализатора с запятыми.

© Eigen.
Licensed under the MPL2 License.
https://eigen.tuxfamily.org/dox/group__TutorialAdvancedInitialization.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API