00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <cfloat>
00028
00029 #include "dbleCHOL.h"
00030 #include "dbleSVD.h"
00031 #include "mx-m-dm.h"
00032 #include "EIG.h"
00033
00034 #include "defun-dld.h"
00035 #include "error.h"
00036 #include "gripes.h"
00037 #include "oct-obj.h"
00038 #include "pr-output.h"
00039 #include "utils.h"
00040
00041 static Matrix
00042 null (const Matrix& A, octave_idx_type& rank)
00043 {
00044 Matrix retval;
00045
00046 rank = 0;
00047
00048 if (! A.is_empty ())
00049 {
00050 SVD A_svd (A);
00051
00052 DiagMatrix S = A_svd.singular_values ();
00053
00054 ColumnVector s = S.diag ();
00055
00056 Matrix V = A_svd.right_singular_matrix ();
00057
00058 octave_idx_type A_nr = A.rows ();
00059 octave_idx_type A_nc = A.cols ();
00060
00061 octave_idx_type tmp = A_nr > A_nc ? A_nr : A_nc;
00062
00063 double tol = tmp * s(0) * DBL_EPSILON;
00064
00065 octave_idx_type n = s.length ();
00066
00067 for (octave_idx_type i = 0; i < n; i++)
00068 {
00069 if (s(i) > tol)
00070 rank++;
00071 }
00072
00073 if (rank < A_nc)
00074 retval = V.extract (0, rank, A_nc-1, A_nc-1);
00075 else
00076 retval.resize (A_nc, 0);
00077
00078 for (octave_idx_type i = 0; i < retval.numel (); i++)
00079 if (std::abs (retval(i)) < DBL_EPSILON)
00080 retval(i) = 0;
00081 }
00082
00083 return retval;
00084 }
00085
00086 static int
00087 qp (const Matrix& H, const ColumnVector& q,
00088 const Matrix& Aeq, const ColumnVector& beq,
00089 const Matrix& Ain, const ColumnVector& bin,
00090 int maxit,
00091 ColumnVector& x, ColumnVector& lambda, int& iter)
00092 {
00093 int info = 0;
00094
00095 iter = 0;
00096
00097 double rtol = sqrt (DBL_EPSILON);
00098
00099
00100 octave_idx_type n = x.length ();
00101
00102
00103 octave_idx_type n_eq = beq.length ();
00104 octave_idx_type n_in = bin.length ();
00105
00106
00107
00108 octave_idx_type n_act = n_eq;
00109
00110 octave_idx_type n_tot = n_eq + n_in;
00111
00112
00113
00114
00115 Matrix Aact = Aeq;
00116 ColumnVector bact = beq;
00117 ColumnVector Wact;
00118
00119 if (n_in > 0)
00120 {
00121 ColumnVector res = Ain*x - bin;
00122
00123 for (octave_idx_type i = 0; i < n_in; i++)
00124 {
00125 res(i) /= (1.0 + std::abs (bin(i)));
00126
00127 if (res(i) < rtol)
00128 {
00129 n_act++;
00130 Aact = Aact.stack (Ain.row (i));
00131 bact.resize (n_act, bin(i));
00132 Wact.resize (n_act-n_eq, i);
00133 }
00134 }
00135 }
00136
00137
00138
00139 EIG eigH (H);
00140
00141 if (error_state)
00142 {
00143 error ("qp: failed to compute eigenvalues of H");
00144 return -1;
00145 }
00146
00147 ColumnVector eigenvalH = real (eigH.eigenvalues ());
00148 Matrix eigenvecH = real (eigH.eigenvectors ());
00149 double minReal = eigenvalH.min ();
00150 octave_idx_type indminR = 0;
00151 for (octave_idx_type i = 0; i < n; i++)
00152 {
00153 if (minReal == eigenvalH(i))
00154 {
00155 indminR = i;
00156 break;
00157 }
00158 }
00159
00160 bool done = false;
00161
00162 double alpha = 0.0;
00163
00164 Matrix R;
00165 Matrix Y (n, 0, 0.0);
00166
00167 ColumnVector g (n, 0.0);
00168 ColumnVector p (n, 0.0);
00169
00170 ColumnVector lambda_tmp (n_in, 0.0);
00171
00172 while (! done)
00173 {
00174 iter++;
00175
00176
00177
00178
00179 g = q + H * x;
00180
00181 if (n_act == 0)
00182 {
00183
00184
00185 if (minReal > 0.0)
00186 {
00187
00188
00189
00190
00191 CHOL cholH (H);
00192
00193 R = cholH.chol_matrix ();
00194
00195 Matrix Hinv = chol2inv (R);
00196
00197
00198
00199
00200 p = -Hinv * g;
00201
00202 info = 0;
00203 }
00204 else
00205 {
00206
00207
00208 p = eigenvecH.column (indminR);
00209
00210
00211
00212 if (p.transpose () * g > DBL_EPSILON)
00213 p = -p;
00214
00215 info = 1;
00216 }
00217
00218
00219 lambda_tmp.fill (0.0);
00220 }
00221 else
00222 {
00223
00224
00225
00226
00227 octave_idx_type rank;
00228
00229 Matrix Z = null (Aact, rank);
00230
00231 octave_idx_type dimZ = n - rank;
00232
00233
00234
00235
00236
00237 Y = Aact.pseudo_inverse ();
00238
00239
00240 Matrix Zt = Z.transpose ();
00241 Matrix rH = Zt * H * Z;
00242
00243 octave_idx_type pR = 0;
00244
00245 if (dimZ > 0)
00246 {
00247
00248
00249
00250 CHOL cholrH (rH, pR);
00251 Matrix tR = cholrH.chol_matrix ();
00252 if (pR == 0)
00253 R = tR;
00254 }
00255
00256 if (pR == 0)
00257 {
00258 info = 0;
00259
00260
00261 if (dimZ > 0)
00262 {
00263
00264
00265 Matrix rHinv = chol2inv (R);
00266
00267 ColumnVector pz = -rHinv * Zt * g;
00268
00269
00270 p = Z * pz;
00271 }
00272 else
00273 {
00274
00275 p.fill (0.0);
00276 }
00277 }
00278 else
00279 {
00280 info = 1;
00281
00282
00283
00284 EIG eigrH (rH);
00285
00286 if (error_state)
00287 {
00288 error ("qp: failed to compute eigenvalues of rH");
00289 return -1;
00290 }
00291
00292 ColumnVector eigenvalrH = real (eigrH.eigenvalues ());
00293 Matrix eigenvecrH = real (eigrH.eigenvectors ());
00294 double mRrH = eigenvalrH.min ();
00295 indminR = 0;
00296 for (octave_idx_type i = 0; i < n; i++)
00297 {
00298 if (mRrH == eigenvalH(i))
00299 {
00300 indminR = i;
00301 break;
00302 }
00303 }
00304
00305 ColumnVector eVrH = eigenvecrH.column (indminR);
00306
00307
00308 p = Z * eVrH;
00309
00310 if (p.transpose () * g > DBL_EPSILON)
00311 p = -p;
00312 }
00313 }
00314
00315
00316 ColumnVector abs_p (n);
00317 for (octave_idx_type i = 0; i < n; i++)
00318 abs_p(i) = std::abs (p(i));
00319 double max_p = abs_p.max ();
00320
00321 if (max_p < rtol)
00322 {
00323
00324 if (n_act - n_eq == 0)
00325
00326
00327 done = true;
00328 else
00329 {
00330
00331
00332
00333 Matrix Yt = Y.transpose ();
00334 Yt = Yt.extract_n (n_eq, 0, n_act-n_eq, n);
00335 lambda_tmp = Yt * (g + H * p);
00336
00337
00338
00339 double min_lambda = lambda_tmp.min ();
00340 if (min_lambda >= 0)
00341 {
00342
00343 done = true;
00344 }
00345 else
00346 {
00347 octave_idx_type which_eig = 0;
00348 for (octave_idx_type i = 0; i < n_act; i++)
00349 {
00350 if (lambda_tmp(i) == min_lambda)
00351 {
00352 which_eig = i;
00353 break;
00354 }
00355 }
00356
00357
00358
00359
00360 n_act--;
00361 for (octave_idx_type i = which_eig; i < n_act - n_eq; i++)
00362 {
00363 Wact(i) = Wact(i+1);
00364 for (octave_idx_type j = 0; j < n; j++)
00365 Aact(n_eq+i,j) = Aact(n_eq+i+1,j);
00366 bact(n_eq+i) = bact(n_eq+i+1);
00367 }
00368
00369
00370 Wact.resize (n_act-n_eq);
00371 bact.resize (n_act);
00372 Aact.resize (n_act, n);
00373 }
00374 }
00375 }
00376 else
00377 {
00378
00379 if (n_act - n_eq == n_in)
00380 {
00381
00382
00383 x += p;
00384 }
00385 else
00386 {
00387
00388
00389 alpha = 1.0;
00390 octave_idx_type is_block = -1;
00391
00392 for (octave_idx_type i = 0; i < n_in; i++)
00393 {
00394 bool found = false;
00395
00396 for (octave_idx_type j = 0; j < n_act-n_eq; j++)
00397 {
00398 if (Wact(j) == i)
00399 {
00400 found = true;
00401 break;
00402 }
00403 }
00404
00405 if (! found)
00406 {
00407
00408
00409
00410 RowVector tmp_row = Ain.row (i);
00411 double tmp = tmp_row * p;
00412 double res = tmp_row * x;
00413
00414 if (tmp < 0.0)
00415 {
00416 double alpha_tmp = (bin(i) - res) / tmp;
00417
00418 if (alpha_tmp < alpha)
00419 {
00420 alpha = alpha_tmp;
00421 is_block = i;
00422 }
00423 }
00424 }
00425 }
00426
00427
00428
00429 if (is_block >= 0)
00430 {
00431
00432
00433 n_act++;
00434 Aact = Aact.stack (Ain.row (is_block));
00435 bact.resize (n_act, bin(is_block));
00436 Wact.resize (n_act-n_eq, is_block);
00437
00438
00439 x += alpha * p;
00440 }
00441 else
00442 {
00443
00444
00445 x += alpha * p;
00446 }
00447 }
00448 }
00449
00450 if (iter == maxit)
00451 {
00452 done = true;
00453
00454 info = 3;
00455 }
00456 }
00457
00458 lambda_tmp = Y.transpose () * (g + H * p);
00459
00460
00461
00462 lambda.resize (n_tot);
00463 lambda.fill (0.0);
00464 for (octave_idx_type i = 0; i < n_eq; i++)
00465 lambda(i) = lambda_tmp(i);
00466
00467 for (octave_idx_type i = n_eq; i < n_tot; i++)
00468 {
00469 for (octave_idx_type j = 0; j < n_act-n_eq; j++)
00470 {
00471 if (Wact(j) == i - n_eq)
00472 {
00473 lambda(i) = lambda_tmp(n_eq+j);
00474 break;
00475 }
00476 }
00477 }
00478
00479 return info;
00480 }
00481
00482 DEFUN_DLD (__qp__, args, ,
00483 "-*- texinfo -*-\n\
00484 @deftypefn {Loadable Function} {[@var{x}, @var{lambda}, @var{info}, @var{iter}] =} __qp__ (@var{x0}, @var{H}, @var{q}, @var{Aeq}, @var{beq}, @var{Ain}, @var{bin}, @var{maxit})\n\
00485 Undocumented internal function.\n\
00486 @end deftypefn")
00487 {
00488 octave_value_list retval;
00489
00490 if (args.length () == 8)
00491 {
00492 const ColumnVector x0 (args(0) . vector_value ());
00493 const Matrix H (args(1) . matrix_value ());
00494 const ColumnVector q (args(2) . vector_value ());
00495 const Matrix Aeq (args(3) . matrix_value ());
00496 const ColumnVector beq (args(4) . vector_value ());
00497 const Matrix Ain (args(5) . matrix_value ());
00498 const ColumnVector bin (args(6) . vector_value ());
00499 const int maxit (args(7) . int_value ());
00500
00501 if (! error_state)
00502 {
00503 int iter = 0;
00504
00505
00506 ColumnVector x = x0;
00507
00508
00509 ColumnVector lambda;
00510
00511 int info = qp (H, q, Aeq, beq, Ain, bin, maxit, x, lambda, iter);
00512
00513 if (! error_state)
00514 {
00515 retval(3) = iter;
00516 retval(2) = info;
00517 retval(1) = lambda;
00518 retval(0) = x;
00519 }
00520 else
00521 error ("qp: internal error");
00522 }
00523 else
00524 error ("__qp__: invalid arguments");
00525 }
00526 else
00527 print_usage ();
00528
00529 return retval;
00530 }
00531
00532
00533
00534
00535
00536
00537