优化涉及多嵌套循环的任务的计算成本

时间:2015-12-18 05:05:34

标签: algorithm

我只是编程的初学者,并且提前抱歉打扰了一个(大概)基本问题。

我想执行以下任务:

Task

(我为不便而道歉;我不知道如何在Stack Overflow中输入TeX-y公式)。我主要考虑在MATLAB或Scilab上实现,但语言并不重要。

我认为,执行此操作最天真的方法是形成一个n嵌套的 for 循环,即(例如,在MATLAB上显示n = 2的情况),

n=2;
x=[x1,x2];
for u=0:1
    y(1)=u;
    if x(1)>0 then
        y(1)=1;
    end
    for v=0:1
        y(2)=v;
        if x(2)>0 then
            y(2)=1;
        end
        z=Function(y);
    end
end

然而,这种实现对于大n来说太费力了,更重要的是,它导致函数的2 ^ n-2 ^ k丰富的评估,其中k是x中的负元素的数量。此外,天真地形成k-嵌套的 for 循环,知道x中的哪个元素是负数,例如

n=2;
x=[-1,2];
y=[1,1];
for u=0:1
    y(1)=u;
    z=Function(y);
end

似乎不是一个好方法;如果我们想为不同的x执行任务,我们必须重写代码。

如果您提供一个实现代码的想法,我将不胜感激,因为(a)只评估函数2 ^ k次(可能的最小评估次数)和(b)我们不必重写代码如果我们改变x。

1 个答案:

答案 0 :(得分:1)

您可以使用递归

轻松评估Function上的y in Ax
function eval(Function, x, y, i, n) {
    if(i == n) {
        // break condition, evaluate Function
        Function(y);
    } else {
        // always evaluate y(i) == 1
        y(i) = 1;
        eval(Function, x, y, i + 1, n);
        // eval y(i) == 0 only if x(i) <= 0
        if(x(i) <= 0) {
            y(i) = 0;
            eval(Function, x, y, i + 1, n);
        }
    }
}

将其转化为高效的Matlab代码是另一个问题。

正如您所说,评估的数量是2^k。让我们对x进行排序,以便只有最后k个元素是非正数。要使用Functiony类型的排列反向评估x索引Function(y(perm))。更好的是,相同的方法允许我们使用Ax直接构建dec2bin

// every column of the resulting matrix is a member of Ax: y_i = Ax(:,i)
function Ax = getAx(x)
    n = length(x);
    // find the k indices of non-positives in x
    is = find(x <= 0);
    k = length(is);
    // construct Y (last k rows are all possible combinations of [0 1])
    Y = [ones(n - k, 2 ^ k); (dec2bin(0:2^k-1)' - '0')];
    // re-order the rows in Y to get Ax according to the permutation is (inverse is)
    perm([setdiff(1:n, is) is]) = 1:n;
    Ax = Y(perm, :);
end

现在重写Function以接受矩阵或迭代Ax = getAx(x);中的列以评估所有Function(y)