Ejemplo n.º 1
0
void ClassicalScaling::run( PointWiseMapping* mymap ){
   // Retrieve the distances from the dimensionality reduction object
   double half=(-0.5); Matrix<double> distances( half*mymap->modifyDmat() ); 
 
   // Apply centering transtion
   unsigned n=distances.nrows(); double sum;
   // First HM
   for(unsigned i=0;i<n;++i){
       sum=0; for(unsigned j=0;j<n;++j) sum+=distances(i,j);
       for(unsigned j=0;j<n;++j) distances(i,j) -= sum/n;
   }
   // Now (HM)H
   for(unsigned i=0;i<n;++i){
      sum=0; for(unsigned j=0;j<n;++j) sum+=distances(j,i);
      for(unsigned j=0;j<n;++j) distances(j,i) -= sum/n; 
   }

   // Diagonalize matrix
   std::vector<double> eigval(n); Matrix<double> eigvec(n,n);
   diagMat( distances, eigval, eigvec );

   // Pass final projections to map object
   for(unsigned i=0;i<n;++i){
      for(unsigned j=0;j<mymap->getNumberOfProperties();++j) mymap->setProjectionCoordinate( i, j, sqrt(eigval[n-1-j])*eigvec(n-1-j,i) ); 
   }
}
Ejemplo n.º 2
0
int main () {

  // Define symmetric matrix
  PLMD::Matrix<double> mat1(3,3); PLMD::OFile out; out.open("output");
  mat1(0,0)=1.0; mat1(0,1)=0.2; mat1(0,2)=0.3;
  mat1(1,0)=0.2; mat1(1,1)=0.2; mat1(1,2)=0.6;
  mat1(2,0)=0.3; mat1(2,1)=0.6; mat1(2,2)=0.4;

  // Test diagonalize
  std::vector<double> eigval(3); PLMD::Matrix<double> eigvec(3,3); 
  diagMat( mat1, eigval, eigvec ); 
  out<<"Eigenvalues "<<eigval[0]<<" "<<eigval[1]<<" "<<eigval[2]<<"\n";
  out<<"Eigenvectors : \n";
  for(unsigned i=0;i<3;++i){
      out<<eigvec(i,0)<<" "<<eigvec(i,1)<<" "<<eigvec(i,2)<<"\n";
  }

  // Test inverse
  out<<"Inverse : \n";
  PLMD::Matrix<double> inverse(3,3); Invert( mat1, inverse );
  for(unsigned i=0;i<3;++i){ 
      for(unsigned j=0;j<3;++j) out<<inverse(i,j)<<" ";
      out<<"\n";
  }

  // Test pseudoinverse 
  out<<"Pseudoinverse : \n";
  PLMD::Matrix<double> mat(3,2);
  mat(0,0)=0.1; mat(0,1)=0.2; 
  mat(1,0)=0.3; mat(1,1)=0.5;
  mat(2,0)=0.4; mat(2,1)=0.6;
  PLMD::Matrix<double> pseu(2,3);
  pseudoInvert( mat, pseu );
  for(unsigned i=0;i<pseu.nrows();++i){
     for(unsigned j=0;j<pseu.ncols();++j) out<<" "<<pseu(i,j);
     out<<"\n";
  }
  out.close();

  return 0;
}
Ejemplo n.º 3
0
double RMSD::optimalAlignment(const  std::vector<double>  & align,
                                     const  std::vector<double>  & displace,
                                     const std::vector<Vector> & positions,
                                     const std::vector<Vector> & reference ,
                                     std::vector<Vector>  & derivatives, bool squared) {
  plumed_massert(displace==align,"OPTIMAL_FAST version of RMSD can only be used when displace weights are same as align weights");

  double dist(0);
  double norm(0);
  const unsigned n=reference.size();
// This is the trace of positions*positions + reference*reference
  double sum00w(0);
// This is positions*reference
  Tensor sum01w;

  derivatives.resize(n);

  Vector cpositions;
  Vector creference;

// first expensive loop: compute centers
  for(unsigned iat=0;iat<n;iat++){
    double w=align[iat];
    norm+=w;
    cpositions+=positions[iat]*w;
    creference+=reference[iat]*w;
  }
  double invnorm=1.0/norm;

  cpositions*=invnorm;
  creference*=invnorm;
  
// second expensive loop: compute second moments wrt centers
  for(unsigned iat=0;iat<n;iat++){
    double w=align[iat];
    sum00w+=(dotProduct(positions[iat]-cpositions,positions[iat]-cpositions)
            +dotProduct(reference[iat]-creference,reference[iat]-creference))*w;
    sum01w+=Tensor(positions[iat]-cpositions,reference[iat]-creference)*w;
  }

  double rr00=sum00w*invnorm;
  Tensor rr01=sum01w*invnorm;

  Matrix<double> m=Matrix<double>(4,4);
  m[0][0]=rr00+2.0*(-rr01[0][0]-rr01[1][1]-rr01[2][2]);
  m[1][1]=rr00+2.0*(-rr01[0][0]+rr01[1][1]+rr01[2][2]);
  m[2][2]=rr00+2.0*(+rr01[0][0]-rr01[1][1]+rr01[2][2]);
  m[3][3]=rr00+2.0*(+rr01[0][0]+rr01[1][1]-rr01[2][2]);
  m[0][1]=2.0*(-rr01[1][2]+rr01[2][1]);
  m[0][2]=2.0*(+rr01[0][2]-rr01[2][0]);
  m[0][3]=2.0*(-rr01[0][1]+rr01[1][0]);
  m[1][2]=2.0*(-rr01[0][1]-rr01[1][0]);
  m[1][3]=2.0*(-rr01[0][2]-rr01[2][0]);
  m[2][3]=2.0*(-rr01[1][2]-rr01[2][1]);
  m[1][0] = m[0][1];
  m[2][0] = m[0][2];
  m[2][1] = m[1][2];
  m[3][0] = m[0][3];
  m[3][1] = m[1][3];
  m[3][2] = m[2][3];

  vector<double> eigenvals;
  Matrix<double> eigenvecs;
  int diagerror=diagMat(m, eigenvals, eigenvecs );

  if (diagerror!=0){
    string sdiagerror;
    Tools::convert(diagerror,sdiagerror);
    string msg="DIAGONALIZATION FAILED WITH ERROR CODE "+sdiagerror;
    plumed_merror(msg);
  }

  dist=eigenvals[0];

  Matrix<double> ddist_dm(4,4);

  Vector4d q(eigenvecs[0][0],eigenvecs[0][1],eigenvecs[0][2],eigenvecs[0][3]);

// This is the rotation matrix that brings reference to positions
// i.e. matmul(rotation,reference[iat])+shift is fitted to positions[iat]

  Tensor rotation;
  rotation[0][0]=q[0]*q[0]+q[1]*q[1]-q[2]*q[2]-q[3]*q[3];
  rotation[1][1]=q[0]*q[0]-q[1]*q[1]+q[2]*q[2]-q[3]*q[3];
  rotation[2][2]=q[0]*q[0]-q[1]*q[1]-q[2]*q[2]+q[3]*q[3];
  rotation[0][1]=2*(+q[0]*q[3]+q[1]*q[2]);
  rotation[0][2]=2*(-q[0]*q[2]+q[1]*q[3]);
  rotation[1][2]=2*(+q[0]*q[1]+q[2]*q[3]);
  rotation[1][0]=2*(-q[0]*q[3]+q[1]*q[2]);
  rotation[2][0]=2*(+q[0]*q[2]+q[1]*q[3]);
  rotation[2][1]=2*(-q[0]*q[1]+q[2]*q[3]);

  double prefactor=2.0*invnorm;
  Vector shift=cpositions-matmul(rotation,creference);

  if(!squared) prefactor*=0.5/sqrt(dist);

// if "safe", recompute dist here to a better accuracy
  if(safe) dist=0.0;

// If safe is set to "false", MSD is taken from the eigenvalue of the M matrix
// If safe is set to "true", MSD is recomputed from the rotational matrix
// For some reason, this last approach leads to less numerical noise but adds an overhead

// third expensive loop: derivatives
  for(unsigned iat=0;iat<n;iat++){
// there is no need for derivatives of rotation and shift here as it is by construction zero
// (similar to Hellman-Feynman forces)
    Vector d(positions[iat]-shift - matmul(rotation,reference[iat]));
    derivatives[iat]= prefactor*align[iat]*d;
    if(safe) dist+=align[iat]*invnorm*modulo2(d);
  }

  if(!squared) dist=sqrt(dist);

  return dist;
}