comparison toolboxes/distance_learning/mlr/util/qplcprog.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:e9a9cd732c1e
1 function [x, fval, status] = qplcprog(H, f, Ai, bi, Ae, be, lb, ub, varargin)
2 %QPLCPROG Positive-semidefinite quadratic programming based on linear complementary programming.
3 %
4 % x = qplcprog(H, f);
5 % [x, fval, status] = qplcprog(H, f, Ai, bi, Ae, be, lb, ub, varargin);
6 %
7 % Inputs:
8 % H - Hessian for objective function (n x n matrix)
9 %
10 % Optional Inputs:
11 % f - Vector for objective function, default is 0 (n x 1 vector)
12 % Ai - Linear inequality constraint matrix, default is [] (ni x n matrix)
13 % bi - Linear inequality constraint vector, default is [] (ni x 1 vector)
14 % Ae - Linear equality constraint matrix, default is [] (ne x n matrix)
15 % be - Linear equality constraint vector, default is [] (ne x 1 vector)
16 % lb - Lower-bound constraint, default is 0 (n x 1 vector)
17 % ub - Upper-bound constraint, default is [] (n x 1 vector)
18 %
19 % maxiter - LCP maximum iterations, default is 100000
20 % tiebreak - Method to break ties for pivot selection (default is 'first'). Options are:
21 % 'first' Select pivot with lowest index.
22 % 'last' Select pivot with highest index.
23 % 'random' Select a pivot at random.
24 % tolpiv - LCP pivot selection tolerance, default is 1.0e-9
25 % tolcon - QP constraint tolerance, default is 1.0e-6
26 %
27 % Outputs:
28 % x - Solution vector (n x 1 vector)
29 % fval - Value of objective function at solution (scalar)
30 % status - Status of optimization with values (integer)
31 % 6 Ray termination
32 % 1 Convergence to a solution (normal termination)
33 % 0 Termination prior to convergence
34 % -2 Infeasible problem
35 % -3 Bad pivot to an infeasible solution
36 %
37 % Notes:
38 % Depending upon the inputs, various types of positive-semidefinite quadratic programs can be
39 % solved. The general problem is
40 %
41 % min 0.5 * x' * H * x + f' * x
42 % x
43 %
44 % subject to any or all of the following constraints
45 %
46 % Ai * x <= bi
47 % Ae * x = be
48 % lb <= x <= ub
49 %
50 % with the current requirement that lb must be specified and finite.
51 %
52 % It is assumed that H is positive-semidefinite. Note that if H = 0, qplcp solves a linear
53 % program.
54
55 % Copyright 2008 The MathWorks, Inc.
56 % $Revision: 1.1.6.3 $ $ Date: $
57
58 if nargin < 1
59 error('Finance:qplcprog:MissingInputArgument', ...
60 'Missing required Hessian matrix for QP.');
61 end
62 H = full(H);
63 n = size(H,1);
64
65 if nargin < 2 || isempty(f)
66 f = zeros(n,1);
67 else
68 f = full(f);
69 f = f(:);
70 end
71
72 if nargin == 3
73 error('Finance:qplcprog:IncompleteConstraintSpecification', ...
74 'Incomplete specification for linear inequality constraints.');
75 end
76 if nargin < 3
77 Ai = [];
78 bi = [];
79 else
80 Ai = full(Ai);
81 bi = full(bi);
82 bi = bi(:);
83 end
84
85 if nargin == 5
86 error('Finance:qplcprog:IncompleteConstraintSpecification', ...
87 'Incomplete specification for linear equality constraints.');
88 end
89 if nargin < 5
90 Ae = [];
91 be = [];
92 else
93 Ae = full(Ae);
94 be = full(be);
95 be = be(:);
96 end
97
98 if nargin < 7 || isempty(lb)
99 error('Finance:qplcprog:MissingBoundConstraint', ...
100 'Lower-bound constraint required.');
101 else
102 lb = full(lb);
103 lb = lb(:);
104 if any(~isfinite(lb))
105 error('Finance:qplcprog:MissingBoundConstraint', ...
106 'Finite lower-bound constraint required.');
107 end
108 end
109
110 if nargin < 8
111 ub = [];
112 else
113 ub = full(ub);
114 ub = ub(:);
115 if all(ub == Inf)
116 ub = [];
117 end
118 end
119 if any(~isfinite(ub))
120 error('Finance:qplcprog:InvalidBoundConstraint', ...
121 'If specified, finite upper-bound constraint required.');
122 end
123
124 % process name-value pairs (if any)
125
126 if nargin > 8
127 if mod(nargin-8,2) ~= 0
128 error('Finance:qplcprog:InvalidNameValuePair', ...
129 'Invalid name-value pairs with either a missing name or value.');
130 end
131
132 names = { 'maxiter', 'tiebreak', 'tolcon', 'tolpiv' }; % names
133 values = { 10000, 'first', 1.0e-4, 1.0e-9 }; % default values
134 try
135 [maxiter, tiebreak, tolcon, tolpiv] = parsepvpairs(names, values, varargin{:});
136
137 catch E
138 E.throw
139 end
140 else
141 maxiter = 100000;
142 tiebreak = 'first';
143 tolpiv = 1.0e-9;
144 tolcon = 1.0e-6;
145 end
146
147 % check arguments
148
149 if maxiter <= 0
150 error('Finance:qplcprog:NonPositiveInteger', ...
151 'Maximum number of iterations (maxiter) must be a positive integer.');
152 end
153
154 if tolcon < 2*eps
155 error('Finance:qplcprog:InvalidTolerance', ...
156 'Unrealistically small constraint tolerance (tolcon) specified.');
157 end
158
159 if tolpiv < 2*eps
160 error('Finance:qplcprog:InvalidTolerance', ...
161 'Unrealistically small pivot tolerance (tolpiv) specified.');
162 end
163
164 % set translation if necessary
165
166 if norm(lb) ~= 0
167 fx = f + H*lb;
168 if ~isempty(Ai) && ~isempty(bi)
169 bxi = bi - Ai*lb;
170 end
171 if ~isempty(Ae) && ~isempty(be)
172 bxe = be - Ae*lb;
173 end
174 if ~isempty(ub)
175 uxb = ub - lb;
176 end
177 translate = true;
178 else
179 fx = f;
180 if ~isempty(Ai) && ~isempty(bi)
181 bxi = bi;
182 end
183 if ~isempty(Ae) && ~isempty(be)
184 bxe = be;
185 end
186 if ~isempty(ub)
187 uxb = ub;
188 end
189 translate = false;
190 end
191
192 % set up constraints
193
194 if ~isempty(Ai) && ~isempty(bi)
195 if ~isempty(Ae) && ~isempty(be)
196 if ~isempty(ub)
197 A = [ Ai; Ae; -Ae; eye(n,n) ];
198 b = [ bxi; bxe; -bxe; uxb ];
199 else
200 A = [ Ai; Ae; -Ae ];
201 b = [ bxi; bxe; -bxe ];
202 end
203 else
204 if ~isempty(ub)
205 A = [ Ai; eye(n,n) ];
206 b = [ bxi; uxb ];
207 else
208 A = Ai;
209 b = bxi;
210 end
211 end
212 else
213 if ~isempty(Ae) && ~isempty(be)
214 if ~isempty(ub)
215 A = [ Ae; -Ae; eye(n,n) ];
216 b = [ bxe; -bxe; uxb ];
217 else
218 A = [ Ae; -Ae ];
219 b = [ bxe; -bxe ];
220 end
221 else
222 if ~isempty(ub)
223 A = eye(n,n);
224 b = uxb;
225 else
226 error('Finance:qplcprog:InvalidConstraints', ...
227 'Insufficient or invalid constraints.');
228 end
229 end
230 end
231
232 % set up lcp problem
233
234 ns = size(A,1);
235
236 M = [ zeros(ns,ns) -A; A' H ];
237 q = [ b; fx ];
238
239 % solve lcp problem
240
241 if isempty(varargin)
242 [z, w, status] = lcprog(M, q); %#ok
243 else
244 [z, w, status] = lcprog(M, q, 'maxiter', maxiter, 'tiebreak', tiebreak, 'tolpiv', tolpiv); %#ok
245 end
246
247 % solve qp problem
248
249 if status > 0
250 x = z(end-n+1:end);
251 if translate
252 x = x + lb;
253 end
254 fval = 0.5*x'*H*x + f'*x;
255
256 if qplcprogrealitycheck(Ai, bi, Ae, be, lb, ub, x)
257 status = -2;
258 x = NaN(n,1);
259 fval = NaN;
260 end
261 else
262 x = NaN(n,1);
263 fval = NaN;
264 end
265
266 function notok = qplcprogrealitycheck(Ai, bi, Ae, be, lb, ub, x, tolcon)
267 %QPLCPROGREALITYCHECK - Make sure candidate solution x is feasible.
268
269 if nargin < 7
270 error('Finance:qplcprog:MissingInputArgument', ...
271 'Missing required input arguments Ai, bi, Ae, be, lb, ub, x.');
272 end
273 if nargin < 8 || isempty(tolcon)
274 tolcon = 1.0e-6;
275 end
276
277 notok = false;
278
279 if ~isempty(Ai)
280 u = max(Ai*x - bi,0);
281 if u > tolcon
282 warning('Finance:qplcprog:InfeasibleProblem', ...
283 'Candidate solution violates inequality constraints.');
284 notok = true;
285 end
286 end
287
288 if ~isempty(Ae)
289 if norm(be - Ae*x,inf) > tolcon
290 warning('Finance:qplcprog:InfeasibleProblem', ...
291 'Candidate solution violates equality constraints.');
292 notok = true;
293 end
294 end
295
296 if ~isempty(lb)
297 u = x - lb;
298 if min(u) < -tolcon
299 warning('Finance:qplcprog:InfeasibleProblem', ...
300 'Candidate solution violates lower-bound constraints.');
301 notok = true;
302 end
303 end
304
305 if ~isempty(ub)
306 u = ub - x;
307 if min(u) < -tolcon
308 warning('Finance:qplcprog:InfeasibleProblem', ...
309 'Candidate solution violates upper-bound constraints.');
310 notok = true;
311 end
312 end
313
314
315 % [EOF]