How store evolution of x over the iterations of lsqnonlin?

3 views (last 30 days)
Hi,
I'm solving a nonlinear system of equations with lsqnonlin and want to save the evolution of values of X.
The ouput of the system is defined by a function file 'error.m', which takes X with size 4x1 and returns a vector of residuals with size 8x1.
I run a script with the structure below that sets the some fixed parameters for error.m, then calls the lsqnonlin solver and error.m for n cases.
clear all,clc,close all
load measure;
%initialization: set some constant inputs for 'error.m' and options for the
%solver
% solve nCases
for i=1:nCases
inputs.measured=measure(i);
X=lsqnonlin(@(x)error(inputs,x),x0,lb,ub,options)
save X X;
end
I want to store the values of X over the iterations, not only the solution. There are these examples in Optimization Solver Output Functions, but they use nested functions and I don't know how to adapt them to my script structure.
function stop = myoutput(x,optimvalues,state);
stop = false;
if isequal(state,'iter')
history = [history; x];
end
end
How will the output function 'myoutput' access the variable X inside the lsqnonlin?
I've tried to write the myoutput at the end of the main script, predefined history = [ ] in the for loop i=1:nCases and set options = optimset('OutputFcn', @myoutput);
However, the function 'myoutput' doesn't find th ehistory variable to append. Why is that happening?
  1 Comment
Marcus
Marcus on 18 Jul 2024
Moved: Torsten on 18 Jul 2024
I just want to save the values and plot them to evaluate the convergence.

Sign in to comment.

Answers (2)

Torsten
Torsten on 18 Jul 2024
Edited: Torsten on 18 Jul 2024
If you can't use the nested approach, define "history" as a persistent variable and call "myoutput" after the computation has finished with a specific value of the "state" variable (e.g. 'plot') to plot deduced results from the "history" matrix.
function stop = myoutput(x,optimvalues,state);
persistent history
if isempty(history)
history = [];
end
stop = 0;
if strcmp(state,'iter')
history = [history; x];
end
end
  2 Comments
Marcus
Marcus on 18 Jul 2024
Thanks Torsten,
I used your code and the values of X are appended now. Just had to change the name of variable to 'evX'. It seems that 'history' has a conflict with some function in the Datafeed toolbox.
However, I didn't understand how to pass the evX matrix as an output after the lsqnonlin has finished. The variable evX is empty the output function, unless I definy it as a global variable instead of persistent.
Torsten
Torsten on 18 Jul 2024
Edited: Torsten on 18 Jul 2024
Most probably there is an easier way, but do you get the idea ?
for i = 1:2
fun();
end
[~,hout] = fun()
hout = 1x3
1 2 3
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
function [stop,hout] = fun()
persistent h s
if isempty(h)
h = [];
s = 0;
end
stop = 0;
s = s + 1;
h = [h,s];
hout = h;
end

Sign in to comment.


Steven Lord
Steven Lord on 18 Jul 2024
The ouput of the system is defined by a function file 'error.m',
Please rename this function! error already has a very important meaning in MATLAB.
I want to store the values of X over the iterations, not only the solution.
What are you hoping to do with this information? Are you trying to avoid evaluating your function repeatedly for the same inputs? If so use memoize instead of trying to build your own cache.
In fact, you could consider going the memoize route regardless of your goal. Set the CacheSize property to a sufficiently large value then ask for the stats of the MemoizedFunction returned by memoize afterwards.
f = memoize(@factorial);
clearCache(f)
f.CacheSize = 100;
for k = randi(10, 1, 20) % 20 random numbers between 1 and 10
tic
y = f(k);
t = toc;
fprintf("Computed factorial of %02d in %f seconds.\n", k, t)
end
Computed factorial of 05 in 0.005255 seconds. Computed factorial of 08 in 0.003171 seconds. Computed factorial of 05 in 0.000807 seconds. Computed factorial of 09 in 0.001112 seconds. Computed factorial of 09 in 0.000207 seconds. Computed factorial of 10 in 0.000096 seconds. Computed factorial of 04 in 0.000072 seconds. Computed factorial of 06 in 0.000111 seconds. Computed factorial of 04 in 0.000042 seconds. Computed factorial of 02 in 0.000200 seconds. Computed factorial of 05 in 0.000034 seconds. Computed factorial of 04 in 0.000016 seconds. Computed factorial of 08 in 0.000019 seconds. Computed factorial of 02 in 0.000017 seconds. Computed factorial of 10 in 0.000017 seconds. Computed factorial of 10 in 0.000016 seconds. Computed factorial of 01 in 0.000095 seconds. Computed factorial of 03 in 0.000071 seconds. Computed factorial of 10 in 0.000026 seconds. Computed factorial of 10 in 0.000019 seconds.
s = stats(f);
s.Cache
ans = struct with fields:
Inputs: {{1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell}} Nargout: [1 1 1 1 1 1 1 1 1] Outputs: {{1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell} {1x1 cell}} HitCount: [2 1 1 4 2 0 1 0 0] TotalHits: 11 TotalMisses: 9
s.Cache.Inputs{1}
ans = 1x1 cell array
{[5]}
This tells me factorial was called three times (from HitCounts) with input 5 (once initially then twice more with the result returned from the cache.) If you look at the list, you can see that the second and third calls were much faster than the first.

Community Treasure Hunt

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

Start Hunting!