#include <stdio.h>#include <math.h>#include <string.h>#include "spd.h"Include dependency graph for sp.c:

Go to the source code of this file.
Functions | |
| void | cngrncb (int itype, int n, double *AP, double *B, double *CP, double *temp) |
| double | inprd (double *X, double *Z, int L, int *blck_szs) |
| int C2F() | spf (int *m, int *L, double *F, int *blck_szs, double *c, double *x, double *Z, double *ul, double *nu, double *abstol, double *reltol, double *tv, int *iters, double *work, int *lwork, int *iwork, int *info) |
| int | sp (int m, int L, double *F, int *blck_szs, double *c, double *x, double *Z, double *ul, double nu, double abstol, double reltol, double tv, int *iters, double *work, int lwork, int *iwork, int *info) |
Definition at line 23 of file sp.c.
References dgemv(), dscal(), dspmv(), F2C(), j, and pos.
Referenced by sp().
00035 : 00036 * - itype = 1: compute C = B*A*B' 00037 * = any other integer: computes C = B'*A*B 00038 * - n dimension of A and B 00039 * - AP (input) double array of size n*(n+1)2; 00040 * the lower triangle of A in packed storage 00041 * - B (input) double array of size n*n; 00042 * - CP (output) double array of size n*(n+1)/2; 00043 * the lower triangle of C in packed storage 00044 * - temp: n-array, workspace 00045 */ 00046 00047 00048 { 00049 int j, pos, lngth = n*(n+1)/2; 00050 int int1=1; 00051 double dbl0=0.0, dbl1=1.0; 00052 00053 /* C := 0 */ 00054 F2C(dscal)(&lngth, &dbl0, CP, &int1); 00055 00056 if (itype == 1){ 00057 00058 for (j=0, pos=0; j<n; pos+=n-j, j++){ 00059 00060 /* temp = A*B(j,:)' */ 00061 F2C(dspmv)("L", &n, &dbl1, AP, B+j, &n, &dbl0, temp, &int1); 00062 00063 /* C(j:n,j) = B(j:n,:)*temp */ 00064 lngth = n-j; 00065 F2C(dgemv)("N", &lngth, &n, &dbl1, B+j, &n, temp, &int1, &dbl0, 00066 CP+pos, &int1); 00067 00068 } 00069 00070 } else { 00071 00072 for (j=0, pos=0; j<n; pos+=n-j, j++){ 00073 00074 /* temp = A*B(:,j) */ 00075 F2C(dspmv)("L", &n, &dbl1, AP, B+j*n, &int1, &dbl0, temp, &int1); 00076 00077 /* C(j:n,j) = B(:,j:n)'*temp */ 00078 lngth = n-j; 00079 F2C(dgemv)("T", &n, &lngth, &dbl1, B+j*n, &n, temp, &int1, &dbl0, 00080 CP+pos, &int1); 00081 00082 } 00083 } 00084 00085 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 88 of file sp.c.
References ddot(), F2C(), i, j, pos, result, and sz.
Referenced by sp().
00097 : 00098 * X,Z: block diagonal matrices with L blocks X^0, ..., X^{L-1}, 00099 * and Z^0, ..., Z^{L-1}. X^j and Z^j have size 00100 * blck_szs[j] times blck_szs[j]. Every block is stored 00101 * using packed storage of the lower triangle. 00102 * L: number of blocks 00103 * blck_szs: integer vector of length L 00104 * blck_szs[i], i=0,...,L-1 is the size of block i 00105 * 00106 */ 00107 00108 { 00109 double result; 00110 int i, j, k, lngth, pos, sz, int1=1; 00111 00112 /* sz = length of Z and X */ 00113 for (i=0, sz=0; i<L; i++) sz += (blck_szs[i]*(blck_szs[i]+1))/2; 00114 00115 /* result = Tr X Z + contributions of diagonal elements */ 00116 result = 2.0*F2C(ddot)(&sz, X, &int1, Z, &int1); 00117 00118 /* correct for diagonal elements 00119 * loop over blocks, j=0,...,L-1 */ 00120 for (j=0, pos=0; j<L; j++) 00121 00122 /* loop over columns, k=0,...,blck_szs[j]-1 00123 * pos is position of (k,k) element of block j 00124 * lngth is length of column k */ 00125 for (k=0, lngth=blck_szs[j]; k<blck_szs[j]; pos+=lngth, 00126 lngth-=1, k++) 00127 00128 /* subtract Z^j_{kk}*X^j_{kk} from result */ 00129 result -= Z[pos]*X[pos]; 00130 00131 return result; 00132 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int sp | ( | int | m, | |
| int | L, | |||
| double * | F, | |||
| int * | blck_szs, | |||
| double * | c, | |||
| double * | x, | |||
| double * | Z, | |||
| double * | ul, | |||
| double | nu, | |||
| double | abstol, | |||
| double | reltol, | |||
| double | tv, | |||
| int * | iters, | |||
| double * | work, | |||
| int | lwork, | |||
| int * | iwork, | |||
| int * | info | |||
| ) |
Definition at line 159 of file sp.c.
References cngrncb(), daxpy(), dcopy(), ddot(), dgels(), dgemv(), dlamch(), dnrm2(), dscal(), dspev(), dspgst(), dspgv(), dtrcon(), dx, F2C(), i, inprd(), j, MAX, MAXITERS, MINABSTOL, MINRCOND, n, NULL, pos, R, rhs, Scistring(), SIGTOL, SQR, str, sz, TOLC, and X.
00174 : the maximum number of iterations, 00175 * on exit: the number of iterations taken */ 00176 double *work; /* work array */ 00177 int lwork; /* size of work */ 00178 int *iwork; /* work array of m integers */ 00179 int *info; /* status on termination */ 00180 00181 /* 00182 * Solves semidefinite program 00183 * 00184 * minimize c'*x 00185 * subject to F_0 + x_1*F_1 + ... + x_m*F_m >= 0 00186 * 00187 * and its dual 00188 * 00189 * maximize -Tr F_0*Z 00190 * subject to Z >= 0 00191 * Tr F_i*Z = c_i, i=1,...,m 00192 * 00193 * 00194 * Convergence criteria: 00195 * (1) maxiters is exceeded 00196 * (2) duality gap is less than abstol 00197 * (3) primal and dual objective are both positive and 00198 * duality gap is less than reltol * dual objective 00199 * or primal and dual objective are both negative and 00200 * duality gap is less than reltol * minus the primal objective 00201 * (4) reltol is negative and primal objective is less than tv 00202 * (5) reltol is negative and dual objective is greater than tv 00203 * 00204 * Arguments: 00205 * - m: number of variables x_i. m >= 1. 00206 * - L: number of diagonal blocks in F_i. L >= 1. 00207 * - F: the block diagonal matrices F_i, i=0,...,m. 00208 * it is assumed that the matrices F_i are linearly 00209 * independent. 00210 * let F_i^j, i=0,..,m, j=0,...,L-1 denote the jth 00211 * diagonal block of F_i, 00212 * the array F contains F_0^0, ..., F_0^{L-1}, F_1^0, ..., 00213 * F_1^{L-1}, ..., F_m^0, ..., F_m^{L-1}, in this order, 00214 * using packed storage for the lower triangular part of 00215 * F_i^j. 00216 * - blck_szs: an integer L-vector. blck_szs[j], j=0,....L-1 gives the 00217 * size of block j, ie, F_i^j has size blck_szs[j] 00218 * times blck_szs[j]. 00219 * - c: m-vector, primal objective. 00220 * - x: m-vector. On entry, a strictly primal feasible point. 00221 * On exit, the last iterate for x. 00222 * - Z: block diagonal matrix with L blocks Z^0, ..., Z^{L-1}. 00223 * Z^j has size blck_szs[j] times blck_szs[j]. 00224 * Every block is stored using packed storage of the lower 00225 * triangular part. 00226 * On entry, a strictly dual feasible point. On exit, the 00227 * last dual iterate. 00228 * - ul: two-vector. On exit, ul[0] is the primal objective value 00229 * c'*x; ul[1] is the dual objective value -Tr F_0*Z. 00230 * - nu: >= 1.0. Controls the rate of convergence. 00231 * - abstol: absolute tolerance, >= MINABSTOL. 00232 * - reltol: relative tolerance. Has a special meaning when negative. 00233 * - tv: target value, only referenced if reltol < 0. 00234 * - iters: on entry: maximum number of iterations >= 0, 00235 * on exit: the number of iterations taken. 00236 * - work: work array of size lwork. 00237 * - lwork: size of work, must be at least: 00238 * (m+2)*sz + up_sz + 2*n + ltemp, with 00239 * ltemp = max( m+sz*nb, 3max_n + max_n*(max_n+1), 3*m ) 00240 * (sz: space needed to store one matrix F_i in packed 00241 * storage, ie, 00242 * sum_{j=0}^{L-1} blck_szs[j]*(blck_szs[j]+1)/2; 00243 * up_sz: space needed to store one matrix F_i in 00244 * unpacked storage, ie, 00245 * sum_{j=0}^{L-1} blck_szs[j]*blck_szs[j]; 00246 * max_n: max block size; 00247 * n: sum of the block sizes. 00248 * nb >= 1, for best performance, nb should be at least 00249 * equal to the optimal block size for dgels. 00250 * - iwork: work array of m integers 00251 * - info: returns 1 if maxiters exceeded, 2 if absolute accuracy 00252 * is reached, 3 if relative accuracy is reached, 00253 * 4 if target value is reached, 5 if target value is 00254 * not achievable; 00255 * negative values indicate errors: -i means argument i 00256 * has an illegal value, -18 stands for all other errors. 00257 * 00258 * 00259 * Returns 0 for normal exit, 1 if an error occurred. 00260 * 00261 */ 00262 00263 00264 { 00265 int i, j, k, n, sz, up_sz, max_n, lngth, pos, pos2, pos3, pos4, ltemp, 00266 maxiters, info2, minlwork; 00267 double q, *rhs, *Fsc, *R, *X, rho, *dx, *sigx, *sigz, *dZ, *temp, scal, 00268 scal2, XdZ, ZdX, alphax, alphaz, lambda_ls, gradx, hessx, 00269 gradz, hessz, dalphax, dalphaz, gap, newgap=0.0, newu=0.0, 00270 newl=0.0, maxpossigx, minnegsigx, maxpossigz, minnegsigz, nrmc, 00271 nrmx, nrmz, nrmmax, rcond; 00272 int int2=2, int1=1; 00273 double dbl1=1.0, dbl0=0.0, sqrt2=sqrt(2.0); 00274 char str[100]; 00275 double dbl_epsilon; 00276 00277 if (m < 1){ 00278 sprintf(str, "m must be at least one. \n"); 00279 Scistring(str); 00280 *info = -1; 00281 return 1; 00282 } 00283 if (L < 1){ 00284 sprintf(str, "L must be at least one. \n"); 00285 Scistring(str); 00286 *info = -2; 00287 return 1; 00288 } 00289 for (i=0; i<L; i++) if (blck_szs[i] < 1){ 00290 sprintf(str, "blck_szs[%d] must be at least one.\n", i); 00291 Scistring(str); 00292 *info = -4; 00293 return 1; 00294 } 00295 if (nu < 1.0){ 00296 sprintf(str, "nu must be at least 1.0. \n"); 00297 Scistring(str); 00298 *info = -9; 00299 return 1; 00300 } 00301 00302 00303 /* 00304 * calculate dimensions: 00305 * n: total size of semidefinite program 00306 * sz: length of one block-diagonal matrix in packed storage 00307 * up_sz: length of one block-diagonal matrix in unpacked storage 00308 * max_n: size of biggest block 00309 */ 00310 00311 for (i=0, n=0, sz=0, up_sz=0, max_n=0; i<L; i++){ 00312 n += blck_szs[i]; 00313 sz += blck_szs[i]*(blck_szs[i]+1)/2; 00314 up_sz += blck_szs[i]*blck_szs[i]; 00315 max_n = MAX(max_n, blck_szs[i]); 00316 } 00317 if (m > sz){ 00318 sprintf(str, "The matrices Fi, i=1,...,m are linearly dependent.\n"); 00319 Scistring(str); 00320 *info = -3; return 1; 00321 } 00322 00323 q = (double)n + nu*sqrt((double)n); 00324 00325 00326 /* 00327 * check if Tr Fi*Z = c_i, i=1,...,m 00328 */ 00329 00330 nrmc = F2C(dnrm2)(&m, c, &int1); 00331 for (i=0; i<m; i++) 00332 if (fabs(inprd(F+(i+1)*sz, Z, L, blck_szs) - c[i]) > nrmc*TOLC){ 00333 sprintf(str, "Z0 does not satisfy equality conditions\ 00334 for dual feasibility.\n"); 00335 Scistring(str); 00336 *info = -7; 00337 return 1; 00338 } 00339 00340 00341 /* 00342 * organize workspace 00343 * 00344 * work: (m+2)*sz + up_sz + 2*n + ltemp 00345 * minimum ltemp: the maximum of 00346 * m+sz*nb, 3*max_n + max_n*(max_n+1), and 3*m 00347 * (nb is at least one) 00348 * 00349 * for dgels: m + sz*nb, nb at least 1 00350 * for dspev("N"): 3*max_n + max_n*(max_n+1) 00351 * for dspgv("N"): 3*max_n + max_n*(max_n+1) 00352 * for dspgv("V"): 3*max_n + max_n*(max_n+1)/2 00353 * for cngrncb: max_n 00354 * for dtrcon: 3*m 00355 * 00356 * rhs (sz): work[0 ... sz-1] 00357 * Fsc (m*sz): work[sz ... (m+1)*sz-1] 00358 * R (up_sz): work[(m+1)*sz ... (m+1)*sz+up_sz-1] 00359 * X (sz): work[(m+1)*sz+up_sz ... (m+2)*sz+up_sz-1] 00360 * sigx (n): work[(m+2)*sz+up_sz ... (m+2)*sz+up_sz+n-1] 00361 * sigz (n): work[(m+2)*sz+up_sz+n ... (m+2)*sz+up_sz+2*n-1] 00362 * temp (remainder): work[(m+2)*sz+up_sz+2*n ... lwork-1] 00363 */ 00364 00365 /* check lwork */ 00366 minlwork = (m+2)*sz + up_sz + 2*n + 00367 MAX( MAX( m+sz, 3*max_n + max_n*(max_n+1) ), 3*m ); 00368 if (lwork < minlwork){ 00369 sprintf(str, "Work space is too small. Need at least\ 00370 %d*sizeof(double).\n", minlwork); 00371 Scistring(str); 00372 *info = -15; 00373 return 1; 00374 } 00375 00376 rhs = work; /* rhs for ls problem */ 00377 dx = work; /* solution of ls system; overlaps with rhs */ 00378 Fsc = rhs + sz; /* scaled matrices */ 00379 dZ = rhs + sz; /* overlaps with first column of Fsc */ 00380 R = Fsc + m*sz; /* eigenvectors of Z*F */ 00381 X = R + up_sz; /* F(x) */ 00382 sigx = X + sz; /* generalized eigenvalues of (dX,X) */ 00383 sigz = sigx + n; /* generalized eigenvalues of (dZ,Z) */ 00384 temp = sigz + n; 00385 ltemp = lwork - (m+2)*sz - up_sz - 2*n; 00386 00387 00388 maxiters = (*iters >= 0) ? *iters : MAXITERS; 00389 for (*iters=0; *iters <= maxiters; (*iters)++){ 00390 00391 00392 /* compute F(x) = F_0 + x_1*F_1 + ... + x_m*F_m, store in X */ 00393 F2C(dcopy)(&sz, F, &int1, X, &int1); 00394 F2C(dgemv)("N", &sz, &m, &dbl1, F+sz, &sz, x, &int1, &dbl1, X, &int1); 00395 00396 00397 /* 00398 * compute generalized eigendecomp Z*F*x = lambda*x 00399 * loop over blocks, i=0,...,L-1 00400 * pos: position of (0,0) element of block i in packed storage 00401 * pos2: position of (0,0) element of block i in unpacked 00402 * storage 00403 * pos3: position of first eigenvalue of block i in sigx 00404 */ 00405 00406 for (i=0, pos=0, pos2=0, pos3=0, gap=0.0; i<L; 00407 pos += blck_szs[i]*(blck_szs[i]+1)/2, 00408 pos2 += blck_szs[i]*blck_szs[i], 00409 pos3 += blck_szs[i], i++){ 00410 00411 lngth = blck_szs[i]*(blck_szs[i]+1)/2; 00412 00413 /* copy block i of Z in temp (need max_n*(max_n+1)/2) */ 00414 F2C(dcopy)(&lngth, Z+pos, &int1, temp, &int1); 00415 00416 /* generalized eigenvalue decomposition Z*F*x = lambda*x 00417 * - eigenvectors V are normalized s.t. V^T*F*V = I 00418 * - store block i of V in R+pos2 00419 * - store eigenvalues of block i in sigx+pos3 00420 * - dspgv replaces X+pos by cholesky factor L of ith 00421 * block of F (F = L*L^T) 00422 * use temp+lngth as workspace (need at least 3*max_n) */ 00423 F2C(dspgv)(&int2, "V", "L", blck_szs+i, temp, X+pos, sigx+pos3, 00424 R+pos2, blck_szs+i, temp+lngth, &info2); 00425 if (info2){ 00426 sprintf(str,"Error in dspgv, info = %d.\n", info2); 00427 Scistring(str); 00428 if (*iters == 0 && info2 > blck_szs[i]){ 00429 sprintf(str, "x0 is not strictly primal feasible.\n"); 00430 Scistring(str); 00431 *info = -6; 00432 } else *info = -18; 00433 return 1; 00434 } 00435 00436 /* - replace sigx+pos3 by lambda^(1/2) 00437 * - normalize block i of V (stored in R+pos2) s.t. 00438 * V^T*F*V = Lambda^(1/2) */ 00439 for (k=0; k<blck_szs[i]; k++){ 00440 scal = sigx[pos3+k]; 00441 if (scal < 0.0){ 00442 if (*iters == 0){ 00443 sprintf(str, "Z0 is not positive definite.\n"); 00444 Scistring(str); 00445 *info = 7; 00446 } else { 00447 sprintf(str, "F(x)*Z has a negative eigenvalue.\n"); 00448 Scistring(str); 00449 *info = -18; 00450 } 00451 return 1; 00452 } 00453 gap += scal; /* duality gap is sum of eigenvalues of ZF */ 00454 scal2 = sqrt(scal); 00455 scal = sqrt(scal2); 00456 sigx[pos3+k] = scal2; 00457 F2C(dscal)(blck_szs+i, &scal, R+pos2+k*blck_szs[i], &int1); 00458 } 00459 00460 } 00461 00462 00463 /* 00464 * check convergence 00465 */ 00466 00467 ul[1] = -inprd(F,Z,L,blck_szs); /* -Tr F_0 Z */ 00468 ul[0] = F2C(ddot)(&m, c, &int1, x, &int1); /* c^T x */ 00469 if (*iters == 0){ 00470 sprintf(str,"\n primal obj. dual obj. dual. gap \n"); 00471 Scistring(str); 00472 } 00473 sprintf(str,"% 13.2e % 12.2e %10.2e \n", ul[0], ul[1], gap); 00474 Scistring(str); 00475 if (gap <= MAX(abstol, MINABSTOL)) *info = 2; 00476 else if ( (ul[1] > 0.0 && gap <= reltol*ul[1]) || 00477 (ul[0] < 0.0 && gap <= reltol*(-ul[0])) ) *info = 3; 00478 else if ( reltol < 0.0 && ul[0] <= tv ) *info = 4; 00479 else if ( reltol < 0.0 && ul[1] >= tv ) *info = 5; 00480 else if ( *iters == maxiters ) *info = 1; 00481 else *info = 0; 00482 if (*info) return 0; 00483 00484 00485 00486 /* 00487 * compute scaled matrices F 00488 */ 00489 00490 for (j=0, pos=0; j<m; j++) for (i=0, pos2=0; i<L; 00491 pos += blck_szs[i]*(blck_szs[i]+1)/2, 00492 pos2 += blck_szs[i]*blck_szs[i], i++) { 00493 00494 /* compute R' * Fj(i) * R, store in Fsc+pos */ 00495 cngrncb(2, blck_szs[i], F+sz+pos, R+pos2, Fsc+pos, temp); 00496 00497 /* correct diagonal elements */ 00498 for (k=0, pos4=pos; k<blck_szs[i]; pos4 += blck_szs[i]-k, k++) 00499 Fsc[pos4] /= sqrt2; 00500 00501 } 00502 00503 00504 /* 00505 * form rhs = Lambda^(-1/2) - (q/gap) * Lambda^(1/2) 00506 */ 00507 00508 F2C(dscal)(&sz, &dbl0, rhs, &int1); /* rhs := 0 */ 00509 rho = -q/gap; 00510 for (i=0, pos=0, pos3=0; i<L; 00511 pos += blck_szs[i]*(blck_szs[i]+1)/2, 00512 pos3 += blck_szs[i], i++) 00513 for (k=0, pos4=pos; k<blck_szs[i]; pos4+=blck_szs[i]-k, k++){ 00514 scal = sigx[pos3+k]; 00515 rhs[pos4] = (1.0/scal + rho*scal)/sqrt2; 00516 } 00517 00518 00519 /* 00520 * solve least-squares problem; need workspace of size m + nb*sz 00521 * - rhs is overwritten by dx 00522 * - in first iteration, estimate condition number of Fsc 00523 */ 00524 00525 F2C(dgels)("N", &sz, &m, &int1, Fsc, &sz, rhs, &sz, temp, <emp, 00526 &info2); 00527 if (info2){ 00528 sprintf(str,"Error in dgels, info = %d.\n", info2); 00529 Scistring(str); 00530 *info = -18; return 1; 00531 } 00532 00533 if (*iters == 0){ 00534 00535 /* estimate the condition number in 1-norm of the R-factor of 00536 * the qr-decomposition of Fsc (is stored in Fsc) 00537 * need work space of size 3*m */ 00538 F2C(dtrcon)("1", "U", "N", &m, Fsc, &sz, &rcond, temp, iwork, 00539 &info2); 00540 if (info2 < 0){ 00541 sprintf(str,"Error in dtrcon, info = %d.\n", info2); 00542 Scistring(str); 00543 *info = -18; return 1; 00544 } 00545 if (rcond < MINRCOND) { 00546 sprintf(str,"The matrices F_i, i=1,...,m are linearly\ 00547 dependent (or the initial points are very badly conditioned).\n"); 00548 Scistring(str); 00549 *info = -3; return 1; 00550 } 00551 00552 } 00553 00554 00555 00556 /* 00557 * - compute dZ = 00558 * R*((q/gap)*Lambda^(1/2) - Lambda^(-1/2) + R^T*dF*R )*R^T 00559 * - compute generalized eigenvalues of (dF, F), store in sigx 00560 * - compute generalized eigenvalues of (dZ, Z), store in sigz 00561 * 00562 * loop over blocks i=0,...,L-1 00563 * pos: position of (0,0) element of block i in packed storage 00564 * pos2: position of (0,0) element of block i in unpacked storage 00565 * pos3: position of first eigenvalue of in sigx and sigz 00566 */ 00567 00568 for (i=0, pos=0, pos2=0, pos3=0; i<L; 00569 pos += blck_szs[i]*(blck_szs[i]+1)/2, 00570 pos2 += blck_szs[i]*blck_szs[i], 00571 pos3 += blck_szs[i], i++){ 00572 00573 lngth = blck_szs[i]*(blck_szs[i]+1)/2; 00574 00575 /* compute ith block of dF = \sum \delta x_i F_i, 00576 * store in temp */ 00577 F2C(dgemv)("N", &lngth, &m, &dbl1, F+sz+pos, &sz, dx, &int1, 00578 &dbl0, temp, &int1); 00579 00580 /* scale dF as R'*dF*R, store in temp + lngth */ 00581 cngrncb(2, blck_szs[i], temp, R+pos2, temp+lngth, temp+2*lngth); 00582 00583 /* add (q/gap)*Lambda^(1/2) - Lambda^(-1/2) */ 00584 for (k=0, pos4=lngth; k<blck_szs[i]; pos4+=blck_szs[i]-k, k++) 00585 temp[pos4] -= rho*sigx[pos3+k] + 1.0/sigx[pos3+k]; 00586 00587 /* replace dF in temp by L^{-1}*dF*L^{-T}, 00588 * (L: cholesky factor of F, stored in X) 00589 * and compute eigenvalues of L^{-1}*dF*L^{-T} */ 00590 F2C(dspgst)(&int1, "L", blck_szs+i, temp, X+pos, &info2); 00591 if (info2){ 00592 sprintf(str,"Error in dspst, info = %d.\n", info2); 00593 Scistring(str); 00594 *info = -18; return 1; 00595 } 00596 /* temp has to be of size max_n*(max_n+1)+3*max_n */ 00597 F2C(dspev)("N", "L", blck_szs+i, temp, sigx+pos3, NULL, &int1, 00598 temp+2*lngth, &info2); 00599 if (info2){ 00600 sprintf(str,"Error in dspev, info = %d.\n", info2); 00601 Scistring(str); 00602 *info = -18; return 1; 00603 } 00604 00605 /* dZ := R*((q/gap)*Lambda^(1/2) - Lambda^(-1/2) + R'*dF*R)*R' */ 00606 cngrncb(1, blck_szs[i], temp+lngth, R+pos2, dZ+pos, 00607 temp+2*lngth); 00608 00609 /* copy ith block of dZ to temp */ 00610 F2C(dcopy)(&lngth, dZ+pos, &int1, temp, &int1); 00611 00612 /* copy ith block of Z to temp + lngth */ 00613 F2C(dcopy)(&lngth, Z+pos, &int1, temp+lngth, &int1); 00614 00615 /* sigz: generalized eigenvalues of (dZ,Z) 00616 * required size of temp: 3*max_n + max_n*(max_n+1) */ 00617 F2C(dspgv)(&int1, "N", "L", blck_szs+i, temp, temp+lngth, sigz+pos3, 00618 NULL, &int1, temp+2*lngth, &info2); 00619 if (info2){ 00620 sprintf(str,"Error in dspgv, info = %d.\n", info2);Scistring(str); 00621 *info = -18; return 1; 00622 } 00623 00624 } 00625 00626 00627 /* 00628 * compute feasible rectangle for plane search 00629 */ 00630 00631 maxpossigx = 0.0; minnegsigx = 0.0; 00632 maxpossigz = 0.0; minnegsigz = 0.0; 00633 for (i=0; i<n; i++) { 00634 if ( sigx[i] > maxpossigx ) 00635 maxpossigx = sigx[i]; /* max pos eigenvalue in sigx */ 00636 else if ( sigx[i] < minnegsigx ) 00637 minnegsigx = sigx[i]; /* min neg eigenvalue in sigx */ 00638 if ( sigz[i] > maxpossigz ) 00639 maxpossigz = sigz[i]; /* max pos eigenvalue in sigz */ 00640 else if ( sigz[i] < minnegsigz ) 00641 minnegsigz = sigz[i]; /* min neg eigenvalue in sigz */ 00642 } 00643 nrmx = F2C(dnrm2)(&n, sigx, &int1); /* norm of scaled dx */ 00644 nrmz = F2C(dnrm2)(&n, sigz, &int1); /* norm of scaled dZ */ 00645 nrmmax = MAX( nrmx, nrmz); 00646 00647 XdZ = inprd(F,dZ,L,blck_szs); /* Tr F0*dZ */ 00648 ZdX = F2C(ddot)(&m, c, &int1, dx, &int1); /* c^T*dx */ 00649 00650 00651 /* 00652 * check corners of feasible rectangle 00653 */ 00654 00655 dbl_epsilon = F2C(dlamch)("e"); 00656 if (nrmx > SIGTOL*nrmmax) 00657 if (ZdX < 0.0) 00658 alphax = (minnegsigx < -dbl_epsilon) ? -1.0/minnegsigx : 0.0; 00659 else 00660 alphax = (maxpossigx > dbl_epsilon) ? -1.0/maxpossigx : 0.0; 00661 else alphax = 0.0; 00662 00663 if (nrmz > SIGTOL*nrmmax) 00664 if (XdZ < 0.0) 00665 alphaz = (minnegsigz < -dbl_epsilon) ? -1.0/minnegsigz : 0.0; 00666 else 00667 alphaz = (maxpossigz > dbl_epsilon) ? -1.0/maxpossigz : 0.0; 00668 else alphaz = 0.0; 00669 00670 newgap = gap + alphax*ZdX + alphaz*XdZ; 00671 newu = ul[0] + alphax*ZdX; 00672 newl = ul[1] - alphaz*XdZ; 00673 00674 if (newgap <= MAX(abstol, MINABSTOL)) *info = 2; 00675 else if ( (newl > 0.0 && newgap <= reltol*newl) || 00676 (newu < 0.0 && newgap <= -reltol*newu) ) *info = 3; 00677 else if ( reltol < 0.0 && newu <= tv ) *info = 4; 00678 else if ( reltol < 0.0 && newl >= tv ) *info = 5; 00679 else if ( *iters == maxiters ) *info = 1; 00680 else *info = 0; 00681 00682 if (*info) { 00683 F2C(daxpy)(&m, &alphax, dx, &int1, x, &int1); 00684 F2C(daxpy)(&sz, &alphaz, dZ, &int1, Z, &int1); 00685 gap = newgap; ul[0] = newu; ul[1] = newl; 00686 sprintf(str,"% 13.2e % 12.2e %10.2e \n", ul[0], ul[1], gap); 00687 Scistring(str); 00688 (*iters)++; 00689 return 0; 00690 } 00691 00692 00693 /* 00694 * plane search 00695 * minimize phi(alphax,alphaz) = 00696 * q*log(dual_gap + alphax*c^T*dx + alphaz* Tr F_0 dZ) 00697 * - sum log (1+alphax*sigx_i) - sum log (1+alphaz*sigz) 00698 */ 00699 00700 alphax = 0.0; alphaz = 0.0; lambda_ls = 1.0; 00701 00702 if (nrmx > SIGTOL*nrmmax) 00703 if (nrmz > SIGTOL*nrmmax) /* compute primal and dual steps */ 00704 while ( lambda_ls > 1e-4 ) { 00705 00706 /* compute 1st and 2nd derivatives of phi */ 00707 rho = q/(gap + alphax*ZdX + alphaz*XdZ); 00708 gradx = rho*ZdX; hessx = 0.0; 00709 gradz = rho*XdZ; hessz = 0.0; 00710 for (i=0; i<n; i++){ 00711 gradx -= sigx[i] / (1.0+alphax*sigx[i]); 00712 hessx += SQR( sigx[i] / (1.0+alphax*sigx[i]) ); 00713 gradz -= sigz[i] / (1.0+alphaz*sigz[i]); 00714 hessz += SQR( sigz[i] / (1.0+alphaz*sigz[i]) ); 00715 } 00716 00717 /* newton step */ 00718 dalphax = -gradx/hessx; dalphaz = -gradz/hessz; 00719 lambda_ls = sqrt( SQR(gradx)/hessx + SQR(gradz)/hessz ); 00720 alphax += (lambda_ls > 0.25) ? 00721 dalphax/(1.0+lambda_ls) : dalphax; 00722 alphaz += (lambda_ls > 0.25) ? 00723 dalphaz/(1.0+lambda_ls) : dalphaz; 00724 00725 } 00726 00727 else while ( lambda_ls > 1e-4 ) { /* primal step only */ 00728 00729 /* compute 1st and 2nd derivatives of phi */ 00730 rho = q/(gap + alphax*ZdX); 00731 gradx = rho*ZdX; hessx = 0.0; 00732 for (i=0; i<n; i++){ 00733 gradx -= sigx[i] / (1.0+alphax*sigx[i]); 00734 hessx += SQR( sigx[i] / (1.0+alphax*sigx[i]) ); 00735 } 00736 00737 /* newton step */ 00738 dalphax = -gradx/hessx; 00739 lambda_ls = fabs(gradx)/sqrt(hessx); 00740 alphax += (lambda_ls > 0.25) ? 00741 dalphax/(1.0+lambda_ls) : dalphax; 00742 00743 } 00744 00745 else if (nrmz > SIGTOL*nrmmax) /* dual step only */ 00746 while ( lambda_ls > 1e-4 ) { 00747 00748 /* compute 1st and 2nd derivatives of phi */ 00749 rho = q/(gap + alphaz*XdZ); 00750 gradz = rho*XdZ; hessz = 0.0; 00751 for (i=0; i<n; i++){ 00752 gradz -= sigz[i] / (1.0+alphaz*sigz[i]); 00753 hessz += SQR( sigz[i] / (1.0+alphaz*sigz[i]) ); 00754 } 00755 00756 /* newton step */ 00757 dalphaz = -gradz/hessz; 00758 lambda_ls = fabs(gradz)/sqrt(hessz); 00759 alphaz += (lambda_ls > 0.25) ? 00760 dalphaz/(1.0+lambda_ls) : dalphaz; 00761 } 00762 00763 00764 00765 /* update x and Z */ 00766 F2C(daxpy)(&m, &alphax, dx, &int1, x, &int1); 00767 F2C(daxpy)(&sz, &alphaz, dZ, &int1, Z, &int1); 00768 00769 } 00770 00771 return -1; /* should never happen */ 00772 }
Here is the call graph for this function:

| int C2F() spf | ( | int * | m, | |
| int * | L, | |||
| double * | F, | |||
| int * | blck_szs, | |||
| double * | c, | |||
| double * | x, | |||
| double * | Z, | |||
| double * | ul, | |||
| double * | nu, | |||
| double * | abstol, | |||
| double * | reltol, | |||
| double * | tv, | |||
| int * | iters, | |||
| double * | work, | |||
| int * | lwork, | |||
| int * | iwork, | |||
| int * | info | |||
| ) |
Definition at line 134 of file sp.c.
References F, info, L, m, nu, sp(), work, x, and Z.
00148 : the maximum number of iterations, 00149 * on exit: the number of iterations taken */ 00150 double *work; /* work array */ 00151 int *lwork; /* size of work */ 00152 int *iwork; /* work array of m integers */ 00153 int *info; /* status on termination */ 00154 { 00155 return(sp(*m,*L,F,blck_szs,c,x,Z,ul,*nu,*abstol,*reltol,*tv,iters, work, 00156 *lwork,iwork,info)); 00157 }
Here is the call graph for this function:

1.5.1