簡體   English   中英

如何縮短以下Matlab代碼的執行時間

[英]How to improve execution time of the following Matlab code

請幫助我改進以下Matlab代碼以縮短執行時間。

實際上,我想制作一個隨機矩陣(大小[8,12,10] ),並且在每一行上,只有112之間的整數值。 我希望隨機矩陣具有元素的總和,每列的值(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

一些一般性建議:

  • 英語命名變量。 如果不清楚,請簡短說明。 例如jum_bag是什么? 對我來說, uk_pop是音樂風格。
  • 即使您自己開發源代碼,也要用英語寫注釋。 如果您必須與外國人共享您的代碼,則將花費大量時間進行解釋或重新翻譯。 例如,我想知道%batasan tidak boleh是什么意思。 您可能在這里描述這只是一個快速的技巧,但是在投入生產之前,應該有人再次進行檢查。

特定於您的代碼:

  • gab1gabh1gabb1混淆確實很容易。
  • 對我來說, 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 

    好處是您可以用另一個循環重寫比較。 在以后計算gabh1gabb1tot時,它也有幫助。

    如果進一步引入了諸如highestNumberToCompare類的變量,則只需確定一次更改即可,只要您確定要檢查其是否也等於5和6, highestNumberToCompare重要。

  • 在每個命令的末尾添加分號。 輸出過多會令人煩惱,而且速度很慢。

  • numel(find(gabb1 ~= 2 & gabb1 ~= 0))最好表示為sum(gabb1(:) ~= 2 & gabb1(:) ~= 0) 不需要find ,因為您不關心索引,而只關心索引的數目,該數目等於true的數目。

  • 當然:此代碼

     for ii=1:uk_pop gab1(:,:,ii) = sum(krom(:,:,ii)==1) end 

    真的,真的很慢。 在每次迭代中,都增加了gab1數組的大小,這意味着您必須i)分配更多的內存,ii)復制舊矩陣,iii)寫入新行。 這是更快 ,如果你設置的尺寸gab1在循環的前陣:

     gab1 = zeros(... final size ...); for ii=1:uk_pop gab1(:,:,ii) = sum(krom(:,:,ii)==1) end 

    也許您還應該重新考慮gab1的大小和形狀。 我不認為,這里需要3D數組,因為sum()已經減小了一個維度(如果krom是3D,則sum()的輸出最多為2D)。

    可能完全可以跳過循環,而使用簡單的sum(krom==1, 3)代替。 但是,在每種情況下,您都應該真正了解結果的大小和形狀。

編輯受Rody Oldenhuis的啟發:

正如Rody指出的那樣,代碼的“問題”是創建一個矩陣(通過隨機分配數字來滿足約束)的可能性很小(盡管不是不可能)。 下面的代碼創建具有以下特征的矩陣temp

  • 數字1 .. maxNumber每列出現兩次或根本不出現。
  • 所有行都是數字1 .. B的隨機排列,其中B等於行的長度(即列數)。

最后, temp矩陣用於填充稱為result的3D數組。 希望您可以適應您的需求。

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

好的,下面的代碼將大大改善計時。 它還不是完美的,可以進一步優化。

但是,在我這樣做之前:我認為您想要的基本上是不可能的。

所以你要

  • 所有行都包含數字1到12,以隨機排列
  • 任何列中的1到4之間的任何值都必須出現兩次或完全不出現

我有一個預感,這是不可能的 (這就是為什么您的代碼永遠不會完成的原因),但讓我再考慮一下。

無論如何,我只有5分鍾的明顯改進版本:

clc
clear all

jum_kel  =  8;
jum_bag  =  12;
uk_pop   =  10;

A = jum_kel; % renamed to make language independent 
B = jum_bag; % and a lot shorter for readability
C = uk_pop;

krom = zeros(A, B, C);
for ii = 1:C;
    for a = 1:A
        krom(a,:,ii) = randperm(B);
    end
end

gab1  = sum(krom == 1);
gab2  = sum(krom == 2);
gab3  = sum(krom == 3);
gab4  = sum(krom == 4);

gabh1 = sum( gab1 ~= 2 & gab1 ~= 0 );
gabh2 = sum( gab2 ~= 2 & gab2 ~= 0 );
gabh3 = sum( gab3 ~= 2 & gab3 ~= 0 );
gabh4 = sum( gab4 ~= 2 & gab4 ~= 0 );

tot   = gabh1+gabh2+gabh3+gabh4;


for ii = 1:C
    ii
    while tot(:,:,ii) ~= 0

        for a = 1:A
            krom(a,:,ii) = randperm(B);
        end

        gabb1  =  sum(krom(:,:,ii) == 1);
        gabb2  =  sum(krom(:,:,ii) == 2);
        gabb3  =  sum(krom(:,:,ii) == 3);
        gabb4  =  sum(krom(:,:,ii) == 4);

        gabbh1 = sum(gabb1 ~= 2 & gabb1 ~= 0)
        gabbh2 = sum(gabb2 ~= 2 & gabb2 ~= 0);
        gabbh3 = sum(gabb3 ~= 2 & gabb3 ~= 0);
        gabbh4 = sum(gabb4 ~= 2 & gabb4 ~= 0);

        tot(:,:,ii) = gabbh1+gabbh2+gabbh3+gabbh4;

    end
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM