Actual source code: taomat.c

  1: #include "tao_general.h"   /*I "tao_solver.h"  I*/
  2: #include "taomat.h"
  3: #include "taovec.h"


  8: /*@C
  9:    TaoMatDestroy - Destroys the TaoMat object.

 11:    Input Parameter:
 12: .  TM - the matrix

 14:    Level: beginner
 15: @*/
 16: int TaoMatDestroy( TaoMat* TM){
 17:   TaoFunctionBegin;
 18:   if (TM) {
 19:     delete TM;
 20:     TM=0;
 21:   }
 22:   TaoFunctionReturn(0);
 23: }

 27: /*@C
 28:    Compatible - Confirms that the operation yy = this * xx is well defined.

 30:    Input Parameters:
 31: .  xx,yy -  vectors like those that will be used for matrix-vector multiplication

 33:    Output Parameters:
 34: .  flag - whether or not a matrix vector product can be performed.

 36:    Level: developer
 37: @*/
 38: int TaoMat::Compatible(TaoVec *xx, TaoVec *yy, TaoTruth *flag){
 39:   TaoFunctionBegin;
 40:   *flag=TAO_FALSE;
 41:   TaoFunctionReturn(0);
 42: }


 47: /*@C
 48:    GetDimensions - Gets the dimensions of the rowspace and columnspace of this matrix.

 50:    Output Parameter:
 51: +  m -  the number of rows
 52: -  n - the number of columns

 54:    Level: intermediate

 56: @*/
 57: int TaoMat::GetDimensions( int* m, int* n ){
 58:   TaoFunctionBegin;
 59:   SETERRQ(56,"Operation not defined");
 60:   /* TaoFunctionReturn(1); */
 61: }

 65: /*@C
 66:    Multiply - Computes  ty = this * tx.

 68:    Input Parameter:
 69: .  tx -  the vector to be multiplied by this matrix.

 71:    Output Parameter:
 72: .  ty -  the destination vector


 75:    Level: intermediate

 77: .seealso TaoMat::MultiplyAdd(), TaoMat::MultiplyTranspose()

 79: @*/
 80: int TaoMat::Multiply(TaoVec* tx,TaoVec* ty){
 81:   TaoFunctionBegin;
 82:   SETERRQ(56,"Operation not defined");
 83:   /* TaoFunctionReturn(1); */
 84: }


 89: /*@C
 90:    MultiplyTranspose - Multiplies the transpose of this matrix by a TaoVec.

 92:    Input Parameter:
 93: .  tx -  the vector to be multiplied by this matrix.

 95:    Output Parameter:
 96: .  ty -  the destination vector


 99:    Level: intermediate

101: .seealso TaoMat::Multiply(), TaoMat::MultiplyTransposeAdd()
102: @*/
103: int TaoMat::MultiplyTranspose(TaoVec* tx,TaoVec* ty){
104:   TaoFunctionBegin;
105:   SETERRQ(56,"Operation not defined");
106:   /* TaoFunctionReturn(1); */
107: }


112: /*@C
113:    SetDiagonal - Sets the diagonal elements of this matrix with the elements
114:    of the vector.

116:    Input Parameter:
117: .  tv -  the vector containing the diagonal elements

119:    Level: intermediate

121: .seealso TaoMat::AddDiagonal(),TaoMat::ShiftDiagonal()
122: @*/
123: int TaoMat::SetDiagonal(TaoVec* tv){
124:   TaoFunctionBegin;
125:   SETERRQ(56,"Operation not defined");
126:   /* TaoFunctionReturn(1); */
127: }

131: /*@C
132:    AddDiagonal - Adds the elements of the vector to the diagonal of this matrix.

134:    Input Parameter:
135: .  tv -  the vector containing the diagonal elements


138:    Level: intermediate

140: .seealso TaoMat::SetDiagonal(),TaoMat::ShiftDiagonal()
141: @*/
142: int TaoMat::AddDiagonal(TaoVec* tv){
143:   TaoFunctionBegin;
144:   SETERRQ(56,"Operation not defined");
145:   /* TaoFunctionReturn(1); */
146: }

150: /*@C
151:    GetDiagonal - Inserts the diagonal elements of this matrix into the vector.

153:    Output Parameter:
154: .  tv -  the vector containing the diagonal elements

156:    Level: intermediate

158: .seealso TaoMat::SetDiagonal()
159: @*/
160: int TaoMat::GetDiagonal(TaoVec* tv){
161:   TaoFunctionBegin;
162:   SETERRQ(56,"Operation not defined");
163:   /* TaoFunctionReturn(1); */
164: }

168: /*@C
169:    ShiftDiagonal - Adds this constant to the diagonal elements of this matrix.

171:    Input Parameter:
172: .  c -  the constant

174:    Level: intermediate

176: .seealso TaoMat::SetDiagonal(), TaoMat::AddDiagonal()
177: @*/
178: int TaoMat::ShiftDiagonal(double c){
179:   TaoFunctionBegin;
180:   SETERRQ(56,"Operation not defined");
181:   /* TaoFunctionReturn(1); */
182: }

186: /*@C
187:    Presolve - Prepares to solve a linear system with this matrix by 
188:    doing some initial setup (e.g., computing parts of a preconditioner,
189:    such as matrix factorization).

191:    Input:

193:    Note:
194:    This routine is optional.  A linear solver object can also be used
195:    to implement this operation.

197:    Level: advanced

199: .seealso TaoMat::Solve()
200: @*/
201: int TaoMat::Presolve(){
202:   TaoFunctionBegin;
203:   TaoFunctionReturn(0);
204: }

208: /*@C
209:    Solve - Solves the linear system $this tx = tb$.

211:    Input Parameter:
212: .  tb -  right hand side

214:    Output Parameter:
215: +  tx -  solution vector
216: -  tt -  TAO_TRUE if solved to prescribed accuracy and TAO_FALSE otherwise

218:    Level: advanced

220:    Note:
221:    This routine is optional.  A linear solver object can also be used
222:    to implement this operation.

224: .seealso TaoApplication::GetLinearSolver(),TaoMat::Presolve()
225: @*/
226: int TaoMat::Solve(TaoVec* tb, TaoVec *tx, TaoTruth *tt){
227:   TaoFunctionBegin;
228:   SETERRQ(56,"No TAO linear solver has been set.");
229:   /* TaoFunctionReturn(1); */
230: }


235: /*@C
236:   CreateReducedMatrix - Creates a new matrix using the specified rows and columns of this matrix.

238:    Input Parameter:
239: +  row -  the rows of this matrix to be extracted
240: -  column -  the columns of this matrix to be extracted

242:    Output Parameter:
243: -  M - the new matrix


246: .seealso TaoMat::SetReducedMatrix()

248:    Level: intermediate
249: @*/
250: int TaoMat::CreateReducedMatrix(TaoIndexSet* row,TaoIndexSet* col, TaoMat **M){
251:   TaoFunctionBegin;
252:   SETERRQ(56,"Operation not defined");
253:   /* TaoFunctionReturn(1); */
254: };

258: /*@C
259:   SetReducedMatrix - Creates a new matrix using the specified rows and columns of this matrix.

261:    Input Parameter:
262: +  row -  the rows of this matrix to be extracted
263: -  col -  the columns of this matrix to be extracted

265:    Output Parameter:
266: .  M - the full new matrix


269: .seealso TaoMat::CreateReducedMatrix()

271:    Level: intermediate
272: @*/
273: int TaoMat::SetReducedMatrix(TaoMat *M, TaoIndexSet* row,TaoIndexSet* col){
274:   TaoFunctionBegin;
275:   SETERRQ(56,"Operation not defined");
276:   /* TaoFunctionReturn(1); */
277: };


282: /*@C
283:   RowScale - Scales the rows of this matrix.

285:    Input Parameter:
286: .  scale - the scaling parameters

288:    Note:
289:    This method can also be called by using a pointer to TaoVec as
290:    input parameters.

292:    Level: intermediate
293: @*/
294: int TaoMat::RowScale(TaoVec* scale){
295:   TaoFunctionBegin;
296:   SETERRQ(56,"Operation not defined");
297:   /* TaoFunctionReturn(1); */
298: };

302: /*@C
303:   ColScale - Scales the columns of this matrix.

305:    Input Parameter:
306: .  scale - the scaling parameters

308:    Level: intermediate
309: @*/
310: int TaoMat::ColScale(TaoVec* scale){
311:   TaoFunctionBegin;
312:   SETERRQ(56,"Operation not defined");
313:   /* TaoFunctionReturn(1); */
314: };

318: inline static double fischer(double a, double b)
319: {

321: #ifdef TODD

323:   if (TaoAbsScalar(a) > TaoAbsScalar(b)) {
324:     return sqrt(a*a + b*b) - a - b;
325:   }
326:   return sqrt(a*a + b*b) - b - a;

328: #else

330:    // Method suggested by Bob Vanderbei

332:    if (a + b <= 0) {
333:      return sqrt(a*a + b*b) - (a + b);
334:    }
335:    return -2.0*a*b / (sqrt(a*a + b*b) + (a + b));

337: #endif

339: }

343: inline static double norm(double a, double b)
344: {
345:   return sqrt(a*a + b*b);
346: }

350: /*@C
351:    D_Fischer - Calculates an element of the B-subdifferential of the 
352:    Fischer-Burmeister function for complementarity problems.
353:   
354:    Input Parameters:   
355: +  this - the jacobian of tf at tx
356: .  tx - current point
357: .  tf - function evaluated at tx
358: .  tl - lower bounds
359: .  tu - upper bounds
360: .  tt1 - work vector
361: -  tt2 - work vector

363:    Output Parameters:
364: +  tda - diagonal perturbation component of the result
365: -  tdb - row scaling component of the result

367:    Level: intermediate

369: .seealso TaoVec::Fischer()
370: @*/
371: int TaoMat::D_Fischer(TaoVec *tx, TaoVec *tf, TaoVec *tl, TaoVec *tu, 
372:                       TaoVec *tt1, TaoVec *tt2, TaoVec *tda, TaoVec *tdb )
373: {
374:   int i,nn1,nn2,nn3,nn4,nn5,nn6,nn7,nn8,info;
375:   TaoTruth flag;
376:   TaoScalar *x,*f,*l,*u,*da,*db,*t1,*t2;
377:   TaoScalar ai,bi,ci,di,ei;

379:   TaoFunctionBegin;

381:   info = this->Compatible(tx, tx, &flag); CHKERRQ(info);
382:   if (flag==TAO_FALSE) {TaoFunctionReturn(1);}

384:   info = tx->GetArray(&x,&nn1);CHKERRQ(info);
385:   info = tf->GetArray(&f,&nn2);CHKERRQ(info);
386:   info = tl->GetArray(&l,&nn3);CHKERRQ(info);
387:   info = tu->GetArray(&u,&nn4);CHKERRQ(info);
388:   info = tda->GetArray(&da,&nn5);CHKERRQ(info);
389:   info = tdb->GetArray(&db,&nn6);CHKERRQ(info);
390:   info = tt1->GetArray(&t1,&nn7);CHKERRQ(info);
391:   info = tt2->GetArray(&t2,&nn8);CHKERRQ(info);

393:   if (nn1!=nn2 || nn2!=nn3 || nn3!=nn4 || nn4!=nn5 || 
394:       nn5!=nn6 || nn6!=nn7 || nn7!=nn8) {
395:     TaoFunctionReturn(1);
396:   }

398:   for (i = 0; i < nn1; i++) {
399:     da[i] = 0;
400:     db[i] = 0;
401:     t1[i] = 0;

403:     if (TaoAbsScalar(f[i]) <= TAO_EPSILON) {
404:       if (l[i] > -TAO_INFINITY && TaoAbsScalar(x[i] - l[i]) <= TAO_EPSILON) {
405:         t1[i] = 1;
406:         da[i] = 1;
407:       }

409:       if (u[i] <  TAO_INFINITY && TaoAbsScalar(u[i] - x[i]) <= TAO_EPSILON) {
410:         t1[i] = 1;
411:         db[i] = 1;
412:       }
413:     }
414:   }

416:   info = tt1->RestoreArray(&t1,&nn7);CHKERRQ(info);
417:   info = tt2->RestoreArray(&t2,&nn8);CHKERRQ(info);
418:   info = this->Multiply(tt1, tt2); CHKERRQ(info);
419:   info = tt2->GetArray(&t2,&nn8); CHKERRQ(info);

421:   for (i = 0; i < nn1; i++) {
422:     if ((l[i] <= -TAO_INFINITY) && (u[i] >= TAO_INFINITY)) {
423:       da[i] = 0;
424:       db[i] = -1;
425:     } 
426:     else if (l[i] <= -TAO_INFINITY) {
427:       if (db[i] >= 1) {
428:         ai = norm(1, t2[i]);

430:         da[i] = -1/ai - 1;
431:         db[i] = -t2[i]/ai - 1;
432:       } 
433:       else {
434:         bi = u[i] - x[i];
435:         ai = norm(bi, f[i]);
436:         ai = TaoMax(TAO_EPSILON, ai);

438:         da[i] = bi / ai - 1;
439:         db[i] = -f[i] / ai - 1;
440:       }
441:     } 
442:     else if (u[i] >=  TAO_INFINITY) {
443:       if (da[i] >= 1) {
444:         ai = norm(1, t2[i]);

446:         da[i] = 1 / ai - 1;
447:         db[i] = t2[i] / ai - 1;
448:       } 
449:       else {
450:         bi = x[i] - l[i];
451:         ai = norm(bi, f[i]);
452:         ai = TaoMax(TAO_EPSILON, ai);

454:         da[i] = bi / ai - 1;
455:         db[i] = f[i] / ai - 1;
456:       }
457:     } 
458:     else if (l[i] == u[i]) {
459:       da[i] = -1;
460:       db[i] = 0;
461:     } 
462:     else {
463:       if (db[i] >= 1) {
464:         ai = norm(1, t2[i]);

466:         ci = 1 / ai + 1;
467:         di = t2[i] / ai + 1;
468:       } 
469:       else {
470:         bi = x[i] - u[i];
471:         ai = norm(bi, f[i]);
472:         ai = TaoMax(TAO_EPSILON, ai);

474:         ci = bi / ai + 1;
475:         di = f[i] / ai + 1;
476:       }

478:       if (da[i] >= 1) {
479:         bi = ci + di*t2[i];
480:         ai = norm(1, bi);

482:         bi = bi / ai - 1;
483:         ai = 1 / ai - 1;
484:       } 
485:       else {
486:         ei = fischer(u[i] - x[i], -f[i]);
487:         ai = norm(x[i] - l[i], ei);
488:         ai = TaoMax(TAO_EPSILON, ai);

490:         bi = ei / ai - 1;
491:         ai = (x[i] - l[i]) / ai - 1;
492:       }

494:       da[i] = ai + bi*ci;
495:       db[i] = bi*di;
496:     }
497:   }

499:   info = tda->RestoreArray(&da,&nn5);CHKERRQ(info);
500:   info = tdb->RestoreArray(&db,&nn6);CHKERRQ(info);

502:   info = tx->RestoreArray(&x,&nn1);CHKERRQ(info);
503:   info = tf->RestoreArray(&f,&nn2);CHKERRQ(info);
504:   info = tl->RestoreArray(&l,&nn3);CHKERRQ(info);
505:   info = tu->RestoreArray(&u,&nn4);CHKERRQ(info);
506:   info = tt2->RestoreArray(&t2,&nn8);CHKERRQ(info);
507:   TaoFunctionReturn(0);
508: };

512: inline static double sfischer(double a, double b, double c)
513: {

515: #ifdef TODD

517:   if (TaoAbsScalar(a) > TaoAbsScalar(b)) {
518:     return sqrt(a*a + b*b + 2.0*c*c) - a - b;
519:   }
520:   return sqrt(a*a + b*b + 2.0*c*c) - b - a;

522: #else

524:    // Method suggested by Bob Vanderbei

526:    if (a + b <= 0) {
527:      return sqrt(a*a + b*b + 2.0*c*c) - (a + b);
528:    }
529:    return 2.0*(c*c - a*b) / (sqrt(a*a + b*b + 2.0*c*c) + (a + b));

531: #endif

533: }

537: inline static double snorm(double a, double b, double c)
538: {
539:   return sqrt(a*a + b*b + 2.0*c*c);
540: }

544: /*@C
545:    D_SFischer - Calculates an element of the B-subdifferential of the
546:    smoothed Fischer-Burmeister function for complementarity problems.
547:  
548:    Input Parameters: 
549: +  this - the jacobian of tf at tx
550: .  tx - current point
551: .  tf - function evaluated at tx
552: .  tl - lower bounds
553: .  tu - upper bounds
554: .  mu - smoothing parameter
555: .  tt1 - work vector
556: -  tt2 - work vector

558:    Output Parameter: 
559: +  tda - diagonal perturbation component of the result
560: .  tdb - row scaling component of the result
561: -  tdm - derivative with respect to scaling parameter

563:    Level: intermediate

565: .seealso TaoVec::SFischer()
566: @*/
567: int TaoMat::D_SFischer(TaoVec *tx, TaoVec *tf, 
568:                        TaoVec *tl, TaoVec *tu, double mu, 
569:                        TaoVec *tt1, TaoVec *tt2, 
570:                        TaoVec *tda, TaoVec *tdb, TaoVec *tdm)
571: {
572:   int i, nn1, nn2, nn3, nn4, nn5, nn6, nn7, info;
573:   TaoTruth flag;
574:   TaoScalar *x, *f, *l, *u, *da, *db, *dm;
575:   TaoScalar ai, bi, ci, di, ei, fi;

577:   TaoFunctionBegin;

579:   if ((mu >= -TAO_EPSILON) && (mu <= TAO_EPSILON)) {
580:     tdm->SetToZero();
581:     D_Fischer(tx, tf, tl, tu, tt1, tt2, tda, tdb);
582:   } 
583:   else {
584:     info = this->Compatible(tx, tx, &flag); CHKERRQ(info);

586:     info = tx->GetArray(&x, &nn1); CHKERRQ(info);
587:     info = tf->GetArray(&f, &nn2); CHKERRQ(info);
588:     info = tl->GetArray(&l, &nn3); CHKERRQ(info);
589:     info = tu->GetArray(&u, &nn4); CHKERRQ(info);
590:     info = tda->GetArray(&da, &nn5); CHKERRQ(info);
591:     info = tdb->GetArray(&db, &nn6); CHKERRQ(info);
592:     info = tdm->GetArray(&dm, &nn7); CHKERRQ(info);

594:     if (nn1!=nn2 || nn2!=nn3 || nn3!=nn4 || nn4!=nn5 || nn5!=nn6 || nn6!=nn7) {
595:       TaoFunctionReturn(1);
596:     }

598:     for (i = 0; i < nn1; ++i) {
599:       if ((l[i] <= -TAO_INFINITY) && (u[i] >= TAO_INFINITY)) {
600:         da[i] = -mu;
601:         db[i] = -1;
602:         dm[i] = -x[i];
603:       } 
604:       else if (l[i] <= -TAO_INFINITY) {
605:         bi = u[i] - x[i];
606:         ai = snorm(bi, f[i], mu);
607:         ai = TaoMax(TAO_EPSILON, ai);

609:         da[i] = bi / ai - 1;
610:         db[i] = -f[i] / ai - 1;
611:         dm[i] = 2.0 * mu / ai;
612:       } 
613:       else if (u[i] >=  TAO_INFINITY) {
614:         bi = x[i] - l[i];
615:         ai = snorm(bi, f[i], mu);
616:         ai = TaoMax(TAO_EPSILON, ai);

618:         da[i] = bi / ai - 1;
619:         db[i] = f[i] / ai - 1;
620:         dm[i] = 2.0 * mu / ai;
621:       } 
622:       else if (l[i] == u[i]) {
623:         da[i] = -1;
624:         db[i] = 0;
625:         dm[i] = 0;
626:       } 
627:       else {
628:         bi = x[i] - u[i];
629:         ai = snorm(bi, f[i], mu);
630:         ai = TaoMax(TAO_EPSILON, ai);
631:   
632:         ci = bi / ai + 1;
633:         di = f[i] / ai + 1;
634:         fi = 2.0 * mu / ai;

636:         ei = sfischer(u[i] - x[i], -f[i], mu);
637:         ai = snorm(x[i] - l[i], ei, mu);
638:         ai = TaoMax(TAO_EPSILON, ai);
639:   
640:         bi = ei / ai - 1;
641:         ei = 2.0 * mu / ei;
642:         ai = (x[i] - l[i]) / ai - 1;
643:   
644:         da[i] = ai + bi*ci;
645:         db[i] = bi*di;
646:         dm[i] = ei + bi*fi;
647:       }
648:     }

650:     info = tx->RestoreArray(&x, &nn1); CHKERRQ(info);
651:     info = tf->RestoreArray(&f, &nn2); CHKERRQ(info);
652:     info = tl->RestoreArray(&l, &nn3); CHKERRQ(info);
653:     info = tu->RestoreArray(&u, &nn4); CHKERRQ(info);
654:     info = tda->RestoreArray(&da, &nn5); CHKERRQ(info);
655:     info = tdb->RestoreArray(&db, &nn6); CHKERRQ(info);
656:     info = tdm->RestoreArray(&dm, &nn7); CHKERRQ(info);
657:   }
658:   TaoFunctionReturn(0);
659: }

663: /*@C
664:   View - Views the contents of this matrix.

666:    Input Parameter:

668:    Level: intermediate
669: @*/
670: int TaoMat::View(){
671:   TaoFunctionBegin;
672:   SETERRQ(56,"Operation not defined");
673:   /* TaoFunctionReturn(1); */
674: };

678: /*@C
679:    Norm1 - Computes the 1-norm of the matrix.

681:    Output Parameter:
682: .  nm -  matrix 1-norm value

684:    Level: intermediate
685: @*/
686: int TaoMat::Norm1(double *nm){
687:   TaoFunctionBegin;
688:   SETERRQ(56,"Operation not defined");
689:   /* TaoFunctionReturn(1); */
690: }