这个问题可以从here看待我的上一个问题的继续/延伸/概括。
一些定义:我有一组整数S = {1,2,...,s}
,比如s = 20
,以及两个矩阵N
和M
,其行是有限的来自S
的数字序列(即可能重复的排列),分别为n
和m
,1 <= n <= m
。让我们将N
视为来自M
的序列的候选子序列的集合。
示例:[2 3 4 3]
是[1 2 2 3 5 4 1 3]
的子序列,以多样性 2出现(=以多少种不同的方式找到子序列。 main seq。),而[3 2 2 3]
不是它的子序列。特别是,根据定义,有效的子序列必须保留索引的顺序。
问题陈述:
(P1)对于M
的每一行,获取N
中作为行出现的多重性且无多重性的子序列数(如果N
)中没有包含它,则它可以为零;
(P2)对于N
的每一行,找出具有多重性且没有多重性的次数,它包含在M
中作为子序列(再次,这个数字可以是零);
示例:允许N = [1 2 2; 2 3 4]
和M = [1 1 2 2 3; 1 2 2 3 4; 1 2 3 5 6]
。然后(P1)为&#39;返回[2; 3; 0]
多重性&#39;和[1; 2; 0]
没有多重性&#39;。 (P2)为&#39;返回[3; 2]
多重性&#39;和[2; 1]
没有多重性。
数量级: M
通常最多可包含30-40列和几千行,但我目前只有M
只有几百行~10列。 N
可能接近其大小
M
或者也可能更小。
到目前为止我所拥有的:说实话,并不多。我相信我可以从我之前的问题稍微修改我的非常好的矢量化解决方案来解决重复的排列问题,但我仍然在考虑这个并且一旦我有工作就会更新。但鉴于我迄今为止(缺乏)经验,很可能非常不理想:(
谢谢!
答案 0 :(得分:1)
此方法仅在M
(P1)或N
(P2)的行上使用一个循环。该代码使用linear indexing和非常强大的bsxfun
函数。请注意,如果列数很大,您可能会因nchoosek
而遇到问题。
[mr mc] = size(M);
[nr nc] = size(N);
%// P1
combs = nchoosek(1:mc, nc)-1;
P1mu = NaN(mr,1);
P1nm = NaN(mr,1);
for r = 1:mr
aux = M(r+mr*combs);
P1mu(r) = sum(ismember(aux, N, 'rows'));
P1nm(r) = sum(ismember(unique(aux, 'rows'), N, 'rows'));
end
%// P2. Multiplicity defined to span across different rows
rr = reshape(repmat(1:mr, size(combs,1), 1),[],1);
P2mu = NaN(nr,1);
P2nm = NaN(nr,1);
for r = 1:nr
aux = M(bsxfun(@plus, rr, mr*repmat(combs, mr, 1)));
P2mu(r) = sum(all(bsxfun(@eq, N(r,:), aux), 2));
P2nm(r) = sum(all(bsxfun(@eq, N(r,:), unique(aux, 'rows')), 2));
end
%// P2. Multiplicity defined restricted to within one row
rr = reshape(repmat(1:mr, size(combs,1), 1),[],1);
P2mur = NaN(nr,1);
P2nmr = NaN(nr,1);
for r = 1:nr
aux = M(bsxfun(@plus, rr, mr*repmat(combs, mr, 1)));
P2mur(r) = sum(all(bsxfun(@eq, N(r,:), aux), 2));
aux2 = unique([aux rr], 'rows'); %// concat rr to differentiate rows...
aux2 = aux2(:,1:end-1); %// ...and now remove it
P2nmr(r) = sum(all(bsxfun(@eq, N(r,:), aux2), 2));
end
示例数据的结果:
P1mu =
2
3
0
P1nm =
1
2
0
P2mu =
3
2
P2nm =
1
1
P2mur =
3
2
P2nmr =
2
1
可以对代码进行一些优化。不确定他们是否值得付出努力:
repmat
替换为另一个bsxfun
(使用第三维)。这可能会节省一些内存答案 1 :(得分:1)
简介:由于每行输入数据的重复,组合查找过程中没有"uniqueness"
之类的元素,这些元素在之前的问题中被利用了因此这里使用了循环。另请注意,without multiplicity
代码不使用nchoosek
,因此我觉得对性能更加乐观。
符号:
p1wim -> P1 with multiplicity
p2wim -> P2 with multiplicity
p1wom -> P1 without multiplicity
p2wom -> P2 without multiplicity
代码:
予。 P1的代码,2具有多重性
permN = permute(N,[3 2 1]);
p1wim(size(M,1),1)=0;
p2wim(size(N,1),1)=0;
for k1 = 1:size(M,1)
d1 = nchoosek(M(k1,:),3);
t1 = all(bsxfun(@eq,d1,permN),2);
p1wim(k1) = sum(t1(:));
p2wim = p2wim + squeeze(sum(t1,1));
end
II。 P1的代码,2没有多重性
eqmat = bsxfun(@eq,M,permute(N,[3 4 2 1])); %// equality matrix
[m,n,p,q] = size(eqmat); %// get sizes
inds = zeros(size(M,1),p,q); %// pre-allocate for indices array
vec1 = [1:m]'; %//' setup constants to loop
vec2 = [0:q-1]*m*n*p;
vec3 = permute([0:p-1]*m*n,[1 3 2]);
for iter = 1:p
[~,ind1] = max(eqmat(:,:,iter,:),[],2);
inds(:,iter,:) = reshape(ind1,m,1,q);
ind2 = squeeze(ind1);
ind3 = bsxfun(@plus,vec1,(ind2-1)*m); %//' setup forward moving equalities
ind4 = bsxfun(@plus,ind3,vec2);
ind5 = bsxfun(@plus,ind4,vec3);
eqmat(ind5(:)) = 0;
end
p1wom = sum(all(diff(inds,[],2)>0,2),3);
p2wom = squeeze(sum(all(diff(inds,[],2)>0,2),1));
像往常一样,我建议您使用gpuArrays
和您最喜欢的parfor
。