%%***************************************************************** %% HSDsqlpcheckconvg: check convergence. %% %% ZpATynorm, AX, normX, normZ are with respect to the %% original variables, not the HSD variables. %%***************************************************************** %% SDPT3: version 4.0 %% Copyright (c) 1997 by %% Kim-Chuan Toh, Michael J. Todd, Reha H. Tutuncu %% Last Modified: 16 Sep 2004 %%***************************************************************** function [param,breakyes,use_olditer,msg] = HSDsqlpcheckconvg(param,runhist) termcode = param.termcode; iter = param.iter; obj = param.obj; relgap = param.relgap; gap = param.gap; prim_infeas = param.prim_infeas; dual_infeas = param.dual_infeas; mu = param.mu; prim_infeas_bad = param.prim_infeas_bad; dual_infeas_bad = param.dual_infeas_bad; printlevel = param.printlevel; stoplevel = param.stoplevel; inftol = param.inftol; gaptol = param.gaptol; kap = param.kap; tau = param.tau; theta = param.theta; breakyes = 0; use_olditer = 0; msg = []; infeas = max(prim_infeas,dual_infeas); prim_infeas_min = min(param.prim_infeas_min, max(prim_infeas,1e-10)); dual_infeas_min = min(param.dual_infeas_min, max(dual_infeas,1e-10)); %% err = max(infeas,relgap); if (obj(2) > 0); homRd = param.ZpATynorm/obj(2); else; homRd = inf; end if (obj(1) < 0); homrp = norm(param.AX)/(-obj(1)); else; homrp = inf; end if (param.normX > 1e15*max(1,param.normX0)) | (param.normZ > 1e15*max(1,param.normZ0)) termcode = 3; breakyes = 1; end if (homRd < min(1e-6,1e-2*sqrt(err*inftol)) & (tau < 1e-4) ... & prim_infeas > 0.5*runhist.pinfeas(iter)) ... | (homRd < 10*tau & tau < 1e-7) termcode = 1; breakyes = 1; end if (homrp < min(1e-6,1e-2*sqrt(err*inftol)) & (tau < 1e-4) ... & dual_infeas > 0.5*runhist.dinfeas(iter)) ... | (homrp < 10*tau & tau < 1e-7) termcode = 2; breakyes = 1; end if (err < gaptol) msg = sprintf('Stop: max(relative gap,infeasibilities) < %3.2e',gaptol); if (printlevel); fprintf('\n %s',msg); end termcode = 0; breakyes = 1; end min_prim_infeas = min(runhist.pinfeas(1:iter)); prim_infeas_bad = prim_infeas_bad + (prim_infeas > ... max(1e-10,5*min_prim_infeas) & (min_prim_infeas < 1e-2)); if (mu < 1e-6) idx = [max(1,iter-1): iter]; elseif (mu < 1e-3); idx = [max(1,iter-2): iter]; else idx = [max(1,iter-3): iter]; end idx2 = [max(1,iter-4): iter]; gap_ratio2 = runhist.gap(idx2+1)./runhist.gap(idx2); gap_slowrate = min(0.8,max(0.6,2*mean(gap_ratio2))); gap_ratio = runhist.gap(idx+1)./runhist.gap(idx); pstep = runhist.step(iter+1); if (infeas < 1e-4 | prim_infeas_bad) & (relgap < 1e-3) ... & (iter > 5) & (prim_infeas > (1-pstep/2)*runhist.pinfeas(iter)) gap_slow = all(gap_ratio > gap_slowrate) & (relgap < 1e-3); min_pinfeas = min(runhist.pinfeas); if (relgap < 0.1*infeas) ... & ((runhist.step(iter+1) < 0.5) | (min_pinfeas < min(1e-6,0.1*prim_infeas))) ... & (dual_infeas > 0.9*runhist.dinfeas(iter) | (dual_infeas < 1e-2*gaptol)) msg = 'Stop: relative gap < infeasibility'; if (printlevel); fprintf('\n %s',msg); end termcode = -1; breakyes = 1; elseif (gap_slow) & (infeas > 0.9*runhist.infeas(iter)) ... & (theta < 1e-8) msg = 'Stop: progress is too slow'; if (printlevel); fprintf('\n %s',msg); end termcode = -5; breakyes = 1; end elseif (prim_infeas_bad) & (iter >50) & all(gap_ratio > gap_slowrate) msg = 'Stop: progress is bad'; if (printlevel); fprintf('\n %s',msg); end termcode = -5; breakyes = 1; elseif (infeas < 1e-8) & (gap > 1.2*mean(runhist.gap(idx))) msg = 'Stop: progress is bad*'; if (printlevel); fprintf('\n %s',msg); end termcode = -5; breakyes = 1; end if (err < 1e-3) & (iter > 10) ... & (runhist.pinfeas(iter+1) > 0.9*runhist.pinfeas(max(1,iter-5))) ... & (runhist.dinfeas(iter+1) > 0.9*runhist.dinfeas(max(1,iter-5))) ... & (runhist.relgap(iter+1) > 0.1*runhist.relgap(max(1,iter-5))); msg = 'Stop: progress is bad**'; if (printlevel); fprintf('\n %s',msg); end termcode = -5; breakyes = 1; end if (infeas > 100*max(1e-12,min(runhist.infeas)) & relgap < 1e-4) msg = 'Stop: infeas has deteriorated too much'; if (printlevel); fprintf('\n %s, %3.1e',msg,infeas); end use_olditer = 1; termcode = -7; breakyes = 1; end if (min(runhist.infeas) < 1e-4 | prim_infeas_bad) ... & (max(runhist.infeas) > 1e-4) & (iter > 5) relgap2 = abs(diff(obj))/(1+mean(abs(obj))); if (relgap2 < 1e-3); step_short = all(runhist.step([iter:iter+1]) < 0.1) ; elseif (relgap2 < 1) idx = [max(1,iter-3): iter+1]; step_short = all(runhist.step(idx) < 0.05); else step_short = 0; end if (step_short) msg = 'Stop: steps too short consecutively'; if (printlevel); fprintf('\n %s',msg); end termcode = -5; breakyes = 1; end end if (iter > 3 & iter < 20) & (max(runhist.step(max(1,iter-3):iter+1)) < 1e-3) ... & (infeas > 1) & (min(homrp,homRd) > 1000*inftol) if (stoplevel >= 2) msg = 'Stop: steps too short consecutively'; if (printlevel); fprintf('\n %s',msg); end termcode = -5; breakyes = 1; end end if (pstep < 1e-4) & (err > 1.1*max(runhist.relgap(iter),runhist.infeas(iter))) msg = 'Stop: steps are too short'; if (printlevel); fprintf('\n %s',msg); end use_olditer = 1; termcode = -5; breakyes = 1; end if (iter == param.maxit) termcode = -6; msg = 'Stop: maximum number of iterations reached'; if (printlevel); fprintf('\n %s',msg); end end if (infeas < 1e-8 & relgap < 1e-10 & kap < 1e-13 & theta < 1e-15) msg = 'Stop: obtained accurate solution'; if (printlevel); fprintf('\n %s',msg); end termcode = 0; breakyes = 1; end param.prim_infeas_bad = prim_infeas_bad; param.prim_infeas_min = prim_infeas_min; param.dual_infeas_bad = dual_infeas_bad; param.dual_infeas_min = dual_infeas_min; param.termcode = termcode; %%*****************************************************************************