1

This question may initially appear similar to this other question but my situation is a little bit different.

I have a function 'deriv' that takes a symbolic expression as its input, then takes the first derivative of that symbolic expression. That derivative is then converted into an anonymous function using matlabFunction(), and is then evaluated over an array of points. I also use the anonymous function later in some other code.

The problem I'm having is that sometimes the input symbolic expression happens to be linear, and thus the derivative is constant; therefore the anonymous function is also a constant. When I evaluate the anonymous function over the array of points, I only get one output instead of an array of outputs.

Here's some code showing what I'm doing. For the sake of simplicity here, let's assume that the symbolic input expressions will involve only one symbolic variable called q.

function[derivFun,derivVals] = deriv(input)
derivSym = diff(input,q);
derivFun = matlabFunction(derivSym,'vars',q);
evalPoints = [1;2;3;4;5]; %in my true application, a much larger array
derivVals = derivFun(evalPoints);
end

So if the input is q^2, then the output derivVals will be [2;4;6;8;10]. But if the input happens to be, say, 3*q, then derivVals will be 3 (just a single scalar). What I'd like is for derivVals to be [3;3;3;3;3]. That is, I'd like derivVals to be the same size as evalPoints even if the input function happens to be linear (or constant). And I don't know ahead of time what the input expression will be.

Can anyone give suggestions for a scheme that would do that? I understand that a constant anonymous function will just return a single constant scalar, regardless of the size of its input. What I'm hoping for is perhaps some way to recognize when the anonymous function is constant and then still cause derivVals to be the same size as evalPoints.

I know that I could use a for loop to evaluate derivFun for every row of evalPoints, but I'd like to avoid using such a loop if possible.

Thank you for your time and consideration.

Community
  • 1
  • 1
Omech
  • 13
  • 3
  • I don't know why I didn't think of this before: using `symvar`. `if isempty(symvar(derivSym))` then `derivFun = @(q) double(derivSym)*ones(size(q));`. Any other ideas? – Omech Nov 18 '13 at 06:49

2 Answers2

0

Not 100% sure I got the problem correctly. Would this solve your issue?:

if isscalar(derivVals)
    derivVals = repmat(derivVals, size(evalPoints));
end
sebastian
  • 9,526
  • 26
  • 54
  • Thanks for your reply. That would definitely work. However, instead of checking a property `derivVals`, I'd prefer that the function `derivFun` already gives an output of the correct size. That's because I use `derivFun` extensively in some other code down the line (which I did not emphasize in the original question). – Omech Nov 18 '13 at 14:26
0

I think that this is a slightly simpler solution. The issue is that you're using matlabFunction, which simplifies down the equations and doesn't allow much customization. However, you can create an anonymous function of an anonymous function. Just add the this line right after your matlabFunction line:

derivFun = @(evalPoints)derivFun(evalPoints)+zeros(size(evalPoints));

This only evaluates the original derivFun once. However, I do like you symvar solution (just remember that adding zeros is always better than multiplying ones).

horchler
  • 18,384
  • 4
  • 37
  • 73
  • Wow, that's pretty clever! I like it. And thanks for the heads up about `matlabFunction` – Omech Nov 20 '13 at 06:55