Passing a vector as multiple inputs to a function
79 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Martin O'Connor
le 23 Déc 2017
Réponse apportée : Bruno
le 2 Nov 2022
I'm writing a vehicle dynamics model using the symbolic maths toolbox and the ODE15 solver. It all seems to be working as expected but I am just trying to make the function slightly more easy to use.
At the moment I am passing a vector of the systems state and their derivatives (S in the below function) and a vector with all the system parameters I want to change quickly (stuff like inertias and spring rates) in a seperate vector (called vars), along with the symbolic equations of motion (called EoM) and some time varying forces as f and ft.
My problem is that when passing values to the equations of motion I need to enter them seperately as S(1),S(2)... and vars(1),vars(2)... which means that if I add additional parameters to my model I will need to update this function to add the new values. Is there a way to convert a vector of values into seperate function inputs so that this will update automatically?
Thanks
Martin
function DS = EoM_func(t,S,EoM,vars,ft,f)
DS = zeros(14,1);
Acc = interp1(ft,f(1,:),t);
Brk = interp1(ft,f(2,:),t);
Cor = interp1(ft,f(3,:),t);
out = EoM(S(1), S(2), S(3), S(4), S(5), S(6), S(7),...
S(8), S(9), S(10),S(11),S(12),S(13),S(14),...
vars(1),vars(2),vars(3),...
vars(4),vars(5),vars(6),...
vars(7),vars(8),vars(9),...
vars(10),vars(11),vars(12),...
vars(13),vars(14),vars(15),...
vars(16),vars(17),vars(18),...
vars(19),vars(20),vars(21),...
Acc,Brk,Cor);
DS(1) = S(2);
DS(2) = out(1);
DS(3) = S(4);
DS(4) = out(2);
DS(5) = S(6);
DS(6) = out(3);
DS(7) = S(8);
DS(8) = out(4);
DS(9) = S(10);
DS(10) = out(5);
DS(11) = S(12);
DS(12) = out(6);
DS(13) = S(14);
DS(14) = out(7);
end
3 commentaires
Stephen23
le 24 Déc 2017
"I need to enter them seperately as S(1),S(2)... and vars(1),vars(2)... "
It really would be much simpler to re-write the function to accept vector inputs. Your code could be significantly simplified by taking advantage of vectors more. For example, rather than individually allocate each value individually to the output variable you just need this:
DS = [S(2:2:14);out(1:7)];
DS = DS(:).';
Réponse acceptée
Stephen23
le 24 Déc 2017
"Is there a way to convert a vector of values into seperate function inputs so that this will update automatically"
Yes there is (but really you should just rewrite that function to accept a vector input). The trick is to use a comma-separated list:
C = num2cell(S)
D = num2cell(vars);
out = EoM(C{:},D{:},Acc,Brk,Cor);
0 commentaires
Plus de réponses (2)
Walter Roberson
le 24 Déc 2017
You can use matlabFunction with the 'vars' parameter. Pass the option a cell array. Each vector of symbols in the cell array will be bundled together into a single input. Use a row vector of symbols if you want the vectorization to be along the columns, and use a column vector of symbols if you want the vectorization to be along the rows (that is, even with symbols bundled together you can vectorize to process multiple groups of values at the same time.)
Example:
x = sym('x', [1 3]);
y = x(1)^3/3 + x(2)^2 / 2 - x(3);
fr = matlabFunction(y, 'vars', {x}); %use this when the function will be passed a row of values, such as for fminsearch
fc = matlabFunction(y, 'vars', {x.'}); %use this when the function will be passed a column of values, such as for ode45()
1 commentaire
Priya Natarajan
le 25 Mar 2019
Walter Roberson, thank you, thank you, thank you!
I've been trying to find this answer for literally hours and been finding all kinds of weird workarounds involving passing the function to a string and back. Why this isn't the top answer, I have no idea. I searched practically all combinations of the terms 'symbolic', 'function', 'variable vector', 'symbolic vector' trying to find a way to define a function to accept a vector as an input before thinking of searching how to turn a vector into multiple inputs.
For Google's sake, this is the correct way to define a symbolic function to receive a vector input! Hopefully this shows up when some other hapless newbie programmer tries to search for the same terms I was searching.
Bruno
le 2 Nov 2022
So if understand correctly you have a function that takes multiple inputs (x1,x2) and you want to pass a vector [x1, x2] that the function know how to interpret, I managed to come with this solution. Basically create a function that wraps the function you want to use and maps each element of the vector to an input of the function.
The example below is a minimalistic example of calculating the gradient and the hessian of the Rosenbrock function with a=1 and b=100, at the point [1,1].
This works pretty much as a Python function decorator, potentially it can be modified to support a variable number of arguments but I didn't put enough time into researching that.
% Definition of symbolic variable x = [x1, x2]
syms x [1,2];
% Original Symbolic expressio
f_sym = ((1-x(1))^2) + (100*(x(2)-(x(1)^2))^2);
x_0 = [1,1];
% Functions of (x1,x2) created from Symbolic Expressions
fun = matlabFunction(f_sym);
fun_grad = matlabFunction(gradient(f_sym,x),'Vars',x);
fun_hess =matlabFunction(jacobian(gradient(f_sym,x),x),'Vars',x);
% Values calculated from x_0 = [1,1] using the wrapper fv.
val = fv(x_0,fun);
grad = fv(x_0,fun_grad);
hess = fv(x_0,fun_hess);
function r = fv(x,fun)
% fv stands for Function Vectorization
r = fun(x(1),x(2));
end
0 commentaires
Voir également
Catégories
En savoir plus sur Symbolic Math Toolbox dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!