0

我编写了这个函数来根据某些标准查找索引。它应该可以工作,问题是在我的电脑上运行需要 2-3 天。有没有办法让它低于一个小时(或更快)?这真的不需要非常快。但是 2 天的速度慢得让人无法接受。

我不希望对该功能进行深入分析(尽管它会很好)。只是一些一般性的改进。

它本质上是 3 个 for 循环,用于使用另一个 256x8 矩阵逻辑填充 8 个大型 3d 数组。然后进行一些逻辑测试以找到所需的索引。

%These are sample values from the g.u.i. and other functions - 
%ignore up til the loops unless you need it to understand something in the loops.

PriceMat=[58867 55620 16682 97384 11660 18175 25896 16300];
CapMat=[1400 1200 450 3600 150 1330 2000 250];
RepMat=[58 53 31 127 15 164 242 27];
DesiredRep=293.04;
DesiredCap=2600;

prevmin=99999999;
P=perms(0:7);

D=zeros(256,8,40320);
Cap=zeros(size(D,3),8);
Rep=zeros(size(D,3),8);
Price=zeros(size(D,3),8);
SufRep=zeros(1,size(D,3));
SufCap=zeros(1,size(D,3));
CapTot=zeros(1,size(D,3));
RepTot=zeros(1,size(D,3));
PriceTot=zeros(1,size(D,3));


for i=1:40320
    for x=1:8

        for   j=1:256
            D(j,x,i)=P(i,x)*Logic(j,x);

            Cap(i,x)=D(j,x,i)*CapMat(x);
            Price(i,x)=D(j,x,i)*PriceMat(x);
            Rep(i,x)=D(j,x,i)*RepMat(x);
            CapTot=sum(Cap,2);
            RepTot=sum(Rep,2);
            PriceTot=sum(Price,2);

            if CapTot(i)>=DesiredCap
                SufCap(i)=true;
            else 
                SufCap(i)=false;
            end

            if RepTot(i)>=DesiredRep
                SufRep(i)=true;
            else 
                SufRep(i)=false;
            end

            if SufRep(i)==true && SufCap(i)==true

                if PriceTot(i)<=prevmin
                    prevmin=i;
                end
            end

        end

    end

end

return prevmin
4

2 回答 2

1

使用bsxfun它非常有趣!

以下是如何D在一行中计算矩阵(无循环):

 D = bsxfun( @times, permute( P, [3 2 1] ), Logic );

我想您可以从这里获取它并以这种方式计算其余矩阵 - 没有循环。

于 2013-07-11T16:32:18.747 回答
0

您说“最好”对您的功能进行深入分析。它非常复杂 - 并且可以大大简化。我有点担心我的解决方案会占用多少内存——你的一个 256x8x40320 阵列大约是 660 MB,我创建了四个。如果这不是问题,那就太好了。否则,您可能必须选择更保守的数据类型来降低内存需求 - 如果您开始交换到磁盘,那么您就死定了,时间明智。

因此,假设您不受 RAM 的限制,那么以下内容将大大加快速度(注意 - 我正在窃取 Shai 使用 bsxfun 的建议)。另请注意,我在取它们的总和后清除“非常大”的数组 - 这可以在一行中完成,但你更难遵循:

D = bsxfun( @times, permute( P, [ 3 2 1] ), Logic );
Cap = bsxfun( @times, D, CapMat );
CapTot = sum( Cap, 2 );
clear Cap

Price = bsxfun( @times, PriceMat );
PriceTot = sum( Price, 2 );
clear Price

Rep = bsxfun( @times, D, RepMat ); % <<<<< STRONGLY recommend not to use RepMat -
                                   % <<<<< to avoid confusion with built in repmat()
RepTot = sum( Rep, 2 );
clear Rep

CapRepOK = ( CapTot >= DesiredCap && RepTot >= DesiredRep ); % logical array - fast, small

[minPrice minPriceInd ] = min(PriceTot(CapRepOK)); % find minimum value and index

% convert index to correct value of `i` in original code:
cs = cumsum(ok(:)); % increases by one for every value that meets criteria
                    % but we need to know which original index that corresponds to:
possibleValues = find( cs == minPriceInd );
[j i] = ind2sub( size(CapRepOK), possibleValues(1) );
prevmin = i;

显然我没有你的数据,所以很难确定这完全复制了你的功能 - 但我相信它确实如此。如果不是 - 这就是评论的目的。

我怀疑经过仔细考虑,永远不可能创建最大的数组(D 等)——如果你真的缺乏可能需要的内存。

于 2013-07-11T17:49:25.003 回答