0

Could you please help me with the following issue: I have the following function handle:

r1 = @(lambda) b + lambda*(r - b); % r and b are vectors of return data

I want to find the optimal lambdas that set me a mean function to zero, for a given set of powers within that function. What I tried to do and didn't work, as it returns me an error for undefined operators for input arguments of type 'function_handle' is:

lambda0 = 0.3;
for a = 2:10    %power coefficient
S1(a) = fzero(mean((r - b)*r1.^(1/(a - 1))),lambda0);
end

Any suggestion as to how to go about this problem is highly appreciated! Thank you in advance.

Astrid
  • 43
  • 1
  • 2
  • 7

1 Answers1

1

fzero accepts a function handle as the first input. As you currently have it, you're trying to pass a statement as the first input. This statement can't even be properly evaluated because you are trying to perform numerical operations on a function handle (more on this in a bit).

You need to instead do something like this where we create a new function handle that evaluates the original function handle and performs the other operations you need.

S1(a) = fzero(@(lambda)mean((r - b)*r1(lambda).^(1/(a - 1))),lambda0);

Further Explanation

Performing operations on a function handle is not the same as performing them on the result.

So for example, if we had a function handle:

func = @(x)2*x;

If we evaluation this, by calling it with an input value for x

func(2)

    4

This works as we would expect. If now we really want the value (2*x)^2, we could try to write it the way that you wrote your statement in your question

func2 = func^2;

We will get an error!

Undefined operator '^' for input arguments of type 'function_handle'.

This does not work because MATLAB attempts to apply the ^ operation to the function handle itself and not the value of the evaluated function handle.

Instead, we would need to create a new function handle that essentially wraps the other one and performs any additional options:

func2 = @(x)func(x)^2;
func2(2)

    16

Bringing it Full-Circle

So if we go back to your question, you defined your anonymous function r1 like this.

r1 = @(lambda) b + lambda*(r - b); % r and b are vectors of return data

This all looks great. You have one input argument and you reference r and b from the parent workspace.

Now when you call fzero you try to perform operations on this function handle in hopes of creating a new function handle.

mean((r - b)*r1.^(1/(a - 1)))

Like we just showed this will result in a very similar error

Undefined operator .^ for input arguments of type 'function_handle'

So we need to wrap this into a new function.

newfunc = @(lambda)mean((r - b)*r1(lambda).^(1 / (a - 1)));

Now we can safely pass this to fzero.

result = fzero(newfunc, lambda0);
Suever
  • 64,497
  • 14
  • 82
  • 101
  • 1
    Thank you for the additional explanation, it really helped me to understand the mechanism behind the problem at hand. – Astrid Mar 18 '16 at 15:49
  • I have a follow-up question: would it be possible to constrain the values of lambdas in [0,1] using fzero? – Astrid Mar 18 '16 at 15:54
  • @Astrid You would pass the `[lower, upper]` bounds for lambda as the second input rather than specifying `lambda0`. [The Documentation](http://www.mathworks.com/help/matlab/ref/fzero.html#inputarg_x0) – Suever Mar 18 '16 at 15:58
  • Thanks for the quick reply. If I replace lambda0 with [0,1] I get the following error: Error using fzero (line 273) The function values at the interval endpoints must differ in sign. – Astrid Mar 18 '16 at 16:05
  • @Astrid Yup. Check the documentation link above and it explains why that is. – Suever Mar 18 '16 at 16:07
  • I also tried with [-0.00001, 1], but it returns me the same result as when I put lambda0, so it doesn't really constrain lambda to be in [0,1]. – Astrid Mar 18 '16 at 16:07
  • @Astrid maybe open a new question so others can help you more – Suever Mar 18 '16 at 16:08
  • Thanks again for your help! – Astrid Mar 18 '16 at 16:11