00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <robot/control/kinematics/IKORFullSpaceSolver>
00026
00027 using robot::control::kinematics::IKORFullSpaceSolver;
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 using base::IVector;
00039 using base::zeroIVector;
00040 using base::equals;
00041
00042 const Real small = 5.0e-05;
00043
00044
00045 IKORFullSpaceSolver::IKORFullSpaceSolver()
00046 : status(Unknown)
00047 {
00048 Logln("Warning: This implementation doesn't work correctly, consider using FullSpaceSolver2 instead.");
00049 }
00050
00051
00052
00053 #define dump_A() { \
00054 printf("A=\n"); \
00055 for(Int r=0; r<Nred; r++) { \
00056 for(Int c=0; c<Mred; c++) { \
00057 printf("%9.6f ",A(slRow[r], slCol[c])); \
00058 } \
00059 printf("\n"); \
00060 } \
00061 printf("\n"); \
00062 }
00063
00064 #define dump_Acol(c) { \
00065 printf("A[:,%d(%d)]=",(c),slCol[c]); \
00066 for(Int r=0; r<Nred; r++) { \
00067 printf("%9.6f ",A(slRow[r], slCol[c])); \
00068 } \
00069 printf("\n"); \
00070 }
00071
00072 #define dump_btemp() { \
00073 printf("btemp=["); \
00074 for(Int r=0; r<Nred; r++) { \
00075 printf("%9.6f",btemp[slRow[r]]); \
00076 if (r!=Nred-1) printf(","); \
00077 } \
00078 printf("]\n"); \
00079 }
00080
00081
00082 base::Matrix IKORFullSpaceSolver::solve(const Matrix& A_in, const Vector& b_in,
00083 array<Int>& dependentRowsEliminated)
00084 {
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 Matrix A(A_in);
00096 Vector b(b_in);
00097 Debugln(Tmp,"\nSOLVE: A=\n" << A << "b=" << b);
00098 const Int N = A.size1();
00099 const Int M = A.size2();
00100
00101 Assert(b.size()==N);
00102
00103 Matrix Ared(N,M);
00104 Vector bred(N);
00105
00106
00107
00108 IVector firstOK(N);
00109 firstOK = zeroIVector(N);
00110
00111 IVector rowElim(N);
00112 IVector colElim(M);
00113 rowElim = zeroIVector(N);
00114 colElim = zeroIVector(M);
00115
00116 systemComplete = false;
00117
00118
00119
00120
00121
00122 bool bIsZero = equals(b,zeroVector(N),small);
00123
00124
00125
00126
00127
00128 Int Nred = N;
00129 Int Mred = M;
00130 Matrix specialg(M-1,M);
00131 Int numSpecialgs;
00132
00133
00134 reduceA(A, Ared, b, bred, M, N, Mred, Nred, colElim, rowElim, specialg, numSpecialgs);
00135
00136 Matrix g(Mred-Nred+1+numSpecialgs, M);
00137 g = zeroMatrix(g.size1(), g.size2());
00138
00139
00140 Debugln(FSP,"\n\n-------------- FSP ---------------");
00141 Debugcln(FSP," Ared:\n" << Ared);
00142 Debugcln(FSP," bred: " << bred);
00143 Debugcln(FSP,"M:" << M << " Mred:" << Mred << " N:" << N << " Nred:" << Nred);
00144 Debugcln(FSP,"rowElim:" << rowElim);
00145 Debugcln(FSP,"colElim:" << colElim);
00146
00147
00148
00149 Int nullity;
00150 Real K2;
00151
00152 bIsZero = equals(Vector(vectorRange(bred,Range(0,Nred))),zeroVector(Nred),small);
00153 if (bIsZero) {
00154 Debugcln(FSP,"A is completely restricted");
00155 Matrix Asub(Nred, Mred);
00156 Asub = matrixRange(Ared,Range(0,Nred), Range(0,Mred) );
00157 Debugcln(Tmp,"Nred=" << Nred << " Mred=" << Mred << " Asub=\n" << Asub);
00158
00159 Matrix n( Math::nullSpace(Asub, nullity, K2) );
00160
00161
00162 const Int Span2 = g.size1()-numSpecialgs;
00163 for(Int gc=0; gc < Mred; gc++) {
00164 for(Int gr=0; gr < Span2-1; gr++)
00165 g(gr,gc) = n(gc,gr);
00166 g(Nred,gc) = 0;
00167 }
00168
00169 systemComplete=true;
00170 status = Restricted;
00171
00172 }
00173 else {
00174
00175 if (Nred != N) {
00176 Debugcln(FSP,"A is restricted for " << Nred << " out of " << N << " vector components");
00177 }
00178
00179 const Int Span2 = g.size1()-numSpecialgs;
00180 Matrix block(Span2, Nred);
00181 block = zeroMatrix(Span2,Nred);
00182 Matrix Asqr(Nred, Nred);
00183
00184 Int nextToFind = 0;
00185
00186
00187
00188
00189
00190
00191 for(Int c=0; c<Nred; c++) block(0,c) = c;
00192 Debugcln(DJ,"initialized block=" << matrixRow(block,0) << " Mred=" << Mred << " Nred=" << Nred);
00193
00194
00195 for(Int k=0, i=0; (i<Mred) && (k<Nred); i++) {
00196 if (block(0,k) == i) {
00197 for(Int r=0; r<Nred; r++)
00198 Asqr(r,k) = Ared(r,i);
00199 k++;
00200 }
00201 }
00202 Matrix n( Math::nullSpace(Asqr, nullity, K2) );
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 while ( (nullity!=0) && (block(0,0) < N) ) {
00213
00214 SInt pos = SInt(Nred)-1;
00215 Assert(pos < SInt(block.size2()) );
00216 while (block(0,pos) == Span2-1+pos) { pos--; Assert(pos>0); }
00217 block(0,pos)++;
00218 Int move=pos+1;
00219 while (move < Nred) {
00220 block(0,move) = block(0,move-1)+1;
00221 move++;
00222 }
00223
00224
00225
00226 for(Int k=0, i=0; (i<Mred) && (k<Nred); i++) {
00227 if (block(0,k) == i) {
00228 for(Int r=0; r<Nred; r++)
00229 Asqr(r,k) = Ared(r,i);
00230 k++;
00231 }
00232 }
00233 Debugcln(FSP,"trying initial block=" << matrixRow(block,0) );
00234 if (block(0,0) <= Nred)
00235 n.reset( Math::nullSpace(Asqr, nullity, K2) );
00236
00237
00238
00239 }
00240 Debugcln(DJ,"found suitable first block=" << matrixRow(block,0) );
00241
00242
00243
00244
00245 IVector tackon = zeroIVector(Mred-Nred);
00246 for(Int k=0, I=0, i=0; i<Mred; i++) {
00247 bool colIncluded = false;
00248 if (k<Nred)
00249 if (block(0,k)==i)
00250 colIncluded=true;
00251 if (!colIncluded) {
00252 tackon[I]=i;
00253 I++;
00254 }
00255 else
00256 k++;
00257 }
00258 Debugcln(DJ,"tackon=" << tackon);
00259
00260
00261 Vector gRow(matrixRow(g,nextToFind));
00262 Vector blockRow(matrixRow(block,nextToFind));
00263 blockColFindX(gRow, tackon, blockRow, bred, Ared, Mred, Nred);
00264 matrixRow(g,nextToFind) = gRow;
00265 matrixRow(block,nextToFind) = blockRow;
00266
00267
00268 Debugcln(FSP,"first solution\nblock:\n" << matrixRow(block,0) << "\nAsqr:\n" << Asqr);
00269 if (Nred==Mred)
00270 systemComplete=true;
00271 else
00272 restOfSoln(M, N, Mred, Nred, nextToFind, block, g, bred, Ared, tackon, firstOK);
00273
00274 Debugcln(FSP,"block:\n" << block << "solutions:\n" << g);
00275
00276 }
00277
00278
00279
00280
00281
00282 bool binRange=false;
00283 if (!systemComplete) {
00284 Debugln(FSP,"System did not complete. Non-fatal; continuing.");
00285 }
00286 else
00287 binRange = checkRange(A,b,g,rowElim);
00288
00289
00290
00291 String reason;
00292 Assert(b.size()==N);
00293 bIsZero = equals(b,zeroVector(N),small);
00294
00295 if (binRange && (!bIsZero) && (status != Restricted)) {
00296
00297 rebuildgs(g, M, N, Mred, Nred, colElim, rowElim, specialg, numSpecialgs);
00298 status = Complete;
00299
00300
00301
00302
00303 }
00304 else {
00305 if (status != Restricted) {
00306 status = NotComplete;
00307 if (!bIsZero)
00308 reason += ": b is not in the range of A";
00309 else
00310 reason += ": special case - b is the zero vector; constrained optimization must be used";
00311 }
00312 }
00313
00314
00315 if (status == NotComplete)
00316 throw std::invalid_argument(Exception(String("FSP method unable to complete solution")+reason));
00317
00318
00319 dependentRowsEliminated.clear();
00320 for(Int r=0; r<N; r++)
00321 if (rowElim[r] == RowEliminated_Dependent)
00322 dependentRowsEliminated.push_back(r);
00323
00324
00325 Matrix gs(M,Mred-Nred+1+numSpecialgs);
00326 for(Int r=0; r<gs.size1(); r++)
00327 for(Int c=0; c<gs.size2(); c++)
00328 gs(r,c) = g(c,r);
00329
00330 return gs;
00331 }
00332
00333
00334
00335
00336 bool IKORFullSpaceSolver::dependency(const Matrix& A, const base::IVector& slRow, Int Nred, Int first, Int second) const
00337 {
00338 bool stop=false;
00339 Real devidor = 0;
00340 Int i=0;
00341 while ((i<Nred) && !stop) {
00342 if ( isSmall(A(slRow[i], first)) && isSmall(A(slRow[i], second)) )
00343 i++;
00344 else if ( (!isSmall(A(slRow[i], first))) && (!isSmall(A(slRow[i], second))) ) {
00345 if (devidor==0) {
00346 devidor = ( A(slRow[i],first) / A(slRow[i],second) );
00347 i++;
00348 }
00349 else if (isSmall(A(slRow[i], first) - (A(slRow[i],second)*devidor)))
00350 i++;
00351 else
00352 stop = true;
00353 }
00354 else
00355 stop = true;
00356
00357 }
00358
00359 return !stop;
00360 }
00361
00362
00363
00364 bool IKORFullSpaceSolver::checkRange(const Matrix& A, const Vector& b, const Matrix& g, const base::IVector& rowElim)
00365 {
00366 for(Int i=0; i<A.size1(); i++) {
00367 if (rowElim[i] == RowEliminated_Dependent) {
00368 for(Int j=0; j<g.size1();j++) {
00369 Real checkValue = 0.0;
00370 for(Int k=0; k<A.size2();k++) checkValue += A(i,k) * g(j,k);
00371 if ( Math::abs(b[i] - checkValue) > 0.01) return false;
00372 }
00373 }
00374 }
00375 return true;
00376 }
00377
00378
00379
00380
00381
00382
00383 void IKORFullSpaceSolver::reduceA(const Matrix& A, Matrix& Ared,
00384 const Vector& b, Vector& bred,
00385 const Int M, const Int N,
00386 Int& Mred, Int& Nred,
00387 IVector& colElim, IVector& rowElim,
00388 Matrix& specialg, Int& numSpecialgs)
00389 {
00390
00391 Nred = N;
00392 Mred = M;
00393 numSpecialgs = 0;
00394 rowElim = zeroIVector(N);
00395 colElim = zeroIVector(M);
00396
00397 IVector slRow(N);
00398 IVector slCol(M);
00399 for(Int i=0; i<N; i++) slRow[i]=i;
00400 for(Int i=0; i<M; i++) slCol[i]=i;
00401
00402 Vector xElim(M);
00403 xElim = zeroVector(M);
00404
00405 Vector btemp(b);
00406
00407 bool doneRed = false;
00408
00409
00410 while (!doneRed) {
00411
00412 doneRed = true;
00413 bool stillChecking = true;
00414
00415
00416
00417
00418
00419
00420
00421 while (stillChecking) {
00422
00423 Int lastNred = Nred;
00424 for(Int i=0; i<Nred; i++) {
00425 SInt j=-1;
00426 Int restriction = 0;
00427
00428
00429 Int nonZeroCol=0;
00430 while ( (j < SInt(Mred-1)) && (restriction < 2) ) {
00431 j++;
00432 if (!isSmall(A(slRow[i],slCol[j])) ) {
00433 restriction++;
00434 nonZeroCol = j;
00435 }
00436 }
00437
00438
00439 if ( (restriction==1) && (rowElim[slRow[i]] != Eliminated_ZeroOrRestriction) ) {
00440
00441 xElim[slCol[nonZeroCol]] = btemp[slRow[i]]/A(slRow[i],slCol[nonZeroCol]);
00442
00443 for(Int k=0; k<Nred; k++)
00444 btemp[slRow[k]] -= A(slRow[k],slCol[nonZeroCol]) * xElim[slCol[nonZeroCol]];
00445
00446
00447 colElim[slCol[nonZeroCol]] = Eliminated_ZeroOrRestriction;
00448 Debugln(DJ,"Eliminating column " << slCol[nonZeroCol] << " due to restriction");
00449
00450 for(Int j=nonZeroCol; j<(Mred-1); j++) slCol[j] = slCol[j+1];
00451 Mred--;
00452
00453 rowElim[slRow[i]] = Eliminated_ZeroOrRestriction;
00454 Debugln(DJ,"eliminated row " << slRow[i] << " due to restriction");
00455 for(Int j=i; j<(Nred-1); j++) slRow[j] = slRow[j+1];
00456 Nred--;
00457
00458
00459 }
00460 else
00461 if ( (restriction==0) && (rowElim[slRow[i]] != Eliminated_ZeroOrRestriction) ) {
00462
00463 rowElim[slRow[i]] = Eliminated_ZeroOrRestriction;
00464 Debugln(DJ,"row " << slRow[i] << " eliminated (all zeros)");
00465 for(Int j=i; j<(Nred-1); j++) slRow[j] = slRow[j+1];
00466 Nred--;
00467
00468 }
00469
00470 }
00471
00472 if (Nred == lastNred)
00473 stillChecking = false;
00474
00475 }
00476
00477
00478
00479 for (Int i=0; i<Mred; i++) {
00480 Int j=0;
00481 while ( (j<Nred) && isSmall(A(slRow[j],slCol[i])) ) j++;
00482
00483 if (j == Nred) {
00484 colElim[slCol[i]] = Eliminated_ZeroOrRestriction;
00485 Debugln(DJ,"4: reducing Mred from " << Mred+1 << " to " << Mred << " (column " << slCol[i] << " of all zeros)");
00486 for(Int j=i; j<(Mred-1); j++) slCol[j] = slCol[j+1];
00487 Mred--;
00488 i--;
00489 }
00490 }
00491
00492
00493
00494 if (Mred != 0) {
00495
00496 Matrix n;
00497 Matrix Atrans(Mred,Mred);
00498
00499 for(Int i=0; i<Nred; i++)
00500 for(Int j=0; j<Mred; j++)
00501 Atrans(j,i) = A(slRow[i], slCol[j]);
00502 for(Int i=Nred; i<Mred; i++)
00503 for(Int j=0; j<Mred; j++)
00504 Atrans(j,i) = 0;
00505
00506 Int nullity;
00507 Real K2;
00508 n.reset( Math::nullSpace(Atrans, nullity, K2) );
00509 nullity += Nred-Mred;
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519 Int nullCount=0;
00520 while (nullCount < nullity) {
00521 Int i=Mred-Nred + nullCount;
00522 Int j=0;
00523 while ( (j!=n.size1()) && isSmall(n(j,i)) ) j++;
00524
00525 if ( (rowElim[slRow[j]] != Eliminated_ZeroOrRestriction) && (j != n.size1()) ) {
00526 rowElim[slRow[j]] = RowEliminated_Dependent;
00527 for(Int k=j; j<(Nred-1); k++) {
00528
00529 slRow[k] = slRow[k+1];
00530 }
00531 Nred--;
00532 Debugln(DJ,"5: reducing Nred from " << Nred+1 << " to " << Nred << " (dependent row)");
00533 }
00534
00535 nullCount++;
00536
00537 }
00538
00539 }
00540
00541
00542
00543
00544 bool stop;
00545 {
00546 IVector nonZero(M);
00547 nonZero = zeroIVector(M);
00548 Int nonZeroCol;
00549
00550 stop=false;
00551 for(SInt i=0; i< SInt(Nred); i++) {
00552
00553 if (isSmall(btemp[slRow[i]])) {
00554 nonZeroCol = 0;
00555 SInt j=0;
00556 stop = false;
00557
00558 while ( (j < (SInt(Mred)-1)) && !stop) {
00559 if (!isSmall(A(slRow[i], slCol[j]))) {
00560 Int k=j+1;
00561 while (!stop && (k<Mred)) {
00562 if (!isSmall(A(slRow[i], slCol[k]))) {
00563 if (dependency(A, slRow, Nred, slCol[j], slCol[k]))
00564 k++;
00565 else
00566 stop=true;
00567 }
00568 else
00569 k++;
00570
00571 }
00572 nonZero[nonZeroCol] = slCol[j];
00573 nonZeroCol++;
00574 j++;
00575 }
00576 else
00577 j++;
00578
00579 }
00580
00581 if (!isSmall(A(slRow[i], slCol[Mred-1]))) {
00582 nonZero[nonZeroCol] = slCol[Mred-1];
00583 nonZeroCol++;
00584 }
00585
00586 if (nonZeroCol==1)
00587 stop = true;
00588
00589 if (!stop) {
00590 doneRed = false;
00591 Debug(DJ,"Discovered specialCase 1 in row " << i << " eliminating cols:");
00592 for(Int r=0; r<nonZeroCol; r++) {
00593 colElim[nonZero[r]] = ColEliminated_SpecialCase1;
00594 Debugc(DJ," " << nonZero[r]);
00595 }
00596 Debugcln(DJ,"");
00597
00598 for(Int count=0, count2=0, position=0; position<Mred; position++) {
00599 if (slCol[position] != nonZero[count2]) {
00600 slCol[count] = slCol[position];
00601 count++;
00602 }
00603 else
00604 count2++;
00605 }
00606
00607
00608
00609 Assert(nonZeroCol > 0);
00610 Matrix Aelim(1,nonZeroCol);
00611 for(Int r=0; r<nonZeroCol; r++)
00612 Aelim(0,r) = A(slRow[i], nonZero[r]);
00613 Int nullity;
00614 Real K2;
00615
00616
00617
00618
00619
00620 Matrix n = Math::nullSpace(Aelim, nullity, K2);
00621
00622
00623
00624
00625
00626
00627
00628 Mred -= nonZeroCol;
00629 Debugln(DJ,"6: SC1: reducing Mred from " << Mred+nonZeroCol << " to " << Mred);
00630
00631
00632 if (Mred == 0)
00633 throw std::invalid_argument(Exception("FSP method unable to complete solution: A reduced to 0 columns (Mred==0)"));
00634
00635
00636 rowElim[slRow[i]] = RowEliminated_Special;
00637 for(Int r=i; r<(Nred-1); r++) slRow[r] = slRow[r+1];
00638 Nred--;
00639 Debugln(DJ,"7: SC1: reducing Nred from " << Nred+1 << " to " << Nred);
00640
00641
00642 if (Nred == 0)
00643 throw std::invalid_argument(Exception("FSP method unable to complete solution: A reduced to 0 rows (Nred==0)"));
00644
00645
00646
00647
00648
00649 for(Int m=0; m<(nonZeroCol-1); m++) {
00650
00651 for(Int r=0; r<M; r++)
00652 specialg(numSpecialgs, r) = 0;
00653
00654 for(Int r=0; r<nonZeroCol; r++) {
00655
00656 specialg(numSpecialgs, nonZero[r]) = n(r,m);
00657 }
00658 numSpecialgs++;
00659 }
00660
00661 }
00662
00663 }
00664
00665 }
00666 dump_A();
00667 dump_btemp();
00668 }
00669
00670
00671
00672
00673 {
00674 bool stop2=false;
00675 Vector constant(N);
00676 constant = zeroVector(N);
00677 Int reference=0;
00678 IVector classA(M);
00679 classA = zeroIVector(M);
00680 Int classANum=0;
00681
00682 SInt i=0;
00683 while ( (i<SInt(Nred)-1) && !stop2 ) {
00684
00685 SInt j=i+1;
00686 while ( (j < SInt(Nred)) && !stop2) {
00687
00688 stop=false;
00689 bool flag=false;
00690 Real beta=0;
00691
00692 if (!isSmall(btemp[slRow[i]]))
00693 beta = btemp[slRow[j]] / btemp[slRow[i]];
00694 else
00695 flag = true;
00696
00697 classANum=0;
00698 Int k=0;
00699 reference=i;
00700
00701 while ( !stop && (k<Mred) ) {
00702 bool goIn = false;
00703
00704 if (isSmall(A(slRow[i], slCol[k]))) {
00705 if (!flag) goIn = true;
00706 }
00707 else {
00708 if (!isSmall( A(slRow[j],slCol[k]) / A(slRow[i],slCol[k]) - beta ) )
00709 goIn=true;
00710 if (flag) goIn=true;
00711 }
00712
00713 if (goIn) {
00714
00715 classA[classANum] = slCol[k];
00716 if (classANum==0) {
00717
00718 if (isSmall(A(slRow[reference],classA[0]))) {
00719 reference=j;
00720 if (isSmall(A(slRow[reference],classA[0])))
00721 stop = true;
00722 }
00723
00724 if (!stop)
00725 for(Int r=0; r<Nred; r++)
00726 constant[r] = A(slRow[r],classA[0]) / A(slRow[reference],classA[0]);
00727
00728 }
00729 else {
00730 if (isSmall(A(slRow[reference],classA[classANum])))
00731 stop = true;
00732 else {
00733 Int r=0;
00734 while ( (r<Nred) && !stop) {
00735 if (!isSmall( (A(slRow[r],classA[classANum]) / A(slRow[reference],classA[classANum]) ) - constant[r]))
00736 stop=true;
00737 r++;
00738 }
00739 }
00740 }
00741
00742 classANum++;
00743
00744 }
00745 k++;
00746
00747 }
00748 if (!stop) stop2=true;
00749 j++;
00750
00751 }
00752 i++;
00753
00754 }
00755
00756
00757 if (stop2) {
00758 Debugln(DJ,"Discovered specialCase 2");
00759
00760 doneRed=false;
00761
00762
00763 Matrix Aelim(1,classANum);
00764 Matrix n(classANum, classANum-1);
00765 for(Int p=0; p<classANum; p++)
00766 Aelim(0,p) = A(slRow[reference], classA[p]);
00767 Int nullity;
00768 Real K2;
00769 n = Math::nullSpace(Aelim, nullity, K2);
00770
00771 for(Int p=0; p<(classANum-1); p++) {
00772 for(Int r=0; r<M; r++)
00773 specialg(numSpecialgs,r)=0;
00774 for(Int r=0; r<classANum; r++)
00775 specialg(numSpecialgs, classA[r]) = n(r,p);
00776 numSpecialgs++;
00777 Debugcln(DJ,"new soln: " << Vector(matrixRow(specialg, numSpecialgs-1)) );
00778 }
00779
00780 Nred--;
00781
00782
00783 if (Nred == 0)
00784 throw std::invalid_argument(Exception("FSP method unable to complete solution: A reduced to 0 rows (Nred==0)"));
00785
00786 rowElim[slRow[reference]] = RowEliminated_Special;
00787 Debugc(DJ,"eliminated row " << slRow[reference] << " and cols:");
00788 for(Int r=0; r<classANum; r++) {
00789 colElim[classA[r]] = ColEliminated_SpecialCase2;
00790 Debugc(DJ," " << classA[r]);
00791 }
00792 Debugcln(DJ,"");
00793 for(Int r=reference; r<Nred; r++) slRow[r] = slRow[r+1];
00794
00795 for(Int count=0, count2=0, position=0; position<Mred; position++)
00796 if (slCol[position] != classA[count2]) {
00797 slCol[count] = slCol[position];
00798 count++;
00799 }
00800 else
00801 count2++;
00802
00803
00804 if ((SInt(Mred) - SInt(classANum)) <= 0)
00805 throw std::invalid_argument(Exception("FSP method unable to complete solution: A reduced to 0 columns (Mred==0)"));
00806
00807 Mred -= classANum;
00808
00809 }
00810
00811 }
00812
00813
00814 }
00815
00816
00817
00818
00819
00820 if ((Nred > 0) && (Mred > 0)) {
00821 Ared.resize(Nred, Mred);
00822 bred.resize(Nred);
00823 SInt j=-1;
00824 for(Int i=0; i<N; i++)
00825 if (rowElim[i] == NotEleminated) {
00826 j++;
00827 bred[j] = btemp[i];
00828 SInt m=-1;
00829 for(Int k=0; k<M; k++)
00830 if (colElim[k] == NotEleminated) {
00831 m++;
00832 Ared(j,m) = A(i,k);
00833 }
00834 }
00835 }
00836 else
00837 throw std::runtime_error(Exception("FSP method error: The A matrix has been reduced to nothing"));
00838
00839 }
00840
00841
00842
00843
00844 void IKORFullSpaceSolver::blockColFindX(Vector& g,
00845 const IVector& tackon, const Vector& block,
00846 const Vector& b, const Matrix& A,
00847 const Int Mred, const Int Nred)
00848 {
00849 Matrix Atemp(Nred, Nred);
00850 Vector btemp(Nred);
00851 Vector blocktemp(Nred);
00852
00853
00854 btemp=b;
00855 blocktemp=block;
00856
00857 for(Int i=(Nred-1); i>0; i--)
00858 for(SInt j=i-1; j>=0; j--)
00859 if (blocktemp[i] < blocktemp[j])
00860 base::swap(blocktemp[i], blocktemp[j]);
00861 Debugln(DJ,"blocktemp=" << blocktemp);
00862
00863 for(Int k=0, i=0; (i<Mred) && (k<Nred); i++) {
00864 if (blocktemp[k] == i) {
00865 matrixColumn(Atemp,k) = matrixColumn(A,i);
00866 k++;
00867 }
00868 }
00869 Debugln(DJ,"Atemp=\n" << Atemp);
00870
00871
00872 Vector gtemp( Math::inverse(Atemp)*btemp );
00873
00874 Debugcln(FSP,"gvector=\n" << gtemp);
00875
00876
00877 for (Int i=0; i<Nred; i++)
00878 g[Int(blocktemp[i])] = gtemp[i];
00879
00880 Assert(Mred-Nred <= tackon.size());
00881 for(Int j=0; j<Mred-Nred; j++) {
00882 if (tackon[j] < g.size()) g[tackon[j]]=0;
00883 }
00884
00885 }
00886
00887
00888
00889
00890
00891
00892 void IKORFullSpaceSolver::restOfSoln(const Int M, const Int N, const Int Mred, const Int Nred,
00893 Int nextToFind,
00894 Matrix& block, Matrix& g,
00895 const Vector& bred, const Matrix& Ared,
00896 const base::IVector& tackon, base::IVector& firstOK)
00897 {
00898 Debugln(FSP,"Entering RestOfSoln()");
00899 nextToFind++;
00900
00901 Int X, Y;
00902
00903 X = nextToFind-1;
00904 Debugcln(FSP,"g=\n" << g);
00905
00906
00907
00908 for(Int i=0; i<Nred; i++)
00909 if ( (!firstOK[i]) && (!isSmall(g(nextToFind-1, Int(block(nextToFind-1,i))))) )
00910 firstOK[i] = Int(true);
00911
00912 IVector changed(Nred);
00913 changed = vectorRange(firstOK,Range(0,Nred));
00914 Debugcln(FSP,"changed=" << changed);
00915
00916 while ( (X < Mred-Nred) && (!systemComplete) ) {
00917
00918 Debugcln(FSP,"X=" << X << " next soln to find is " << nextToFind);
00919
00920
00921
00922 Matrix Asub(Nred,Nred+1);
00923 for(Int i=0; i<Nred; i++)
00924 for(Int r=0; r<Nred; r++)
00925 Asub(r,i) = Ared(r, Int(block(nextToFind-1,i)) );
00926 for(Int r=0; r<Nred; r++)
00927 Asub(r,Nred) = Ared(r,tackon[X]);
00928
00929 Int nullity;
00930 Real K2;
00931 Matrix n( Math::nullSpace(Asub, nullity, K2) );
00932
00933 Y=0;
00934
00935
00936 while ( (Y < Nred) && (!systemComplete) ) {
00937
00938 Debugcln(FSP,"Y=" << Y << " X=" << X);
00939 Debugcln(FSP, "compare column " << tackon[X] << " with " << Int(block(nextToFind-1,Y)) );
00940 Debugcln(FSP, " it is " << Math::abs(n(Y,0)) << " and firstOK[Y]=" << firstOK[Y]);
00941
00942 if ( (!isSmall(n(Y,0))) && (firstOK[Y]) ) {
00943
00944 Debugcln(FSP,"*************** " << nextToFind << " ****************");
00945
00946 Debugcln(FSP,"** block=\n" << block);
00947 Debugcln(FSP,"** tackon=" << tackon);
00948 Debugcln(DJ, "** X=" << X << " Y=" << Y);
00949
00950 IVector newTack(M-N);
00951 for(Int i=0; i<Nred; i++) block(nextToFind,i) = block(nextToFind-1,i);
00952 newTack[0] = Int(block(nextToFind,Y));
00953 block(nextToFind,Y) = tackon[X];
00954 for(Int i=0; i<X; i++) newTack[i+1] = tackon[i];
00955 for(Int j=X+1; j<Mred-Nred; j++)
00956 newTack[j] = tackon[j];
00957
00958 Debugcln(FSP,"** newTack=" << newTack);
00959 Debugcln(FSP,"** block=\n" << block);
00960 Debugcln(FSP,"** g=\n" << g);
00961
00962 Vector gRow(matrixRow(g,nextToFind));
00963 Vector blockRow(matrixRow(block,nextToFind));
00964 blockColFindX(gRow, newTack, blockRow, bred, Ared, Mred, Nred);
00965 matrixRow(g,nextToFind) = gRow;
00966 matrixRow(block,nextToFind) = blockRow;
00967
00968 Debugln(FSP,"** block=\n" << block);
00969 Debugcln(FSP,"** g=\n" << g);
00970
00971 Debugcln(FSP," it will be g(nextToFind,block(nextToFind,Y)=" << Math::abs(g(nextToFind,Int(block(nextToFind,Y)))));
00972
00973
00974
00975
00976 if ( !isSmall(g(nextToFind,Int(block(nextToFind,Y)))) ) {
00977 if (nextToFind < (Mred-Nred)) {
00978
00979 Debugcln(FSP,"solutions:\n" << g);
00980
00981
00982 restOfSoln(M, N, Mred, Nred, nextToFind, block, g, bred, Ared, newTack, changed);
00983 }
00984 else {
00985 systemComplete=true;
00986 }
00987 }
00988
00989
00990 if (!systemComplete)
00991 block(nextToFind,Y) = newTack[0];
00992
00993 }
00994
00995 Y++;
00996
00997 }
00998
00999 X++;
01000
01001 }
01002
01003
01004 }
01005
01006
01007
01008
01009 void IKORFullSpaceSolver::rebuildgs(Matrix& g,
01010 const Int M, const Int N, const Int Mred, const Int Nred,
01011 const IVector& colElim, const IVector& rowElim,
01012 const Matrix& specialg, const Int numSpecialgs)
01013 {
01014 Matrix gtemp(g);
01015
01016 for(Int k=0, j=0; j<M; j++) {
01017
01018 if (colElim[j] != NotEleminated) {
01019 for(Int i=0; i<g.size1(); i++) g(i,j) = 0;
01020 }
01021 else {
01022 for(Int i=0; i<g.size1(); i++) g(i,j) = gtemp(i,k);
01023 k++;
01024 }
01025 }
01026
01027
01028 for(Int i=(Mred-Nred+1); i<(Mred-Nred+1+numSpecialgs); i++)
01029 for(Int j=0; j<M; j++) {
01030 if (colElim[j] != NotEleminated)
01031 g(i,j) = specialg(i-Mred+Nred-1,j);
01032 else
01033 g(i,j) = g(0,j);
01034 }
01035
01036 }
01037
01038
01039