int testBasis() { int numErr = 0; logMessage(_T("TESTING - class GM_3dBasis ...\n\n")); // Default constructor, basis must be invalid GM_3dBasis b; if (b.isValid()) { logMessage(_T("\tERROR - Default constructor creates valid basis\n")); numErr++; } else { logMessage(_T("\tOK - Default constructor creates invalid basis\n")); } // Constructor from three vectors GM_3dVector v1(getRandomDouble(), getRandomDouble(), getRandomDouble()); GM_3dVector v2(getRandomDouble(), getRandomDouble(), getRandomDouble()); GM_3dVector v3(getRandomDouble(), getRandomDouble(), getRandomDouble()); GM_3dBasis b1(v1, v2, v3); if (!b1.isValid()) { logMessage(_T("\tERROR - Constructor from three vectors not working\n")); numErr++; } else { logMessage(_T("\tOK - Constructor from three vectors working\n")); } // Copy constructor GM_3dBasis bCopy(b1); if (!bCopy.isValid() || bCopy[0] != b1[0] || bCopy[1] != b1[1] || bCopy[2] != b1[2]) { logMessage(_T("\tERROR - Copy constructor not working\n")); numErr++; } else { logMessage(_T("\tOK - Copy constructor working\n")); } // Linear independency check GM_3dBasis bIndep(GM_3dVector(getRandomDouble(), 0.0, 0.0), GM_3dVector(0.0, getRandomDouble(), 0.0), GM_3dVector(0.0, 0.0, getRandomDouble())); GM_3dBasis bDep(v1, v2, v1*getRandomDouble() + v2*getRandomDouble()); double det = bIndep[0].x() * bIndep[1].y() * bIndep[2].z(); if (!bDep.isValid() || !bIndep.isValid() || bDep.isLinearlyInd() || !bIndep.isLinearlyInd()) { logMessage(_T("\tERROR - Linear independency check not working\n")); numErr++; } else { logMessage(_T("\tOK - Linear independency check working\n")); } return numErr; }
int Simplex::solve(std::vector<double>& rhs) const { // save the input matrix and rhs vector so we get a chance to // recover in case of a singular matrix. const double residualTol = 1.e-8; std::vector<double> mat(mnpdims * mndims); // build the matrix system for (size_t jcol = 0; jcol < mnpdims; ++jcol) { for (size_t irow = 0; irow < mndims; ++irow) { mat[irow + jcol*mndims] = mvertices[jcol + 1][irow] - mvertices[0][irow]; } } std::vector<double> matCopy(mnpdims * mndims); std::vector<double> bCopy(rhs.size()); std::copy(mat.begin(), mat.end(), matCopy.begin()); std::copy(rhs.begin(), rhs.end(), bCopy.begin()); int nrow = (int) mndims; int ncol = (int) mnpdims; char t = 'n'; int one = 1; int mn = ncol; int nb = 1; // optimal block size int lwork = mn + mn*nb; std::vector<double> work((size_t) lwork); int errCode = 0; _GELS_(&t, &nrow, &ncol, &one, &matCopy.front(), &nrow, &rhs.front(), &nrow, &work.front(), &lwork, &errCode); if (!errCode) { // merrCode == 0 indicates everything was fine // merrCode < 0 indicates bad entry // in either case return return errCode; } else if (errCode > 0) { if (nrow <= 1) { return errCode; } for (size_t i = 0; i < mndims; ++i) { rhs[i] = bCopy[i]; } errCode = 0; // relative accuracy in the matrix data double rcond = std::numeric_limits<double>::epsilon(); int rank; std::vector<int> jpvt(ncol); lwork = mn + 3*ncol + 1 > 2*mn + nb*1? mn + 3*ncol + 1: 2*mn + nb*1; work.resize(lwork); _GELSY_(&nrow, &ncol, &one, &matCopy.front(), &nrow, &rhs.front(), &nrow, &jpvt.front(), &rcond, &rank, &work.front(), &lwork, &errCode); // check if this is a good solution double residualError = 0.0; for (size_t i = 0; i < mndims; ++i) { double rowSum = 0.0; for (size_t j = 0; j < mnpdims; ++j) { rowSum += mat[i + nrow*j]*rhs[j]; } residualError += std::abs(rowSum - bCopy[i]); } if (residualError < residualTol) { // good enough errCode = 1; return errCode; } // some error errCode = 2; return errCode; } // we should never reach that point errCode = 0; return errCode; }