Measurement::Measurement(MatrixXcd observable) { ComplexEigenSolver<MatrixXcd> solver(observable); MatrixXcd vectors = solver.eigenvectors(); for (int i = 0; i < vectors.cols(); ++i) addOperator(vectors.col(i) * vectors.col(i).transpose(), i_to_string(i)); _checkOperatorsAreValid(); }
Rcpp::List EigsGen::extract() { int nconv = iparam[5 - 1]; int niter = iparam[9 - 1]; // Sometimes there are nconv = nev + 1 converged eigenvalues, // mainly due to pairs of complex eigenvalues. // We will truncate at nev. int truenconv = nconv > nev ? nev : nconv; // Converged eigenvalues from aupd() VectorXcd evalsConverged(nconv); evalsConverged.real() = MapVec(workl + ncv * ncv, nconv); evalsConverged.imag() = MapVec(workl + ncv * ncv + ncv, nconv); // If only eigenvalues are requested if(!retvec) { if(nconv < nev) ::Rf_warning("only %d eigenvalues converged, less than k", nconv); sortDesc(evalsConverged); if(evalsConverged.size() > truenconv) evalsConverged.conservativeResize(truenconv); return returnResult(returnRealIfPossible(evalsConverged), R_NilValue, wrap(truenconv), wrap(niter)); } // Recompute the Hessenburg matrix, since occasionally // aupd() will give us the incorrect one recomputeH(); MapMat Hm(workl, ncv, ncv); MapMat Vm(V, n, ncv); RealSchur<MatrixXd> schur(Hm); MatrixXd Qm = schur.matrixU(); MatrixXd Rm = schur.matrixT(); VectorXcd evalsRm(ncv); VectorXi selectInd(nconv); eigenvalueSchur(Rm, evalsRm); findMatchedIndex(evalsConverged.head(nconv), evalsRm, selectInd); //Rcpp::Rcout << evalsRm << "\n\n"; //Rcpp::Rcout << evalsConverged << "\n\n"; truenconv = selectInd.size(); if(truenconv < 1) { ::Rf_warning("no converged eigenvalues found"); return returnResult(R_NilValue, R_NilValue, wrap(0L), wrap(niter)); } // Shrink Qm and Rm to the dimension given by the largest value // in selectInd. Since selectInd is strictly increasing, // we can just use its last value. int lastInd = selectInd[selectInd.size() - 1]; Qm.conservativeResize(Eigen::NoChange, lastInd + 1); Rm.conservativeResize(lastInd + 1, lastInd + 1); // Eigen decomposition of Rm EigenSolver<MatrixXd> es(Rm); evalsRm = es.eigenvalues(); MatrixXcd evecsA = Vm * (Qm * es.eigenvectors()); // Order and select eigenvalues/eigenvectors for(int i = 0; i < truenconv; i++) { // Since selectInd[i] >= i for all i, it is safe to // overwrite the elements and columns. evalsRm[i] = evalsRm[selectInd[i]]; } if(evalsRm.size() > truenconv) evalsRm.conservativeResize(truenconv); transformEigenvalues(evalsRm); // Now (evalsRm, selectInd) gives the pair of (value, location) sortDescPair(evalsRm, selectInd); if(truenconv > nev) { truenconv = nev; evalsRm.conservativeResize(truenconv); } MatrixXcd evecsConverged(n, truenconv); for(int i = 0; i < truenconv; i++) { evecsConverged.col(i) = evecsA.col(selectInd[i]); } if(truenconv < nev) ::Rf_warning("only %d eigenvalues converged, less than k", truenconv); return returnResult(returnRealIfPossible(evalsRm), returnRealIfPossible(evecsConverged), wrap(truenconv), wrap(niter)); }
bool Ellipsoid::overlapsWith(Ellipsoid ellipsoid, bool &ellipsoidMatrixDecompositionIsSuccessful) { // Construct translation matrix MatrixXd T1 = MatrixXd::Identity(Ndimensions+1,Ndimensions+1); MatrixXd T2 = MatrixXd::Identity(Ndimensions+1,Ndimensions+1); T1.bottomLeftCorner(1,Ndimensions) = (-1.0) * centerCoordinates.transpose(); T2.bottomLeftCorner(1,Ndimensions) = (-1.0) * ellipsoid.getCenterCoordinates().transpose(); // Construct ellipsoid matrix in homogeneous coordinates MatrixXd A = MatrixXd::Zero(Ndimensions+1,Ndimensions+1); MatrixXd B = A; A(Ndimensions,Ndimensions) = -1; B(Ndimensions,Ndimensions) = -1; A.topLeftCorner(Ndimensions,Ndimensions) = covarianceMatrix.matrix().inverse(); B.topLeftCorner(Ndimensions,Ndimensions) = ellipsoid.getCovarianceMatrix().matrix().inverse(); MatrixXd AT = T1*A*T1.transpose(); // Translating to ellipsoid center MatrixXd BT = T2*B*T2.transpose(); // Translating to ellipsoid center // Compute Hyper Quadric Matrix generating from the two ellipsoids // and derive its eigenvalues decomposition MatrixXd C = AT.inverse() * BT; MatrixXcd CC(Ndimensions+1,Ndimensions+1); CC.imag() = MatrixXd::Zero(Ndimensions+1,Ndimensions+1); CC.real() = C; ComplexEigenSolver<MatrixXcd> eigenSolver(CC); // If eigenvalue decomposition fails, set control flag to false // to stop the nested sampling and print the results if (eigenSolver.info() != Success) { ellipsoidMatrixDecompositionIsSuccessful = false; } MatrixXcd E = eigenSolver.eigenvalues(); MatrixXcd V = eigenSolver.eigenvectors(); bool ellipsoidsDoOverlap = false; // Assume no overlap in the beginning double pointA; // Point laying in this ellipsoid double pointB; // Point laying in the other ellipsoid // Loop over all eigenvectors for (int i = 0; i < Ndimensions+1; i++) { // Skip inadmissible eigenvectors if (V(Ndimensions,i).real() == 0) { continue; } else if (E(i).imag() != 0) { V.col(i) = V.col(i).array() * (V.conjugate())(Ndimensions,i); // Multiply eigenvector by complex conjugate of last element V.col(i) = V.col(i).array() / V(Ndimensions,i).real(); // Normalize eigenvector to last component value pointA = V.col(i).transpose().real() * AT * V.col(i).real(); // Evaluate point from this ellipsoid pointB = V.col(i).transpose().real() * BT * V.col(i).real(); // Evaluate point from the other ellipsoid // Accept only if point belongs to both ellipsoids if ((pointA <= 0) && (pointB <= 0)) { ellipsoidsDoOverlap = true; // Exit if ellipsoidsDoOverlap is found break; } } } return ellipsoidsDoOverlap; }
/*! \brief Partial pivoted LU to construct low-rank. */ void partial_Piv_LU(const int start_Row, const int start_Col, const int n_Rows, const int n_Cols, const double tolerance, int& computed_Rank, MatrixXcd& U, MatrixXcd& V) { /********************************/ /* PURPOSE OF EXISTENCE */ /********************************/ /*! Obtains the low-rank decomposition of the matrix to a desired tolerance using the partial pivoting LU algorithm, i.e., given a sub-matrix 'A' and tolerance 'epsilon', computes matrices 'U' and 'V' such that ||A-UV||_F < epsilon. The norm is Frobenius norm. */ /************************/ /* INPUTS */ /************************/ /// start_Row - Starting row of the sub-matrix. /// start_Col - Starting column of the sub-matrix. /// n_Rows - Number of rows of the sub-matrix. /// n_Cols - Number of columns of the sub-matrix. /// tolerance - Tolerance of low-rank approximation. /************************/ /* OUTPUTS */ /************************/ /// computed_Rank - Rank obtained for the given tolerance. /// U - Matrix forming the column basis. /// V - Matrix forming the row basis. /// If the matrix is small enough, do not do anything int tolerable_Rank = 5; if (n_Cols <= tolerable_Rank){ kernel->get_Matrix(start_Row, start_Col, n_Rows, n_Cols, U); V = MatrixXcd::Identity(n_Cols, n_Cols); computed_Rank = n_Cols; return; } else if (n_Rows <= tolerable_Rank){ U = MatrixXcd::Identity(n_Rows, n_Rows); kernel->get_Matrix(start_Row, start_Col, n_Rows, n_Cols, V); computed_Rank = n_Rows; return; } vector<int> rowIndex; /// This stores the row indices, which have already been used. vector<int> colIndex; /// This stores the column indices, which have already been used. vector<VectorXcd> u; /// Stores the column basis. vector<VectorXcd> v; /// Stores the row basis. srand (time(NULL)); complex<double> max, unused_max, Gamma; /* INITIALIZATION */ /// Initialize the matrix norm and the the first row index double matrix_Norm = 0; rowIndex.push_back(0); int pivot; computed_Rank = 0; VectorXcd a, row, col; double row_Squared_Norm, row_Norm, col_Squared_Norm, col_Norm; /// Repeat till the desired tolerance is obtained do { /// Generation of the row kernel->get_Matrix_Row(start_Col, n_Cols, start_Row+rowIndex.back(), a); /// Row of the residuum and the pivot column row = a; for (int l=0; l<computed_Rank; ++l) { row = row-u[l](rowIndex.back())*v[l]; } pivot = kernel->max_Abs_Vector(row, colIndex, max); int max_tries = 100; int count = 0; int count1 = 0; /// This randomization is needed if in the middle of the algorithm the row happens to be exactly the linear combination of the previous rows. while (abs(max)<tolerance && count < max_tries) { int new_rowIndex; rowIndex.pop_back(); do { new_rowIndex = rand()%n_Rows; ++count1; } while (find(rowIndex.begin(),rowIndex.end(),new_rowIndex)!=rowIndex.end() && count1 < max_tries); count1 = 0; rowIndex.push_back(new_rowIndex); /// Generation of the row kernel->get_Matrix_Row(start_Col, n_Cols, start_Row+rowIndex.back(), a); /// Row of the residuum and the pivot column row = a; for (int l=0; l<computed_Rank; ++l) { row = row-u[l](rowIndex.back())*v[l]; } pivot = kernel->max_Abs_Vector(row, colIndex, max); ++count; } if (count == max_tries) break; count = 0; colIndex.push_back(pivot); /// Normalizing constant Gamma = 1.0/(max); /// Generation of the column kernel->get_Matrix_Col(start_Row, n_Rows, start_Col+colIndex.back(), a); /// Column of the residuum and the pivot row col = a; for (int l=0; l<computed_Rank; ++l) { col = col-v[l](colIndex.back())*u[l]; } pivot = kernel->max_Abs_Vector(col, rowIndex, unused_max); /// This randomization is needed if in the middle of the algorithm the columns happens to be exactly the linear combination of the previous columns. while (abs(max)<tolerance && count < max_tries) { colIndex.pop_back(); int new_colIndex; do { new_colIndex = rand()%n_Cols; } while (find(colIndex.begin(),colIndex.end(),new_colIndex)!=colIndex.end() && count1 < max_tries); count1 = 0; colIndex.push_back(new_colIndex); /// Generation of the column kernel->get_Matrix_Col(start_Row, n_Rows, start_Col+colIndex.back(), a); /// Column of the residuum and the pivot row col = a; for (int l=0; l<computed_Rank; ++l) { col = col-u[l](colIndex.back())*v[l]; } pivot = kernel->max_Abs_Vector(col, rowIndex, unused_max); ++count; } if (count == max_tries) break; count = 0; rowIndex.push_back(pivot); /// New vectors u.push_back(Gamma*col); v.push_back(row); /// New approximation of matrix norm row_Squared_Norm = row.squaredNorm(); row_Norm = sqrt(row_Squared_Norm); col_Squared_Norm = col.squaredNorm(); col_Norm = sqrt(col_Squared_Norm); matrix_Norm = matrix_Norm + abs(Gamma*Gamma*row_Squared_Norm*col_Squared_Norm); for (int j=0; j<computed_Rank; ++j) { matrix_Norm = matrix_Norm + 2.0*abs(u[j].dot(u.back()))*abs(v[j].dot(v.back())); } ++computed_Rank; } while (row_Norm*col_Norm > abs(max)*tolerance*matrix_Norm && computed_Rank <= fmin(n_Rows, n_Cols)); /// If the computed_Rank is close to full-rank then return the trivial full-rank decomposition if (computed_Rank>=fmin(n_Rows, n_Cols)) { if (n_Rows < n_Cols) { U = MatrixXcd::Identity(n_Rows,n_Rows); kernel->get_Matrix(start_Row, start_Col, n_Rows, n_Cols, V); computed_Rank = n_Rows; return; } else { kernel->get_Matrix(start_Row, start_Col, n_Rows, n_Cols, U); V = MatrixXcd::Identity(n_Cols,n_Cols); computed_Rank = n_Cols; return; } } U = MatrixXcd(n_Rows,computed_Rank); V = MatrixXcd(computed_Rank,n_Cols); for (int j=0; j<computed_Rank; ++j) { U.col(j) = u[j]; V.row(j) = v[j]; } };
int main() { // The eigen approach ArrayXd n = ArrayXd::LinSpaced(N+1,0,N); double multiplier = M_PI/N; Array<double, 1, N+1> nT = n.transpose(); ArrayXd x = - cos(multiplier*n); ArrayXd xsub = x.middleRows(1, N-1); ArrayXd ysub = (x1-x0)/2*xsub + (x1+x0)/2; ArrayXXd T = cos((acos(x).matrix()*nT.matrix()).array()); ArrayXXd Tsub = cos((acos(xsub).matrix()*nT.matrix()).array()); ArrayXd sqinx = 1/sqrt(1-xsub*xsub); MatrixXd inv1x2 = (sqinx).matrix().asDiagonal(); // Can't use the following to test elements of inv1x2 // std::cout << inv1x2(0,0) << "\n"; MatrixXd Usub = inv1x2 * sin(((acos(xsub).matrix())*nT.matrix()).array()).matrix(); MatrixXd dTsub = Usub*(n.matrix().asDiagonal()); MatrixXd d2Tsub = ((sqinx*sqinx).matrix().asDiagonal())*((xsub.matrix().asDiagonal()) * (dTsub.matrix()) - (Tsub.matrix()) * ((n*n).matrix().asDiagonal())); MatrixXd d2T(N+1, N+1); RowVectorXd a = (pow((-1),nT))*(nT*nT+1)*(nT*nT)/3; RowVectorXd b = (nT*nT+1)*(nT*nT)/3; d2T.middleRows(1,N-1) = d2Tsub; d2T.row(0) = a; d2T.row(N) = b; MatrixXd D2 = d2T.matrix() * ((T.matrix()).inverse()); MatrixXd E2 = D2.middleRows(1,N-1).middleCols(1,N-1); MatrixXd Y = ysub.matrix().asDiagonal(); MatrixXd H = - (4 / ((x1-x0)*(x1-x0))) * E2 + k*Y; Eigen::EigenSolver<Eigen::MatrixXd> HE(H); VectorXcd D = HE.eigenvalues(); MatrixXcd V = HE.eigenvectors(); std::cout << HE.info() << std::endl; // Open ofstream ofstream Dfile; Dfile.open("D-output.txt"); ofstream Vfile; Vfile.open("V-output.txt"); ofstream V544file; V544file.open("V544-output.txt"); Dfile.precision(15); Dfile << D.real() << "\n"; Vfile.precision(15); Vfile << V.real() << "\n"; V544file.precision(15); for(int i = 1; i<N-1; i++) { V544file << ysub[i-1]; V544file << " " << V.col(544).row(i-1).real() << "\n"; } Dfile.close(); Vfile.close(); V544file.close(); system("gnuplot -p plot.gp"); system("rsvg-convert -w 2000 -o V544-plot.png V544-plot.svg"); }