【问题标题】:make efficient the copy of symmetric matrix in c#在c#中有效地复制对称矩阵
【发布时间】:2012-02-20 18:57:52
【问题描述】:

我想在数组中存储一个对称矩阵

对于我正在做的矩阵

    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]);
    }

如果我想存储在一个数组中

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

而不是

 double[,] mat

最有效的方法是什么?

使用mat[i*n+j]?

【问题讨论】:

  • 哪一个是问题?内存还是 CPU 性能?
  • 我还不能写评论 - size 有什么限制?
  • @Saeed Amiri 表演
  • 所以正常操作(将所有数据保存在 RAM 中)就足够了。
  • 如果矩阵是稀疏的,您将需要一个 spart 矩阵实用程序。

标签: c# loops matrix


【解决方案1】:

是的。

按行存储元素,其中i-th 行和j-th 列存储在索引k=i*NC+j 中,NC 列数。这适用于非对称一般矩阵。

要存储大小为N 的对称矩阵,您只需要数组中的N*(N+1)/2 元素。您可以假设 i&lt;=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

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

例如当 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 |

所需的总元素是5*(5+1)/2 = 15,因此索引来自0..14

i-th 对角线的索引为 k(i,i) = i*(N+1)-i*(i+1)/2。所以第 3 行 (i=2) 的对角线索引为 k(2,2) = 2*(5+1)-2*(2+1)/2 = 9

i-th 行的最后一个元素的索引 = k(i,N) = N*(i+1)-i*(i+1)/2-1。所以第三行的最后一个元素是k(2,4) = 5*(2+1)-2*(2+1)/2-1 = 11

您可能需要的最后一部分是如何从数组索引k 转到i 行和j 列。再次假设i&lt;=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

为了检查上述内容,我对N=5k=0..14 运行此命令并得到以下结果:

这是正确的!

要制作副本,只需在超快的元素上使用Array.Copy()。此外,要执行加法和缩放等操作,您只需要处理数组中的缩减元素,而不是完整的N*N 矩阵。矩阵乘法有点棘手,但可行。如果你愿意,也许你可以问另一个问题。

【讨论】:

【解决方案2】:

关于选择的答案,除非我是个十足的白痴,否则代码不正确:

试试这个:

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

从所选答案中的矩阵我们看到 (2,1) 不是 7,它似乎是 6。事实上(因为这似乎是 0 基数),7 出现在 (3,1) 或(1,3)。 i > j 的第二个公式似乎不准确,除非我遗漏了什么。

更新:

如果您将 i > j 公式更改为:

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

【讨论】:

  • 在此之后似乎已更正所选答案。
【解决方案3】:

如果 n 是方阵的大小,则对称矩阵需要 n * (n + 1) / 2 个总值。这是 1 + 2 + 3 + ... (n - 2) + (n - 1) + n 的总和。

但请注意,总是尝试为给定的行和列计算正确的索引将是一个很大的痛苦,如果矩阵是,我只会远离更直观的 2D 数组会很大,内存会成为问题。

【讨论】:

  • 对吗mat[i*n +j] = mat[j*n+i] = (n * other_matrix[i,j]);
  • 嗯...有点。它会是这样的: if(i n +j]; } else { 返回垫子[jn+i]; }。 i 和 j 的全部范围在 mat 数组中不可用,因为您只存储了整个矩阵的一半(因为您不需要全部存储它——它是对称的)。但就像我说的,索引的东西变得相当棘手。我建议帮自己一个忙,将它全部包装在一个 SymmetricMatrix 类或其他东西中,并允许使用该类的人在大多数情况下将其视为普通矩阵。您只需要处理类内的索引。
  • 1,2,3..N 的总和是N*(N+1)/2。检查它在wolframalpha.com/input/?i=sum%28i%2Ci%2C1%2CN%29
  • @ja72:你说得对。我会更新我的答案。我把它写在纸上(我用手重新推导出来)但写错了。对不起!
猜你喜欢
  • 2012-10-13
  • 2011-05-27
  • 1970-01-01
  • 2021-10-06
  • 1970-01-01
  • 2019-09-10
  • 1970-01-01
  • 1970-01-01
  • 2018-12-13
相关资源
最近更新 更多