请帮助我改进以下Matlab代码以缩短执行时间.
实际上我想制作一个随机矩阵(大小[8,12,10]),并且在每一行上,只有1和之间的整数值12.我希望随机矩阵具有每列的值(1,2,3,4)相等的元素之和2.
以下代码将使事情更加清晰,但速度非常慢.谁能给我一个建议?
clc
clear all
jum_kel=8
jum_bag=12
uk_pop=10
for ii=1:uk_pop;
for a=1:jum_kel
krom(a,:,ii)=randperm(jum_bag); %batasan tidak boleh satu kelompok melakukan lebih dari satu aktivitas dalam satu waktu
end
end
for ii=1:uk_pop;
gab1(:,:,ii) = sum(krom(:,:,ii)==1)
gab2(:,:,ii) = sum(krom(:,:,ii)==2)
gab3(:,:,ii) = sum(krom(:,:,ii)==3)
gab4(:,:,ii) = sum(krom(:,:,ii)==4)
end
for jj=1:uk_pop;
gabh1(:,:,jj)=numel(find(gab1(:,:,jj)~=2& gab1(:,:,jj)~=0))
gabh2(:,:,jj)=numel(find(gab2(:,:,jj)~=2& gab2(:,:,jj)~=0))
gabh3(:,:,jj)=numel(find(gab3(:,:,jj)~=2& gab3(:,:,jj)~=0))
gabh4(:,:,jj)=numel(find(gab4(:,:,jj)~=2& gab4(:,:,jj)~=0))
end
for ii=1:uk_pop;
tot(:,:,ii)=gabh1(:,:,ii)+gabh2(:,:,ii)+gabh3(:,:,ii)+gabh4(:,:,ii)
end
for ii=1:uk_pop;
while tot(:,:,ii)~=0;
for a=1:jum_kel
krom(a,:,ii)=randperm(jum_bag); %batasan tidak boleh satu kelompok melakukan lebih dari satu aktivitas dalam satu waktu
end
gabb1 = sum(krom(:,:,ii)==1)
gabb2 = sum(krom(:,:,ii)==2)
gabb3 = sum(krom(:,:,ii)==3)
gabb4 = sum(krom(:,:,ii)==4)
gabbh1=numel(find(gabb1~=2& gabb1~=0));
gabbh2=numel(find(gabb2~=2& gabb2~=0));
gabbh3=numel(find(gabb3~=2& gabb3~=0));
gabbh4=numel(find(gabb4~=2& gabb4~=0));
tot(:,:,ii)=gabbh1+gabbh2+gabbh3+gabbh4;
end
end
Run Code Online (Sandbox Code Playgroud)
一些一般性建议:
jum_bag例如是什么?对我来说uk_pop就是音乐风格.%batasan tidak boleh意味着什么
.也许,你在这里描述这只是一个快速的黑客,但有人应该在投入生产之前再次检查这一点.特定于您的代码:
gab1与gabh1或混淆gabb1.krom与内置功能太相似了kron.事实上,我首先想到你正在计算很多张量产品.gab1 .. gab4 可能最好组合成一个数组或一个单元格,例如你可以使用
gab = cell(1, 4);
for ii = ...
gab{1}(:,:,ii) = sum(krom(:,:,ii)==1);
gab{2}(:,:,ii) = sum(krom(:,:,ii)==2);
gab{3}(:,:,ii) = sum(krom(:,:,ii)==3);
gab{4}(:,:,ii) = sum(krom(:,:,ii)==4);
end
Run Code Online (Sandbox Code Playgroud)
优点是你可以用另一个循环重写comparsisons.它还有助于计算gabh1,gabb1以及tot以后.
如果你进一步引入一个变量highestNumberToCompare,你只需要进行一次更改,当你确定要检查它是否重要时,如果元素也等于5和6.
在每个命令的末尾添加一个分号.输出太多很烦人也很慢.
将numel(find(gabb1 ~= 2 & gabb1 ~= 0))是更好的表示
sum(gabb1(:) ~= 2 & gabb1(:) ~= 0).find不需要A ,因为你不关心索引而只关心索引的数量,它等于true's 的数量.
当然:这段代码
for ii=1:uk_pop
gab1(:,:,ii) = sum(krom(:,:,ii)==1)
end
Run Code Online (Sandbox Code Playgroud)
是真的,真的很慢.在每次迭代中,您都会增加gab1
数组的大小,这意味着您必须i)分配更多内存,ii)复制旧矩阵和iii)编写新行.这是多快,如果你设置的尺寸
gab1在循环的前阵:
gab1 = zeros(... final size ...);
for ii=1:uk_pop
gab1(:,:,ii) = sum(krom(:,:,ii)==1)
end
Run Code Online (Sandbox Code Playgroud)
也许你应该重新思考它的大小和形状gab1.我不认为,你需要一个3D数组,因为sum()已经减少了一个维度(如果krom是3D输出sum()最多是2D).
也许你可以跳过循环并使用简单的sum(krom==1, 3)代替.但是,在每种情况下,您都应该真正了解结果的大小和形状.
编辑灵感来自Rody Oldenhuis:
正如Rody指出的那样,代码的"问题"在于,通过随机分配数字来创建满足约束条件的矩阵是极不可能的(尽管不是不可能).下面的代码创建了一个temp具有以下特征的矩阵:
1 .. maxNumber每列两次或根本不显示.1 .. B,其中B等于行的长度(即列数).最后,temp矩阵用于填充称为的3D数组result.我希望,您可以根据自己的需求进行调整.
clear all;
A = 8; B = 12; C = 10;
% The numbers [1 .. maxNumber] have to appear exactly twice in a
% column or not at all.
maxNumber = 4;
result = zeros(A, B, C);
for ii = 1 : C
temp = zeros(A, B);
for number = 1 : maxNumber
forbiddenRows = zeros(1, A);
forbiddenColumns = zeros(1, A/2);
for count = 1 : A/2
illegalIndices = true;
while illegalIndices
illegalIndices = false;
% Draw a column which has not been used for this number.
randomColumn = randi(B);
while any(ismember(forbiddenColumns, randomColumn))
randomColumn = randi(B);
end
% Draw two rows which have not been used for this number.
randomRows = randi(A, 1, 2);
while randomRows(1) == randomRows(2) ...
|| any(ismember(forbiddenRows, randomRows))
randomRows = randi(A, 1, 2);
end
% Make sure not to overwrite previous non-zeros.
if any(temp(randomRows, randomColumn))
illegalIndices = true;
continue;
end
end
% Mark the rows and column as forbidden for this number.
forbiddenColumns(count) = randomColumn;
forbiddenRows((count - 1) * 2 + (1:2)) = randomRows;
temp(randomRows, randomColumn) = number;
end
end
% Now every row contains the numbers [1 .. maxNumber] by
% construction. Fill the zeros with a permutation of the
% interval [maxNumber + 1 .. B].
for count = 1 : A
mask = temp(count, :) == 0;
temp(count, mask) = maxNumber + randperm(B - maxNumber);
end
% Store this page.
result(:,:,ii) = temp;
end
Run Code Online (Sandbox Code Playgroud)