【问题标题】:symmetric matrix half vectorization对称矩阵半向量化
【发布时间】:2013-05-30 14:36:34
【问题描述】:

我面临一个关于如何将给定对称矩阵(它是距离矩阵)的下三角因子存储到向量中的问题。

一般来说,我想通过只给出矩形网格上一组点的坐标(Y,Z) 来直接生成下三角形条目:实际上这是我被卡住的地方。

因此,我开始考虑从稍微不同的角度解决问题:生成全距离矩阵(再次给出 (Y,Z) 对),然后对距离矩阵进行半向量化。

尽管如此,我对如何通过for 循环实现目标并没有真正的想法。

此外我还知道可能有任何外部Java 库实现vech 函数:vech 返回通过消除方阵X 的所有上对角元素获得的向量和将结果堆叠在一列之上。这在矩阵演算中使用,其中基础矩阵是对称的,将值保持在主对角线之上是没有意义的。

基本上,给定一个矩阵A = {{a,c},{b,d}},通过应用vech(A),结果将是 vech(A) = {a,b,d}.

编辑

我的意思是这样的:

    a11 a12 a13 a14
        a22 a23 a24
 A=         a33 a34  (aij = aji)
                a44

A上三角的打包存储:

  AP = { a11, a12, a22, a13, a23, a33, a14, a24, a34, a44 }

【问题讨论】:

  • 最后一句话;到目前为止你尝试过什么?
  • @OliCharlesworth:我尝试了几个 for 循环,但没有成功,我将编辑我的问题,包括我的试用。
  • 我建议交换你的问题 - 首先询问如何使用标准 for 循环来做到这一点,然后提到你还想了解一个库,否则这个问题往往没有建设性。

标签: java matrix


【解决方案1】:
public static double[] vech(double[][] a) {
    int na = Math.min(a.length, a[0].length); // Dimension of the matrix
    int nv = na * (na + 1) / 2; // 1 + 2 + 3 + .. + na
    double[] v = new double[nv];
    int k = 0; // index in v.
    for (int i = 0; i < na; ++i) {
        for (int j = 0; j <= i; ++j) {
            v[k] = a[i][j];
            ++k;
        }
    }
    return v;
}

案例 2x2 矩阵:

选择 [0][0]、[1][0]、[1][1](跳过 [0][1])

行主要顺序:(C, C#, Java) a[i][j] 是第 i 行第 j 列的元素。

代码使左下角的三角形变平。

列主序:(MATLAB, SciLab) a[i][j] 是第 i 列第 j 行的元素。

代码使右上角的三角形变平。

其他序列

另一个三角形将被给出为:

        for (int j = i; j < na; ++j) {

结合主对角线的镜像,再次得到原三角形:

            a[j][i]

【讨论】:

  • 如果我想以column-major 的方式访问v 元素?
  • 行优先和列优先的区别是 [i][j][j][i] 或在主对角线上镜像。
【解决方案2】:

我想不出一个库可以让你这样做,虽然我确信某处有一个,但你可以使用如下的 for 循环:

ArrayList<ArrayList<int>> matrix = new ArrayList<ArrayList<int>>();
// add other arraylists to your matrix here i.e.:

ArrayList<Integer> first = new ArrayList<Integer>();
first.add(1);
first.add(2);
first.add(3);

ArrayList<Integer> second = new ArrayList<Integer>();
second.add(4);
second.add(5);
second.add(6);

ArrayList<Integer> third = new ArrayList<Integer>();
third.add(7);
third.add(8);
third.add(9);

matrix.add(first);
matrix.add(second);
matrix.add(third);

ArrayList<int> finalArray = new ArrayList<int>();

for(int i=0; i<matrix.size(); i++)
{
    ArrayList<Integer> inner = matrix.get(i);
    for(int j=0; j<i+1; j++)
    {
        finalArray.add(inner.get(j));
    }
}   

这给出:matrix=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]finalArray=[1, 4, 5, 7, 8, 9]

当然,这是假设您的矩阵是使用数组列表构造的。

【讨论】:

    【解决方案3】:

    所有这些包装还有一个有趣的地方。您还可以定义一个映射算法,将对称矩阵中的(i, j) 位置转换为展平数组中的等效偏移量(就像您描述的那样)。您可以使用Arithmetic progression 的思想来定义这样的映射。我在la4j 中处理RandomSymmetricMatrixSource.java 类时这样做了。所以,你可以使用这些公式(i == j时不处理这种情况):

    int flatten(int i, int j) {
      int offset = -1;
    
      if (i < j) {
        offset = j - (i + 1) + (int)((((size - 1) + (size - i)) / 2.0) * i);
      } else {
        offset = i - (j + 1) + (int)((((size - 1) + (size - j)) / 2.0) * j);
      }
    
      return offset;
    }
    

    ,其中size是对称矩阵的大小。

    【讨论】:

      猜你喜欢
      • 2017-02-15
      • 2021-12-01
      • 2022-10-21
      • 1970-01-01
      • 2012-06-17
      • 2014-01-03
      • 2011-06-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多