Stop fminsearch when objective function reach certain value - matlab

How to stop fminsearch when objective function exceeded certain value (minima or maxima)
options = optimset('MaxFunEvals',9999);
[x,fval,exitflag,output] = fminsearch(#(var)objectiveFunction(variables), changingParameters,options);
How to stop the function if I reach certain objective function value (for example 1000) [within the 9999 iterations]
I've tried 'TolFun' , I am not sure if this is correct
options = optimset('MaxFunEvals',999,'TolFun',1000);
[x,fval,exitflag,output] = fminsearch(#(var)objectiveFunction(variables), changingParameters,options);

You can manually stop the search procedure by placing an appropriate function in the options.OutputFcn input struct. This function is called in every iteration of the search, and permits to signal back that the search is to be terminated. For example, you could define
function stop = custom_stop_fun(~, optimValues, ~)
if optimValues.fval >= 1000
stop = true;
else
stop = false;
end
end
and then set it via
options.OutputFcn = #custom_stop_fun;
Check out the full OutputFcn documentation

Related

Create an array that grows at a regular interval on Matlab

I have been thinking about how to create an array that grows at a regular interval of time (for instance every 5 seconds) on Matlab.
I figured out 2 ways, either using tic/ toc or timer function. Later this program will be complexified. I am not sure which way is the best but so far I am trying with using timer.
Here is what I have tried :
clc;
period=5;%period at which the file should be updated
freq=4;
l=freq*period;
time=[0];
a = timer('ExecutionMode','fixedRate','Period',period,'TimerFcn',{#time_append, time,l,freq},'TasksToExecute',3 );
start(a);
function [time]=time_append(obj,event,time,l,freq)
time_append=zeros(l,1);
last_time=time(end)
for i=1:1:l
time_append(i)=last_time+i/freq;
end
time=[time;time_append];
end
After compiling this code, I only get a time array of length 1 containing the value 0 wheras it should contain values from 0 to 3x5 =15 I think it is a stupid mistake but I can't see why. I have tried the debug mode and it seems that at the end of the line time=[time;time_append], the concatenation works but the time array is reinitialised when we go out of the function. Also I have read that callback function can't have output. Does someone would know how I could proceed? Using globals? Any other suggestion?
Thank you for reading
You can do this by using nested functions. Nested functions allow you to access "uplevel variables", and you can modify those. Here's one way to do it:
function [a, fcn] = buildTimer()
period=5;%period at which the file should be updated
freq=4;
l=freq*period;
time=0;
function time_append(~,~,l,freq)
time_append=zeros(l,1);
last_time=time(end);
for i=1:1:l
time_append(i)=last_time+i/freq;
end
time=[time;time_append];
end
function out = time_get()
out = time;
end
fcn = #time_get;
a = timer('ExecutionMode','fixedRate',...
'Period',period,...
'TimerFcn',{#time_append,l,freq},...
'TasksToExecute',3 );
start(a);
end
Note that the variable time is shared by time_append and time_get. The timer object invokes time_append, and updates time. You need to hand out the function handle time_get to retrieve the current value of time.
>> [a,fcn] = buildTimer; size(fcn()), pause(10); size(fcn())
ans =
21 1
ans =
61 1

Function 'subsindex' is not defined for values of class 'struct'

I am using the matlab to solve a simple model in economics. But I came across an error
Function 'subsindex' is not defined for values of class 'struct'
when I run the last line of code.
omega=mkt_share(Par,w,Grid);
It appears wired to me as I call this function repeatedly in the code before reaching the last line, it works fine. Could anyone inform me how to solve the problem? Thanks!
I post the full code of my program as following
clear all
Par.theta = 1.5;
Par.gamma = 6;
Par.beta = 0.1;
Par.zeta = 15;
Par.n = 100;
Grid.q = sort( gprnd(1/Par.zeta,1/Par.zeta,1,Par.n,1));
Grid.q = Grid.q./Grid.q(1);
w0=0.0001;
We0=tot_mkt_share(Par,w0,Grid);
mkt_share=mkt_share(Par,w0,Grid);
w1=0.01;
We1=tot_mkt_share(Par,w1,Grid);
while(We0*We1>0)
if We0<0
w0=w0*0.5;
We0=tot_mkt_share(Par,w0,Grid);
end
if We1>0
w1=w1*1.5;
We1=tot_mkt_share(Par,w1,Grid);
end
end
iconv2=0;
tol2=0.0000001;
maxit2=1000;
it2=1;
while(iconv2==0 && it2<=maxit2)
w=(w0+w1)/2;
We=tot_mkt_share(Par,w,Grid);
if abs(We)<tol2
iconv2=1;
disp('wage has converged in')
it2
else
if We*We1>0
w1=w;
else
w0=w;
end
it2=it2+1;
end
end
if it2>=maxit2
disp('Warning: Zero profit condition not satisfied')
end
omega=mkt_share(Par,w,Grid);
The code for function mkt_share
function omega=mkt_share(Par,w0,Grid)
omega=w0;
for i=2:Par.n
rel_q=Grid.q(i);
fcn=#(omega) (rel_q)^(-Par.gamma)*(omega/w0)^(1-Par.beta*Par.gamma)*((1-
((1-w0)/Par.gamma+w0/Par.theta))/(1-
((1omega)/Par.gamma+omega/Par.theta)))^(Par.gamma-1)-1;
omega_i=fsolve(fcn,w0);
omega=[omega',omega_i]';
end
The code for function tot_mkt_share, which calls function mkt_share
function tot_mkt_share=tot_mkt_share(Par,w0,Grid)
tot_mkt_share=sum(mkt_share(Par,w0,Grid))-1;
When you do:
mkt_share=mkt_share(Par,w0,Grid);
you create a variable with the same name as the function. From this point on, the function is no longer accessible, it is shadowed. The last line attempts to index into this variable, rather than call the function as you intend, because the function is shadowed.

Matlab - Is there a way to capture messages sent to the workspace?

I'm working on a GUI (without GUIDE) in Matlab. The GUI will ultimately be compiled to an application and released to my coworkers.
My GUI calls some custom functions I wrote ages ago. These custom functions display status/progress messages to the workspace window.
As I understand it, I could have my executable write those messages to a log file, but then that leaves the user without any status updates on the GUI while the program is running.
I'm working on some pretty intensive 3D data manipulation, which has the potential to run for 5-10 minutes between function calls, so while I could provide status updates between function calls, it still leaves the end user with no idea what's going on and/or the appearance that the program locked up.
What I would like to do is to have something that works akin to the 'try-catch' method, where there's some way I can execute a function and capture messages intended for the workspace and redirect them to a uicontrol text box.
:EDIT:
I'm adding this for posterity, in the event anyone wants to use it. This is a functional demo that shows how to implement Peter's answer below.
First, create and save a function called "EndlessLoop":
function EndlessLoop(handles,loopCallback)
if nargin<1
handles = [];
loopCallback = #loop_Callback;
else
disp('Callback already set!');
end
tic;
abort = false;
while true
statusText = sprintf('Current Elapsed Time:\n%.2f',toc);
abort = loopCallback(handles,statusText);
if abort
statusText = sprintf('Abort request processed.\nEnding now.');
[~] = loopCallback(handles,statusText);
break;
end
pause(0.1);
end
return;
function abort = loop_Callback(~,myText)
clc;
abort = false;
disp(myText)
return;
Then, create a GUI that calls on EndlessLoop:
function TestGUI
close all;
myTest = figure('Visible','on','Units','normalized','Position',[0.1 0.1 0.8 0.8],'Name','Test GUI','NumberTitle','off');
set(myTest,'menubar','none');
handles = guihandles(myTest);
handles.goButton = uicontrol('Style','pushbutton','Units','normalized','Position',[0 0.5 0.5 0.5],'String','Go');
handles.abortButton = uicontrol('Style','pushbutton','Units','normalized','Position',[0 0 0.5 0.5],'String','Abort','Enable','off');
handles.statusText = uicontrol('Style','text','Units','normalized','Position',[0.5 0 0.5 1],'String','Press Go when ready.');
set(handles.goButton,'Callback',#goButton_Callback,'interruptible','on');
set(handles.abortButton,'Callback',#abortButton_Callback,'interruptible','on');
handles.abortButton.UserData = false;
guidata(myTest,handles);
return;
function goButton_Callback(hObject,~)
handles = guidata(gcbo);
hObject.Enable = 'off';
handles.abortButton.Enable = 'on';
EndlessLoop(handles,#StatusUpdate)
handles.abortButton.String = 'Abort';
handles.abortButton.Enable = 'off';
hObject.Enable = 'on';
pause(0.5);
handles.statusText.String = 'Press Go to start again.';
handles.abortButton.UserData = false;
guidata(gcbo,handles);
return;
function abortButton_Callback(hObject,~)
handles = guidata(gcbo);
if handles.abortButton.UserData
handles.abortButton.UserData = false;
hObject.String = 'Abort';
else
handles.abortButton.UserData = true;
hObject.String = sprintf('Abort pending...');
end
guidata(gcbo,handles);
return;
function abort = StatusUpdate(handles,statusText)
clc;
abort = handles.abortButton.UserData;
disp(handles.abortButton.UserData)
handles.statusText.String = statusText;
return;
A couple things I found when playing with this trying to get it to work:
I have been just adding variables to the handles structure for whatever I needed. In this case it would have been handles.abortRequest = false;. However, it appears that when I pass handles to the EndlessLoop function it becomes stale - handles never updates again. To get around this, I had to store what I wanted in the UserData section of the abortButton. I think this is because the handle to abortButton is still valid, because it hasn't changed, and I get fresh UserData because I'm able to poll with the valid handle. I can't access handles.abortRequest because it's not an object - I can't poll it; it simply exists, and it exists in the "snapshot" that was when I sent handles to EndlessLoop. At least, this is my understanding.
I needed to set the 'Interruptible' property of the goButton callback to 'on' in order for the abortButton to function while the process "hung" on EndlessLoop. With Interruptible set to off no other callbacks may be processed until that particular callback completes, which will never happen with endless loop.
So, in conclusion, this is a complete functional example that answers my question. Thanks to Peter for the answer - this also includes his ProTip of being able to pass an abort option back to the process that's taking a long time to complete. I've never used callbacks like this before so hopefully others will find this useful in the future.
This answer elaborates on my comment to the question.
Assume you have function that outputs stuff to the command window:
function out = longcomputation(param1, param2)
%
while(for_a_long_time)
process_one_step();
percent_complete = something;
fprintf('Step result: %f Complete: %f', stuff, percent_complete);
end
You can make the output function configurable by passing a function handle. Here I'm making it optional by testing nargin:
function out = longcomputation(param1, param2, outputfcn)
function display_progress_to_console(msg, percentage)
sprintf('%s, Complete %f', msg, percentage);
end
if(nargin < 3) % Supply a default output function if none passed in
outputfcn = #display_progress_to_console;
end
while(for_a_long_time)
process_one_step();
percent_complete = something;
msg = sprintf('Step result: %f', stuff);
outputfcn(msg, percent_complete);
end
Now, in your GUI, you can define and pass in a different output callback. This can live right in your GUI code so that the function has access to the GUI objects you need.
ProTip: In addition, have this callback function return true or false to signal the user's desire to abort. The GUI can then present a cancel button to drive that return value, and the long-running code can periodically send the status message AND check if abort has been requested.
You could potentially use the built-in diary functionality to accomplish something similar to what you're trying to do.
diary on % Uses "diary" for filename
diary('logfile.log') % Custom filename
This will write all command line output to the specified file. Then you can periodically poll this file and update your uicontrol with the contents (or last few lines if you want).
logfile = 'logfile.log';
diary(logfile);
u = uicontrol('style', 'text');
% Check every 5 seconds
t = timer('Period', 5, ...
'ExecutionMode', 'FixedRate', ...
'TimerFcn', #(s,e)populate(s));
start(t);
function populate(src)
fid = fopen(logfile, 'rb');
contents = fread(fid, '*char').';
set(src, 'String', contents);
fclose(fid);
end

Save values that are calculated in a function for each iteration of fminsearch

I want to find the Minimum of a function using
[x,fval] = fminsearch(#(param) esm6(param,identi),result(k,1:end-1),options)
now for each Iteration step i want some values that the function 'esm6' calculates to be saved in an Array. I tried the following:
In the first line of the function i wrote
identi.sim.i_optiIter = identi.sim.i_optiIter + 1;
to have an iteration-variable counting the iteration steps of fminsearch. And later to catch the values that I need I used
identi.sim.guete_werte.gew(identi.sim.i_optiIter,:,:) = y_sim;
identi.sim.guete_werte.ungew(identi.sim.i_optiIter,:,:) = y_sim_ungew;
and to make sure that I use the new values of the identi-struct for the next function call, I wrote this at the end of the function:
assignin('base','identi',identi);
Now unfortunatly it doesn't do what I wanted it to do. Can anyone help me with this?
EDIT:
I made another attempt on it, using an Output function. I extendend my Options like this:
options = optimset('Display','iter','MaxIter',3,'OutputFcn',#outfun);
But now the Problem is that i cannot figure out where to put this outfun. The outfun Looks like this:
function stop = outfun(x,optimvalues,state,iteration,y_sim,y_sim_ungew)
stop = false;
if state == 'iter'
guete_werte.gew(iteration,:,:) = y_sim;
guete_werte.ungew(iteration,:,:) = y_sim_ungew;
end
end
Now the Problem with it is, that i can not put it in the file, where i call the fminsearch, because that is a script. If i put the outputfunction into a separate .m-function file, it is not able to Access the variables of the esm6 function. And if I add it to the esm6-function file, matlab can't find the function and says
??? Error using ==> feval Undefined function or method 'outfun' for
input arguments of type 'struct'.

Passing a variable out of local functions

I'm having some trouble with local functions within my code so I've pasted a simple example below:
function [avg,testvar] = test(x) %Warning
n = length(x);
avg = mymean(x,n);
end
function [a,testvar] = mymean(v,n)
a = sum(v)/n;
testvar=123;
end
One can probably see what I'm attempting; to pass testvar out of the local functions. However Matlab returns the warning:
"The function return value 'testvar' might be unset"
with respect to the line I've commented "%Warning".
What's the best way of getting around this?
You need to specify the value of the second output of test(). Otherwise how can MATLAB know what its value is supposed to be? It doesn't know the second output of mymean() should be routed to the second output of test(). Perhaps this will solve your problem.
function [avg,testvar] = test(x) %Warning
n = length(x);
[avg, testvar] = mymean(x,n);
end
function [a,testvar] = mymean(v,n)
a = sum(v)/n;
testvar=123;
end
The variables between brackets after function are the output variables.
In your first function, you did not assign any value to testvar hence the warning. If you add testvar = 123; in the first function, the warning goes away. Or you can remove testvar from the output variables, leaving:
function avg = test(x)