【问题标题】:How to handle the indices of a 9-dimensional matrix如何处理 9 维矩阵的索引
【发布时间】:2017-07-03 13:06:10
【问题描述】:

我是一名物理学家,目前正在编写一个处理多维积分的 C++ 程序;特别是,我正在考虑的函数最多可以有 D=9 维。

从数学角度来看,我需要处理 NxNxN...xN(D 次)矩阵,但从编程的角度来看,我被指示使用 NxNxN...xN 元素的数组。据我所知,为了通用性和所有随后涉及指针的计算,数组更好。

但是,现在我遇到了一个我无法解决的问题。

我需要执行一些计算,其中我的矩阵的单个索引是固定的,而所有其他的都取所有不同的值。

如果它是一个 3x3x3 矩阵,代码将类似于以下内容:

double test[3][3][3];
for(int i=0;i<3;i++) {
    for(int j=0;j<3;j++) {
    test[0][i][j]=i*j;
    }
}

即我可以固定一个索引并循环浏览其他索引。 同样的过程也可以扩展到第二个和第三个索引。

如何使用double test[3*3*3] 实现相同的效果?请记住,三维矩阵只是一个例子;我正在处理的真实矩阵是 9 维的,因此我需要一种通用方法来保持矩阵的单个索引固定并循环遍历所有其他矩阵。

TL;DR:我有一个表示 NxNxN...xN(9 次)矩阵的数组。 我需要对数组执行一些计算,就好像我的矩阵的单个索引是固定的,而所有其他索引都在循环遍历它们所有可能的值。

我知道对于二维矩阵映射到一维数组的情况有一个简单的表达式;这里有类似的东西吗?

【问题讨论】:

  • 只是一些强迫症术语 - 矩阵是一个 2 维张量
  • @spug OCD?真的吗?
  • @Walter as in,我知道 OP 的意思,但还是觉得有必要纠正他
  • 关于您的示例的旁注:您应该为您的尺寸使用不同的尺寸。为3*3*3 编写解决方案意味着您永远不知道哪个3 代表哪个维度;)
  • 从编程的角度来看,我被指示使用 NxNxN...xN 个元素的数组来代替...为什么?这是锻炼吗?是为了速度吗?

标签: c++ arrays matrix


【解决方案1】:

Raster scan 是二维元素排序的标准方式。

如果您有一个二维数组test[3][3],并且您通过test[i][j] 访问它,则对应的一维数组将是

double raster[3 * 3];

您可以按如下方式访问它:

raster[i * 3 + j];

这可以概括为 3 个维度:

double raster[3 * 3 * 3];
...
raster[a * 9 + b * 3 + c];

或到 9 个维度:

double raster[3 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3];
...
raster[a * 6561 + b * 2187 + c * 729 + d * 243 + e * 81 + f * 27 + g * 9 + h * 3 + i];

使任何a ... i 索引变量保持不变,并在循环中更改其余变量,将访问 9 维数组中的 8 维切片。


您可能想要定义一些 struct 来保存所有这些索引,例如:

struct Pos
{
    int a, b, c, d, e, f, g, h, i;
};

然后您可以轻松地将位置转换为一维索引:

int index(Pos p)
{
    return p.a * 6561 + p.b * 2187 + p.c * 729 + p.d * 243 + p.e * 81 + p.f * 27 + p.g * 9 + p.h * 3 + p.i;
}

【讨论】:

    【解决方案2】:

    一般来说,一个扁平化的数组会以下列方式包含它的元素:最后一维的元素将被映射到重复的组中,最里面的组将是从后面算起的第二个维度,依此类推:

    values[x][y][z] => { x0 = { y0_0 = { z0_0_0, z0_0_1, ..., z0_0_N }, y0_1 = { z0_1_0, z0_1_1, ... }, ... y0_N }, x1 = ... }
    values[x*y*z] => { z0_0_0, z0_0_1, ..., z0_0_N, z0_1_0, z0_0_1, ... }
    

    我希望这在我的大脑之外有意义。

    因此,任何元素访问都需要计算,在它之前有多少个元素块:

    访问[2][1][3] 意味着,跳过2 个x 块,每个块包含y 块和z 元素,然后跳过另外1 个y 块包含z 元素并访问第三个元素下一个区块:

    values[2 * y * z + 1 * z + 3];
    

    所以更一般地对于 N 维 d1, d2, d3 .. dn 和要访问的 n 维索引 i1, i2, .. iN

    [i1 * d2 * ... * dN + i2 * d3 * ... * dN + ... + iN]
    

    回到你的例子:

    double test[3*3*3];
    for(int i = 0; i < 3; i++)
    {
        for(int j = 0; j < 3; j++)
        {
            // test[0*3*3 + i*3 + j] = i * j;
            test[i*3 + j] = i * j;
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果矩阵的所有维度都具有相同的大小,那么您可以像这样访问它们:

      m[x + y*N + z*N*N + w*N*N*N ...]
      

      大小不同的情况下,稍微复杂一点:

      m[x + y*N1 + z*N1*N2 + w*N1*N2*N3 ...]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-17
        • 1970-01-01
        • 2012-04-26
        • 1970-01-01
        • 2012-09-25
        • 1970-01-01
        相关资源
        最近更新 更多