/////////////////////////////////////////////////////////////////////////////// // /// Finds the zeroes of P(x) in the domain \f$a < x <= b\f$, putting the /// results into Z // /////////////////////////////////////////////////////////////////////////////// void AntisymmetricExpFit::find_zeroes(RealVector &P, const Real &a, const Real &b, RealVector &Z) { const int N = P.size(); RealMatrix cm(N-1,N-1); int i,j; // --- Form the companion matrix // ----------------------------- cm.fill(0.0); for(j=0; j<N-1; ++j) { cm(0,j) = -P(N-2-j)/P(N-1); } for(i=1; i<N-1; ++i) { cm(i,i-1) = 1.0; } // --- find eigenvalues of // --- companion matrix and // --- extract roots in [0:1] // -------------------------- EigenSolver<RealMatrix> roots(cm,false); Z.resize(N); i = 0; for(j = 0; j<roots.eigenvalues().size(); ++j) { if(fabs(roots.eigenvalues()(j).imag()) < 1e-15 && roots.eigenvalues()(j).real() > a && roots.eigenvalues()(j).real() <= b) { Z(i) = roots.eigenvalues()(j).real(); ++i; } } Z.conservativeResize(i); }
/////////////////////////////////////////////////////////////////////////////// // /// Find zeroes of the polynomial \f$y = sum_i e_ix^i\f$, /// where \f$e\f$ is the \f$c^{th}\f$ eigenvector, and put any zeroes /// that lie in the interval [0:1] into \c k. /// /// \param c The identifier of the eigenvector to find zeroes of. // /////////////////////////////////////////////////////////////////////////////// void AntisymmetricExpFit::fit_exponents(int c) { const int N = 2.0*ESolver.eigenvectors().rows(); int i,j; // --- Construct the eigenpolynomial // --- from the eigenvalues // --------------------------------- RealVector P(N); // eigen polynomial coefficients if(provable) { // --- PA = P_q(x) - x^{N/2} P_q(x^{-1}) // --- P = PA/(1-x) RealVector PA(N+1); // eigen polynomial coefficients PA(N/2) = 0.0; PA.topRows(N/2) = ESolver.eigenvectors().col(c).real(); PA.bottomRows(N/2) = -ESolver.eigenvectors().col(c).real().reverse(); P(0) = PA(0); for(i = 1; i<P.size(); ++i) { P(i) = P(i-1) + PA(i); } } else { P.topRows(N/2) = ESolver.eigenvectors().col(c).real(); P.bottomRows(N/2) = ESolver.eigenvectors().col(c).real().reverse(); } RealVector Q; // eigenpolynomial with changed variable RealVector Z; // scaled positions of zeroes long double alpha; // scaling factor of polynomial long double s; // scale k.resize(c); i = 0; alpha = 2.0/3.0; if(P.size() > 64) { while(i < c && alpha > 1e-8) { change_variable(P,alpha,Q); j = Q.size()-1; s = pow(2.0,j); while(j && fabs(Q(j))/s < 1e-18) { s /= 2.0; --j; } Q.conservativeResize(j+1); find_zeroes(Q, -0.5, 0.5, Z); for(j = Z.size()-1; j>=0; --j) { s = 1.0 - alpha*(1.0 -Z(j)); k(i) = s; ++i; } alpha /= 3.0; } } else { find_zeroes(P, 0.0, 1.0, k); } }