矢量化帕累托前沿算法

时间:2014-07-03 09:33:24

标签: algorithm matlab optimization vectorization mathematical-optimization

首先,这是我的设置:

  • x是一个n x 1向量,包含第一个成本函数的值。
  • y是另一个n x 1向量,包含第二个成本函数的值。
  • a是一个m x 1向量,包含要检查的xy索引,用于有选择地从算法中排除值。除非需要,否则可以将其替换为1:n
  • 可以安全地假设所有组合(x,y)都是唯一的。

任务是找到pareto最佳值对(x,y),即所有未被支配的对。如果存在另一对(u,v)u <= x && v <= y并且这些比较中的一个是严格的,那么一对被称为支配:u < x || v < y。换句话说,如果另一对在一个值中更好而在另一个值中没有更差,则一对占主导地位。

到目前为止,我的研究已经产生了三种工作算法,遗憾的是它们都依赖于循环。以下是他们的工作方式以及我使用xya1e8来运行它们的时间:

  
      
  1. 按升序排序x。将第一对添加到帕累托集中。
  2.   
  3. 循环浏览x。将每对添加到pareto集合中,其中y低于之前的pareto对y
  4.         

    经过的时间是80.204052秒。

  
      
  1. 查找min(x)。将该对添加到帕累托集中。
  2.   
  3. 选择y低于之前添加的对y的所有对。
  4.   
  5. 转到第1步,除非第2步导致空集。
  6.         

    经过的时间是2.993350秒。

  
      
  1. 遍历所有对(x,y)
  2.   
  3. 使用(u,v)删除所有对x >= u && y >= v
  4.         

    经过的时间是105.924814秒。

现在我要做的是创建一个矢量化算法。它不必基于上述之一,但我无法找到任何其他工作算法。我能做的最好的就是:

ap = a(y < min(y(x == min(x))) | x < min(x(y == min(y))));

通常会找到所有帕累托最优对,但包括min(x)min(y)中不由该对支配的所有对,即使一个支配另一个。我通常说,因为如果只有一个全局最优对支配其他每一对,那么它完全失败了。用<替换<=可以解决第二个问题,但找到更多支配对(那些只有一个更差值的对)。我也通过与上面相同的计时器来运行它:

  

经过的时间是0.800385秒。


这是我用来检查算法如何运行的测试脚本,随时可以使用

for i=1:25
    x = randi(8,10,1);
    y = randi(8,10,1);
    a = 1:10;
    ap = a(y < min(y(x == min(x))) | x < min(x(y == min(y)))); %// algorithm here
    figure(1);
    subplot(5,5,i);
    plot(a,x,'b',a,y,'r',ap,x(ap),'b.',ap,y(ap),'r.','MarkerSize',20);
    axis([0,11,0,9]);
    set(gca,'XGrid','on','YGrid','on','XTick',1:10,'YTick',0:8);
    figure(2);
    subplot(5,5,i);
    plot(x,y,'b.',x(ap),y(ap),'ro','MarkerSize',10);
    axis([0,9,0,9]);
end

1 个答案:

答案 0 :(得分:1)

所以,如果速度是主要特征(在正确性之后),那么我发现更快的循环版本的递归版本要快30%以上:

>> testPareto(1e8);
Recursive:
Elapsed time is 4.507267 seconds.
Loop:
Elapsed time is 6.136856 seconds.
Vector:
Elapsed time is 7.246806 seconds.

同样,时间取决于机器,甚至可能取决于matlab的版本。这是代码:

function testPareto(dim)

x = rand(dim, 1);
y = rand(dim, 1);

tic;
rR = paretoRecursive(x, y);
disp('Recursive:');
toc;

tic;
rL = paretoLoop(x, y);
disp('Loop:');
toc;

tic;
rV = paretoVector(x, y);
disp('Vector:');
toc;

end

function result = paretoLoop(x, y)
    result = zeros(numel(x), 2);
    off = 1;
    loop = true;
    while loop
        xmin = min(x);
        ymin = min(y(x == xmin));
        yfilter = y < ymin;
        result(off, :) = [xmin ymin];
        off = off + 1;
        if any(yfilter)
            x = x(yfilter);
            y = y(yfilter);
        else
            loop = false;
            result(off:end, :) = [];
        end
    end
end

function result = paretoRecursive(x, y)
    xmin = min(x);
    ymin = min(y(x == xmin));
    yfilter = y < ymin;
    if any(yfilter)
        result = [xmin ymin; paretoRecursive(x(yfilter), y(yfilter))];
    else
        result = [xmin ymin];
    end
end

function result = paretoVector(x, y)
    xmin = min(x);
    xfilter = x == xmin;
    ymin = min(y(xfilter));
    yfilter = y < ymin;
    if any(yfilter)
        [x, ind] = sort(x(yfilter));
        y = y(yfilter);
        y = y(ind);
        yfilter = [true; y(2:end) < cummin(y(1:end-1))];
        result = [xmin x(yfilter)'; ymin y(yfilter)']';
    else
        result = [xmin ymin];
    end
end