What is the recommended way to pass long list of parameters between main workspace and function?

27 vues (au cours des 30 derniers jours)
In my work I encountered a problem with passing variables betwen main script and function. Of course I can do it manually:
a1=1;a2=2;a3=3;a4=4;a5=5; %The list is much longer in my project, here just example
sum=calcvalues(a1,a2,a3,a4,a5);
function sum=calcvalues(a1,a2,a3,a4,a5)
sum=0;
b=[1,2,3];
for i=1:3
sum_tmp=sum_support(a1,a2,a3,a4,a5,b(i));
sum=sum+sum_tmp;
end
end
function sum_support = sum_support(a1,a2,a3,a4,a5,b)
sum_support=a1*a2+a3^b+a4*a5;
end
But I have to retype all values every time, and after any modification in list of function inputs there is no option to sync with other executions. Additionally, the list is very long, and take space in every function, making the code less readable. My intention was to override this with
function sum=calcvalues(varargin)
But this doesn't preserve file names. The output is just a 1x5 cell with anonymouse numbers. So far I managed to use eval to assign names dyanmicaly but this does not looks like a good practise. What is the recommended way to restore/preserve the names?
EDIT to clarify:
Here is the closest solution to what I expected. However this requires to use save command to unpack the structure. Is it possible to do this in more elegant way?
a1=1;a2=2;a3=3;a4=4;a5=5; %The list is much longer in my project, here just example
value_holder=struct('a1',a1,'a2',a2,'a3',a3,'a4',a4,'a5',a5);
sum=calcvalues(value_holder)
function sum=calcvalues(value_holder)
sum=0;
b=[1,2,3];
for i=1:3
sum_tmp=sum_support(value_holder,b(i));
sum=sum+sum_tmp;
end
end
function sum_support = sum_support(value_holder,b)
save('temp.mat','-struct','value_holder')
load('temp.mat')
sum_support=a1*a2+a3^b+a4*a5;
end
  7 commentaires
Karol P.
Karol P. le 24 Mai 2022
Modifié(e) : Karol P. le 24 Mai 2022
Does any of ODE solvers support nested function? If no, @Matt J proposition is so far the best.
Stephen23
Stephen23 le 24 Mai 2022
Modifié(e) : Stephen23 le 24 Mai 2022
"Does any of ODE solvers support nested function?"
There is nothing preventing you from using nested functions as the objective function in an ODE solver.

Connectez-vous pour commenter.

Réponse acceptée

dpb
dpb le 24 Mai 2022
If the variables are such as your example of a sequence of number variables with same root name, that implies they're related/same thing, just different instances. In that case I'd use an array and indexing -- "A" instead.
Alternatively, if they are actually different variables, take those that are related and create a structure to pass for succinctness and then reference the component variables in the struct.
Alternatively, if there are a lot of disparate variables, consider putting them into a table and pass the table.
Would need a lot more information about the actual variables and their use to have specifics, but design the data structure around the problem and then implement it, don't just create variables willy-nilly with no overall structure.
  10 commentaires
Karol P.
Karol P. le 24 Mai 2022
Ok, after using profiler I must say that your solution is better. Maybe I will have to add extra few lines, but load/save tasks consume like half of the total operation time, so the choose is quite oblivious. I was not expecting they are so much slower than working inside workspace. Thank you!
Matt J
Matt J le 24 Mai 2022
Modifié(e) : Matt J le 24 Mai 2022
Alright, I'm mentioning this against my better judgement, but you can unpack the variables in the implicit manner that you want by doing,
eval(structvars(s)')
This might be a compromise in performance between load/save and my suggestion. However, eval() has at least the same programming hazards as load(), so take great heed of the discussion here,

Connectez-vous pour commenter.

Plus de réponses (3)

Steven Lord
Steven Lord le 24 Mai 2022
If all your variables are related and so should remain together, I would pack them into a struct array.
s = struct('a1',1,'a2',2)
s = struct with fields:
a1: 1 a2: 2
s.a3 = 3;
s.a4 = 4;
s.a5 = 5
s = struct with fields:
a1: 1 a2: 2 a3: 3 a4: 4 a5: 5
Now you can pass s into and out of your function and use the values in its fields in your function. Functions that need some but not all of the fields in the struct can ignore the ones they don't need, and you can add fields to the struct without affecting existing code.
  3 commentaires
Steven Lord
Steven Lord le 24 Mai 2022
Unpack just the variables that ODE function needs at the top of the ODE function. Or if a variable only appears once in the ODE function, you can index into the struct rather than creating an additional variable.
s = struct('a1',1,'a2',2,'a3',3,'a4',4, 'a5', 5);
function sum=calcvalues(s)
sum=0;
You shouldn't name your variable sum. That identifier already has a meaning in MATLAB.
b=[1,2,3];
for i=1:3
sum_tmp=sum_support(s,b(i));
sum=sum+sum_tmp;
end
end
function sum_support = sum_support(s,b)
% The next few lines were added
a1 = s.a1;
a2 = s.a2;
a3 = s.a3;
a4 = s.a4;
% a5 = s.a5; % Instead of doing this you can use s.a5
sum_support=a1*a2+a3^b+a4*s.a5; % like I did here
end
dpb
dpb le 25 Mai 2022
Modifié(e) : dpb le 25 Mai 2022
For something that looks likes OP's example of a bunch of constants to retrieve, I think I'd do as you suggest and retrieve in the individual ODE functions the ones needed for the function --
s=struct('coeff',[1:5]); % put all the coefficients in array instead of many (unuseful anyway) names
Then in each ODE function can write something like
IDX=[1,3,4]; % the needed coefficients for this ODE
S=sum_support(s,IDX); % call the function with needed index array
function sum_support = sum_support(s,b)
sum_support=sum(s.coeff(b))
end
At command line to show syntax works as expected...
>> s = struct('coeff',[1:5]);
>> IDX=[1 3];
>> sum(s.coeff(IDX))
ans =
4.00
>>
One could make things more simple for using for the ODE functions by creating either a struct array of an element of the coefficients for the given ODE and even have a name to ensure use right array element or if it's not too complicated, use a 2D array where each row contains the coefficents for the given ODE so the very long 1D string is given some structure associated with its use.
The disadvantage is that they are then position dependent so Steven's solution is better in that regards.

Connectez-vous pour commenter.


Matt J
Matt J le 24 Mai 2022
Modifié(e) : Matt J le 24 Mai 2022
In the case of your posted example, the appropriate re-implementation would be,
a=1:5;
result=calcvalues(a);
function accum=calcvalues(a)
accum=0;
b=[1,2,3];
for i=1:3
accum=accum+sum_support(a,b(i));
end
end
function sum_support = sum_support(a,b)
sum_support=a(1)*a(2)+a(3)^b+a(4)*a(5);
end
  6 commentaires
Karol P.
Karol P. le 24 Mai 2022
But why you think the vectors are the same lenght? I never said that.
Matt J
Matt J le 24 Mai 2022
Modifié(e) : Matt J le 24 Mai 2022
I said "if" they are, not that I know that for a fact. If they aren't the same length, you can still possibly use a cell array.
The point though is that you should go through your variables to see which ones are similar in size and type, and which can be grouped into arrays.

Connectez-vous pour commenter.


Catalytic
Catalytic le 24 Mai 2022
Modifié(e) : Catalytic le 24 Mai 2022
Do not use load/save to introduce undeclared variables in your workspace. This can have unexpected effects as described in this doc page -
which also mentions recommended alternatives.
  5 commentaires
Catalytic
Catalytic le 24 Mai 2022
The fact that you have a million different variables in your calculation means that the code will already be unreadable. Like the other contributors, I wonder if your variables could be better aggregated into vectors, matrices, and other array types. The MAT in MATLAB stands for matrix, and you should be using them.
Karol P.
Karol P. le 24 Mai 2022
The project is very complicated, and no, the values cannot be grouped like you suggest. If it would be that simple I would not bother to ask. Anyway, thank you for your suggestions, in more generalised case, you're right of course.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Logical dans Help Center et File Exchange

Produits


Version

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by