如何减少for循环层次

发布时间 2023-10-24 09:32:58作者: Emi-lia

背景

数值上计算能量本征值往往采用矩阵对角化的方法。第一步是需要生成如下的矩阵:

\[\braket{n|H|n^{\prime}} \]

在计算这个矩阵的时候,只涉及两个变量:\(n\),\(n^{\prime}\)。因此两重for循环就可以解决这个问题。

但是其他的情况下(如:系统中有两个粒子),需要生成的矩阵变成了:

\[\braket{n_1,n_2|H|n_{1}^{\prime},n_{2}^{\prime}} \]

这种模式。就涉及到了四个变量,难道要写四重for循环吗?

for循环降维

在计算机存储中高维的矩阵其实都是线性存储的。并且所有的高维数组都可以被拉成一维。

二维

如下图所示的一个N\(\times\)M的二维矩阵,其中N=3,M=3。用\(i\)表示每一个矩阵元的编号,用\(n\)表示矩阵的行编号,用\(m\)表示矩阵的列编号。图中红圈圈中的就是第一行第一列第4个矩阵元,原本我们表示这个矩阵元需要\((1,1)\),现在可以直接用\(4\)表示。原本我们表示某一个矩阵元需要\((n,m)\),现在可以直接用\(i=n*M+m\)表示。

N
M
4
0
1
2
3
5
6
7
8

三维

通常表示三维矩阵中的一个矩阵元需要\((n,m,l)\),先利用二维矩阵的处理方法,将前两维看成一维,则矩阵元可以表示为\((n*M+m,l)\),拉成一维以后则可以用\((n*M+m)*L+l\)来表示。

N
M
4
0
1
2
3
5
6
7
8
...
L

更高维度的表示方法与此类似(逐维降低:四维拉成三维——>三维拉成二维——>二维拉成一维)。

代码展示

//降维前
for(int n1=0;n1<n_1m;n1++){
    for(int n2=0;n2<n_2m;n2++){
        for(int n11=0;n11<n_1m;n11++){
            for(int n21=0;n21<n_2m;n21++>){
                pass
            }
        }
    }
}
\\降维后
n = n_1m*n_2m;
for(int i=0;i<n;i++){
    n1 = i/n_2m;
    n2 = i%n_2m;
    for(int j=0;j<n;j++){
        n11 = j/n_2m;
        n21 = j%n_2m;
    }
}

其他的应用

动态分配内存的时候分配二维的地址往往很麻烦,将数组拉成一维然后动态存储也是可以的。