0

I am using the global maximization toolbox to maximize the following function:

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

where I am minimizing x by changing the values of w1, w2, and w3, which are weights that are assigned to other functions calculated in evaluating the value of x. The remaining parameters are constants and structures containing data. The value of x, as well as the three weight variables depend on the data that is fed into the function via the structures.

Is there a way to change one of the weight variables (i.e. the variables that the optimizer changes to minimize x) to a constant from within the function being optimized? Sometimes, depending on conditions met by the input data, one of the w variables needs to be set to 0. Is there a way to do this from within the function?

I tried doing a simple if statement, but the optimizer still assigned a non-zero value to the weight in question.

EDIT: Here is a more specific example. Sometimes, the function associated with w3 will evaluate to NaN (and should therefore be excluded from the calculation of x). When that happens, I would like to assign a 0 to the w variable for that iteration of the optimization run.

Currently, I have a simple if statement in the objective function that will exclude the the function associated with w3 from the calculation of x, but the optimizer assigns a value to w3 regardless.

2
  • 1
    At what point in time do you know if you want to exclude the w variable? Is it before you call the optimizer, or only after the optimizer has run for a while? Commented Jul 15, 2013 at 15:53
  • @mars: Thatnk you for your reply. I know I could control for whether or not w3 drops out outside of the optimizer (and then set the upper and lower bounds of w3 to 0 before running it), but this solution is not ideal. I am wondering if there is a way to set the w3 variable to a constant after the optimizer begins running. Commented Jul 15, 2013 at 16:06

1 Answer 1

1

You can abort the search as soon as you encounter a w that you want to drop. In this case, resume the optimization with the remaining w.

To keep track of what is currently ignored, you can use a state machine. The following incomplete code shows states w123 for all variables, w12 for only w1 and w2 and so on. Instead of using matlab classes I am using plain structs, writing out the this/self variable where needed for function calls because I don't know if you want to write matlab classes or not.

I am simply assuming that your computation is expensive enough so that any overhead in stopping and starting the optimizer is not critical.

Implementing the missing states is left as an exercise for the reader.

% 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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.