Function handle with multiple outputs

17 views (last 30 days)
Yasir Al-Latifi
Yasir Al-Latifi on 16 Mar 2017
Commented: John BG on 19 Mar 2017
This first block of code is just for reference if you want to test the code yourself. The code in this block should not be changed.
A = [-2 0 3 1 1 1 -2 -1 -3; -2 0 0 3 -1 -3 1 2 1;
-2 0 3 -2 1 -2 2 1 -1];
syms x y z real
xiyjzk=kron(x.^(0:2)'*y.^(0:2),z.^(0:2));
p = sum(sum(A.*xiyjzk));
f = [ exp(-x.^2-y.^2-z.^2).*atan(p); x.^2+y.^2-z.^2-1/4;
x.^2+y.^2+z.^2-4 ];
Df = jacobian(f,[x,y,z]);
f = matlabFunction(f);
Df = matlabFunction(Df);
This produces a function f with three outputs, let's call them f1, f2 and f3. It looks like this:
f=@(x,y,z)[f1;f2;f3]
Now, if I try to run this function:
gradient(f,[x,y,z])
it doesn't work. I think the problem is that the f function produces three outputs. Is it possible to somehow access just f1 or f2 or f3 from my function f? Basically, it should work if it was like this:
gradient(f1,[x,y,z])
gradient(f2,[x,y,z])
gradient(f3,[x,y,z])
How can I access these three functions individually from my function f?

Answers (2)

Walter Roberson
Walter Roberson on 17 Mar 2017
There are two functions named gradient.
  • One of them accepts a numeric array as its first argument. A function handle is not numeric, so you are not using that one.
  • the other accepts a symbolic expression or symbolic function as its first argument. A function handle is not symbolic, so you are not using that one either.
  2 Comments
Walter Roberson
Walter Roberson on 17 Mar 2017
Your function handle is not returning multiple outputs. It is returning an array of outputs. The size of that array is going to depend on the size of the inputs. It is difficult to visualize the size of the result of the kron when your variables are nonscalar, and if they are nonscalar but not vectors of length 3 then the .^ is not defined. The .* with the 9 x 3 array A would probably fall apart to except maybe in some sizes and using R2016b or later with its automatic bsxfun equivalent.
Remember when you use matlabFunction that it is assumed that the computation can be vectorized in the input variables.
At the very least you should call f passing in the symbolic variables x y z, and get back a symbolic array. Then pick out an element of the array and gradient that.
You should probably be looking at hessian instead of Jacobian.
John BG
John BG on 19 Mar 2017
Jacobian, not Hessian.
From the data provided in the question I doubt the Hessian is needed here.
John BG

Sign in to comment.


John BG
John BG on 17 Mar 2017
Edited: John BG on 17 Mar 2017
Hi Yasir
1. the way you have defined f, function f is a field, not a potential function.
This is a potential function
func(x,y,z)
this is a field function
gx(x,y,z)*ux+gy(x,y,z)*uy+gz(x,y,z)*uz
where ux uy uz are normalised directing vectors (abs(ux)=abs(uy)=abs(uz)=1), and are orthogonal, they are the reference base of the space used to define the field.
Since you have defined the input function like this
[fx(x,y,z),fy(x,y,z),fz(x,y,z)]
gradient doesn't start because it's expecting a function like
h(x,y,z)
2.
an easy way to use the symbolic expressions that you have defined x y z is:
fx = exp(-x.^2-y.^2-z.^2).*atan(p);
fy= x.^2+y.^2-z.^2-1/4;
fz= x.^2+y.^2+z.^2-4 ;
jacobian([fx,fy,fz])
ans =
[ (exp(- x^2 - y^2 - z^2)*(3*y - 4*x + y^2*z^2 - 4*x*y - y*z + 4*x*y^2 + 6*x*z^2 - 3*y*z^2 + 2*y^2*z + y^2 - 4*x*y*z^2 + 2*x*y^2*z - 2*x*y^2*z^2 + 2*x*y*z - 2))/((- x^2*y^2*z^2 + x^2*y^2*z + 2*x^2*y^2 - 2*x^2*y*z^2 + x^2*y*z - 2*x^2*y + 3*x^2*z^2 - 2*x^2 + x*y^2*z^2 + 2*x*y^2*z + x*y^2 - 3*x*y*z^2 - x*y*z + 3*x*y - 2*x - 3*y^2*z^2 - y^2*z - 2*y^2 + y*z^2 + y*z + y + 3*z^2 - 2)^2 + 1) - 2*x*atan(- x^2*y^2*z^2 + x^2*y^2*z + 2*x^2*y^2 - 2*x^2*y*z^2 + x^2*y*z - 2*x^2*y + 3*x^2*z^2 - 2*x^2 + x*y^2*z^2 + 2*x*y^2*z + x*y^2 - 3*x*y*z^2 - x*y*z + 3*x*y - 2*x - 3*y^2*z^2 - y^2*z - 2*y^2 + y*z^2 + y*z + y + 3*z^2 - 2)*exp(- x^2 - y^2 - z^2), (exp(- x^2 - y^2 - z^2)*(3*x - 4*y + z - 2*x^2*z^2 + 2*x*y - x*z - 2*y*z + 4*x^2*y - 3*x*z^2 + x^2*z - 6*y*z^2 - 2*x^2 + z^2 + 2*x*y*z^2 + 2*x^2*y*z - 2*x^2*y*z^2 + 4*x*y*z + 1))/((- x^2*y^2*z^2 + x^2*y^2*z + 2*x^2*y^2 - 2*x^2*y*z^2 + x^2*y*z - 2*x^2*y + 3*x^2*z^2 - 2*x^2 + x*y^2*z^2 + 2*x*y^2*z + x*y^2 - 3*x*y*z^2 - x*y*z + 3*x*y - 2*x - 3*y^2*z^2 - y^2*z - 2*y^2 + y*z^2 + y*z + y + 3*z^2 - 2)^2 + 1) - 2*y*atan(- x^2*y^2*z^2 + x^2*y^2*z + 2*x^2*y^2 - 2*x^2*y*z^2 + x^2*y*z - 2*x^2*y + 3*x^2*z^2 - 2*x^2 + x*y^2*z^2 + 2*x*y^2*z + x*y^2 - 3*x*y*z^2 - x*y*z + 3*x*y - 2*x - 3*y^2*z^2 - y^2*z - 2*y^2 + y*z^2 + y*z + y + 3*z^2 - 2)*exp(- x^2 - y^2 - z^2), (exp(- x^2 - y^2 - z^2)*(y + 6*z + x^2*y^2 - x*y + 2*y*z + 2*x*y^2 + x^2*y + 6*x^2*z - 6*y^2*z - y^2 + 2*x*y^2*z - 4*x^2*y*z - 2*x^2*y^2*z - 6*x*y*z))/((- x^2*y^2*z^2 + x^2*y^2*z + 2*x^2*y^2 - 2*x^2*y*z^2 + x^2*y*z - 2*x^2*y + 3*x^2*z^2 - 2*x^2 + x*y^2*z^2 + 2*x*y^2*z + x*y^2 - 3*x*y*z^2 - x*y*z + 3*x*y - 2*x - 3*y^2*z^2 - y^2*z - 2*y^2 + y*z^2 + y*z + y + 3*z^2 - 2)^2 + 1) - 2*z*atan(- x^2*y^2*z^2 + x^2*y^2*z + 2*x^2*y^2 - 2*x^2*y*z^2 + x^2*y*z - 2*x^2*y + 3*x^2*z^2 - 2*x^2 + x*y^2*z^2 + 2*x*y^2*z + x*y^2 - 3*x*y*z^2 - x*y*z + 3*x*y - 2*x - 3*y^2*z^2 - y^2*z - 2*y^2 + y*z^2 + y*z + y + 3*z^2 - 2)*exp(- x^2 - y^2 - z^2)]
[ 2*x, 2*y, -2*z]
[ 2*x, 2*y, 2*z]
.
.
if you find this answer useful would you please be so kind to mark my answer as Accepted Answer?
To any other reader, please if you find this answer
please click on the thumbs-up vote link
thanks in advance
John BG

Community Treasure Hunt

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

Start Hunting!