Efficient search for permutations that contain sub-permutations via array operations?

后端 未结 3 911
时光说笑
时光说笑 2021-01-06 11:04

I have a set of integers, say S = {1,...,10}, and two matrices N and M, whose rows are some (but not necessarily all possible) permutations of elements from S of orders, say

3条回答
  •  感动是毒
    2021-01-06 11:32

    Approach #1

    [val,ind] = max(bsxfun(@eq,permute(M,[4 2 1 3]),permute(N,[2 3 4 1])),[],2)
    matches = squeeze(all(diff(ind,1)>0,1).*all(val,1))
    out1 = any(matches,2) %// Solution - 1
    out2 = sum(matches,1) %// Solution - 2
    

    Approach #2

    Another approach that avoids permuting N and might be better for longish N -

    [val,ind] = max(bsxfun(@eq,N,permute(M,[3 4 1 2])),[],4)
    matches = squeeze(all(diff(ind,[],2)>0,2).*all(val,2))
    out1 = any(matches,1) %// Solution - 1
    out2 = sum(matches,2) %// Solution - 2
    

    Approach #3

    Memory-scroogey approach for large datasizes -

    out1 = false(size(M,1),1);  %// Storage for Solution - 1
    out2 = zeros(size(N,1),1);  %// Storage for Solution - 2
    for k=1:size(N,1)
        [val3,ind3] = max(bsxfun(@eq,N(k,:),permute(M,[1 3 2])),[],3);
        matches = all(diff(ind3,[],2)>0,2).*all(val3,2);
        out1 = or(out1,matches);
        out2(k) = sum(matches);
    end
    

    Approach #4

    Memory-scroogey approach for GPU -

    gM = gpuArray(M);
    gN = gpuArray(N);
    
    gout1 = false(size(gM,1),1,'gpuArray');  %// GPU Storage for Solution - 1
    gout2 = zeros(size(gN,1),1,'gpuArray');  %// GPU Storage for Solution - 2
    for k=1:size(gN,1)
        [val3,ind3] = max(bsxfun(@eq,gN(k,:),permute(gM,[1 3 2])),[],3);
        matches = all(diff(ind3,[],2)>0,2).*all(val3,2);
        gout1 = or(gout1,matches);
        gout2(k) = sum(matches);
    end
    out1 = gather(gout1);  %// Solution - 1
    out2 = gather(gout2);  %// Solution - 2
    

    Now, this GPU approach has blown away all other approaches. It was run with M : 320000X5 and N : 2100X3 (same as your input sizes) filled with random integer numbers. With a GTX 750 Ti, it took just 13.867873 seconds!! So if you have a GPU with sufficient memory, this might be your winner approach too.


    Approach #5

    Extremely-memory-scroogey approach for GPU -

    gM = gpuArray(M);
    gN = gpuArray(N);
    
    gout1 = false(size(gM,1),1,'gpuArray');  %// GPU Storage for Solution - 1
    gout2 = zeros(size(gN,1),1,'gpuArray');  %// GPU Storage for Solution - 2
    for k=1:size(gN,1)
        [val2,ind2] = max(bsxfun(@eq,gM,permute(gN(k,:),[1 3 2])),[],2);
        matches = all(diff(ind2,[],3)>0,3).*all(val2,3);
        gout1 = or(gout1,matches);
        gout2(k) = sum(matches);
    end
    out1 = gather(gout1);  %// Solution - 1
    out2 = gather(gout2);  %// Solution - 2
    

提交回复
热议问题