/** * \file GaussianProcessInterpolationRestraint.cpp * * Copyright 2007-2013 IMP Inventors. All rights reserved. */ #include #include #include #include #include #include #include #include IMPISD_BEGIN_NAMESPACE GaussianProcessInterpolationRestraint::GaussianProcessInterpolationRestraint( GaussianProcessInterpolation *gpi) : ISDRestraint("GaussianProcessInterpolationRestraint %1%"), gpi_(gpi) { //O(M^2) //number of observation points IMP_LOG_TERSE( "GPIR: init" << std::endl); M_ = gpi_->M_; // build multivariate normal with // mean : prior mean // covariance : prior covariance // observed at : the original observations IMP_LOG_TERSE( "GPIR: multivariate normal()" << std::endl); //args are: sample mean, jacobian, true mean, // nobs, sample variance, true variance mvn_ = new MultivariateFNormalSufficient( gpi_->get_I(), 1.0, gpi_->get_m(), 1, Eigen::MatrixXd::Zero(M_,M_), gpi_->get_Omega()); mvn_->set_use_cg(false,0.0); IMP_LOG_TERSE( "GPIR: done init" << std::endl); } void GaussianProcessInterpolationRestraint::set_model(Model *m) { if (m) { IMP_LOG_TERSE( "GPIR: registering the model and scorestate"<sigma_->get_model(); ss_ = new GaussianProcessInterpolationScoreState(this); m->add_score_state(ss_); } else { if (ss_) { if (ss_->get_is_part_of_model()) { Model *m = ss_->get_model(); m->remove_score_state(ss_); ss_=nullptr; } } } Restraint::set_model(m); } ModelObjectsTemp GaussianProcessInterpolationRestraint::do_get_inputs() const { // call the existing implementation ModelObjectsTemp ret; ret+=gpi_->get_input_particles(); ret+=gpi_->get_input_containers(); // add the score state ret.push_back(ss_); return ret; } double GaussianProcessInterpolationRestraint::unprotected_evaluate( DerivativeAccumulator *accum) const { //the functions are all up-to-date since //the ScoreState has taken care of this if (accum) // O(M) if unchanged, O(M^2) if mean changed, else O(M^3) { //derivatives for mean particles VectorXd dmv = mvn_->evaluate_derivative_FM(); unsigned npart=gpi_->get_number_of_m_particles(); //std::cout << "derivs: "; for (unsigned i=0; iget_m_particle_is_optimized(i)) continue; VectorXd dmean = gpi_->get_m_derivative(i); double tmp = dmv.transpose()*dmean; //std::cout << i << " = " << tmp << " "; gpi_->add_to_m_particle_derivative(i, tmp, *accum); } //derivatives for covariance particles MatrixXd dmvS = mvn_->evaluate_derivative_Sigma(); npart=gpi_->get_number_of_Omega_particles(); for (unsigned i=0; iget_Omega_particle_is_optimized(i)) continue; MatrixXd dcov = gpi_->get_Omega_derivative(i); double tmp = (dmvS.transpose()*dcov).trace(); //std::cout << i+2 << " = " << tmp << " "; gpi_->add_to_Omega_particle_derivative(i, tmp, *accum); } //std::cout << std::endl; } double ene = mvn_->evaluate(); //O(M^3) if Omega has changed else O(M) return ene; } double GaussianProcessInterpolationRestraint::get_minus_log_normalization() const { ss_->do_before_evaluate(); return mvn_->get_minus_log_normalization(); } double GaussianProcessInterpolationRestraint::get_minus_exponent() const { ss_->do_before_evaluate(); return mvn_->get_minus_exponent(); } MatrixXd GaussianProcessInterpolationRestraint::get_hessian() const { //update everything ss_->do_before_evaluate(); //get how many and which particles are optimized unsigned mnum = gpi_->get_number_of_m_particles(); std::vector mopt; unsigned mnum_opt = 0; for (unsigned i=0; iget_m_particle_is_optimized(i)); if (mopt.back()) mnum_opt++; } unsigned Onum = gpi_->get_number_of_Omega_particles(); std::vector Oopt; unsigned Onum_opt = 0; for (unsigned i=0; iget_Omega_particle_is_optimized(i)); if (Oopt.back()) Onum_opt++; } unsigned num_opt = mnum_opt + Onum_opt; // Only upper corner of hessian will be computed MatrixXd Hessian(MatrixXd::Zero(num_opt,num_opt)); //d2E/(dm_k dm_l) * dm^k/dTheta_i dm^l/dTheta_j MatrixXd dmdm = mvn_->evaluate_second_derivative_FM_FM(); std::vector funcm; for (unsigned i=0; iget_m_derivative(i)); // dm_k/dTheta_i = 0 if i is a covariance particle // only fill upper triangle e.g. j>=i for (unsigned i=0; i > dodo; // get values for (unsigned m=0; m tmp; for (unsigned n=0; nevaluate_second_derivative_Sigma_Sigma(m,n)); dodo.push_back(tmp); } std::vector< MatrixXd > funcO; for (unsigned i=0; iget_Omega_derivative(i)); // compute contribution for (unsigned i=mnum_opt; i dmdo; for (unsigned k=0; kevaluate_second_derivative_FM_Sigma(k)); //compute hessian for (unsigned j=mnum_opt; jevaluate_derivative_FM()); for (unsigned i=0, iopt=0; iget_m_second_derivative(i,j); jopt++; } iopt++; } dem.resize(0); // dE/dOm_kl * d2Om^kl/(dTheta_i dTheta_j) MatrixXd dOm(mvn_->evaluate_derivative_Sigma()); for (unsigned i=mnum, iopt=mnum_opt; iget_Omega_second_derivative(i-mnum,j-mnum)).trace(); jopt++; } iopt++; } dOm.resize(0,0); //return hessian as full matrix for (unsigned i=0; i(); return Hessian; } FloatsList GaussianProcessInterpolationRestraint::get_hessian(bool) const { MatrixXd tmp(get_hessian()); FloatsList ret; for (unsigned i=0; i ldlt(get_hessian()); if (!ldlt.isPositive()) IMP_THROW("Hessian matrix is not positive definite!", ModelException); return ldlt.vectorD().array().abs().log().sum(); } void GaussianProcessInterpolationScoreState::do_before_evaluate() { IMP_LOG_TERSE( "GPISS: do_before_evaluate()" << std::endl); GaussianProcessInterpolation *gpi_; gpi_ = gpir_->gpi_; MultivariateFNormalSufficient *mvn_; mvn_ = gpir_->mvn_; // gpi_->update_flags_covariance(); //O(1) gpi_->update_flags_mean(); //O(1) if (!(gpi_->flag_m_gpir_)) // gpi says that our m is not up to date { mvn_->set_FM(gpi_->get_m()); // O(M_) gpi_->flag_m_gpir_ = true; IMP_LOG_TERSE( " updated mean"); } if (!(gpi_->flag_Omega_gpir_)) { mvn_->set_Sigma(gpi_->get_Omega()); // O(M^2) gpi_->flag_Omega_gpir_ = true; IMP_LOG_TERSE( " updated covariance"); } IMP_LOG_TERSE( std::endl); /*ParticlesTemp tmp(gpir_->get_input_particles()); std::cout << "values: "; for (unsigned i=0; igpi_->get_input_containers(); } ContainersTemp GaussianProcessInterpolationScoreState::get_output_containers() const { return ContainersTemp(); } ParticlesTemp GaussianProcessInterpolationScoreState::get_input_particles() const { //gpir needs to update internal values computed from particles return gpir_->gpi_->get_input_particles(); } ParticlesTemp GaussianProcessInterpolationScoreState::get_output_particles() const { //gpir does not change particles' attributes. return ParticlesTemp(); } void GaussianProcessInterpolationScoreState::do_show(std::ostream &out) const { out << "GPI score state" << std::endl; } IMPISD_END_NAMESPACE