function r = ooIter(prob, r)
% disp(r.x.')
global globstat
if ~isfield(r, 'istop'); r.istop = 0; end
if ismember(r.istop, prob.advanced.ignoreIStop)
r.istop = 0;
end
istop = 0;% continue calculations
% if isfield(r,'x'); x = r.x; else x = r.xf; end
% if isfield(r,'f'); f = r.f; else f = r.ff; end
% isNonSmoothSolve = isfield(prob, 'TolFunSolve') || isequal(lower(prob.solverName), 'nonsmoothsolve');
x = globstat.xPrevF;
if isfield(prob, 'TolFunSolve');
x = r.x;
end
if any(size(x)~=[prob.n 1])
if size(x,1)~= prob.n && size(x,2) == prob.n
x=x.';
if ~globstat.nIter; prob.warn(('you must pass n x 1 vector x to the iterfcn, not 1 x n')); end
elseif size(x,1) == prob.n && size(x,2) > 1
x = x(:,1);
% prob.err('you must pass (size prob.n x 1) vector x to the iterfcn')
end
end
f = globstat.fPrevF;
if isfield(prob, 'TolFunSolve')
f = r.f;
end
if numel(f)>1
if size(f,2)>1; f=f(1); end
f = sum(f);%by columns
end
violations = prob.advanced.getViolations(x, prob);
MaxV = max(abs(violations));
if isempty(MaxV)
if isfield(prob, 'TolFunSolve') || isequal(lower(prob.solverName), 'nonsmoothsolve') && globstat.isFinished
% called from ooRunProbSolver, solver already finished
MaxV = norm(prob.f(r.xf, inf));
else
if ~prob.primal.isUC; prob.warn('something wrong was occured'); end
MaxV = 0;
end
end
% if ~globstat.nIter; globstat.tmp.min_violations = violations; end
% if norm(globstat.tmp.min_violations, 1)<= norm(violations, 1)
% violationsAreDecreased = 1;
% else
% violationsAreDecreased = 0;
% end
% if r.f< globstat.ff && (~any(violations>prob.TolCon) || norm(violations,1) <= norm(globstat.tmp.prev_violations, 1)) ||...
% (globstat.ff-norm(violations,1)>=r.f-norm(globstat.tmp.prev_violations, 1) && ~any(violations>prob.TolCon))
% WARN! don't replace ~any() by all() - it doesn't work for empty matricies
if f < globstat.ff %&& (~any(violations>prob.TolCon) || violationsAreDecreased)
%&& ~(any(violations>prob.TolCon) && norm(violations,1) > norm(globstat.tmp.prev_violations, 1))
globstat.ff = f;
globstat.xf = x;
end%todo: handle fiter - xiter mismatch case
% if violationsAreDecreased
% globstat.tmp.min_violations = violations;
% end
if ~isfield(globstat, 'fPrev'); globstat.fPrev=inf; end
if ~isempty(prob.user.outputfcn)
r = feval(prob.user.outputfcn, prob, r);
end
if prob.iterPrint>0 && (~mod(globstat.nIter, prob.iterPrint) || globstat.isFinished)
f1=' ';
f2='';
if isfield(globstat, 'lastX')
val = prob.normx(x-globstat.lastX);
if isfinite(val); f1 = sprintf(' %0.2e', val); end
end
if isfield(r, 'df'); f2 = sprintf(' %0.2e', norm(r.df)); end
if ~globstat.nIter
if globstat.tmp.dispBestVal
secondColumn = 'Best ObjFuncVal ';
else
secondColumn = 'max(abs(constr))';
end
s = sprintf(' Iter Current ObjFunVal %s norm(deltaX)', secondColumn);
if isfield(r, 'df'); s = [s ' norm(gradient)']; end
disp(s)
end
if globstat.tmp.dispBestVal
secondColumn = globstat.ff;
else secondColumn = MaxV;
end
iterspaces = char(' ' * ones(1, 7-ceil(log10(globstat.nIter+0.1+~globstat.nIter))));
outMsg = sprintf(' %d%s%+0.8e %+0.8e', globstat.nIter, iterspaces, f, secondColumn);
s = [outMsg f1 f2];
if ~ispc
s = strrep(s, 'e+', 'e+0');
s = strrep(s, 'e-', 'e-0');
end
disp(s)
end
NOW = now;
TimeFromStart = 24*60*60*(NOW - prob.advanced.timeStart);
if ~globstat.isFinished && (~isfield(r, istop) || ~r.istop)%may be 1st cond is enough?//Dmitrey.
[mf indOpt]= min(f);
if globstat.nIter%so fields lastX & fPrev already exist
EpsFun = norm(globstat.fPrev - mf);
EpsX = norm(globstat.lastX - x(:,indOpt));
if EpsFun<prob.TolFun && EpsFun && ~ismember(4, prob.advanced.ignoreIStop); istop = 4; end
globstat.fPrev = mf;
if EpsX<prob.TolX && EpsX && ~ismember(3, prob.advanced.ignoreIStop); istop = 3; end
globstat.lastX = x(:,indOpt);
else
globstat.fPrev = mf;
globstat.lastX = x(:,indOpt); %#ok<FNDSB>
globstat.tmp.lastDrawTime = NOW;
end
globstat.nIter = globstat.nIter + 1;
globstat.iterCPUTime(globstat.nIter) = cputime - prob.advanced.cputimeStart - globstat.advanced.drawCPUTime;
globstat.iterTime(globstat.nIter) = TimeFromStart - globstat.advanced.drawTime;
globstat.iterFvals(globstat.nIter) = mf;
if f<prob.fEnough && ~ismember(10, prob.advanced.ignoreIStop); istop = 10; end
%is actual, for example, for hPSO
% if globstat.nIter>prob.MaxNonEnhance && norm(diff(globstat.iterFvals(globstat.nIter-prob.MaxNonEnhance:globstat.nIter)))<min(prob.TolFun, prob.TolCon) && ~ismember(5, prob.advanced.ignoreIStop)
% istop = 5;
% end
if any(isnan(x)) && ~ismember(-4, prob.advanced.ignoreIStop)
istop = -4;
end
if prob.advanced.traceIterX
globstat.iterFvals(:, globstat.nIter) = x(:,indOpt);
end
if globstat.nIter >= prob.MaxIter && ~ismember(-7, prob.advanced.ignoreIStop)
istop = -7;
end
if cputime-prob.advanced.cputimeStart > prob.MaxCPUTime && ~ismember(-8, prob.advanced.ignoreIStop)
istop = -8;
end
if TimeFromStart > prob.MaxTime && ~ismember(-9, prob.advanced.ignoreIStop)
istop = -9;
end
if istop && ~ismember(istop, prob.advanced.ignoreIStop)
r.istop = istop;
r.xf = globstat.xf;
r.ff = globstat.ff;
end
if ~prob.doPlot || ...
(globstat.nIter~=1 && 24*60*60*(NOW-globstat.tmp.lastDrawTime)<prob.graphics.timePlotInterval) ||...
(mod(globstat.nIter, prob.graphics.minNPoints2draw) && ~(globstat.nIter==1))
return
end
else
if isempty(globstat.iterFvals)...%for example, solver failed before 1st iter end, then iterfcn was called from ooRun to update figure
|| ~prob.doPlot;return; end
end
cpu_time = cputime;
now_time = NOW;% to economy now() calls, which are rather expensive
globstat.tmp.lastDrawTime = now_time;
prob.draw(prob, r);% prob.draw can point to other func then oodraw
% so I decided to place time handling here, not in oodraw,
% it's more general case (however, user can use another func then ooIter)
cpu_time = cputime - cpu_time;%elapsed for drawing
now_time = (now-now_time)*24*60*60;%elapsed for drawing
globstat.advanced.drawCPUTime = globstat.advanced.drawCPUTime + cpu_time;
globstat.advanced.drawTime = globstat.advanced.drawTime + now_time;