sp.c File Reference

#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)


Function Documentation

void cngrncb ( int  itype,
int  n,
double *  AP,
double *  B,
double *  CP,
double *  temp 
)

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:

double inprd ( double *  X,
double *  Z,
int  L,
int blck_szs 
)

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, &ltemp, 
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:


Generated on Sun Mar 4 16:10:41 2007 for Scilab [trunk] by  doxygen 1.5.1