Code covered by the BSD License  

Highlights from
OpenOpt

image thumbnail

OpenOpt

by

 

25 Nov 2006 (Updated )

nonSmoothSolve (similar to fsolve), non-smooth & noisy local + some global solvers; works in Octave

nonSmoothSolve(arg1, x0, options, varargin)
function [x fval exitflag output jacobian] = nonSmoothSolve(arg1, x0, options, varargin)
% usage:
% [x fval exitflag output jacobian] = nonSmoothSolve(fun, x0, options)
% or better OpenOpt-style:
% prob = ooAssign(...);
% r = nonSmoothSolve(prob);
% x = r.xf;
% fval = r.ff;
% see nonSmoothSolveEx.m in OpenOpt/Examples
% see also r.isFeasible and other output structure fields
% WARNING! curent version of MATLAB fsolve uses very strange stop
% criterium TolFun, something like:
% Optimization terminated: norm of relative change in X is less
%  than max(options.TolX^2,eps) and  sum-of-squares of function 
%  values is less than sqrt(options.TolFun)
%
% OpenOpt nonSmoothSolve uses norm(F, inf)<=TolFun (norm(F, inf)=max(abs(F)))
% so you should handle TolFun carefully (now default is 1e-6 for both nonSmoothSolve & fsolve)
% if nonSmoothSolve search failed, try increasing TolFun, diffInt(up to 1e-4...1e-2), MaxIter, MaxFunEvals

if ~isstruct(arg1); matlabLikeCall = 1; else matlabLikeCall = 0; end
if matlabLikeCall
    objFun = arg1;
    prob = ooAssign(@(x) 0, x0);
    prob.df = @(x) zeros(size(x));
    prob.h = objFun;
    prob.primal.h = prob.primal.f;
    prob.primal.dh = prob.primal.df;
    prob.TolFun = 1e-6;
    prob.TolCon = 1e-6;
    prob.diffInt = 1e-4;

    prob.ralg.alp = 2.0;% todo: checkme!
    if nargin<3 && exist('optimset', 'file')
        try
            options = optimset(@fsolve);
        catch
            options = [];
        end
    end
    prob = parseMATLABOptimToolboxOptions(options, prob);
    if isempty(prob.MaxTime); prob.MaxTime=inf; end
else
    prob = arg1;
    prob.assert(nargin==1, 'incorrect input');
    prob.h = @oo_h;
    
%     prob.TolFun = max(prob.TolFun, 1e-3);
    %todo: handle it in other way (in nonSmoothAssign)!!!!
    
    if iscell(prob.h)
        if length(prob.h)>1
            prob.warn('cell func in nonSmoothSolve: can''t handle this case properly yet')
        else
            prob.h = prob.h{1};
        end
    end
    prob.f = @(varargin) 0;
    prob.dh = prob.primal.df;
    prob.df = @(x, varargin) zeros(size(x));
    prob.hPattern = prob.fPattern;
    prob.fPattern = [];
    prob.primal.h = prob.primal.f;
    prob.primal.dh = prob.primal.df;
end

if iscell(prob.primal.h)
    if length(prob.primal.h)>1
        prob.warn('cell func in nonSmoothSolve: can''t handle this case properly yet')
    else
        prob.primal.h = prob.primal.h{1};
    end
end
solver = @ralg;
ExtractRoutineParamsFromProb;

prob.parallel.h = prob.parallel.f;
prob.parallel.f = 0;

prob.primal.f =  @(x) 0;
prob.primal.df = @(x) zeros(size(x));
prob.f0 = 0;
if matlabLikeCall
    h0 = prob.h(prob.x0);
else
    h0 = prob.h(prob.x0, prob);
end
prob.nh = length(h0);
% prob.h0 = h0;
if ~isvector(h0)
    ooPwarn('it is highly recomended using vector-output function, not matrix');
end
prob.osolve.iterfcn = prob.iterfcn;
prob.iterfcn = @ooSolveIterFcn;
% prob.MaxIter = 1500;
% prob.TolFun = length(h0) * prob.TolCon;
prob.TolFunSolve = prob.TolFun;
prob.TolFun = 1e-15;
prob.TolCon = 1e-15;
prob.TolX = 1e-15;

%todo: what if other than h() constraints are present in nonsmoothsolve
prob.advanced.dispBestVal = 0;

if matlabLikeCall
    r = ooRun(prob, solver);
else
    if prob.diffInt==1e-7
        prob.info('default val prob.diffInt is changed from 1e-7 to 1e-4'); 
        prob.diffInt = 1e-4;
        prob.MaxIter = 1e4;
    end
    r = solver(prob);
end

x = r.xf;

if matlabLikeCall
    fval = prob.h(r.xf, varargin{:});
else
    fval = prob.h(r.xf, prob);
end

r.ff = fval;
globstat.ff = r.ff;

% exitflag can be OTHER (than MATLAB fminsearch)! 
% So using ominsearch is not recomended, use it only for comparing
exitflag = stopcase(r);
if exitflag < 1
    prob.info('nonSmoothSolve search failed, try increasing TolFun, diffInt, MaxIter, MaxFunEvals')
end

output.algorithm = r.alg;
% global globstat
if matlabLikeCall
    output.funcCount = r.nFunEvals;
    output.iterations = r.nIter;
    output.message = r.msg;
    output.randInfo = r.randInfo;
else
    x = r;
%     output.funcCount = globstat.nFunEvals;
%     output.iterations = globstat.nIter;
%     output.message = msgstop(r);
%     output.randInfo = ooRandInfo(prob);    
end
%todo: fixme
%jacobian = 'currently unavailable';
jacobian = r.df;

Contact us