Search code examples
matlabmathematical-optimizationanonymous-function

How to evaluate a MATLAB anonymous function that takes an arbitrary number of variables n, given a n-dimensional vector?


I'm relatively new to MATLAB so perhaps there's something I'm missing. The task is the following: we must program a certain algorithm for optimizing a continuous function f: Rn ---> R. The thing is, to do so I need to minimize a scalar function that depends on f, and work with said minimum, for example:

%given f, and a vector y

g=@(s) f(y + s*e_i)   %e_i is the i-th canonical vector
[lambda, ~]=fminsearch(g,0)

disp(lambda)

The problem is that, if for example f(x,y)=x+y, one can't input f([1,2]), you need to write f(1,2), so I don't know how to define the function g properly so I can find the needed scalar value.

I know that if f were a fixed dimension, let's say 3, I could literally write

eval_f = @(v) f(v(1), v(2), v(3))

g = @(s) eval_f(y + s*e_i)

but the code must be open to receive any function. I have also tried using f(num2cell(y + s*e_i){:}) but I get an "Invalid array indexing" error, as I can't chain the parenthesis and an output. I have tried creating a more complex auxiliary function

eval_f=@(fun,v) fun(feval(@(x) x{:},num2cell(v)));
g=@(s) eval_f(f,y + s*ei);

But doing feval(@(x) x{:},v) in the end only returns the first element of v, and f doesn't get evaluated correctly and thus g isn't correctly defined.

How could I define g?


Solution

  • Note that you need a function handle to minimise, but that doesn't mean you have to define everything in anonymous functions. It might be easier to test and debug if you just write a complete function block, so you have your main function g which evaluates some variable-sized v using a predefined f:

    function x = g( f, v )
    % v is an array of unknown size, the values of which should be 
    % passed as separate inputs to f
        % Convert to cell so we can use {:} syntax in function call
        vc = num2cell( v );
        % Evaluate
        x = f( v{:} );
    end
    

    Then all your anonymous function needs to do is wrap this up so that it accepts a single input

    gf = @(s) g( f, y + s*e_i )
    [lambda,~] = fminsearch( gf, 0 )
    

    Alternatively if you'd written the definition of f directly within the function block for g then you wouldn't need to define gf at all, you could point directly at g if it took a single input.


    If you have these in the same script, you would normally put the function block at the bottom (although since R2024b they can go anywhere)