Language agnostic 如何存储对称矩阵?

Language agnostic 如何存储对称矩阵?,language-agnostic,matrix,Language Agnostic,Matrix,在内存中存储对称矩阵的最佳方法是什么 在不过分牺牲结构的速度和复杂性的情况下,节省一半的空间是很好的。这是一个语言不可知的问题,但是如果你需要做一些假设,假设它是一个很好的普通的编程语言,如C或C++……/P> 这似乎是一件有意义的事情,只是如果有一种方法可以让事情简单化,或者只是当矩阵本身非常大的时候,我说的对吗 出于形式上的考虑,我的意思是,对于我要存储的数据,这个断言总是正确的 matrix[x][y] == matrix[y][x] 我会尝试一个三角形矩阵,像这样: int[][] s

在内存中存储对称矩阵的最佳方法是什么

在不过分牺牲结构的速度和复杂性的情况下,节省一半的空间是很好的。这是一个语言不可知的问题,但是如果你需要做一些假设,假设它是一个很好的普通的编程语言,如C或C++……/P> 这似乎是一件有意义的事情,只是如果有一种方法可以让事情简单化,或者只是当矩阵本身非常大的时候,我说的对吗

出于形式上的考虑,我的意思是,对于我要存储的数据,这个断言总是正确的

matrix[x][y] == matrix[y][x]

我会尝试一个三角形矩阵,像这样:

int[][] sym = new int[rows][];
for( int i = 0; i < cols; ++i ) {  
     sym=new int[i+1];
}
int[] new matrix[(rows * (rows + 1 )) >> 1];
int z;
matrix[ ( ( z = ( x < y ? y : x ) ) * ( z + 1 ) >> 1 ) + ( y < x ? y : x ) ] = yourValue; 
int[]sym=新的int[rows][];
对于(int i=0;i
但是,当有人想进入“另一边”时,你将不得不面对这个问题。例如,他希望访问[0][10],但在您的情况下,此val存储在[10][0](假设为10x10)


也许“最好”的方法是懒惰的方法——在用户请求之前不要做任何事情。因此,如果用户键入诸如print(矩阵[4])之类的内容,则可以加载特定行。

如果您使用的是支持运算符重载的内容(例如C++),则很容易透明地处理此问题。只需创建一个检查两个下标的矩阵类,如果第二个下标大于第一个,则交换它们:

template <class T>
class sym_matrix { 
    std::vector<std::vector<T> > data;
public:
    T operator()(int x, int y) {
        if (y>x)
            return data[y][x];
        else
            return data[x][y];
    }
};
模板
类sym_矩阵{
std::矢量数据;
公众:
T运算符()(整数x,整数y){
如果(y>x)
返回数据[y][x];
其他的
返回数据[x][y];
}
};

目前,我跳过了所有其他内容,只讨论了订阅。实际上,要正确地处理作为左值和右值的使用,通常需要直接返回代理而不是T。您将需要一个将
数据
创建为三角形(即,对于NxN矩阵,第一行将有N个元素,第二行将有N-1,依此类推——或者,相当于1,2,…N)。你也可以考虑创建<代码>数据<代码>作为一个单一的代码>矢量< /代码>——你必须计算正确的偏移量,但是这不是很困难,它会使用更少的内存,运行得更快一些。我会使用第一个版本的简单代码,必要时再优化。

你可以使用交错数组。(或者不管他们叫什么)如果你的语言支持它,当x n x n矩阵的伪代码(有点Python风格,但不是真的):

matrix[n][]

for i from 0 to n-1:
    matrix[i] = some_value_type[i + 1]

[next, assign values to the elements of the half-matrix]
当提到价值观时

if x < y:
    return matrix[y][x]
else:
    return matrix[x][y]
如果x
我发现许多高性能软件包只存储整个矩阵,但只读取上三角或下三角。它们可能会在计算过程中使用额外的空间来存储临时数据

但是,如果存储确实是一个问题,那么只需将构成上三角形的
n(n+1)/2
元素存储在一维数组中。如果这使访问变得复杂,只需定义一组帮助函数

在C中,要访问矩阵
matA
,可以定义宏:

#define A(i,j, dim) ((i <= j)?matA[i*dim + j]:matA[j*dim + i])

#定义一个(i,j,dim)((i如果你想使用一个一维数组,代码应该是这样的:

int[][] sym = new int[rows][];
for( int i = 0; i < cols; ++i ) {  
     sym=new int[i+1];
}
int[] new matrix[(rows * (rows + 1 )) >> 1];
int z;
matrix[ ( ( z = ( x < y ? y : x ) ) * ( z + 1 ) >> 1 ) + ( y < x ? y : x ) ] = yourValue; 
int[]新矩阵[(行*(行+1))>>1];
intz;
矩阵[((z=(x>1+(y
如果创建一个额外的查找表,则可以消除乘法:

int[] new matrix[(rows * (rows + 1 )) >> 1];
int[] lookup[rows];
for ( int i= 0; i < rows; i++)
{
   lookup[i] = (i * (i+1)) >> 1;
}
matrix[ lookup[ x < y ? y : x ] + ( x < y ? x : y )  ] = yourValue;
int[]新矩阵[(行*(行+1))>>1];
int[]查找[行];
对于(int i=0;i>1;
}
矩阵[查找[x
这里有一个存储对称矩阵的好方法,它只需要N(N+1)/2个内存:

int fromMatrixToVector(int i, int j, int N)
{
   if (i <= j)
      return i * N - (i - 1) * i / 2 + j - i;
   else
      return j * N - (j - 1) * j / 2 + i - j;
}
1D表示(例如存储在
std::vector
中)如下所示:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
调用fromMatrixToVector(1,2,4)返回5,因此矩阵数据为vector[5]->5


有关更多信息,请参见
sym[i]=new int[i+1]
?是否应该将“reffering to values”放在像这样一个返回值getElement(x,y)的包装函数中?(我不知道Python)这似乎是一个很好的解决方案,在接受之前让我尝试一下:)我很难理解宏。宏用于访问1D数组中的元素吗?@Rajath,我认为给定一个带有
dim
行的方阵,
a(I,j,dim)
返回1D数组中
I,j
的索引。宏不准确,因为它可能试图访问定义范围n以外的元素(n+1)/2.@Ale宏是精确的,它总是从上三角子矩阵读取。没有意图让它使用
n(n+1)/2
存储。看看这个答案()可以帮助将对称矩阵存储到1D数组中。Ben Axelrod的文章(你引用)有一些很好的三角形数组的ASCII图,以及它在1D中的样子。也许你可以将它们复制到你的答案中?它们帮助我将其可视化。添加了矩阵可视化。第一个表达式可以重写为
(2*N-i-1)*i/2+j