Conversion of symbolic expression to double without obtaining complex numbers

13 views (last 30 days)
I have written a function which should return the inserted values x0 of the partial derivatives of a mathematical function fun. My variables in the mathematical function are symbolic and at the end I need to convert Y, because I want to get some double values. My MATLAB function looks as follows:
function Y = patial_derivatives(fun, x0)
syms x y z P real
variables = [x y z];
for i = 1:numel(x0)
P(i) = diff(fun, variables(i));
Y = subs(P,{x,y,z},{x0(1),x0(2),x0(3)});
and I want to call the function like this:
patial_derivatives(@(x,y,z) x^ y*exp(z), [-10 1 100])
One derivative of my function obtains the logarithm and that is where it is geeting complex when I want to convert it to a double value. Does anybody have an idea how I can avoid complex numbers here?
Walter Roberson
Walter Roberson on 8 Aug 2023
Looking at the code:
Things that are not symbolic variables or sym() class get sym() applied to them. And sym() of a function handle creates a symbolic expression.
The documented permitted values for the item to be differentiated are stricter than what is actually accepted. For example the documentation lists single and double but not any of the integer data types, but the integer types are accepted as well
diff(uint8(1:5), sym('x'))
ans = 
Paul on 8 Aug 2023
Edited: Paul on 8 Aug 2023
Thanks for pointing out that use of sym that takes in a function handle and creates a symbolic expression.
I'm almost there.
I guess we are dealing with this case from the Function Precedence Order:
7. Object functions
An object function accepts a particular class of object in its input argument list. When there are multiple object functions with the same name, MATLAB checks the classes of the input arguments to determine which function to use.
In this case, there is no object function diff for a function_handle, so we go to the object function diff for class sym. So I don't think this is a dominant class situation (but I'm probably wrong). And I don't know what happens if the argument list contains two (or more) objects of different classess that have a same-named object function, but neither class is inferior to the other. Probably goes left to right.
Anyway, now that Matlab has determined that sym->diff is to be called, it applies sym() to the first argument. Is that a rule that's always applied in classes in general? That is, if there's not an exact signature match for the object function being called, Matlab will always try to make a matching signature by applying the class constructor to the non-matching arguments? I don't do OO programming in Matlab, so I might be asking basic questions.
Regardless of how it gets done, it appears that the first argument to sym->-diff will try to get converted by sym() if it's not already sym-like (like a symfun, or symmatrix) that I assume don't need sym() applied if they are the first argument. But, if that's the case, then (as I think you're alluding to) the documentation is overly restrictive in the list of acceptable data types. Seems like it should either list all of the types that are convertible to a sym (including function_handle and uint_8) or get rid of that "single | double" and replace it with language to the effect of "anything convertible to a sym." As written, a reasonable reader might infer that a function_handle, or uint_8, should throw an error (or result in undefined behavior) because the doc explicitly calls out only single and double.

Sign in to comment.

Answers (2)

VBBV on 8 Aug 2023
Edited: VBBV on 8 Aug 2023
oneway, is to use a conditional statement for negative input values through abs function. But if you want to avoid complex value then simply use real function
patial_derivatives(@(x,y,z) (x)^y*exp(z), [-10 1 100])
ans = 
function Y = patial_derivatives(fun, x0)
syms x y z P real
variables = [x y z];
for k = 1:numel(x0)
P(k) = diff(fun, variables(k));
Y = real(subs(P,{x,y,z},{x0(1),x0(2),x0(3)}));

Dyuman Joshi
Dyuman Joshi on 8 Aug 2023
Edited: Dyuman Joshi on 8 Aug 2023
"Is there any possibility to garantuee that Matlab takes the abs values for the log if I get the log inside my derivative"
You can try this -
out = patial_derivatives(@(x,y,z) (x)^y*exp(z), [-10 1 100])
P = 
out = 
function Y = patial_derivatives(fun, x0)
syms x y z P
variables = [x y z];
for k = 1:numel(x0)
P(k) = diff(fun, variables(k));
%Changing log() terms to log(abs())
P = subs(P,log(variables),log(abs(variables)))
Y = subs(P,variables,x0);
Note that this only changes for log(), if the input has any other function that returns complex values for particular inputs, that will require additional modifiction.
You should also keep in mind what @Walter Roberson commented - "But that would mean working with a different function, one that has discontinuous derivatives at x == 0."

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!