6

我有一个下三角 MatrixXd,我想将其较低的值复制到上侧,因为它将成为一个对称矩阵。我该怎么做?

到目前为止,我已经完成了:

 MatrixXd m(n,n); 
 .....
 //do something with m
 for(j=0; j < n; j++)
       {
         for(i=0; i<j; i++)
           {
             m(i,j) = m(j,i);

           }
       }

有最快的方法吗?我正在考虑一些能够将下三角矩阵“复制”到上三角矩阵的内部方法。假设我有这个矩阵,我们称之为m

1 2 3
4 5 6
7 8 9

我需要获得的m是:

1 4 7
4 5 8
7 8 9

我也知道你可以让矩阵的上部或下部做一些事情:

MatrixXd m1(n,n);
 m1 = m.triangularView<Eigen::Upper>();
cout << m1 <<endl;

1 2 3
0 5 6
0 0 9

但是我还没有得到我想要的...

4

7 回答 7

4

I assume here that you are referring to working with the Eigen3 c++ library. This is not clear from your question. if not, you should consider it. In any case, within Eigen, there is no need to actually copy the triangular part, to get a selfadjoint matrix. Eigen has the concept of views, and you can use a self adjoint view in order to perform an operation like e.g.

using namespace Eigen;
MatrixXd m(m,n);
...
(generate uppper triangular entries in m)
...
VectorXd r(n), p(n);
r = m.selfadjointView<Upper>() * p;

here is a small example to illustrate using fixed size matrices:

#include <Eigen/Core>

using namespace std;
using namespace Eigen;

int main()
{
    Matrix2d m,c;
    m << 1, 2,
         0, 1;

    Vector2d x(0,2), r;

    // perform copy operation 
    c = m.selfadjointView<Upper>(); 
    cout << c << endl;

    // directly apply selfadjoint view in matrix operation
    // (no entries are copied)
    r = m.selfadjointView<Upper>() * x;
} 

the output will be [1, 2, 2, 1]. now, the result in r is the same as if you had used c * x instead. Just that there is no need for copying the values in the original matrix to make it selfadjoint.

于 2012-08-23T08:16:16.877 回答
4

如果 selfadjointView 不适合您,解决方案是在目标矩阵上使用 triangularView:

m.triangularView<Lower>() = m.transpose();

于 2012-09-02T09:20:19.517 回答
2

我能想到的最简单的方法是将m矩阵的上半部分移到上半部分:

    m.triangularView<Upper>() = m.transpose();

例如,下面的代码:

    MatrixXd m(3,3);
    m << 1, 2, 3, 4, 5, 6, 7, 8, 9;

    m.triangularView<Upper>() = m.transpose();
    std::cout << m << std::endl;

给出您要求的输出:

1 4 7
4 5 8
7 8 9

问候。

于 2014-04-09T15:35:36.023 回答
2

简单地:

m = m.selfadjointView<Upper>();
于 2017-11-07T20:10:35.743 回答
1

我认为你的做法是正确的。如果您了解矩阵中数据的内存布局的一些细节,您可以使用一些低级优化。其中一种技术是循环平铺

于 2012-08-22T14:25:45.670 回答
1

如果速度是一个大问题,我不会复制任何东西,只是用一个坐标反转对象来装饰/包装矩阵对象,该对象会将 (x,y) 翻转为 (y,x)。如果您将 () 运算符设为内联函数,则使用它时不会产生任何重大成本。

于 2012-08-22T14:25:51.210 回答
-1

这行得通,你可以剪一些东西,但你至少需要 n*m/2 (少一些东西),所以只有 2x

编辑:我看到你使用这个矩阵对象......语法不同,但算法是这样的,无论如何

#include <stdio.h>


int main ( )
{
    int mat [ 4 ] [ 4 ];
    int i, j;

    mat [ 0 ] [ 0 ] = 0;
    mat [ 0 ] [ 1 ] = 1;
    mat [ 0 ] [ 2 ] = 2;
    mat [ 0 ] [ 3 ] = 3;
    mat [ 1 ] [ 0 ] = 4;
    mat [ 1 ] [ 1 ] = 5;
    mat [ 1 ] [ 2 ] = 6;
    mat [ 1 ] [ 3 ] = 7;
    mat [ 2 ] [ 0 ] = 8;
    mat [ 2 ] [ 1 ] = 9;
    mat [ 2 ] [ 2 ] = 10;
    mat [ 2 ] [ 3 ] = 11;
    mat [ 3 ] [ 0 ] = 12;
    mat [ 3 ] [ 1 ] = 13;
    mat [ 3 ] [ 2 ] = 14;
    mat [ 3 ] [ 3 ] = 15;

    for ( i = 0; i < 4; i++ )
    {
        for ( j = 0; j < 4; j++ )
            printf ( "%02d", mat [ i ] [ j ] );
        printf ( "\n" );
    }
    printf ( "\n" );

    for ( i = 1; i < 4; i++ )
    {
        for ( j = 0; j < i; j++ )
            mat [ j ] [ i ] = mat [ i ] [ j ];
    }

    for ( i = 0; i < 4; i++ )
    {
        for ( j = 0; j < 4; j++ )
            printf ( "%02d ", mat [ i ] [ j ] );
        printf ( "\n" );
    }
    printf ( "\n" );

    scanf ( "%d", &i );
}
于 2012-08-22T14:18:33.953 回答