【问题标题】:Changing Optimization Variable to Constant Dynamically (Matlab)将优化变量动态更改为常数(Matlab)
【发布时间】:2013-07-16 14:41:23
【问题描述】:

我正在使用全局最大化工具箱来最大化以下功能:

    function x = NameOfFunction (w1, w2, w3, a, b, c, Structure1, Structure2, Structure3)

我通过更改w1w2w3 的值来最小化x,这些值是分配给在评估x 的值时计算的其他函数的权重。其余参数是常量和包含数据的结构。 x 的值以及三个权重变量取决于通过结构输入函数的数据。

有没有办法将权重变量之一(即优化器更改为最小化x 的变量)从正在优化的函数中更改为常数?有时,根据输入数据满足的条件,w 变量之一需要设置为 0。有没有办法从函数内部执行此操作?

我尝试做一个简单的if 语句,但优化器仍然为有问题的权重分配了一个非零值。

编辑:这是一个更具体的例子。有时,与w3 关联的函数将评估为NaN(因此应从 x 的计算中排除)。发生这种情况时,我想为优化运行的迭代分配一个 0 给 w 变量。

目前,我在目标函数中有一个简单的if 语句,它将从x 的计算中排除与w3 关联的函数,但优化器无论如何都会为w3 分配一个值。

【问题讨论】:

  • 什么时候知道是否要排除w 变量?是在调用优化器之前,还是在优化器运行一段时间之后?
  • @mars:谢谢你的回复。我知道我可以控制w3 是否退出优化器(然后在运行之前将w3 的上限和下限设置为0),但是这种解决方案并不理想。我想知道优化器开始运行后是否有办法将w3 变量设置为常量。

标签: matlab


【解决方案1】:

您可以在遇到要删除的w 时立即中止搜索。在这种情况下,使用剩余的w 继续优化。

要跟踪当前忽略的内容,您可以使用state machine。以下不完整的代码显示了所有变量的状态 w123w12 仅用于 w1w2 等等。我没有使用 matlab 类,而是使用普通结构,在函数调用需要的地方写出 this/self 变量,因为我不知道你是否想编写 matlab 类。

我只是假设您的计算足够昂贵,因此停止和启动优化器的任何开销都不是关键。

实现缺失的状态留给读者作为练习。

% file so.m (so for stack overflow)
function so
Parameters=0;

w123.description='w1, w2, w3';
w123.getStartvalues=@(w) w; % identity
w123.get_w=@(p) p; % identity
w123.getTargetfunction=@(x) NameOfFunction(x, Parameters);
w123.ignore_w1=@(state) state.w23;
w123.ignore_w2=@(state) state.w13;
w123.ignore_w3=@(state) state.w12;

w12.description='w1, w2, 0';
w12.getStartvalues=@(w) [w(1), w(2)];
w12.get_w=@(p) [p(1), p(2), 0];
w12.getTargetfunction=@(x) NameOfFunction([x(1), x(2), 0], Parameters);
w12.ignore_w1=@(state) state.w2;
w12.ignore_w2=@(state) state.w1;
w12.ignore_w3=@(state) state.w12; % w3 is already ignored

w13.description='w1, 0, w3';
w13.getStartvalues=@(w) [w(1), w(3)];
w13.get_w=@(p) [p(1), 0, p(2)];
w13.getTargetfunction=@(x) NameOfFunction([x(1), 0, x(2)], Parameters);
w13.ignore_w1=@(state) state.w3;
w13.ignore_w2=@(state) state.w13; % w2 is already ignored
w13.ignore_w3=@(state) state.w1;

% ... and so on for w23, w1, w2, w3

% ... fill in all the states from above
state.w123=w123;
state.w12=w12;
state.w13=w13;
state.current=state.w123; % initial state
state.ignore_w1=@(s) s.current.ignore_w1(s);
state.ignore_w2=@(s) s.current.ignore_w2(s);
state.ignore_w3=@(s) s.current.ignore_w3(s);
state.getTargetfunction=@(s) s.current.getTargetfunction;
state.getStartvalues=@(s, w) s.current.getStartvalues(w);

% Startvalues for w
initial_w=[1, 2, 3];

% Don't lose the intermediate result
w_before_abort=initial_w;

best_w=initial_w;
while true
    try
        fprintf('Starting an optimization run using %s\n', state.current.description);
        best_fit=fminsearch(state.getTargetfunction(state), state.getStartvalues(state,best_w));
        best_w=state.get_w(state, best_fit);
        break;
    catch event
        if strcmp(event.identifier, 'NameOfFunction:ignore_w1')
            state.current = state.ignore_w1(state);
        elseif strcmp(event.identifier, 'NameOfFunction:ignore_w2')
            state.current = state.ignore_w2(state);
        elseif strcmp(event.identifier, 'NameOfFunction:ignore_w3')
            state.current = state.ignore_w3(state);
        else
            event.stack(1)
            throw(event);
        end
        best_w=w_before_abort;
    end
end
best_w


% Nested function; watch out for name collisions in the enclosing namespace
% w_before_abort is intentional, everything else is not.
function x=NameOfFunction(w, Parameters)
    % debug output:
    w1=w(1)
    w2=w(2)
    w3=w(3)

    % run this code if you want to ignore w1:
    w_before_abort=w; % save the last inspected w
    throw(MException('NameOfFunction:ignore_w1', 'Set w1 to zero.'));

    % run this code if you want to ignore w2:
    w_before_abort=w; % save the last inspected w
    throw(MException('NameOfFunction:ignore_w2', 'Set w2 to zero.'));    
end

end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    • 2012-03-26
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    相关资源
    最近更新 更多