Mercurial > hg > camir-aes2014
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] |