Passing a vector as multiple inputs to a function

조회 수: 56 (최근 30일)
Martin O'Connor
Martin O'Connor 2017년 12월 23일
답변: Bruno 2022년 11월 2일
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
Stephen23
Stephen23 2017년 12월 24일
"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(:).';
Martin O'Connor
Martin O'Connor 2017년 12월 24일
Vectorising the DS vector assignment is a good shout, thanks. The function is still in the "just make everything work" phase.
I can't re-write it with vector inputs because that function handle is generated by the matlabFunction() function which requires all the symbolic variables in the expression to be added as separate inputs (I think?)

댓글을 달려면 로그인하십시오.

채택된 답변

Stephen23
Stephen23 2017년 12월 24일
"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);

추가 답변 (2개)

Walter Roberson
Walter Roberson 2017년 12월 24일
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
Priya Natarajan
Priya Natarajan 2019년 3월 25일
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
Bruno 2022년 11월 2일
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

카테고리

Help CenterFile Exchange에서 Symbolic Math Toolbox에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by