numpy 邻接表中邻接矩阵的花式索引计算

pn9klfpd  于 2022-11-23  发布在  其他
关注(0)|答案(3)|浏览(176)

问题

在给定邻接表E_ij的情况下,我想计算几次邻接矩阵A_ij,其中E_ij[t,i] = j给出了从ij的边,时间为t
我可以用下面的代码做到这一点:

import numpy as np

nTimes = 100
nParticles = 10
A_ij = np.full((nTimes, nParticles, nParticles), False)
E_ij = np.random.randint(0, 9, (100, 10))

for t in range(nTimes):
    for i in range(nParticles):
        A_ij[t, i, E_ij[t,i]] = True

问题:

如何以矢量化的方式来实现它,要么使用花哨的索引,要么使用像np.take_along_axis这样的numpy函数?

我尝试的是:

我希望这能奏效:

A_ij[:,np.arange(nParticles)[None,:,None], E_ij[:,None,np.arange(nParticles)]] = True

但事实并非如此。
相关项目:Trying to convert adjacency list to adjacency matrix in Python

yiytaume

yiytaume1#

我想这可能行得通:

import numpy as np

nTimes = 100
nParticles = 10
A_ij = np.full((nTimes, nParticles, nParticles), False)
E_ij = np.random.randint(0, 9, (100, 10))

np.put_along_axis(A_ij, E_ij[..., None], True, axis=2)
mwecs4sa

mwecs4sa2#

另一种方法,接近你在最后实际尝试的方法,是这样的:

i, j = np.mgrid[:nTimes, :nParticles]
A_ij[i, j, E_ij] = True

但公认的答案肯定是解决问题的更好方法,不需要构建指数。

vojdkbi0

vojdkbi03#

为了防止可能对其他人有帮助,我还找到了一种方法在这个问题上做花哨的索引,但@ Chrysophylax的答案更快更简单(我猜我对索引感到困惑,无法思考它)。我还添加了@Mercury的答案以供比较。

代码:

import numpy as np
import matplotlib.pyplot as plt
import time

nTimes = 1000000
nParticles = 10
A_ij1 = np.full((nTimes, nParticles, nParticles), False)
A_ij2 = np.full((nTimes, nParticles, nParticles), False)
A_ij3 = np.full((nTimes, nParticles, nParticles), False)
A_ij4 = np.full((nTimes, nParticles, nParticles), False)

E_ij = np.random.randint(0, 9, (nTimes, 10))

start_time = time.time()
for t in range(nTimes):
    for i in range(nParticles):
        A_ij1[t, i, E_ij[t,i]] = True
print("Loop: %s s" % (time.time() - start_time))

        
start_time = time.time()
A_ij2[np.arange(nTimes)[:,None],np.arange(nParticles)[None,:], E_ij[np.arange(nTimes)[:,None],np.arange(nParticles)[None,:]]] = True
print("Fancy indexing: %s s" % (time.time() - start_time))

start_time = time.time()
np.put_along_axis(A_ij3, E_ij[..., None], True, axis=2)
print("Put along axis: %s s" % (time.time() - start_time))

start_time = time.time()
i, j = np.mgrid[:nTimes, :nParticles]
A_ij4[i, j, E_ij] = True
print("mgrid: %s s" % (time.time() - start_time))

print(np.allclose(A_ij1, A_ij2))
print(np.allclose(A_ij1, A_ij3))
print(np.allclose(A_ij1, A_ij4))

输出:

Loop: 2.5006823539733887 s
Fancy indexing: 0.11996173858642578 s
Put along axis: 0.0814671516418457 s
mgrid: 0.19223332405090332 s
True
True
True

相关问题