简体   繁体   English

在c#中高效复制对称矩阵

[英]make efficient the copy of symmetric matrix in c#

I want to store in an array a symmetric matrix 我想在一个数组中存储一个对称矩阵

for a matrix I was doing this 对于矩阵我正在这样做

    double[,] mat = new double[size,size];
    for (int i = 0; i < size; i++)
    {
      for (int j = 0; j <= i; j++)
           mat[i, j] = mat[j, i] = (n * other_matrix[i,j]);
    }

If I want to store in an array 如果我想存储在一个数组中

double[] mat = new double[size*size];

instead of 代替

 double[,] mat

What would be the most efficient way? 什么是最有效的方式?

using mat[i*n+j] ? 使用mat[i*n+j]

Yes. 是。

Store the elements by row, where the i -th row and j -th column is stored in index k=i*NC+j with NC the number of columns. 按行存储元素,其中第i行和第j列存储在索引k=i*NC+j其中NC为列数。 This applies to a non-symmetric general matrix. 这适用于非对称通用矩阵。

To store a symmetric matrix of size N you only need N*(N+1)/2 elements in the array. 要存储大小为N的对称矩阵,您只需要在数组中使用N*(N+1)/2元素。 You can assume that i<=j such that the array indexes go like this: 您可以假设i<=j ,使得数组索引如下所示:

k(i,j) = i*N-i*(i+1)/2+j            i<=j  //above the diagonal
k(i,j) = j*N-j*(j+1)/2+i            i>j   //below the diagonal

with

i = 0 .. N-1
j = 0 .. N-1

Example when N=5, the array indexes go like this 当N = 5时,数组索引就像这样

| 0   1   2   3   4 |
|                   |
| 1   5   6   7   8 |
|                   |
| 2   6   9  10  11 |
|                   |
| 3   7  10  12  13 |
|                   |
| 4   8  11  13  14 |

The total elements needed are 5*(5+1)/2 = 15 and thus the indexes go from 0..14 . 所需的总元素是5*(5+1)/2 = 15 ,因此索引从0..14 校验

The i -th diagonal has index k(i,i) = i*(N+1)-i*(i+1)/2 . i个对角线具有索引k(i,i) = i*(N+1)-i*(i+1)/2 So the 3rd row ( i=2 ) has diagonal index k(2,2) = 2*(5+1)-2*(2+1)/2 = 9 . 因此第3行( i=2 )具有对角线索引k(2,2) = 2*(5+1)-2*(2+1)/2 = 9 校验

The last element of the i -th row has index = k(i,N) = N*(i+1)-i*(i+1)/2-1 . i行的最后一个元素具有index = k(i,N) = N*(i+1)-i*(i+1)/2-1 So the last element of the 3rd row is k(2,4) = 5*(2+1)-2*(2+1)/2-1 = 11 . 所以第3行的最后一个元素是k(2,4) = 5*(2+1)-2*(2+1)/2-1 = 11 校验

The last part that you might need is how to go from the array index k to the row i and column j . 您可能需要的最后一部分是如何从数组索引k到第i行和第j列。 Again assuming that i<=j (above the diagonal) the answer is 再假设i<=j (在对角线上方)答案是

i(k) = (int)Math.Floor(N+0.5-Math.Sqrt(N*(N+1)-2*k+0.25))
j(k) = k + i*(i+1)/2-N*i

To check the above I run this for N=5 , k=0..14 and got the following results: 为了检查上面的内容,我运行N=5k=0..14 ,得到以下结果:

索引表

Which is correct! 哪个是对的! 校验

To make the copy then just use Array.Copy() on the elements which is super fast. 要制作副本,只需对Array.Copy()的元素使用Array.Copy() Also to do operations such as addition and scaling you just need to work on the reduced elements in the array, and not on the full N*N matrix. 另外,要进行添加和缩放等操作,只需要处理数组中的简化元素,而不是完整的N*N矩阵。 Matrix multiplication is a little tricky, but doable. 矩阵乘法有点棘手,但可行。 Maybe you can ask another question for this if you want. 如果你愿意,也许你可以提出另一个问题。

Regarding the selected answer, unless I am being a complete idiot the code isn't correct: 关于选定的答案,除非我是一个完全白痴,否则代码不正确:

Try this: 尝试这个:

i = 2, j = 1

therefore we use:

k(i,j) = j*N-j*(j-1)/2+i

to find the index k, solving:

k(i,j) = 1*5 - 1*(1-1)/2 + 2

k(i,j) = 5 - 0 + 2 = 7

From the matrix in the selected answer we see that (2,1) is not 7, it seems to be 6. In fact (since this seems to be 0-base), 7 occurs at (3,1) or (1,3). 从所选答案中的矩阵我们看到(2,1)不是7,它似乎是6.事实上(因为这似乎是0基),7发生在(3,1)或(1, 3)。 The second formula for i > j seems to be inaccurate unless I am missing something. i> j的第二个公式似乎不准确,除非我遗漏了什么。

UPDATE: 更新:

This seems to work if you alter the i > j formula to: 如果你改变i> j公式,这似乎有效:

k(i,j) = j*(N-1)-j*(j-1)/2+i

If n is the size of the square matrix, you need n * (n + 1) / 2 total values for a symmetric matrix. 如果n是方阵的大小,则对称矩阵需要n *(n + 1)/ 2个总值。 This is the sum of 1 + 2 + 3 + ... (n - 2) + (n - 1) + n. 这是1 + 2 + 3 + ...(n - 2)+(n - 1)+ n的总和。

A word of caution, though, it's going to be a big pain to be always trying to calculate the correct index for a given row and column, and I'd only move away from the more intuitive 2D array if the matrices are going to be large, and memory is going to be an issue. 但需要注意的是,总是试图计算给定行和列的正确索引将是一件很大的痛苦,如果矩阵将会是更加直观的二维数组,我只会离开它。大,记忆将是一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM