我有一个矩阵
sV:=[0 -1;
1 1;
1 0;
2 1;
2 0;
3 1;
3 0]
想象一下,矩阵sV
表示一个元素,其元素是上面列出的1x2
行向量。
我们可以通过多种方式在5个非空集(140 here)中对集合sV
进行分区。
例如,5分区sV
的方式是:
{(0,-1)}
{(1,1)}
{(1,0)}
{(2,1)}
{(2,0), (3,2), (3,0)}
分区集的可能基数为1,1,1,1,3
或1,1,1,2,2
(不考虑订单)。
问题:
你能帮我构建一个1x2
单元格V_all
,以便
V_all{1,1}
是一个mx5
单元,列出了对集合sV
进行5分区的所有可能方式,以便分区集分别具有基数1,1,1,1,3
。具体来说,对于任何j = 1,...,m,V_all{1,1}{j,1}
应该是1x2
向量,V_all{1,1}{j,2}
应该是1x2
向量,V_all{1,1}{j,3}
应该成为1x2
向量,V_all{1,1}{j,4}
应为1x2
向量,V_all{1,1}{j,5}
应为3x2
向量。
V_all{1,2}
是一个nx5
单元,列出了对集合sV
进行5分区的所有可能方式,以便分区集分别具有基数1,1,1,2,2
。具体来说,对于任何j = 1,...,n,V_all{1,1}{j,1}
应该是1x2
向量,V_all{1,1}{j,2}
应该是1x2
向量,V_all{1,1}{j,3}
应该成为1x2
向量,V_all{1,1}{j,4}
应为2x2
向量,V_all{1,1}{j,5}
应为2x2
向量。
请注意m+n=140
。
这是我的尝试。可能存在错误,因为我获得了超过140个分区。
%3+1+1+1+1
k=3;
M=reshape(sV(nchoosek(1:size(sV,1),k),:),[],k,size(sV,2));
V_1=cell(size(M,1),2);
for p=1:size(M,1)
V_1{p,1}=squeeze(M(p,:,:));
left=~ismember(sV, V_1{p,1}, 'rows');
V_1{p,2}=sV(left,:);
end
%Rearrange
for j=1:size(V_1,1)
V_1new{j,1}=V_1{j,1};
V_1new{j,2}=V_1{j,2}(1,:);
V_1new{j,3}=V_1{j,2}(2,:);
V_1new{j,4}=V_1{j,2}(3,:);
V_1new{j,5}=V_1{j,2}(4,:);
end
V_all{1,1}=V_1new;
%2+2+1+1+1
k=4;
M=reshape(sV(nchoosek(1:size(sV,1),k),:),[],k,size(sV,2));
V_2=cell(size(M,1),2);
for p=1:size(M,1)
V_2{p,1}=squeeze(M(p,:,:));
left=~ismember(sV, V_2{p,1}, 'rows');
V_2{p,2}=sV(left,:);
end
k=2;
count=0;
for j=1:size(V_2,1)
M=reshape(V_2{j,1}(nchoosek(1:size(V_2{j,1},1),k),:),[],k,size(V_2{j,1},2));
V_2_22=cell(size(M,1),2);
for p=1:size(M,1)
V_2_22{p,1}=squeeze(M(p,:,:));
left=~ismember(V_2{j,1}, V_2_22{p,1}, 'rows');
V_2_22{p,2}=V_2{j,1}(left,:);
end
for l=1:size(V_2_22,1)
V_2new{count+l,1}=V_2_22{l,1};
V_2new{count+l,2}=V_2_22{l,2};
V_2new{count+l,3}=V_2{j,2}(1,:);
V_2new{count+l,4}=V_2{j,2}(2,:);
V_2new{count+l,5}=V_2{j,2}(3,:);
end
count=size(V_2new,1);
end
V_all{1,2}=V_2new;
答案 0 :(得分:0)
为了找到分区的位置,我们可以使用powerset 例如,如果powerset的元素是[2 3],则该集合将以这种方式分配:
0 -1;
1 1;
----- <-- 2
1 0;
----- <-- 3
2 1;
2 0;
3 1;
3 0]
然后我们可以在这种情况下获得每个分区(num_el)中的元素数量:[2,1,4] 这是基数,但因为基数中元素的顺序不是重要的,所以[2,1,4]与[1 4 2]相同,我们可以对它进行排序以获得[1 2 4]
然后我们需要一个关联容器(字典)来将基数映射到一组分区。
matlab中的关联容器可以通过struct实现,所以我们需要将基数表示形式的数字数组更改为字符串,这样就可以用作struct的键,然后得到:'_1_2_4'V_all是作为结构数组实现的关联容器:
V_all('_ 1_2_4')= {{} ....}
sV=[0 -1;
1 1;
1 0;
2 1;
2 0;
3 1;
3 0]
n = size(sV,1)
p=powerset(1:(n-1));
cardinality =sprintf('_%i',n);
V_all.(cardinality)(end+1)={sV};
for i = 2:numel(p)
num_el = [p{i} n] - [0 p{i}];
cardinality = sprintf('_%i',sort(num_el));
cum = [0 cumsum(num_el)];
temp = {};
for j = 2: numel(cum)
temp(end + 1) = {sV(cum(j-1)+1:cum(j),:)};
end
V_all.(cardinality)(end+1)={temp};
end