【发布时间】:2020-07-30 10:44:43
【问题描述】:
背景
我正在尝试对可以在每个时间步更改其配置的系统进行建模。配置的多样性是预先知道的,并且不依赖于时间步长。某些配置之间允许转换,而其他配置之间则禁止转换。目标是构建一个允许转换的邻接连接矩阵,该矩阵跨越多个时间步。
设置
让A 是一个s*s*k 逻辑矩阵,表示允许的转换,A1...Ak 表示A 的页面/切片:
A1 = A(:,:,1); A2 = A(:,:,2); ... Ak = A(:,:,k);
第3维的意思是一次转换需要多少个时间步,例如:如果A(1,3,2)不为零,则表示状态#1可以转换到状态#3,这需要@987654331 @时间步长。
让B 成为我们要构建的邻接矩阵,它代表nt 时间步长。 B 的形状应该是示意性的(以块矩阵表示法):
_ _
| [0] [A1] [A2] ... [Ak] [0] ... [0] |
B = | [0] [0] [A1] [A2] ... [Ak] ... [0] |
| ⋮ ⋮ ⋱ ⋱ ⋱ ⋮ |
|_[0] [0] … … … … … … … … [0]_| "[A1] [A2] ... [Ak]"
主块对角线由nt 0 块组成,A 的切片逐渐“推”到右侧直到“时间用完”,A 的切片最终“向外”的B ⇒ 表示不再可能进行转换。由于B 由nt*nt s*s 块组成,其大小为(nt*s)×(nt*s)。
问题:给定
A和nt,我们如何以最节省CPU 和内存的方式构造B?
注意事项
- 由于
B大部分都用零填充,所以sparse可能是有意义的。 - 在我的应用程序中,CPU 效率(运行时)比内存效率更重要。
- 在真正的问题中,
s=250和nt=6000。 - 欢迎使用外部脚本/类/工具。
- 我的一个想法不是最初构建交错矩阵,而是使用
[A1]块和circshift-ing 的主对角线,并在其他所有操作完成后进行屏蔽。
演示 + 朴素实施
s = 3; k = 4; nt = 8;
A = logical(cat(3, triu(ones(s)), eye(s), zeros(s), [0 0 0; 0 0 0; 0 1 0]));
% Unwrap A (reshape into 2D):
Auw = reshape(A, s, []);
% Preallocate a somewhat larger B:
B = false(nt*s, (nt+k)*s);
% Assign Auw into B in a staggered fashion:
for it = 1:nt
B( (it-1)*s+1:it*s, it*s+1:(it+k)*s ) = Auw;
end
% Truncate the extra elements of B (from the right)
B = B(1:nt*s, 1:nt*s);
spy(B);
导致:
【问题讨论】:
-
我有一个矢量化解决方案,需要多 10 倍的时间:-D
-
对于像这样具有稀疏图的图算法,使用每个节点都有一个相邻节点 ID 数组(节点数组的索引)的表示通常更有效。访问节点的所有邻居变得更快。
-
@Cris 我们计划在转换矩阵完成后使用
digraph。该函数接受两种输入类型(即转换列表或邻接矩阵),并且很可能在早期将它们内部转换为相同的表示形式。我个人认为构建矩阵更容易,尽管这些系统之间的转换非常简单。如果您决定发布一个,我相信未来的读者可以从您建议的解决方案中受益:)
标签: performance matlab matrix graph-theory adjacency-matrix