Emi*_*son 4 algorithm hash matlab dictionary
worldStates 是一个 Matlab MxNxL 3D 数组(张量),包含一个 MxN 二进制值网格的 L 个状态。
ps 是与不同状态相关联的概率的长度 L 列表。
该函数[worldStates, ps] = StateMerge(worldStates, ps)应删除重复的世界状态,并将合并状态的概率与剩余的单个状态相加。重复状态是具有完全相同的二进制值配置的状态。
这是此功能的当前实现:
function [worldStates, ps] = StateMerge(worldStates, ps)
M = containers.Map;
for i = 1:length(ps)
s = worldStates(:,:,i);
s = mat2str(s);
if isKey(M, s)
M(s) = M(s) + ps(i);
else
M(s) = ps(i);
end
end
stringStates = keys(M);
n = length(stringStates);
sz = size(worldStates);
worldStates = zeros([sz(1:2), n]);
ps = zeros(1, 1, n);
for i = 1:n
worldStates(:,:,i) = eval(stringStates{i});
ps(i) = M(stringStates{i});
end
end
Run Code Online (Sandbox Code Playgroud)
它使用 Map 能够在 O(L) 时间内删除重复项,使用状态作为键,使用概率作为值。由于 Matlab 映射不允许将通用数据结构作为键,因此状态被转换为字符串表示以用作键,然后使用 eval 函数转换回数组。
事实证明,这段代码可以满足我的需求,因为我想多次(10 ^ 3)处理许多状态(幅度~10 ^ 6)。问题在于将矩阵转换为字符串,这需要花费大量时间并且随着状态大小的缩放很差。下面给出了小 25x25 状态的示例:
如何以更有效的方式创建密钥?除了使用会产生更好结果的地图之外,还有其他解决方案吗?
编辑:按要求运行的代码。这个例子使得合并的可能性很小:
worldStates = double(rand(25,25, 1000) > 0.5);
weights = rand(1,1, 1000);
ps = weights./sum(weights);
[worldStates, ps] = StateMerge(worldStates, ps);
Run Code Online (Sandbox Code Playgroud)
在这个例子中会有很多合并:
worldStates = double(rand(25,25) > 0.5) .* ones(1,1,1000);
worldStates(1:2,1:2,:) = rand(2,2,1000) > 0.5;
weights = rand(1,1, 1000);
ps = weights./sum(weights);
[worldStates, ps] = StateMerge(worldStates, ps);
Run Code Online (Sandbox Code Playgroud)
使用unique提取独特(合并)状态和accumarray总结的概率合并状态。请注意,此解决方案与您的解决方案一样,不会保留原始状态的顺序。正如@Wolfie 在评论中所建议的,您可以使用unique'stable' 选项来保留状态的顺序:
function [worldStates, ps] = StateMerge(worldStates, ps)
[M, N, L] = size (worldStates);
worldStates1 = reshape(worldStates, M*N, L).';
[~, uc, ui] = unique(worldStates1, 'rows');
ps = accumarray(ui, ps(:));
worldStates = worldStates (:, :, uc);
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
70 次 |
| 最近记录: |