在 Matlab 中将矩阵分成 5 组
Partitioning a matrix in 5 sets in Matlab
我有一个矩阵
sV:=[0 -1;
1 1;
1 0;
2 1;
2 0;
3 1;
3 0]
假设矩阵 sV
表示一个集合,其元素是上面列出的 1x2
行向量。
我们可以通过多种方式将集合 sV
划分为 5 个非空集合(here 中的 140 个)。
例如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;
为了找到分区的位置我们可以使用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
我有一个矩阵
sV:=[0 -1;
1 1;
1 0;
2 1;
2 0;
3 1;
3 0]
假设矩阵 sV
表示一个集合,其元素是上面列出的 1x2
行向量。
我们可以通过多种方式将集合 sV
划分为 5 个非空集合(here 中的 140 个)。
例如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;
为了找到分区的位置我们可以使用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