const Matrix<complex<double> > gslMatrixSqrt( const Matrix<complex<double> >& mat ) { if( mat.num_rows() != mat.num_cols() ) throw("Matrices not square"); Vector<double> eigVals( mat.num_rows() ); Matrix<complex<double> > eigVects = nan_to_zero(mat); // eigVals = Hermitian_eigenvalue_solve( eigVects ); Matrix<complex<double> > tmpMat2 = dagger(eigVects)*mat*eigVects; const complex<double> zero(0.0,0.0); Matrix<complex<double> > out(mat.num_rows(), mat.num_rows(), zero); for (int i=1; i<=mat.num_rows(); i++ ) { out(i,i) = sqrt( tmpMat2(i,i) ); } return nan_to_zero(eigVects*out*dagger(eigVects)); }
const Vector<double> gslMatrixEigVals( const Matrix<complex<double> >& mat ) { if( mat.num_rows() != mat.num_cols() ) throw("Matrices not square"); Vector<double> eigVals( mat.num_rows() ); Matrix<complex<double> > eigVects = nan_to_zero(mat); // eigVals = Hermitian_eigenvalue_solve( eigVects ); return eigVals; }
extern void printDiffs( ofstream& outFile, const int iteration, const Matrix<complex<double> >& mat1, const Matrix<complex<double> >& mat2 ) { // errbnds on Bures? outFile << iteration << ' ' << distBures(mat1,mat2) << ' '; const Vector<double> eVals = eigVals(mat2); // const double eValErrBnd = get_eps() * // max( eVals[0], eVals[ eVals.size() - 1 ] ); // too small for now for ( int i=eVals.size() -1; i>=0; i-- ) { outFile << eVals[i] << ' '; } outFile << endl; }
bool computeInitialCoords(const RDNumeric::SymmMatrix<double> &distMat, RDGeom::PointPtrVect &positions, RDKit::double_source_type &rng, bool randNegEig, unsigned int numZeroFail) { unsigned int N = distMat.numRows(); unsigned int nPt = positions.size(); CHECK_INVARIANT(nPt == N, "Size mismatch"); unsigned int dim = positions.front()->dimension(); const double *data = distMat.getData(); RDNumeric::SymmMatrix<double> sqMat(N), T(N, 0.0); RDNumeric::DoubleMatrix eigVecs(dim, N); RDNumeric::DoubleVector eigVals(dim); double *sqDat = sqMat.getData(); unsigned int dSize = distMat.getDataSize(); double sumSqD2 = 0.0; for (unsigned int i = 0; i < dSize; i++) { sqDat[i] = data[i] * data[i]; sumSqD2 += sqDat[i]; } sumSqD2 /= (N * N); RDNumeric::DoubleVector sqD0i(N, 0.0); double *sqD0iData = sqD0i.getData(); for (unsigned int i = 0; i < N; i++) { for (unsigned int j = 0; j < N; j++) { sqD0iData[i] += sqMat.getVal(i, j); } sqD0iData[i] /= N; sqD0iData[i] -= sumSqD2; if ((sqD0iData[i] < EIGVAL_TOL) && (N > 3)) { return false; } } for (unsigned int i = 0; i < N; i++) { for (unsigned int j = 0; j <= i; j++) { double val = 0.5 * (sqD0iData[i] + sqD0iData[j] - sqMat.getVal(i, j)); T.setVal(i, j, val); } } unsigned int nEigs = (dim < N) ? dim : N; RDNumeric::EigenSolvers::powerEigenSolver(nEigs, T, eigVals, eigVecs, (int)(sumSqD2 * N)); double *eigData = eigVals.getData(); bool foundNeg = false; unsigned int zeroEigs = 0; for (unsigned int i = 0; i < dim; i++) { if (eigData[i] > EIGVAL_TOL) { eigData[i] = sqrt(eigData[i]); } else if (fabs(eigData[i]) < EIGVAL_TOL) { eigData[i] = 0.0; zeroEigs++; } else { foundNeg = true; } } if ((foundNeg) && (!randNegEig)) { return false; } if ((zeroEigs >= numZeroFail) && (N > 3)) { return false; } for (unsigned int i = 0; i < N; i++) { RDGeom::Point *pt = positions[i]; for (unsigned int j = 0; j < dim; ++j) { if (eigData[j] >= 0.0) { (*pt)[j] = eigData[j] * eigVecs.getVal(j, i); } else { // std::cerr<<"!!! "<<i<<"-"<<j<<": "<<eigData[j]<<std::endl; (*pt)[j] = 1.0 - 2.0 * rng(); } } } return true; }