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: }