00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <stdio.h>
00015 #include <math.h>
00016 #include <string.h>
00017 #include "spd.h"
00018
00019 #ifdef _MSC_VER
00020 extern void Scistring (char *str);
00021 #endif
00022
00023 void cngrncb(itype,n,AP,B,CP,temp)
00024 int itype;
00025 int n;
00026 double *AP;
00027 double *B;
00028 double *CP;
00029 double *temp;
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
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
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
00061 F2C(dspmv)("L", &n, &dbl1, AP, B+j, &n, &dbl0, temp, &int1);
00062
00063
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
00075 F2C(dspmv)("L", &n, &dbl1, AP, B+j*n, &int1, &dbl0, temp, &int1);
00076
00077
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 }
00086
00087
00088 double inprd(X,Z,L,blck_szs)
00089 double *X;
00090 double *Z;
00091 int L;
00092 int *blck_szs;
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 {
00109 double result;
00110 int i, j, k, lngth, pos, sz, int1=1;
00111
00112
00113 for (i=0, sz=0; i<L; i++) sz += (blck_szs[i]*(blck_szs[i]+1))/2;
00114
00115
00116 result = 2.0*F2C(ddot)(&sz, X, &int1, Z, &int1);
00117
00118
00119
00120 for (j=0, pos=0; j<L; j++)
00121
00122
00123
00124
00125 for (k=0, lngth=blck_szs[j]; k<blck_szs[j]; pos+=lngth,
00126 lngth-=1, k++)
00127
00128
00129 result -= Z[pos]*X[pos];
00130
00131 return result;
00132 }
00133
00134 int C2F(spf)(m,L,F,blck_szs,c,x,Z,ul,nu,abstol,reltol,tv,iters,
00135 work,lwork,iwork,info)
00136 int *m;
00137 int *L;
00138 double *F;
00139 int *blck_szs;
00140 double *c;
00141 double *x;
00142 double *Z;
00143 double *ul;
00144 double *nu;
00145 double *abstol;
00146 double *reltol;
00147 double *tv;
00148 int *iters;
00149
00150 double *work;
00151 int *lwork;
00152 int *iwork;
00153 int *info;
00154 {
00155 return(sp(*m,*L,F,blck_szs,c,x,Z,ul,*nu,*abstol,*reltol,*tv,iters, work,
00156 *lwork,iwork,info));
00157 }
00158
00159 int sp(m,L,F,blck_szs,c,x,Z,ul,nu,abstol,reltol,tv,iters,work,
00160 lwork,iwork,info)
00161
00162 int m;
00163 int L;
00164 double *F;
00165 int *blck_szs;
00166 double *c;
00167 double *x;
00168 double *Z;
00169 double *ul;
00170 double nu;
00171 double abstol;
00172 double reltol;
00173 double tv;
00174 int *iters;
00175
00176 double *work;
00177 int lwork;
00178 int *iwork;
00179 int *info;
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
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
00305
00306
00307
00308
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
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
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
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;
00377 dx = work;
00378 Fsc = rhs + sz;
00379 dZ = rhs + sz;
00380 R = Fsc + m*sz;
00381 X = R + up_sz;
00382 sigx = X + sz;
00383 sigz = sigx + n;
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
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
00399
00400
00401
00402
00403
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
00414 F2C(dcopy)(&lngth, Z+pos, &int1, temp, &int1);
00415
00416
00417
00418
00419
00420
00421
00422
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
00437
00438
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;
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
00465
00466
00467 ul[1] = -inprd(F,Z,L,blck_szs);
00468 ul[0] = F2C(ddot)(&m, c, &int1, x, &int1);
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
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
00495 cngrncb(2, blck_szs[i], F+sz+pos, R+pos2, Fsc+pos, temp);
00496
00497
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
00506
00507
00508 F2C(dscal)(&sz, &dbl0, rhs, &int1);
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
00521
00522
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
00536
00537
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
00558
00559
00560
00561
00562
00563
00564
00565
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
00576
00577 F2C(dgemv)("N", &lngth, &m, &dbl1, F+sz+pos, &sz, dx, &int1,
00578 &dbl0, temp, &int1);
00579
00580
00581 cngrncb(2, blck_szs[i], temp, R+pos2, temp+lngth, temp+2*lngth);
00582
00583
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
00588
00589
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
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
00606 cngrncb(1, blck_szs[i], temp+lngth, R+pos2, dZ+pos,
00607 temp+2*lngth);
00608
00609
00610 F2C(dcopy)(&lngth, dZ+pos, &int1, temp, &int1);
00611
00612
00613 F2C(dcopy)(&lngth, Z+pos, &int1, temp+lngth, &int1);
00614
00615
00616
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
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];
00636 else if ( sigx[i] < minnegsigx )
00637 minnegsigx = sigx[i];
00638 if ( sigz[i] > maxpossigz )
00639 maxpossigz = sigz[i];
00640 else if ( sigz[i] < minnegsigz )
00641 minnegsigz = sigz[i];
00642 }
00643 nrmx = F2C(dnrm2)(&n, sigx, &int1);
00644 nrmz = F2C(dnrm2)(&n, sigz, &int1);
00645 nrmmax = MAX( nrmx, nrmz);
00646
00647 XdZ = inprd(F,dZ,L,blck_szs);
00648 ZdX = F2C(ddot)(&m, c, &int1, dx, &int1);
00649
00650
00651
00652
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
00695
00696
00697
00698
00699
00700 alphax = 0.0; alphaz = 0.0; lambda_ls = 1.0;
00701
00702 if (nrmx > SIGTOL*nrmmax)
00703 if (nrmz > SIGTOL*nrmmax)
00704 while ( lambda_ls > 1e-4 ) {
00705
00706
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
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 ) {
00728
00729
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
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)
00746 while ( lambda_ls > 1e-4 ) {
00747
00748
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
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
00766 F2C(daxpy)(&m, &alphax, dx, &int1, x, &int1);
00767 F2C(daxpy)(&sz, &alphaz, dZ, &int1, Z, &int1);
00768
00769 }
00770
00771 return -1;
00772 }
00773