Code to run script multiple times
Show older comments
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 Comments
per isakson
on 9 Apr 2019
Edited: per isakson
on 9 Apr 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
on 9 Apr 2019
per isakson
on 9 Apr 2019
So why did you write "fsolve(NFRO3Script)" in your question?
Alex Mcaulley
on 9 Apr 2019
for loop??
Accepted Answer
More Answers (1)
per isakson
on 9 Apr 2019
Edited: per isakson
on 9 Apr 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 Comments
madhan ravi
on 9 Apr 2019
Edited: madhan ravi
on 9 Apr 2019
Per as far as I know globals are not recommended but is persistent not recommended too? . Just curious.
Alice Shen
on 9 Apr 2019
Edited: per isakson
on 9 Apr 2019
Alice Shen
on 9 Apr 2019
per isakson
on 9 Apr 2019
Edited: per isakson
on 12 Apr 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
on 9 Apr 2019
Edited: madhan ravi
on 9 Apr 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
on 9 Apr 2019
Edited: per isakson
on 12 Apr 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
on 11 Apr 2019
Edited: per isakson
on 11 Apr 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.
Categories
Find more on Function Creation in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!