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
00026 #include "math/matrix.h"
00027
00028 #include <limits>
00029 #include <math.h>
00030
00031 #ifdef MKL
00032 #include "mkl_wrappers.h"
00033 #else
00034 #include "lapack_wrappers.h"
00035 #endif
00036
00037
00038 #include "maxdet.h"
00039
00040 #include "matvec3D.h"
00041
00042
00043 #include "debug.h"
00044
00045
00046 #ifdef MOSEK_QP
00047 #include "mosek_qp.h"
00048 #endif
00049 #ifdef OASES_QP
00050 #include "qpoases.h"
00051 #endif
00052
00053 const double Matrix::EPS = 1.0e-7;
00054
00055 void Matrix::initialize(int m, int n)
00056 {
00057 mRows = m;
00058 mCols = n;
00059 if (mRows>0 && mCols>0) {
00060 try {
00061 mData = new double[mRows*mCols];
00062 } catch(std::bad_alloc) {
00063 DBGA("Not enough memory for dense matrix of size " <<
00064 mRows << " by " << mCols);
00065 assert(0);
00066 mData = NULL;
00067 }
00068 } else {
00069 mRows = mCols = 0;
00070 mData = NULL;
00071 }
00072 sequentialReset();
00073 }
00074
00075 Matrix::Matrix(int m, int n)
00076 {
00077 initialize(m,n);
00078 }
00079 Matrix::Matrix(const Matrix &M)
00080 {
00081 initialize(M.rows(), M.cols());
00082 if (mRows) {
00083 memcpy(mData, M.mData, mRows*mCols*sizeof(double));
00084 }
00085 }
00086
00087 Matrix::Matrix(const double *M, int m, int n, bool colMajor)
00088 {
00089 initialize(m,n);
00090 if (colMajor) {
00091 setFromColMajor(M);
00092 } else {
00093 setFromRowMajor(M);
00094 }
00095 }
00096
00097 Matrix::~Matrix()
00098 {
00099 if (mRows) {
00100 delete [] mData;
00101 }
00102 }
00103
00104 void Matrix::resize(int m, int n)
00105 {
00106 if (mRows) {
00107 delete [] mData;
00108 }
00109 initialize(m,n);
00110 }
00111
00112 SparseMatrix::SparseMatrix(const SparseMatrix &SM) : Matrix(0,0)
00113 {
00114 mRows = SM.mRows;
00115 mCols = SM.mCols;
00116 mDefaultValue = SM.mDefaultValue;
00117 mFoo = SM.mFoo;
00118 mSparseData = SM.mSparseData;
00119 }
00120
00121 void SparseMatrix::resize(int m, int n)
00122 {
00123 mRows = m;
00124 mCols = n;
00125 mSparseData.clear();
00126 }
00127
00128 double&
00129 Matrix::elem(int m, int n)
00130 {
00131 assert(m<mRows);
00132 assert(n<mCols);
00133 return mData[n*mRows + m];
00134 }
00135
00136 const double&
00137 Matrix::elem(int m, int n) const
00138 {
00139 assert(m<mRows);
00140 assert(n<mCols);
00141 return mData[n*mRows + m];
00142 }
00143
00149 double&
00150 SparseMatrix::elem(int, int)
00151 {
00152 assert(0);
00153 DBGA("WARNING: You should not call non-const elements of a sparse matrix");
00154 DBGA("This call is GUARANTEED to fail miserably");
00155 return mFoo;
00156 }
00157
00158 const double&
00159 SparseMatrix::elem(int m, int n) const
00160 {
00161 std::map<int, double>::const_iterator it = mSparseData.find(key(m,n));
00162 if (it==mSparseData.end()) return mDefaultValue;
00163 else return it->second;
00164 }
00165
00166 std::auto_ptr<double>
00167 SparseMatrix::getDataCopy() const
00168 {
00169 double *data = new double[mRows * mCols];
00170 for (int i=0; i<mRows * mCols; i++) {
00171 data[i] = mDefaultValue;
00172 }
00173 std::map<int,double>::const_iterator it;
00174 for (it=mSparseData.begin(); it!=mSparseData.end(); it++) {
00175
00176 data[it->first] = it->second;
00177 }
00178 return std::auto_ptr<double>(data);
00179 }
00180
00181 void
00182 SparseMatrix::getData(std::vector<double> *data) const
00183 {
00184 data->resize(mRows*mCols);
00185 for (int i=0; i<mRows * mCols; i++) {
00186 data->at(i) = mDefaultValue;
00187 }
00188 std::map<int,double>::const_iterator it;
00189 for (it=mSparseData.begin(); it!=mSparseData.end(); it++) {
00190
00191 data->at(it->first) = it->second;
00192 }
00193 }
00194
00195 double*
00196 SparseMatrix::getDataPointer()
00197 {
00198 assert(0);
00199 return NULL;
00200 }
00201
00202 Matrix
00203 Matrix::EYE(int m, int n)
00204 {
00205 assert( m>0 && n>0 );
00206 Matrix I(m,n);
00207 I.setAllElements(0.0);
00208 for(int i=0; i<std::min(m,n); i++) {
00209 I.elem(i,i) = 1.0;
00210 }
00211 return I;
00212 }
00213
00214 SparseMatrix
00215 SparseMatrix::EYE(int m, int n)
00216 {
00217 assert( m>0 && n>0 );
00218 SparseMatrix I(m,n);
00219 for(int i=0; i<std::min(m,n); i++) {
00220 int key = I.key(i,i);
00221 I.mSparseData.insert(std::pair<int,double>(key,1.0));
00222 }
00223 return I;
00224 }
00225
00226 Matrix
00227 Matrix::NEGEYE(int m, int n)
00228 {
00229 assert( m>0 && n>0 );
00230 Matrix NI(m,n);
00231 NI.setAllElements(0.0);
00232 for(int i=0; i<std::min(m,n); i++) {
00233 NI.elem(i,i) = -1.0;
00234 }
00235 return NI;
00236 }
00237
00238 SparseMatrix
00239 SparseMatrix::NEGEYE(int m, int n)
00240 {
00241 assert( m>0 && n>0 );
00242 SparseMatrix I(m,n);
00243 for(int i=0; i<std::min(m,n); i++) {
00244 int key = I.key(i,i);
00245 I.mSparseData.insert(std::pair<int,double>(key,-1.0));
00246 }
00247 return I;
00248 }
00249
00250 Matrix
00251 Matrix::PERMUTATION(int n, int *jpvt)
00252 {
00253 assert(n>0);
00254 Matrix P(n,n);
00255 P.setAllElements(0.0);
00256 for (int c=0; c<n; c++) {
00257 assert (jpvt[c] > 0 && jpvt[c] <= n);
00258 P.elem(c, jpvt[c]-1) = 1.0;
00259 }
00260 return P;
00261 }
00262
00263 Matrix
00264 Matrix::ROTATION(const mat3 &rot)
00265 {
00266 Matrix R(3,3);
00267 for (int i=0; i<3; i++) {
00268 for (int j=0; j<3; j++) {
00269 R.elem(i,j) = rot.element(j,i);
00270 }
00271 }
00272 return R;
00273 }
00274
00275 Matrix
00276 Matrix::MAX_VECTOR(int rows)
00277 {
00278 Matrix v(rows, 1);
00279 v.setAllElements(std::numeric_limits<double>::max());
00280 return v;
00281 }
00282
00283 Matrix
00284 Matrix::MIN_VECTOR(int rows)
00285 {
00286 Matrix v(rows, 1);
00287 v.setAllElements(-std::numeric_limits<double>::max());
00288 return v;
00289 }
00290
00295 Matrix
00296 Matrix::ROTATION2D(double theta)
00297 {
00298 Matrix R(2,2);
00299 R.elem(0,0) = cos(theta); R.elem(0,1) = -sin(theta);
00300 R.elem(1,0) = sin(theta); R.elem(1,1) = cos(theta);
00301 return R;
00302 }
00303
00304 void
00305 Matrix::setFromColMajor(const double *M)
00306 {
00307 assert(mRows);
00308 memcpy(mData, M, mRows*mCols*sizeof(double));
00309 }
00310
00311 void
00312 Matrix::setFromRowMajor(const double *M)
00313 {
00314 assert(mRows);
00315 for(int row = 0; row<mRows; row++) {
00316 for(int col = 0; col<mCols; col++) {
00317 elem(row, col) = M[row*mCols + col];
00318 }
00319 }
00320 }
00321
00322 std::auto_ptr<double>
00323 Matrix::getDataCopy() const
00324 {
00325 double *data = new double[mRows*mCols];
00326 memcpy( data, mData, mRows*mCols*sizeof(double) );
00327 return std::auto_ptr<double>(data);
00328 }
00329
00330 void
00331 Matrix::getData(std::vector<double> *data) const
00332 {
00333 data->resize(mRows * mCols, 0.0);
00334 memcpy( &((*data)[0]), mData, mRows*mCols*sizeof(double) );
00335 }
00336
00337 double* Matrix::getDataPointer()
00338 {
00339 return mData;
00340 }
00341
00342 int
00343 Matrix::rank() const
00344 {
00345 int size = std::min(mRows, mCols);
00346 double *sv = new double[size];
00347 int lwork = 5 * std::max(mRows, mCols);
00348 double *work = new double[lwork];
00349 int info;
00350 std::vector<double> data; getData(&data);
00351 dgesvd("N", "N", mRows, mCols, &(data[0]), mRows, sv,
00352 NULL, 1, NULL, 1, work, lwork, &info);
00353 if (info) {
00354 DBGA("Rank computation failed with info " << info);
00355 }
00356 int rank = 0;
00357 for (int i=0; i<size; i++) {
00358
00359 if ( sv[i] > EPS ) rank++;
00360 }
00361 delete [] sv;
00362 delete [] work;
00363 return rank;
00364 }
00365
00366 double
00367 Matrix::fnorm() const
00368 {
00369 double norm = 0.0;
00370 for (int r=0; r<mRows; r++) {
00371 for(int c=0; c<mCols; c++) {
00372 norm += elem(r,c) * elem(r,c);
00373 }
00374 }
00375 return sqrt(norm);
00376 }
00377
00378 double
00379 Matrix::absMax() const
00380 {
00381 double max = fabs(elem(0,0));
00382 double m;
00383 for (int r=0; r<mRows; r++) {
00384 for(int c=0; c<mCols; c++) {
00385 m = fabs(elem(r,c));
00386 if (m>max) max = m;
00387 }
00388 }
00389 return max;
00390 }
00391
00392 double
00393 Matrix::elementSum() const
00394 {
00395 double sum=0.0;
00396 for (int r=0; r<mRows; r++) {
00397 for(int c=0; c<mCols; c++) {
00398 sum += elem(r,c);
00399 }
00400 }
00401 return sum;
00402 }
00403
00404
00405 void
00406 Matrix::sequentialReset() const
00407 {
00408 mSequentialI = 0;
00409 mSequentialJ = 0;
00410 }
00411
00412 bool
00413 Matrix::nextSequentialElement(int &i, int &j, double &val) const
00414 {
00415 do {
00416 if (mSequentialJ >= mCols) {
00417 mSequentialJ = 0;
00418 mSequentialI ++;
00419 }
00420 if (mSequentialI >= mRows) {
00421 return false;
00422 }
00423 i = mSequentialI;
00424 j = mSequentialJ;
00425 val = elem(i,j);
00426 mSequentialJ++;
00427 } while (val==0.0);
00428 return true;
00429 }
00430
00431
00432 void
00433 SparseMatrix::sequentialReset() const
00434 {
00435 mSequentialIt = mSparseData.begin();
00436 }
00437
00438 bool
00439 SparseMatrix::nextSequentialElement(int &i, int &j, double &val) const
00440 {
00441
00442
00443
00444 assert(mDefaultValue == 0.0);
00445 if (mSequentialIt == mSparseData.end()) {
00446 return false;
00447 }
00448 reverseKey(mSequentialIt->first, i, j);
00449 val = mSequentialIt->second;
00450 mSequentialIt++;
00451 return true;
00452 }
00453
00454 Matrix
00455 Matrix::getColumn(int c) const
00456 {
00457 assert(c<mCols);
00458 Matrix col(mRows, 1);
00459 for (int i=0; i<mRows; i++) {
00460 col.elem(i,0) = elem(i, c);
00461 }
00462 return col;
00463 }
00464
00465 Matrix
00466 Matrix::getRow(int r) const
00467 {
00468 assert(r<mRows);
00469 Matrix row(1, mCols);
00470 for(int i=0; i<mCols; i++) {
00471 row.elem(0,i) = elem(r,i);
00472 }
00473 return row;
00474 }
00475
00476 Matrix
00477 Matrix::getSubMatrix(int startRow, int startCol, int rows, int cols) const
00478 {
00479 assert(rows>0 && cols>0);
00480 assert(startRow+rows <= mRows && startCol+cols <= mCols);
00481 Matrix M(rows, cols);
00482 M.copySubBlock(0, 0, rows, cols, *this, startRow, startCol);
00483 return M;
00484 }
00485
00486 void Matrix::setAllElements(double val) {
00487
00488 for(int row = 0; row<mRows; row++) {
00489 for(int col = 0; col<mCols; col++) {
00490 elem(row, col) = val;
00491 }
00492 }
00493 }
00494
00495 void Matrix::copySubBlock(int startRow, int startCol, int rows, int cols,
00496 const Matrix &m, int startMRow, int startMCol)
00497 {
00498 assert(startMRow + rows <= m.rows());
00499 assert(startMCol + cols <= m.cols());
00500 assert(startRow + rows <= mRows);
00501 assert(startCol + cols <= mCols);
00502 for (int r = 0; r < rows; r++) {
00503 for(int c = 0; c < cols; c++) {
00504 elem(startRow+r, startCol+c) = m.elem(startMRow+r, startMCol+c);
00505 }
00506 }
00507 }
00508
00509 void SparseMatrix::copySubBlock(int startRow, int startCol, int rows, int cols,
00510 const Matrix &m, int startMRow, int startMCol)
00511 {
00512 assert(startMRow + rows <= m.rows());
00513 assert(startMCol + cols <= m.cols());
00514 assert(startRow + rows <= mRows);
00515 assert(startCol + cols <= mCols);
00516
00517 bool sparseCopy = true;
00518 if (sparseCopy && m.getType()==SPARSE && m.getDefault() == mDefaultValue) {
00519 DBGP("Sparse - sparse copy");
00520 int i,j;
00521 double value;
00522 std::map<int, double>::iterator it = mSparseData.begin();
00523
00524 while (it!=mSparseData.end()) {
00525 reverseKey(it->first, i, j);
00526 if ( i>=startRow && i<startRow+rows && j>=startCol && j<startCol+cols) {
00527 std::map<int, double>::iterator foo = it;
00528 it++;
00529 mSparseData.erase(foo);
00530 } else {
00531 it++;
00532 }
00533 }
00534
00535 m.sequentialReset();
00536 while (m.nextSequentialElement(i, j, value)) {
00537 if (i>=startMRow && i<startMRow+rows && j>=startMCol && j<startMCol+cols) {
00538 i = i - startMRow + startRow;
00539 j = j - startMCol + startCol;
00540 assert(i>=0 && i<mRows);
00541 assert(j>=0 && j<mCols);
00542 mSparseData[key(i,j)] = value;
00543 }
00544 }
00545 } else {
00546
00547 for (int r = 0; r < rows; r++) {
00548 for(int c = 0; c < cols; c++) {
00549 int k = key(startRow+r, startCol+c);
00550 double value = m.elem(startMRow+r, startMCol+c);
00551 std::map<int, double>::iterator it = mSparseData.find(k);
00552 if (value == mDefaultValue) {
00553 if (it!=mSparseData.end()) {
00554 mSparseData.erase(it);
00555 }
00556 } else {
00557 mSparseData[k] = value;
00558 }
00559 }
00560 }
00561 }
00562 }
00563
00564 void
00565 SparseMatrix::transpose()
00566 {
00567 std::vector<int> rows;
00568 std::vector<int> cols;
00569 std::vector<double> vals;
00570 std::map<int, double>::iterator it;
00571 for (it=mSparseData.begin(); it!=mSparseData.end(); it++) {
00572 int m,n;
00573 reverseKey(it->first, m, n);
00574 rows.push_back(m);
00575 cols.push_back(n);
00576 vals.push_back(it->second);
00577 }
00578 mSparseData.clear();
00579 for (int i=0; i<(int)rows.size(); i++) {
00580 int k = key(cols[i], rows[i]);
00581 mSparseData[k] = vals[i];
00582 }
00583 }
00584
00585 std::ostream &
00586 operator<<(std::ostream &os, const Matrix &m)
00587 {
00588 for (int row = 0; row<m.mRows; row++) {
00589 for(int col = 0; col<m.mCols; col++) {
00590 os << m.elem(row, col) << " ";
00591 }
00592 os << std::endl;
00593 }
00594 return os;
00595 }
00596
00597 void Matrix::print(FILE *fp) const
00598 {
00599 std::auto_ptr<double> data = getDataCopy();
00600 disp_mat(fp, data.get(), mRows, mCols, 0);
00601 }
00602
00603 void
00604 Matrix::swapCols(int c1, int c2)
00605 {
00606 for (int r=0; r<mRows; r++) {
00607 std::swap( elem(r,c1), elem(r,c2) );
00608 }
00609 }
00610
00611 void
00612 Matrix::swapRows(int r1, int r2)
00613 {
00614 for (int c=0; c<mCols; c++) {
00615 std::swap( elem(r1,c), elem(r2,c) );
00616 }
00617 }
00618
00619 void
00620 Matrix::transpose()
00621 {
00622
00623 assert(mRows);
00624 std::swap(mRows, mCols);
00625 double *oldData = mData;
00626 mData = new double[mRows * mCols];
00627 for (int r=0; r<mRows; r++) {
00628 for (int c=0; c<mCols; c++) {
00629 elem(r,c) = oldData[r*mCols + c];
00630 }
00631 }
00632 delete [] oldData;
00633 }
00634
00635 void
00636 Matrix::eye()
00637 {
00638 for (int r=0; r<mRows; r++) {
00639 for (int c=0; c<mCols; c++) {
00640 if (r==c) {
00641 elem(r,c) = 1.0;
00642 } else {
00643 elem(r,c) = 0.0;
00644 }
00645 }
00646 }
00647 }
00648
00649 void
00650 Matrix::multiply(double s)
00651 {
00652 for (int r=0; r<mRows; r++) {
00653 for (int c=0; c<mCols; c++) {
00654 elem(r,c) *= s;
00655 }
00656 }
00657 }
00658
00659 Matrix Matrix::transposed() const
00660 {
00661 Matrix t(*this);
00662 t.transpose();
00663 return t;
00664 }
00665
00666 void
00667 matrixMultiply(const Matrix &L, const Matrix &R, Matrix &M)
00668 {
00669 assert( L.cols() == R.rows() );
00670 assert( L.rows() == M.rows() );
00671 assert( R.cols() == M.cols() );
00672 assert( L.cols() );
00673
00674
00675
00676 for (int i=0; i<M.rows(); i++) {
00677 for (int j=0; j<M.cols(); j++) {
00678 double m = 0;
00679 for (int k=0; k<L.cols(); k++) {
00680 m += L.elem(i,k) * R.elem(k,j);
00681 }
00682 M.elem(i,j) = m;
00683 }
00684 }
00685 }
00686
00687 void
00688 matrixAdd(const Matrix &L, const Matrix &R, Matrix &M)
00689 {
00690 assert( L.rows()==R.rows() && L.rows()==M.rows() );
00691 assert( L.cols()==R.cols() && L.cols()==M.cols() );
00692 for (int r=0; r<L.rows(); r++) {
00693 for(int c=0; c<L.cols(); c++) {
00694 M.elem(r,c) = L.elem(r,c) + R.elem(r,c);
00695 }
00696 }
00697 }
00698
00699 bool
00700 matrixEqual(const Matrix &R, const Matrix &L)
00701 {
00702 assert (R.rows() == L.rows() && R.cols() == L.cols());
00703 Matrix minL(L);
00704 minL.multiply(-1.0);
00705 matrixAdd(R, minL, minL);
00706 double norm = minL.fnorm();
00707 if (norm < Matrix::EPS) {
00708 return true;
00709 }
00710 return false;
00711 }
00712
00713 int
00714 triangularSolve(Matrix &A, Matrix &B)
00715 {
00716 assert(A.rows());
00717 assert(A.rows() == A.cols());
00718 assert(A.rows() == B.rows());
00719 int info;
00720 int *ipiv = new int[A.rows()];
00721
00722 std::auto_ptr<double> Adata = A.getDataCopy();
00723 dgesv(A.rows(), B.cols(), Adata.get(), A.rows(),ipiv,
00724 B.getDataPointer(), B.rows(), &info);
00725 delete [] ipiv;
00726 return info;
00727 }
00728
00734 int
00735 linearSolveMPInv(Matrix &A, Matrix &B, Matrix &X)
00736 {
00737 assert( X.rows() == A.cols() );
00738 assert( X.cols() == B.cols() );
00739
00740
00741 Matrix ATran(A.transposed());
00742 Matrix ASq(A.cols(), A.cols());
00743 matrixMultiply(ATran, A, ASq);
00744 Matrix ATB(A.cols(), B.cols());
00745 matrixMultiply(ATran, B, ATB);
00746
00747
00748 int rank = ASq.rank();
00749 if (rank < A.cols()) {
00750
00751 DBGA("Undet solve w. MPI: rank-deficient lhs with rank " << rank);
00752 }
00753
00754
00755 int info = triangularSolve(ASq, ATB);
00756
00757
00758 X.copyMatrix(ATB);
00759 return info;
00760 }
00761
00767 int
00768 linearSolveSVD(Matrix &A, Matrix &B, Matrix &X)
00769 {
00770 assert( X.rows() == A.cols() );
00771 assert( X.cols() == B.cols() );
00772
00773
00774 int minSize = std::min(A.rows(), A.cols());
00775 int maxSize = std::max(A.rows(), A.cols());
00776 Matrix S(minSize, 1);
00777 Matrix U(A.rows(), A.rows());
00778 Matrix VT(A.cols(), A.cols());
00779 int lwork = 5 * maxSize;
00780 double *work = new double[lwork];
00781 int info;
00782 dgesvd("A", "A", A.rows(), A.cols(), A.getDataCopy().get(), A.rows(), S.getDataPointer(),
00783 U.getDataPointer(), A.rows(), VT.getDataPointer(), A.cols(),
00784 work, lwork, &info);
00785 delete [] work;
00786
00787 if (info) {
00788 DBGA("SVD decomposition failed with code " << info);
00789 return info;
00790 }
00791
00792
00793 int result = 0;
00794 for (int c=0; c<B.cols(); c++) {
00795 Matrix x(Matrix::ZEROES<Matrix>(A.cols(),1));
00796 for (int r=0; r<minSize; r++) {
00797 Matrix utb(1,1);
00798 matrixMultiply( U.getColumn(r).transposed(), B.getColumn(c), utb );
00799 if (S.elem(r,0) < Matrix::EPS) {
00800 DBGA("Rank deficient matrix in underDeterminedSolve:");
00801 if (fabs(utb.elem(0,0)) > Matrix::EPS) {
00802 DBGA("... system has no solution " << utb.elem(0,0));
00803 if (!result) result = r;
00804 continue;
00805 } else {
00806
00807 DBGA("...but system still has solution.");
00808 }
00809 }
00810 utb.multiply( 1.0 / S.elem(r,0) );
00811 Matrix utbv(1, A.cols());
00812
00813 matrixMultiply( utb, VT.getRow(r), utbv);
00814 matrixAdd(x, utbv.transposed(), x);
00815 }
00816 X.copySubMatrix(0, c, x);
00817 }
00818 return result;
00819 }
00820
00821 int underDeterminedSolveQR(Matrix &A, Matrix &B, Matrix &X)
00822 {
00823
00824
00825 assert( X.rows() == A.cols() );
00826 assert( X.cols() == B.cols() );
00827
00828
00829 if (A.rows() > A.cols()) {
00830 DBGA("Undet QR: system is overdetermined");
00831 return -1;
00832 }
00833
00834
00835 Matrix ATran(A.transposed());
00836
00837 int info;
00838 std::vector<double> data;
00839 ATran.getData(&data);
00840 int minSize = ATran.cols();
00841 std::vector<int> jpvt(ATran.cols(), 0);
00842 std::vector<double> tau(minSize, 0.0);
00843 int lwork = (ATran.cols() + 1) * 15;
00844 std::vector<double> work(lwork, 0.0);
00845
00846 dgeqp3(ATran.rows(), ATran.cols(), &(data[0]), ATran.rows(),
00847 &jpvt[0], &tau[0], &work[0], lwork, &info);
00848 if (info) {
00849 DBGA("QR Factorization failed, info " << info);
00850 return -1;
00851 }
00852
00853
00854 Matrix P(Matrix::PERMUTATION(ATran.cols(), &jpvt[0]).transposed());
00855
00856
00857
00858 Matrix R(Matrix::ZEROES<Matrix>(minSize, ATran.cols()));
00859 for (int col=0; col<ATran.cols(); col++) {
00860 for (int row=0; row<std::min(minSize, col+1); row++) {
00861
00862 R.elem(row,col) = data[col*ATran.rows() + row];
00863 }
00864 }
00865
00866 int rank = ATran.rank();
00867 if (rank < minSize) {
00868 double fn = R.getSubMatrix(rank, rank, minSize - rank, ATran.cols() - rank).fnorm();
00869 if (fn > Matrix::EPS) {
00870 DBGA("Column pivoting fails to produce full rank R11");
00871 return -1;
00872 }
00873 }
00874 DBGP("Rank: " << rank);
00875
00876 Matrix R11T(R.getSubMatrix(0,0,rank,rank).transposed());
00877 Matrix PB(B);
00878 matrixMultiply(P.transposed(), B, PB);
00879 Matrix Z( PB.getSubMatrix(0, 0, rank, PB.cols()) );
00880 std::vector<double> R11Tdata; R11T.getData(&R11Tdata);
00881 std::vector<double> Zdata; Z.getData(&Zdata);
00882 dtrtrs("L", "N", "N", rank, Z.cols(), &(R11Tdata[0]), rank,
00883 &(Zdata[0]), Z.rows(), &info);
00884 if (info) {
00885 DBGA("Triangular solve failed in QR solve, info " << info);
00886 return -1;
00887 }
00888
00889 bool success = true;
00890 if (rank < minSize) {
00891 Matrix R22T( R.getSubMatrix(0, rank, rank, R.cols()-rank).transposed() );
00892 Matrix PB22( PB.getSubMatrix(rank, 0, PB.rows() - rank, PB.cols()) );
00893 Matrix PBtest( PB.rows() - rank, PB.cols() );
00894 matrixMultiply( R22T, Z, PBtest);
00895 if (!matrixEqual(PBtest, PB22)) {
00896 DBGA("System has no solution in QR solve");
00897 success = false;
00898 }
00899 }
00900
00901
00902 dorgqr(ATran.rows(), ATran.cols(), rank, &data[0], ATran.rows(),
00903 &tau[0], &work[0], lwork, &info);
00904 if (info) {
00905 DBGA("Building matrix Q failed, info " << info);
00906 return -1;
00907 }
00908 Matrix Q(&data[0], ATran.rows(), ATran.cols(), true);
00909
00910
00911 Matrix Q1( Q.getSubMatrix(0,0,ATran.rows(), rank) );
00912 matrixMultiply(Q1, Z, X);
00913 DBGP("X: " << X);
00914 if (!success) return 1;
00915 return 0;
00916 }
00917
00922 int
00923 matrixInverse(const Matrix &A, Matrix &AInv)
00924 {
00925
00926 assert(A.rows() == A.cols());
00927 assert(AInv.rows() == AInv.cols());
00928 assert(A.rows() == AInv.rows());
00929 int size = A.rows() * A.cols();
00930 std::vector<double> data(size,0.0);
00931 A.getData(&data);
00932 std::vector<int> ipiv(A.rows(),0);
00933 int info;
00934 dgetrf(A.rows(), A.cols(), &data[0], A.rows(), &ipiv[0], &info);
00935 if (info < 0) {
00936 DBGA("Inverse failed at factorization, info " << info);
00937 return -1;
00938 } else if (info > 0) {
00939 DBGA("Inverse of rank-deficient matrix requested");
00940 return 1;
00941 }
00942 int lwork = size;
00943 std::vector<double> work(lwork, 0.0);
00944 dgetri(A.rows(), &data[0], A.rows(), &ipiv[0], &work[0], lwork, &info);
00945 if (info < 0) {
00946 DBGA("Inverse failed, info " << info);
00947 return -1;
00948 } else if (info > 0) {
00949 DBGA("Inverse of rank-deficient matrix requested...");
00950 return 1;
00951 }
00952 AInv.copyMatrix(Matrix(&data[0], A.rows(), A.cols(), true));
00953 return 0;
00954 }
00955
00969 int QPSolver(const Matrix &Q, const Matrix &Eq, const Matrix &b,
00970 const Matrix &InEq, const Matrix &ib,
00971 const Matrix &lowerBounds, const Matrix &upperBounds,
00972 Matrix &sol, double* objVal)
00973 {
00974 if (Eq.rows()) {
00975 assert( Eq.cols() == sol.rows() );
00976 assert( Eq.rows() == b.rows() );
00977 }
00978 if (InEq.rows()) {
00979 assert( InEq.cols() == sol.rows() );
00980 assert( InEq.rows() == ib.rows() );
00981 }
00982 assert( Q.rows() == Q.cols() );
00983 assert( Q.rows() == sol.rows() );
00984 assert( sol.cols() == 1 );
00985 assert(lowerBounds.rows() == sol.rows());
00986 assert(upperBounds.rows() == sol.rows());
00987 assert(lowerBounds.cols() == 1);
00988 assert(upperBounds.cols() == 1);
00989
00990 #ifdef MOSEK_QP
00991 int result = mosekNNSolverWrapper(Q, Eq, b, InEq, ib,
00992 lowerBounds, upperBounds, sol,
00993 objVal, MOSEK_OBJ_QP);
00994 #elif defined OASES_QP
00995 int result = QPOASESSolverWrapperQP(Q, Eq, b, InEq, ib,
00996 lowerBounds, upperBounds, sol,
00997 objVal);
00998 #else
00999 int result = 0;
01000 DBGA("No QP Solver installed");
01001 return 0;
01002 #endif
01003
01004 return result;
01005 }
01006
01019 int factorizedQPSolver(const Matrix &Qf,
01020 const Matrix &Eq, const Matrix &b,
01021 const Matrix &InEq, const Matrix &ib,
01022 const Matrix &lowerBounds, const Matrix &upperBounds,
01023 Matrix &sol, double *objVal)
01024 {
01025 if (Eq.rows()) {
01026 assert( Eq.cols() == sol.rows() );
01027 assert( Eq.rows() == b.rows() );
01028 }
01029 if (InEq.rows()) {
01030 assert( InEq.cols() == sol.rows() );
01031 assert( InEq.rows() == ib.rows() );
01032 }
01033 assert( Qf.cols() == sol.rows() );
01034 assert( sol.cols() == 1 );
01035 assert(lowerBounds.rows() == sol.rows());
01036 assert(upperBounds.rows() == sol.rows());
01037 assert(lowerBounds.cols() == 1);
01038 assert(upperBounds.cols() == 1);
01039
01040
01041 int numVar = sol.rows() + Qf.rows();
01042 Matrix xy(numVar, 1);
01043
01044
01045 SparseMatrix ExtInEq(Matrix::ZEROES<SparseMatrix>(InEq.rows(), numVar));
01046 ExtInEq.copySubMatrix(0, 0, InEq);
01047
01048 SparseMatrix ExtEq(Matrix::ZEROES<SparseMatrix>(Eq.rows() + Qf.rows(), numVar));
01049 ExtEq.copySubMatrix(0, 0, Eq);
01050 ExtEq.copySubMatrix(Eq.rows(), 0, Qf);
01051 ExtEq.copySubMatrix(Eq.rows(), Eq.cols(), SparseMatrix::NEGEYE(Qf.rows(), Qf.rows()));
01052
01053 Matrix extB(Matrix::ZEROES<Matrix>(b.rows()+Qf.rows(),1));
01054 extB.copySubMatrix(0, 0, b);
01055
01056 SparseMatrix ExtQ(Matrix::ZEROES<SparseMatrix>(numVar, numVar));
01057 ExtQ.copySubMatrix(sol.rows(), sol.rows(), SparseMatrix::EYE(Qf.rows(), Qf.rows()));
01058
01059
01060 Matrix extLow(Matrix::MIN_VECTOR(numVar));
01061 extLow.copySubMatrix(0, 0, lowerBounds);
01062 Matrix extUp(Matrix::MAX_VECTOR(numVar));
01063 extUp.copySubMatrix(0, 0, upperBounds);
01064
01065 int result = QPSolver(ExtQ, ExtEq, extB, ExtInEq, ib, extLow, extUp, xy, objVal);
01066
01067 sol.copySubBlock(0, 0, sol.rows(), 1, xy, 0, 0);
01068
01069 return result;
01070 }
01071
01089 void testQP()
01090 {
01091
01092 Matrix Eq(1,2);
01093 Matrix b(1,1);
01094 Eq.elem(0,0) = 1.0; Eq.elem(0,1) = -1.0; b.elem(0,0) = -4.0;
01095
01096 Matrix InEq(2,2);
01097 Matrix ib(2,1);
01098 InEq.elem(0,0) = 1; InEq.elem(0,1) = 1; ib.elem(0,0) = 7;
01099 InEq.elem(1,0) = -1; InEq.elem(1,1) = 2; ib.elem(1,0) = -4;
01100
01101 Matrix Q(Matrix::ZEROES<Matrix>(2,2));
01102 Q.elem(0,0) = 1; Q.elem(1,1) = 4;
01103
01104 Matrix sol(2,1);
01105 Matrix lowerBounds(Matrix::MIN_VECTOR(2));
01106 Matrix upperBounds(Matrix::MAX_VECTOR(2));
01107 double objVal;
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128 int result = QPSolver(Q, Eq, b, InEq, ib, lowerBounds, upperBounds, sol, &objVal);
01129
01130 if (result == 0) {
01131 DBGA("Test QP solved");
01132 DBGA("Solution: [" << sol.elem(0,0) << " " << sol.elem(1,0) << "]");
01133 DBGA("Objective: " << objVal);
01134 } else if (result > 0) {
01135 DBGA("Test QP reports problem is unfeasible");
01136 } else {
01137 DBGA("Test QP reports error in computation");
01138 }
01139 }
01140
01153 int
01154 LPSolver(const Matrix &Q,
01155 const Matrix &Eq, const Matrix &b,
01156 const Matrix &InEq, const Matrix &ib,
01157 const Matrix &lowerBounds, const Matrix &upperBounds,
01158 Matrix &sol, double* objVal)
01159 {
01160 assert(sol.cols() == 1);
01161 assert(Q.cols() == sol.rows());
01162 assert(Q.rows() == 1);
01163 if (Eq.rows()) {
01164 assert(Eq.cols() == sol.rows());
01165 assert(Eq.rows() == b.rows());
01166 }
01167 if (InEq.rows()) {
01168 assert(InEq.cols() == sol.rows());
01169 assert(InEq.rows() == ib.rows());
01170 }
01171 assert(lowerBounds.rows() == sol.rows());
01172 assert(upperBounds.rows() == sol.rows());
01173 assert(lowerBounds.cols() == 1);
01174 assert(upperBounds.cols() == 1);
01175
01176 #ifdef MOSEK_QP
01177 int result = mosekNNSolverWrapper(Q, Eq, b, InEq, ib,
01178 lowerBounds, upperBounds, sol, objVal, MOSEK_OBJ_LP);
01179 #elif defined OASES_QP
01180 int result = QPOASESSolverWrapperLP(Q, Eq, b, InEq, ib,
01181 lowerBounds, upperBounds, sol,
01182 objVal);
01183 #else
01184 int result = 0;
01185 DBGA("No LP Solver installed");
01186 return result;
01187 #endif
01188
01189 return result;
01190 }
01191
01212 void
01213 testLP()
01214 {
01215 Matrix Eq(Matrix::ZEROES<Matrix>(3,4));
01216 Matrix b(Matrix::ZEROES<Matrix>(3,1));
01217
01218 Eq.elem(0,0) = Eq.elem(0,1) = 1.0; Eq.elem(0,2) = -1.0;
01219 Eq.elem(1,0) = 3.0; Eq.elem(1,1) = -1.0;
01220 Eq.elem(2,1) = 1.0; Eq.elem(2,3) = -1.0;
01221
01222 Matrix Obj(1,4);
01223 Obj.elem(0,0) = 1.0; Obj.elem(0,1) = Obj.elem(0,2) = -1.0; Obj.elem(0,3) = -1.0;
01224
01225 Matrix InEq(Matrix::ZEROES<Matrix>(1,4));
01226 InEq.elem(0,0) = 1.0;
01227 Matrix ib(1,1);
01228 ib.elem(0,0) = 5.0;
01229
01230 Matrix x(4,1);
01231
01232 Matrix low(Matrix::MIN_VECTOR(4));
01233 Matrix high(Matrix::MAX_VECTOR(4));
01234
01235 #ifdef MOSEK_QP
01236 double obj;
01237 int result = mosekNNSolverWrapper(Obj, Eq, b, InEq, ib, x, low, high, &obj, MOSEK_OBJ_LP);
01238 if (result > 0) {
01239 DBGA("Test failed: program unfeasible");
01240 } else if (result < 0) {
01241 DBGA("Test failed: error in computation");
01242 } else {
01243 DBGA("Test minimum: " << obj);
01244 DBGA("Solution:\n" << x);
01245 }
01246 #endif
01247 }