Help with converting symbolic gradient/Hessian to anonymous function

Hi,
I have a symbolic function f, which is a function of a 2x1 symbolic vector. I've taken the gradient and Hessian of it without issue. However, I want to convert both of them to anonymous functions, so that I can input some vector double x0 (like [1; 1] for example), and return a 2x1 vector double for the gradient and a 2x2 matrix double for the Hessian. I've been using matlabFunction, but it always splits the symbolic inputs into two inputs x1 and x2, whereas I want one input, the vector x. I've tried specifying the variables that matlabFunction is to use by getting MATLAB to detect the symbolic variables in the function f with symvar, and tried to just input the original symbolic vector x, but neither works. Interestingly, the Hessian anonymous function has no issue with a single input, but maybe that's because in my case the Hessian in constant anyways. Anyways, here's my code:
% define function
syms x [2, 1]
f = x(1)^2 + x(2)^2 - 6*x(1) - 2*x(2) + 10;
% define initial guess
x0 = [1; 1];
xMinNM = newmet(f, x, x0);
function x = newmet(f, x, x0)
fSyms = symvar(f);
% find gradient and hessian
grad = gradient(f, x);
H = hessian(f, x);
if isa(grad, 'sym')
grad = matlabFunction(grad, 'Vars', x); % alternatively, replace x with fSyms
end
if isa(H, 'sym')
H = matlabFunction(H, 'Vars', x); % alternatively, replace x with fSyms
end
% other stuff i didn't copy
% |
% |
% |
% v
end
Thanks!

 Réponse acceptée

matlabFunction(grad, 'Vars', {x})
When you pass a cell array as Vars, then each element of the cell array is a group of variables to be bundled together into the same input parameter.

4 commentaires

This works great, thanks a ton. Do you happen to know how to get the symbolic vector x out of symvar(), by chance?
When you do
syms x [2, 1]
then that is internally equivalent to
syms x1
syms x2
x = [x1, x2];
The syms x1 generates an internal MuPAD variable named x1 and returns a reference to the internal variable and does x1 (at the MATLAB level) = (internal reference) . So there is an actual internal x1 generated, but the x1 at the MATLAB level is a reference to the internal variable
struct(x1)
Warning: Calling STRUCT on an object prevents the object from hiding its implementation details and should thus be avoided. Use DISP or DISPLAY to see the visible public details of an object. See 'help struct' for more information.
ans = struct with fields:
s: '_symans_[[32,129,52]]' mathmlOutput: [] Digits: []
Here the '_symans_[[32,129,52]]' is the internal reference.
The x = [x1, x2] part retrieves the internal references to x1 and to x2, constructs the vector concatenation of the two references inside the symbolic engine, and constructs an internal reference to the vector, and returns the internal reference... which then gets assigned to x . No vector named x is constructed in the symbolic engine!! No symbolic variable named x is built -- the vector of references to x1 and x2 is built into an anonymous vector and the reference to the anonymous vector is returned and happens to be assigned to x at the MATLAB level.
As far as the symbolic engine is concerned, you could equally have done
syms x1
syms x2
kibosh = [x1, x2];
podunk = [x1, x2];
This is true for pretty much the entire way that MATLAB uses the symbolic engine: individual symbolic variables get created in the symbolic engine, and those continue to exist as referring to themselves only, and all non-trivial computations with symbolic variables generate anonymous arrays of results, with the reference to the anonmous arrays being assigned at the MATLAB level. Individual scalar variable names are atomic in the symbolic engine, and everything else is anonymous references to expressions.
(It did not have to be this way; internally the symbolic engine is able to meaningfully name expressions and do operations such as replace parts of named expressions. But this is how the MATLAB interface to the symbolic engine is structured.)
Under the circumstances... there is no way for symvar on an expression involving x1 and x2 to return the name x . The name x exists at the MATLAB level but not at the level of the symbolic engine.
It is true that the MATLAB level could potentially search through all the symbolic variables in the present workspace, and match names... but if it did that, how would it know that it was supposed to return the name x and not the name kibosh or podunk since those contain the same [x1, x2] content as well? How would symvar be expected to treat
syms y1 y2 y3
foobar = [y1 y2];
bizbas = [y2 y3];
symvar(y1 + y2 + y3)
Should it be expected to return [foobar y3] or should it be expect to return [y1 bizbas] ?
I appreciate the in-depth answer, it makes a lot more sense now.
Thanks!
@Cole You should Accept-click the answer, since it appears to have resolved your question.

Connectez-vous pour commenter.

Plus de réponses (0)

Produits

Version

R2024b

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by