如何提高以下Matlab代码的执行时间

Feb*_*ono 2 matlab

请帮助我改进以下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)

Meh*_*olf 5

一些一般性建议:

  • 英语命名变量.如果没有立即清楚,它们缩进的内容给出一个简短的解释.jum_bag例如是什么?对我来说uk_pop就是音乐风格.
  • 即使您只为自己开发源代码,也要用英语撰写评论.如果您必须与外国人分享您的代码,您将花费大量时间来解释或重新翻译.我想知道例如,%batasan tidak boleh意味着什么 .也许,你在这里描述这只是一个快速的黑客,但有人应该在投入生产之前再次检查这一点.

特定于您的代码:

  • 它很容易gab1gabh1或混淆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)