【问题标题】:Vectorizing a pareto front algorithm向量化帕累托前沿算法
【发布时间】:2014-08-24 08:40:27
【问题描述】:

首先,这是我的设置:

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

任务是找到值对的帕累托最优集合(x,y),即所有不占优的对。如果存在另一对 (u,v) 使得 u <= x && v <= y 并且其中一个比较是严格的:u < x || v < y,则该对被称为主导。换句话说,如果另一对在一个值上更好而不在另一个值上更差,则一对被支配。

到目前为止,我的研究已经产生了三种有效的算法,不幸的是它们都依赖于循环。以下是它们的工作方式以及我用xya(长度为1e8)运行它们的时间:

  1. 按升序对x 进行排序。将第一对添加到帕累托集。
  2. 循环通过x。将每一对添加到帕累托集中,其中y 低于前一个帕累托对的y

经过的时间是 80.204052 秒。

 

  1. 找到min(x)。将该对添加到帕累托集。
  2. 选择y 低于先前添加的对的y 的所有对。
  3. 除非第 2 步导致空集,否则请转到第 1 步。

经过的时间是 2.993350 秒。

 

  1. 循环遍历所有对 (x,y)
  2. 删除所有对 (u,v)x >= u && y >= v

经过的时间是 105.924814 秒。

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

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

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

经过的时间是 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

【问题讨论】:

  • 我一直用this function from File Exchange,它真的很快就能上千分,所以你可以偷偷溜进去看看他们是怎么做到的。 (使用和引用!)
  • @thewaywewalk 我也发现了这个,但除非我遗漏了什么,否则这只是一个编译好的 mex 文件,我无法查看实际的源代码并弄清楚它的作用。我不习惯使用我不理解的外部资源...
  • 好吧,你是对的,我之前没有检查过。对不起。

标签: algorithm matlab optimization vectorization mathematical-optimization


【解决方案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

【讨论】:

  • 时间才是最重要的。我给出的示例是我设法构建的唯一矢量化近似值,时间基准是我正在寻找的指南。实际有效的最佳循环解决方案(请注意我在问题中所说的矢量化近似实际上不能充分工作/充分执行任务)仍然需要(不工作)矢量化近似的 4 倍。请花时间运行基准测试,因为在这种情况下,这可以验证您的答案。
  • 我不同意。我建议给出正确的结果比时间更重要。但是没问题,我很快就会运行它,但是对于之前的结果,我不清楚输入是什么:randi(8,1e8,1)?还是 rand(1e8, 1)?
  • 我刚刚意识到我的答案在处理整数时存在严重问题,因为它们很容易重复,而对于双精度数,我想这不是一个问题。尽管如果重复不是问题,那么可以删除慢速唯一性并将其转换为排序。顺便说一句,使用 1e8 随机双打,没有唯一性大约需要 10 秒。但是,绝大多数时间都花在了排序上,所以我想看看如何规避它。
  • 嗯,我确实有一个(循环的)算法,它可以在 3 秒内提供正确的结果,所以给出正确的结果并不重要,除非它更快。这就是问题的意图,我不是为了它而寻找矢量化算法,而是因为它们通常更快。
  • 我找到了一个更快的递归版本。我还尝试通过使每个级别的递归过滤掉更多元素来改进它。首先通过找到剩余对的最小 y 并对 x 执行与之前相同的逻辑。此外,要将它们组合成复数 x +i*y,并过滤掉那些相位比第一个识别的对更高的相位,因为该方法会找到相位单调递减的对。在这两种情况下,递归方法的性能都会受到影响,至少对于高样本是这样。我没有尝试过较小的样本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多