IMP_Eigen::VectorXd GaussianProcessInterpolation::get_wx_vector_derivative( Floats xval, unsigned p) const { const_cast<GaussianProcessInterpolation *>(this)->update_flags_covariance(); unsigned nm = get_number_of_m_particles(); // derivative wrt mean particles and/or sigma is zero if (p <= nm) return IMP_Eigen::VectorXd::Zero(M_); IMP_Eigen::VectorXd ret(M_); for (unsigned i = 0; i < M_; i++) { FloatsList xv; xv.push_back(xval); xv.push_back(x_[i]); ret(i) = covariance_function_->get_derivative_matrix(p - (nm + 1), xv)(0, 1); } return ret; }
FloatsList GaussianProcessInterpolation::get_data_variance() const { FloatsList ret; IMP_Eigen::MatrixXd S(get_S()); for (unsigned i = 0; i < M_; i++) { Floats val; for (unsigned j = 0; j < M_; j++) val.push_back(S(i, j)); ret.push_back(val); } return ret; }
FloatsList GaussianProcessInterpolationRestraint::get_hessian(bool) const { IMP_Eigen::MatrixXd tmp(get_hessian()); FloatsList ret; for (unsigned i = 0; i < tmp.rows(); ++i) { Floats buf; for (unsigned j = 0; j < tmp.cols(); ++j) buf.push_back(tmp(i, j)); ret.push_back(buf); } return ret; }
FloatsList GaussianProcessInterpolation::get_posterior_covariance_hessian( Floats x, bool) const { IMP_Eigen::MatrixXd mat(get_posterior_covariance_hessian(x)); FloatsList ret; for (unsigned j = 0; j < mat.rows(); j++) { Floats tmp; for (unsigned i = 0; i < mat.cols(); i++) tmp.push_back(mat(i, j)); ret.push_back(tmp); } return ret; }
IMP_Eigen::VectorXd GaussianProcessInterpolation::get_posterior_covariance_derivative(Floats x) const { const_cast<GaussianProcessInterpolation *>(this)->update_flags_covariance(); // get how many and which particles are optimized unsigned mnum = get_number_of_m_particles(); std::vector<bool> mopt; unsigned mnum_opt = 0; for (unsigned i = 0; i < mnum; i++) { mopt.push_back(get_m_particle_is_optimized(i)); if (mopt.back()) mnum_opt++; } unsigned Onum = get_number_of_Omega_particles(); std::vector<bool> Oopt; unsigned Onum_opt = 0; for (unsigned i = 0; i < Onum; i++) { Oopt.push_back(get_Omega_particle_is_optimized(i)); if (Oopt.back()) Onum_opt++; } unsigned num_opt = mnum_opt + Onum_opt; unsigned sigma_opt = Oopt[0] ? 1 : 0; IMP_Eigen::VectorXd ret(num_opt); ret.head(mnum_opt + sigma_opt).setZero(); // build vector of dcov(q,q)/dparticles FloatsList xv; xv.push_back(x); for (unsigned i = 0, j = 0; i < Onum - 1; i++) // skip sigma if (Oopt[i + 1]) ret(mnum_opt + sigma_opt + j++) = covariance_function_->get_derivative_matrix(i, xv)(0, 0); // add dcov/dw(q) * dw(q)/dparticles IMP_Eigen::MatrixXd dwqdp(M_, num_opt); for (unsigned i = 0, j = 0; i < mnum + Onum; i++) if (((i < mnum) && mopt[i]) || (i >= mnum && Oopt[i - mnum])) dwqdp.col(j++) = get_wx_vector_derivative(x, i); ret += dwqdp.transpose() * get_dcov_dwq(x); // add dcov/dOm * dOm/dparticles IMP_Eigen::MatrixXd dcovdOm(get_dcov_dOm(x)); for (unsigned i = 0, j = 0; i < Onum; i++) if (Oopt[i]) ret.tail(Onum_opt)(j++) += (dcovdOm.transpose() * get_Omega_derivative(i)).trace(); return ret; }
IMP_Eigen::MatrixXd GaussianProcessInterpolation::get_posterior_covariance_hessian(Floats x) const { const_cast<GaussianProcessInterpolation *>(this)->update_flags_covariance(); // get how many and which particles are optimized unsigned mnum = get_number_of_m_particles(); std::vector<bool> mopt; unsigned mnum_opt = 0; for (unsigned i = 0; i < mnum; i++) { mopt.push_back(get_m_particle_is_optimized(i)); if (mopt.back()) mnum_opt++; } unsigned Onum = get_number_of_Omega_particles(); std::vector<bool> Oopt; unsigned Onum_opt = 0; for (unsigned i = 0; i < Onum; i++) { Oopt.push_back(get_Omega_particle_is_optimized(i)); if (Oopt.back()) Onum_opt++; } // total number of optimized particles unsigned num_opt = mnum_opt + Onum_opt; // whether sigma is optimized unsigned sigma_opt = Oopt[0] ? 1 : 0; // cov_opt: number of optimized covariance particles without counting sigma unsigned cov_opt = Onum_opt - sigma_opt; // init matrix and fill with zeros at mean particle's indices // dprior_cov(q,q)/(dsigma d.) is also zero IMP_Eigen::MatrixXd ret(IMP_Eigen::MatrixXd::Zero(num_opt, num_opt)); // build vector of dcov(q,q)/dp1dp2 with p1 and p2 covariance particles FloatsList xv; xv.push_back(x); FloatsList tmplist; for (unsigned pa = 0; pa < Onum; ++pa) { if (!Oopt[pa]) continue; // skip not optimized particles if (pa == 0) continue; // skip sigma even when it is optimized Floats tmp; for (unsigned pb = pa; pb < Onum; ++pb) { if (!Oopt[pb]) continue; // skip not optimized particles // sigma has already been skipped tmp.push_back(covariance_function_->get_second_derivative_matrix( pa - 1, pb - 1, xv)(0, 0)); } tmplist.push_back(tmp); } for (unsigned pa_opt = 0; pa_opt < cov_opt; pa_opt++) for (unsigned pb_opt = pa_opt; pb_opt < cov_opt; pb_opt++) ret.bottomRightCorner(cov_opt, cov_opt)(pa_opt, pb_opt) = tmplist[pa_opt][pb_opt - pa_opt]; // compute and store w(q) derivatives (skip mean particles) IMP_Eigen::MatrixXd dwqdp(M_, Onum_opt); for (unsigned i = 0, j = 0; i < Onum; i++) if (Oopt[i]) dwqdp.col(j++) = get_wx_vector_derivative(x, i + mnum); // add d2cov/(dw(q)_k * dw(q)_l) * dw(q)^k/dp_i * dw(q)^l/dp_j ret.bottomRightCorner(cov_opt, cov_opt).noalias() += dwqdp.rightCols(cov_opt).transpose() * get_d2cov_dwq_dwq() * dwqdp.rightCols(cov_opt); // compute and store Omega derivatives (skip mean particles) std::vector<IMP_Eigen::MatrixXd> dOmdp; for (unsigned i = 0; i < Onum; i++) { if (Oopt[i]) dOmdp.push_back(get_Omega_derivative(i)); } // add d2cov/(dOm_kl * dOm_mn) * dOm^kl/dp_i * dOm^mn/dp_j std::vector<std::vector<IMP_Eigen::MatrixXd> > d2covdo; for (unsigned m = 0; m < M_; m++) { std::vector<IMP_Eigen::MatrixXd> tmp; for (unsigned n = 0; n < M_; n++) tmp.push_back(get_d2cov_dOm_dOm(x, m, n)); d2covdo.push_back(tmp); } for (unsigned i = 0; i < Onum_opt; i++) { IMP_Eigen::MatrixXd tmp(M_, M_); for (unsigned m = 0; m < M_; ++m) for (unsigned n = 0; n < M_; ++n) tmp(m, n) = (d2covdo[m][n].transpose() * dOmdp[i]).trace(); for (unsigned j = i; j < Onum_opt; j++) ret.bottomRightCorner(Onum_opt, Onum_opt)(i, j) += (dOmdp[j].transpose() * tmp).trace(); } for (unsigned i = 0; i < d2covdo.size(); i++) d2covdo[i].clear(); d2covdo.clear(); // compute cross-term std::vector<IMP_Eigen::MatrixXd> d2covdwdo; for (unsigned k = 0; k < M_; k++) d2covdwdo.push_back(get_d2cov_dwq_dOm(x, k)); // compute derivative contribution into temporary IMP_Eigen::MatrixXd tmpH(Onum_opt, Onum_opt); for (unsigned i = 0; i < Onum_opt; i++) { IMP_Eigen::VectorXd tmp(M_); for (unsigned k = 0; k < M_; k++) tmp(k) = (d2covdwdo[k].transpose() * dOmdp[i]).trace(); for (unsigned j = 0; j < Onum_opt; j++) tmpH(i, j) = dwqdp.col(j).transpose() * tmp; } ret.bottomRightCorner(Onum_opt, Onum_opt) += tmpH + tmpH.transpose(); // deallocate unused stuff // tmpH.resize(0,0); d2covdwdo.clear(); dOmdp.clear(); // dwqdp.resize(0,0); // dcov/dw_k * d2w^k/(dp_i dp_j) IMP_Eigen::VectorXd dcwq(get_dcov_dwq(x)); for (unsigned i = 0; i < cov_opt; i++) for (unsigned j = i; j < cov_opt; j++) ret.bottomRightCorner(cov_opt, cov_opt)(i, j) += dcwq.transpose() * get_wx_vector_second_derivative(x, mnum + 1 + i, mnum + 1 + j); // dcwq.resize(0,0); // dcov/dOm_kl * d2Om^kl/(dp_i dp_j), zero when p_i or p_j is sigma or mean IMP_Eigen::MatrixXd dcOm(get_dcov_dOm(x)); for (unsigned i = 0; i < cov_opt; i++) for (unsigned j = i; j < cov_opt; j++) ret.bottomRightCorner(cov_opt, cov_opt)(i, j) += (dcOm.transpose() * get_Omega_second_derivative(i + 1, j + 1)) .trace(); // dcOm.resize(0,0); // return as symmetric matrix for (unsigned i = mnum_opt; i < num_opt; ++i) for (unsigned j = mnum_opt + 1; j < num_opt; ++j) ret(j, i) = ret(i, j); return ret; }