Code to run script multiple times
Mostrar comentarios más antiguos
I have two codes, one is a big system of equations (NFRO3), and one is a script that runs fsolve(NFRO3Script). How do I write a code that runs the script multiple times while changing one number in the original code each time? (basically, one of my equations is like f(50) = x(49) - .r and I want to change that r from in .001 increments from like .7 to 1 [r = .7:.001:1]). (the equations only converge for very specific r values and i don't want to manually test them)
4 comentarios
per isakson
el 9 de Abr. de 2019
Editada: per isakson
el 9 de Abr. de 2019
Read fsolve, Solve system of nonlinear equations and notice especially that the first input argument of fsolve shall be a function handle or a function name. (I assume that NFRO3Script is a script (in Matlab's meaning of the word).)
Alice Shen
el 9 de Abr. de 2019
per isakson
el 9 de Abr. de 2019
So why did you write "fsolve(NFRO3Script)" in your question?
Alex Mcaulley
el 9 de Abr. de 2019
for loop??
Respuesta aceptada
Más respuestas (1)
per isakson
el 9 de Abr. de 2019
Editada: per isakson
el 9 de Abr. de 2019
Assumtions:
- NFRO3Rec is a function that "accepts a vector x and returns a vector F"
- r is not changed in your code
Alternate solutions:
- see Passing Extra Parameters ( recommended)
- make r global in NFRO3Rec and NFRO3Script (not recommended)
- use persistent according to the outline below (not tested)
- modify the code of NFRO3Rec.m (not recommended)
- and others, which I cannot think of
%% NFRO3Script
fun = @NFRO3Rec;
x0 = [(some guesses)];
for r = 0.7 : 0.001 : 1
NFRO3Rec( [], r );
x = fsolve( fun, x0 );
% assign x together with r to an array
x0 = x;
end
and
function F = NFRO3Rec( x, varargin )
persistent r
if isempty( r )
r = nan; % anything that will produce an error
end
if nargin == 2
r = varargin{1};
F = [];
return
end
% your code
f(50) = x(49) - r; % I assume the period, ".", is a typo
% more code
end
It's easier to test NFRO3Rec if it's in a separate file.
8 comentarios
madhan ravi
el 9 de Abr. de 2019
Editada: madhan ravi
el 9 de Abr. de 2019
Per as far as I know globals are not recommended but is persistent not recommended too? . Just curious.
Alice Shen
el 9 de Abr. de 2019
Editada: per isakson
el 9 de Abr. de 2019
Alice Shen
el 9 de Abr. de 2019
per isakson
el 9 de Abr. de 2019
Editada: per isakson
el 12 de Abr. de 2019
@Madhan
Caveat: I answered this question to try fsolve. I'm a beginner. The recommendations are mine.
I don't want to encourage anybody to use globals. In a small script with a local function globals might not hurt, but it's better to ban them so that one doesn't makes it a habbit using them.
The construct based on persistent isn't in the documentation as far as I can see. Now I've made a simple implementation based on an example of the documentation.
%% NFRO3Script
fun = @NFRO3Rec_persistent;
x0 = [0;0];
opt = optimoptions('fsolve','Display','none'); % don't ask me why this helps
Result = struct( 'x', cell(11,1), 'r', cell(11,1) );
jj = 0;
for r = 0.40 : 0.01 : 0.60
NFRO3Rec_persistent( [], r );
x = fsolve( fun, x0, opt );
jj = jj + 1;
Result(jj).r = r;
Result(jj).x = x;
x0 = x;
end
figure;
plot( [Result.r], [Result.x], 'd' );
%
function F = NFRO3Rec_persistent( x, varargin )
persistent r
if isempty( r )
r = nan; % anything that will produce an error
end
if nargin == 2
r = varargin{1};
F = [];
return
end
F = NFRO3Rec( x, r );
end
and
function F = NFRO3Rec( x, r )
F(1) = exp(-exp(-(x(1)+x(2)))) - x(2)*(1+x(1)^2);
F(2) = x(1)*cos(x(2)) + x(2)*sin(x(1)) - r;
end
Now I've tested the approach:
- It seems to work well.
- It's conceptually fairly simple
- NFRO3Rec is hardly modified and doesn't contain any strange code
- the function handle is created outside the loop
- problems will surely surface after some use.
I realized too late that I was reinventing the wheel and searched the documetation and added the link. The MathWorks' solution shall be recommended. Or I recommended to read the documentation.
madhan ravi
el 9 de Abr. de 2019
Editada: madhan ravi
el 9 de Abr. de 2019
@Per: What’s your point? Are you saying using persistent is not a big deal? Paremeterizing the function should do the trick right?
per isakson
el 9 de Abr. de 2019
Editada: per isakson
el 12 de Abr. de 2019
@Madhan
The problem is to paremeterize the function without changing the signature that fsolve uses. (Users shouldn't modify fsolve.)
There are three constructs on the page, "Passing Extra Parameters"
- Anonymous Functions
- Nested Functions
- Global Variables
The two first "embed" the parameters values in the function handle. Thus, the function handle must be recreated in every iteration.
At the moment I think my persistent-construct is a big deal, since its relatively simple and not included in the page, "Passing Extra Parameters"
There is another page, Pass Extra Parameters in Problem-Based Approach. I don't know if it's relevant to the current problem. (There are many pages, which I've never read.)
"The two first "embedd" the parameters values in the function handle. "
Nested functions do not have to "embed" any parameters in the function handle.
Why would it be necessary that "the function handle must be recreated in every iteration" for a nested function? I use nested function often for parameterizing functions, and I have not experienced any need to "recreate" the function handle just because a variable in the parent workspace has changed. That would entirely defeat the point of nested functions!
A nested function would also be simpler than using persistent (which requires special cases added to the objective function).
per isakson
el 11 de Abr. de 2019
Editada: per isakson
el 11 de Abr. de 2019
Yes, I was mistaken regarding nested function.
An even bigger mistake was that I answered the question without knowing that the documentation includes good solutions. I searched the documentation and added the link as an afterthought.
In this thread of comments I showed a somewhat better version of my "persistent" construct. And here is my current version (still missing error checking and documentation):
function F = objective_function_proxy( x, varargin )
%
% Syntax
% x = objective_function_proxy( x )
% x = objective_function_proxy( [], objective_function )
% x = objective_function_proxy( [], [], p1, p2, p3, ... )
persistent objective_function parameters
if isempty( objective_function )
parameters = {nan}; % something that will produce an error
objective_function = '';
end
if nargin == 2
objective_function = varargin{1};
F = [];
return
end
if nargin >= 3
parameters = varargin(2:end);
F = [];
return
end
F = feval( objective_function, x, parameters{:} );
end
Example of using objective_function_proxy()
%% NFRO3Script
fun = @objective_function_proxy;
x0 = [0;0];
opt = optimoptions('fsolve','Display','none');
Result = struct( 'x', cell(11,1), 'r', cell(11,1) );
jj = 0;
fun( [], 'NFRO3Rec' ); % set objective function
for r = 0.40 : 0.01 : 0.60
fun( [], [], r ); % set parameter value
x = fsolve( fun, x0, opt ); % call fsolve
jj = jj + 1;
Result(jj).r = r;
Result(jj).x = x;
x0 = x;
end
figure;
plot( [Result.r], [Result.x], 'd' );
where
function F = NFRO3Rec( x, r )
F(1) = exp(-exp(-(x(1)+x(2)))) - x(2)*(1+x(1)^2);
F(2) = x(1)*cos(x(2)) + x(2)*sin(x(1)) - r;
end
Comments:
- objective_function_proxy() doesn't contain any case specific code, i.e. no references to NFRO3.
- objective_function_proxy() should be possible to use in different cases without any modification.
- NFRO3Script includes two calls of objective_function_proxy(), but no code that depends on the inner workings of objective_function_proxy().
- The objective function, NFRO3Rec(), has no special code added.
Categorías
Más información sobre Function Creation en Centro de ayuda y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!