как построить блочно-диагональную матрицу

В Matlab эта функция blkdiag создает блочную диагональную матрицу. Например, если у меня есть

a = [ 2,     2;
      2,     2]

Затем blkdiag(a,a) вернет этот вывод

>> blkdiag(a,a)

ans =

     2     2     0     0
     2     2     0     0
     0     0     2     2
     0     0     2     2

Есть ли альтернатива в Eigen Library для blkdiag? Размер большой матрицы варьируется, поэтому классические подходы не работают. Я имею в виду непосредственно построить матрицу, подобную вышеупомянутому выводу.


person CroCo    schedule 09.03.2015    source источник
comment
Вы должны сделать немного менее конкретный пример. Потому что для этого я бы сделал функцию, которая склеивает две постоянные квадратные матрицы. Могут ли аргументы быть полностью общими по размеру и содержанию, или всегда одна и та же матрица с одним и тем же значением внутри?   -  person luk32    schedule 09.03.2015
comment
Да, размер подматрицы фиксирован. Я могу выполнить функцию для достижения вышеуказанного вывода, но проблема в том, что размер большой матрицы зависит от того, сколько подматриц предполагается объединить в большую матрицу.   -  person CroCo    schedule 09.03.2015


Ответы (2)


Простая функция вроде

MatrixXd blkdiag(const MatrixXd& a, int count)
{
    MatrixXd bdm = MatrixXd::Zero(a.rows() * count, a.cols() * count);
    for (int i = 0; i < count; ++i)
    {
        bdm.block(i * a.rows(), i * a.cols(), a.rows(), a.cols()) = a;
    }

    return bdm;
}

делает работу.

Если подматрица аргумента a может иметь фиксированный размер, динамический размер или выражение, то следующий выбор является лучшим выбором.

template <typename Derived>
MatrixXd blkdiag(const MatrixBase<Derived>& a, int count)
{
    MatrixXd bdm = MatrixXd::Zero(a.rows() * count, a.cols() * count);
    for (int i = 0; i < count; ++i)
    {
        bdm.block(i * a.rows(), i * a.cols(), a.rows(), a.cols()) = a;
    }

    return bdm;
}
person cassinaj    schedule 11.03.2015

Ваша проблема уже решена! Просто посмотрите документацию по eigen для верхнего и нижнего правого углов в http://eigen.tuxfamily.org/dox. /classEigenA1DenseBase.html#a6f5fc5fe9d3fb70e62d4a9b1795704a8 и A1DenseBase.html#a2b9618f3c9eb4d4c9813ae8f6a8e70c5 соответственно.

Все, что вам нужно сделать, это присвоить этим местам матрицу, примерно такую:

// Предполагая, что A является результатом и имеет правильный размер, выделенный нулями, а a - это матрица, которая у вас есть.

A.topLeftCorner(a.rows(),a.cols())=a;

то же самое для нижнего правого угла, если вы не хотите перевернуть матрицу (попробуйте методы .reverse() и .transpose(), чтобы получить желаемый эффект переворота) a, прежде чем копировать ее туда.

Вы также можете попробовать функцию .block() для лучшей обработки матриц.

person Aperture Laboratories    schedule 11.03.2015