1

I'd like to dynamically construct a function that can then be referred to with a function handle for later use in Matlab functions such as integral(fun,a,b).

As an example imagine a function with terms:

(x-A)/(D-A) * (x-B)/(D-B) * (x-C)/(D-C)

where x is a variable and A,B,C,D are constants from a vector (call it K=[A,B,C,D]' as an example) generated by a different function.

I could do:

fun = @(x) (x-A)/(D-A) * (x-B)/(D-B) * (x-C)/(D-C)

However, this restricts me to three terms. I'd like to be able to take an arbitrary length vector of constants and generate a function of similar form to the one above. Normally this is easy in Matlab, but it seems like function handles expect 'x' to be a scalar, so something like:

prod( (x - K(1:3)) ./ K(4)-K(1:3) )

returns an error.

Robert Seifert
  • 25,078
  • 11
  • 68
  • 113
Josh
  • 13
  • 3

1 Answers1

1

It's not true that

function handles expect 'x' to be a scalar

The problem is not the function handle, nor the fact that the function is anoymous. The problem is simply the operation you use to define that function: you can't do

prod( (x - K(1:3)) ./ K(4)-K(1:3) )

when both x and K are vectors with arbitrary sizes. As a side note, you have a pair of brackets missing in the denominator.

What you want (if I understand correctly) can be done using bsxfun twice. Assuming both x and K are column vectors, use

prod(bsxfun(@rdivide, bsxfun(@minus, x.', K(1:end-1)), K(end)-K(1:end-1)))

to compute your function.

So: first define K and then you can define the anonymous function and its handle as

fun = @(x) prod(bsxfun(@rdivide,bsxfun(@minus,x.',K(1:end-1)),K(end)-K(1:end-1)))

Note that the value of K is "hardwired" into the anonymous function when you define the latter. The function won't change if you later modify K (unless of course you define the function again with the new K).

Example:

>> K = [3 4 5 6].';
>> fun = @(x)prod(bsxfun(@rdivide,bsxfun(@minus,x.',K(1:end-1)),K(end)-K(1:end-1)));
>> x = [1 2].';
>> fun(x)
ans =
    -4    -1

Check:

>> prod( (x(1) - K(1:3)) ./ (K(4)-K(1:3)) )
ans =
    -4

>> prod( (x(2) - K(1:3)) ./ (K(4)-K(1:3)) )
ans =
    -1
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • Thanks, works as expected! When you say "when both x and K are vectors with arbitrary sizes" do you mean that when 'fun' is declared it needs to know at time of execution the size of the vectors? I'm assuming that 'bsxfun' doesn't have this restriction and we essentially "wrap" the arbitrary sized stuff inside. – Josh Sep 09 '14 at 00:47
  • @Joshbevan What I meant is that, for example, when computing `x - K(1:3)` the sizes of `x` and and `K(1:3)` should match, otherwise the operation is undefined. But even if they match, you don't really want to subtract `x - K(1:3)` (element-wise). You want to subtract every element of `K(1:3)` from every element of `x`, that is, all combinations. That's what `bsxfun` does when the vectors have different orientations (one is column vector, the other is a row vector) – Luis Mendo Sep 09 '14 at 11:08