⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qp.m

📁 模式识别工具箱,本人毕业论文时用到的,希望对大家有用!
💻 M
字号:
function [X,lambda,how]=qp(H,f,A,B,vlb,vub,X,neqcstr,verbosity,negdef,normalize)%QP	Quadratic programming. %	X=QP(H,f,A,b) solves the quadratic programming problem:%%            min 0.5*x'Hx + f'x   subject to:  Ax <= b %             x    %%       [x,LAMBDA]=QP(H,f,A,b) returns the set of Lagrangian multipliers,%       LAMBDA, at the solution.%%       X=QP(H,f,A,b,VLB,VUB) defines a set of lower and upper%       bounds on the design variables, X, so that the solution  %       is always in the range VLB < X < VUB.%%       X=QP(H,f,A,b,VLB,VUB,X0) sets the initial starting point to X0.%%       X=QP(H,f,A,b,VLB,VUB,X0,N) indicates that the first N constraints defined%       by A and b are equality constraints.%%       QP produces warning messages when the solution is either unbounded%       or infeasible. Warning messages can be turned off with the calling%       syntax: X=QP(H,f,A,b,VLB,VUB,X0,N,-1).%	Copyright (c) 1990-94 by The MathWorks, Inc.%	$Revision: 1.22 $  $Date: 1994/01/25 18:16:56 $%	Andy Grace 7-9-90.% Handle missing argumentsif nargin < 11, normalize = 1;	if nargin <	10, negdef = 0; 		if nargin< 9, verbosity = []; 			if nargin< 8, neqcstr=[]; 				if nargin < 7, X=[]; 					if nargin<6, vub=[]; 						if nargin<5, vlb=[];end, end, end, end, end, end, end[ncstr,nvars]=size(A);nvars = length(f); % In case A is emptyif ~length(verbosity), verbosity = 0; endif ~length(neqcstr), neqcstr = 0; endif ~length(X), X=zeros(nvars,1); end% !DR1 - Some built-in safety. If the number of iterations%        grows too large, or if the condition of a certain%        matrix does not change, we know nothing good will%        come of it, so we just return [].maxiterations	= 50000;iteration 		=  0;prev_rcond		= -1;f=f(:);B=B(:);simplex_iter = 0;if  norm(H,'inf')==0 | ~length(H), H=0; is_qp=0; else, is_qp=~negdef; endhow = 'ok'; normf = 1;if normalize > 0	if ~is_qp		normf = norm(f);		f = f./normf;	endend% Handle bounds as linear constraintslenvlb=length(vlb);if lenvlb > 0     	A=[A;-eye(lenvlb,nvars)];	B=[B;-vlb(:)];endlenvub=length(vub);if lenvub>0	A=[A;eye(lenvub,nvars)];	B=[B;vub(:)];end ncstr=ncstr+lenvlb+lenvub;errcstr = 100*sqrt(eps)*norm(A); % Used for determining threshold for whether a direction will violate% a constraint.normA = ones(ncstr,1);if normalize > 0 	for i=1:ncstr		n = norm(A(i,:));		if (n ~= 0)			A(i,:) = A(i,:)/n;			B(i) = B(i)/n;			normA(i,1) = n;		end	endelse 	normA = ones(ncstr,1);enderrnorm = 0.01*sqrt(eps); lambda=zeros(ncstr,1);aix=lambda;ACTCNT=0;ACTSET=[];ACTIND=0;CIND=1;eqix = 1:neqcstr; %------------EQUALITY CONSTRAINTS---------------------------Q = zeros(nvars,nvars);R = [];if neqcstr>0	aix(eqix)=ones(neqcstr,1);	ACTSET=A(eqix,:);	ACTIND=eqix;	ACTCNT=neqcstr;	if ACTCNT >= nvars - 1, simplex_iter = 1; end	CIND=neqcstr+1;	[Q,R] = qr(ACTSET');	if max(abs(A(eqix,:)*X-B(eqix)))>1e-10 		X = ACTSET\B(eqix);		% X2 = Q*(R'\B(eqix)); does not work here !	end	%	Z=null(ACTSET);	[m,n]=size(ACTSET);	Z = Q(:,m+1:n);	err = 0; 	if neqcstr > nvars 		err = max(abs(A(eqix,:)*X-B(eqix)));		if (err > 1e-8) 			how='infeasible'; 			if verbosity > -1				disp('Warning: The equality constraints are overly stringent;')				disp('         there is no feasible solution.') 			end		end		actlambda = -R\(Q'*(H*X+f)); 		lambda(eqix) = normf * (actlambda ./normA(eqix));		return	end	if ~length(Z) 		actlambda = -R\(Q'*(H*X+f)); 		lambda(eqix) = normf * (actlambda./normA(eqix));		if (max(A*X-B) > 1e-8)			how = 'infeasible';			disp('Warning: The constraints or bounds are overly stringent;')			disp('         there is no feasible solution.') 			disp('         Equality constraints have been met.')		end		return	end% Check whether in Phase 1 of feasibility point finding. 	if (verbosity == -2)		cstr = A*X-B; 		mc=max(cstr(neqcstr+1:ncstr));		if (mc > 0)			X(nvars) = mc + 1;		end	endelse	Z=1;end% Find Initial Feasible Solutioncstr = A*X-B;mc=max(cstr(neqcstr+1:ncstr));if mc>eps	A2=[[A;zeros(1,nvars)],[zeros(neqcstr,1);-ones(ncstr+1-neqcstr,1)]];	[XS,lambdas]=qp([],[zeros(nvars,1);1],A2,[B;1e-5],[],[],[X;mc+1],neqcstr,-2,0,-1);	X=XS(1:nvars);	cstr=A*X-B;	if XS(nvars+1)>eps 		if XS(nvars+1)>1e-8 			how='infeasible';			if verbosity > -1				disp('Warning: The constraints are overly stringent;')				disp('         there is no feasible solution.')			end		else			how = 'overly constrained';		end		lambda = normf * (lambdas(1:ncstr)./normA);		return	endendif (is_qp)	gf=H*X+f;	SD=-Z*((Z'*H*Z)\(Z'*gf));% Check for -ve definite problems:%  if SD'*gf>0, is_qp = 0; SD=-SD; endelse	gf = f;	SD=-Z*Z'*gf;	if norm(SD) < 1e-10 & neqcstr		% This happens when equality constraint is perpendicular		% to objective function f.x.		actlambda = -R\(Q'*(H*X+f)); 		lambda(eqix) = normf * (actlambda ./ normA(eqix));		return;	endend% Sometimes the search direction goes to zero in negative% definite problems when the initial feasible point rests on% the top of the quadratic function. In this case we can move in% any direction to get an improvement in the function so try % a random direction.if negdef	if norm(SD) < sqrt(eps)		SD = -Z*Z'*(rand(nvars,1) - 0.5);	endendoldind = 0; t=zeros(10,2);tt = zeros(10,1);% The maximum number of iterations for a simplex type method is:%maxiters = prod(1:ncstr)/(prod(1:nvars)*prod(1:max(1,ncstr-nvars)))%ncstr%nvars%--------------Main Routine-------------------while 1% Find distance we can move in search direction SD before a % constraint is violated.	% Gradient with respect to search direction.	GSD=A*SD;	% Note: we consider only constraints whose gradients are greater	% than some threshold. If we considered all gradients greater than 	% zero then it might be possible to add a constraint which would lead to	% a singular (rank deficient) working set. The gradient (GSD) of such	% a constraint in the direction of search would be very close to zero.	indf = find((GSD > errnorm * norm(SD))  &  ~aix);	if ~length(indf)		STEPMIN=1e16;	else		dist = abs(cstr(indf)./GSD(indf));		[STEPMIN,ind2] =  min(dist);		ind2 = find(dist == STEPMIN);% Bland's rule for anti-cycling: if there is more than one blocking constraint% then add the one with the smallest index.		ind=indf(min(ind2));% Non-cycling rule:		% ind = indf(ind2(1));	end%------------------QP-------------	if (is_qp) % If STEPMIN is 1 then this is the exact distance to the solution.		if STEPMIN>=1			X=X+SD;			if ACTCNT>0				if ACTCNT>=nvars-1 & CIND <= size(ACTSET,1)				CIND				size(ACTSET)				size(ACTIND)					ACTSET(CIND,:)=[];ACTIND(CIND)=[]; 				end								rlambda = -R\(Q'*(H*X+f));				actlambda = rlambda;				actlambda(eqix) = abs(rlambda(eqix));				indlam = find(actlambda < 0);				if (~length(indlam)) 					lambda(ACTIND) = normf * (rlambda./normA(ACTIND));					return				end% Remove constraint				lind = find(ACTIND == min(ACTIND(indlam)));				lind=lind(1);				ACTSET(lind,:) = [];				aix(ACTIND(lind)) = 0;				[Q,R]=qrdelete(Q,R,lind);				ACTIND(lind) = [];				ACTCNT = ACTCNT - 2;				simplex_iter = 0;				ind = 0;			else				return			end		else			X=X+STEPMIN*SD;		end		% Calculate gradient w.r.t objective at this point		gf=H*X+f;	else 		% Unbounded Solution		if ~length(indf) | ~finite(STEPMIN)			if norm(SD) > errnorm				if normalize < 0					STEPMIN=abs((X(nvars)+1e-5)/(SD(nvars)+eps));				else 					STEPMIN = 1e16;				end				X=X+STEPMIN*SD;				how='unbounded'; 			else				how = 'ill posed';			end			if verbosity > -1				if norm(SD) > errnorm					disp('Warning: The solution is unbounded and at infinity;')					disp('         the constraints are not restrictive enough.') 				else					disp('Warning: The search direction is close to zero; the problem is ill posed.')					disp('         The gradient of the objective function may be zero')					disp('         or the problem may be badly conditioned.')				end			end			return		else 			X=X+STEPMIN*SD;		end	end %if (qp)% Update X and calculate constraints	cstr = A*X-B;	cstr(eqix) = abs(cstr(eqix));% Check no constraint is violated	if normalize < 0 		if X(nvars,1) < eps			return;		end	end				if max(cstr) > 1e5 * errnorm		if max(cstr) > norm(X) * errnorm 			if verbosity > -1				disp('Warning: The problem is badly conditioned;')				disp('         the solution is not reliable') 				verbosity = -1;% !DR1X=[];return% !DR1			end			how='unreliable'; 			if 0				X=X-STEPMIN*SD;				return			end		end	end% Sometimes the search direction goes to zero in negative% definite problems when the current point rests on% the top of the quadratic function. In this case we can move in% any direction to get an improvement in the function so % foil search direction by giving a random gradient.	if negdef		if norm(gf) < sqrt(eps)			gf = randn(nvars,1);		end	end	if ind		aix(ind)=1;		ACTSET(CIND,:)=A(ind,:);		ACTIND(CIND)=ind;		[m,n]=size(ACTSET);		[Q,R] = qrinsert(Q,R,CIND,A(ind,:)');	end	if oldind 		aix(oldind) = 0; 	end	if ~simplex_iter		% Z = null(ACTSET);		[m,n]=size(ACTSET);		Z = Q(:,m+1:n);		ACTCNT=ACTCNT+1;		if ACTCNT == nvars - 1, simplex_iter = 1; end		CIND=ACTCNT+1;		oldind = 0; 	else		rlambda = -R\(Q'*gf);		if rlambda(1) == -Inf			fprintf('         Working set is singular; results may still be reliable.\n');			[m,n] = size(ACTSET);			rlambda = -(ACTSET + sqrt(eps)*randn(m,n))'\gf;		end		actlambda = rlambda;		actlambda(eqix)=abs(actlambda(eqix));		indlam = find(actlambda<0);		if length(indlam)			if STEPMIN > errnorm				% If there is no chance of cycling then pick the constraint which causes				% the biggest reduction in the cost function. i.e the constraint with				% the most negative Lagrangian multiplier. Since the constraints				% are normalized this may result in less iterations.				[minl,CIND] = min(actlambda);			else				% Bland's rule for anti-cycling: if there is more than one 				% negative Lagrangian multiplier then delete the constraint				% with the smallest index in the active set.				CIND = find(ACTIND == min(ACTIND(indlam)));			end			[Q,R]=qrdelete(Q,R,CIND);			Z = Q(:,nvars);			oldind = ACTIND(CIND);		else			lambda(ACTIND)= normf * (rlambda./normA(ACTIND));			return		end	end %if ACTCNT<nvars	if (is_qp)		Zgf = Z'*gf; 		if (norm(Zgf) < 1e-15)			SD = zeros(nvars,1); 		elseif ~length(Zgf) 			% Only happens in -ve semi-definite problems			disp('Warning: QP problem is -ve semi-definite.')			SD = zeros(nvars,1);		else% !DR1 - if the condition remains equal (ly bad), we know%        something is wrong.if ((rcond (Z'*H*Z) == prev_rcond) & (prev_rcond < 1.0e-10))	bla = rcond (Z'*H*Z)	prev_rcond	disp ('Matrix condition does not change')	X = [];	returnelse	prev_rcond = rcond(Z'*H*Z);end			SD=-Z*((Z'*H*Z)\(Zgf));		end		% Check for -ve definite problems		% if SD'*gf>0, is_qp = 0; SD=-SD; end	else		if ~simplex_iter			SD = -Z*Z'*gf;			gradsd = norm(SD);		else			gradsd = Z'*gf;			if  gradsd > 0				SD = -Z;			else				SD = Z;			end		end		if abs(gradsd) < 1e-10  % Search direction null			% Check whether any constraints can be deleted from active set.			% rlambda = -ACTSET'\gf;			if ~oldind				rlambda = -R\(Q'*gf);			end			actlambda = rlambda;			actlambda(1:neqcstr) = abs(actlambda(1:neqcstr));			indlam = find(actlambda < errnorm);			lambda(ACTIND) = normf * (rlambda./normA(ACTIND));			if ~length(indlam)				return			end			cindmax = length(indlam);			cindcnt = 0;			newactcnt = 0;			while (abs(gradsd) < 1e-10) & (cindcnt < cindmax)								cindcnt = cindcnt + 1;				if oldind					% Put back constraint which we deleted					[Q,R] = qrinsert(Q,R,CIND,A(oldind,:)');				else					simplex_iter = 0;					if ~newactcnt						newactcnt = ACTCNT - 1;					end				end				CIND = indlam(cindcnt);				oldind = ACTIND(CIND);				[Q,R]=qrdelete(Q,R,CIND);				[m,n]=size(ACTSET);				Z = Q(:,m:n);				if m ~= nvars					SD = -Z*Z'*gf;					gradsd = norm(SD);				else					gradsd = Z'*gf;					if  gradsd > 0						SD = -Z;					else						SD = Z;					end				end			end			if abs(gradsd) < 1e-10  % Search direction still null				return;			end			lambda = zeros(ncstr,1);			if newactcnt 				ACTCNT = newactcnt;			end		end	end	if simplex_iter & oldind		ACTIND(CIND)=[];		ACTSET(CIND,:)=[];		CIND = nvars;	end % !DR1 - If we have cycled through more than 100 iterations, we know%        something is wrong.	iteration = iteration + 1;  if (verbosity > 0)    fprintf ('*');  end	if (iteration > maxiterations)		disp ('More than enough iterations')		X = []		return;	end;end % while 1

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -