www.gusucode.com > mbcdesign 工具箱 matlab 源码程序 > mbcdesign/@conbase/bringInside.m
function X = bringInside(con, X) %BRINGINSIDE Move a set of points so they are all inside the constraint. % % Y = BRINGINSIDE(CON, X) is the data set X but with any points outside the % constraint CON projected into the constraint. % If X(i,:) is inside the constraint, then Y(i,:) = X(i,:). % If X(i,:) is outside the constraint, then Y(:,i) will be the closest point to % X(i,:) that is inside (on the boundary of) the constraint. % % If for any point X(i,:) the algorithm can not find an interior point % then NaN will be returned for that point. % % See also CONBASE, CONBASE/ISINSIDE, CONBASE/CONSTRAINTDISTANCE. % Copyright 2004-2016 The MathWorks, Inc. % For each point x = X(i,:) we need to solve the following problem % % minimize || y - x ||_2^2 % y % subject to constraintDistance( CON, y ) <= 0 % % Because we have a nice simple objective function, if CON is a linear % constraint then we can use LSQLIN. However if CON is non-linear then we must % use FMINCON as this is the only routine that supports non-lienar constraints. % % Note that X(i,:) defines the _objective_ for each iteration. There for the % optimization functions that we set-up take in this point. We also use this % point as the start point, x0, for each optimization. % % The constraint object, CON, defines the constraint for the optimizations and % therefore this is fixed over all iterations. % % The choice of norm is a scaled 2-norm. The norm is scaled to reflect the % ranges of the input variables so that the norm along any edge of bounding % box is constant. % || y - x ||_s^2 = || S * (y - x) ||_2^2 % where S = diag( 1./(cif.Max - cif.Min ) ) % Number of points NP = size( X, 1 ); if islinear( con ) optimFun = i_makeLinearOptimFun( con ); else optimFun = i_makeNonlinearOptimFun( con ); end % Only process points that are outside the constraint in = isInside( con, X, true( 1, NP ) ); for i = find( ~in ) X(i,:) = optimFun( X(i,:) ); end end function S = i_objectiveScaleFactor( con ) cif = getInputFactors( con ); S = diag( 1./(cif.Max - cif.Min ) ); end function optimFun = i_makeLinearOptimFun( con ) % Setup for the linear optimization routine % Optimization options options = i_lsqlinOptions(); % Constraint [A, b] = getLinearForm( con ); % Set-up for objective function S = i_objectiveScaleFactor( con ); % Optimization function optimFun = @n_lsqlin; function y = n_lsqlin( x ) % If symmetry makes you happy, imagine we have defined % >> objective = @( y ) ||(y - x)*S||_2^2; % and then used this in place of the first two arguments to LSQLIN % [x, norm, resd, flag]=LSQLIN( C, d, A, b, Aeq, beq, lb, ub, x0, options ) [y, ~, ~, flag] = lsqlin( S, x*S, A, b, [], [], [], [], x, options ); if flag <= 0 % Falied to converge y = NaN( size( y ) ); end end end function optimFun = i_makeNonlinearOptimFun( con ) % Setup for the non-linear optimization routine % % We need to use the same objective function but we have non-linear % constraints. Therefore we need to use fmincon % Optimization options options = i_fminconOptions(); % Constraint function [c, ceq] = n_constraint( y ) c = constraintDistance( con, y ); ceq = []; end % Optimization function S = i_objectiveScaleFactor( con ); optimFun = @n_fmincon; function y = n_fmincon( x ) objective = @( y ) sum( ((y - x)*S).^2, 2 ); % [x, fval, flag]=fmincon( fun, x0, A, b, Aeq, beq, lb, ub, nonlcon, options ) [y, ~, flag] = fmincon( objective, x, [], [], [], [], [], [], @( y )n_constraint( y ), options ); if flag <= 0 % Falied to converge y = NaN( size( y ) ); end end end function options = i_fminconOptions() options = i_optimset( 'fmincon', ... 'Display', 'none', ... 'Algorithm', 'interior-point' ); end function options = i_lsqlinOptions() options = i_optimset( 'lsqlin', ... 'Display', 'none', ... 'Algorithm', 'interior-point' ); end function options = i_optimset( optimFunction, varargin ) options = optimset( optimFunction ); options = optimset( options, varargin{:} ); end