8 #ifndef IMPISD_BIVARIATE_FUNCTIONS_H
9 #define IMPISD_BIVARIATE_FUNCTIONS_H
11 #include <IMP/isd/isd_config.h>
17 #include <Eigen/Dense>
19 #define IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM 1e-7
21 IMPISD_BEGIN_NAMESPACE
33 const Floats& x2)
const = 0;
39 virtual Eigen::MatrixXd operator()
44 bool stupid)
const = 0;
47 virtual bool has_changed()
const = 0;
50 virtual void update() = 0;
53 virtual void add_to_derivatives(
63 virtual void add_to_particle_derivative(
unsigned particle_no,
70 virtual Eigen::MatrixXd get_derivative_matrix(
78 bool stupid)
const = 0;
81 virtual Eigen::MatrixXd get_second_derivative_matrix(
82 unsigned particle_a,
unsigned particle_b,
86 virtual FloatsList get_second_derivative_matrix(
87 unsigned particle_a,
unsigned particle_b,
89 bool stupid)
const = 0;
92 virtual unsigned get_ndims_x1()
const = 0;
93 virtual unsigned get_ndims_x2()
const = 0;
96 virtual unsigned get_ndims_y()
const = 0;
99 virtual unsigned get_number_of_particles()
const = 0;
102 virtual bool get_particle_is_optimized(
unsigned particle_no)
const = 0;
105 virtual unsigned get_number_of_optimized_particles()
const = 0;
130 double alpha=2.0,
double jitter =0.0,
double cutoff=1e-7) :
132 tau_(tau), lambda_(ilambda), J_(jitter),
135 IMP_LOG_TERSE(
"Covariance1DFunction: constructor" << std::endl);
138 lambda_val_=
Scale(ilambda).get_nuisance();
139 tau_val_=
Scale(tau).get_nuisance();
140 do_jitter = (jitter>IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM);
141 alpha_square_ = (std::abs(alpha-2) <
142 IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM);
146 double tmpt =
Scale(tau_).get_nuisance();
147 double tmpl =
Scale(lambda_).get_nuisance();
148 if ((std::abs(tmpt - tau_val_) >
149 IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM)
150 || (std::abs(tmpl - lambda_val_) >
151 IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM))
162 lambda_val_=
Scale(lambda_).get_nuisance();
163 tau_val_=
Scale(tau_).get_nuisance();
165 << tau_val_ <<
" lambda:=" << lambda_val_
181 Floats ret(1, get_value(x1[0],x2[0]));
187 const unsigned M=xlist.size();
188 Eigen::MatrixXd Mret(M,M);
189 for (
unsigned i=0; i<M; i++)
191 for (
unsigned j=i; j<M; j++)
194 "expecting a 1-D vector");
196 "expecting a 1-D vector");
197 double x1 = xlist[i][0];
198 double x2 = xlist[j][0];
199 double ret = get_value(x1,x2);
201 if (i != j) Mret(j,i) = ret;
209 Eigen::MatrixXd mat((*
this)(xlist));
211 for (
unsigned i=0; i<xlist.size(); i++)
212 for (
unsigned j=0; j<xlist.size(); j++)
213 ret.push_back(
Floats(1,mat(i,j)));
222 double val = get_value(x1[0],x2[0]);
223 double tauderiv = 2./tau_val_ * val;
225 "tau derivative is nan.");
226 Scale(tau_).add_to_nuisance_derivative(tauderiv, accum);
231 std::pow((std::abs(x1[0]-x2[0])/lambda_val_),alpha_)
234 "lambda derivative is nan.");
235 Scale(lambda_).add_to_nuisance_derivative(lambdaderiv, accum);
245 "tau derivative is nan.");
246 Scale(tau_).add_to_nuisance_derivative(value, accum);
250 "lambda derivative is nan.");
251 Scale(lambda_).add_to_nuisance_derivative(value, accum);
254 IMP_THROW(
"Invalid particle number", ModelException);
259 unsigned particle_no,
265 unsigned N=xlist.size();
266 Eigen::MatrixXd ret(N,N);
273 diag = get_value(xlist[0][0],xlist[0][0]);
287 "derivative matrix is nan on the diagonal.");
288 for (
unsigned i=0; i<N; i++) ret(i,i) = diag;
290 bool initial_loop=
true;
291 double abs_cutoff = cutoff_*diag;
293 for (
unsigned i=0; i<N; i++)
295 for (
unsigned j=i+1; j<N; j++)
297 double x1(xlist[i][0]), x2(xlist[j][0]);
299 double dist(std::abs(x1-x2));
303 if (initial_loop || dist <= dmax)
310 val = get_value(xlist[i][0],xlist[j][0]);
317 if (dist<IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM) {
320 val = get_value(xlist[i][0],xlist[j][0]);
323 (dist/lambda_val_), alpha_)
334 if (std::abs(val) <= abs_cutoff)
338 initial_loop =
false;
340 }
else if (dist < dmax)
349 "derivative matrix is nan at position("
350 << i <<
"," << j <<
").");
359 unsigned particle_no,
364 for (
int i=0; i<mat.rows(); i++)
367 for (
int j=0; j<mat.cols(); j++)
368 line.push_back(mat(i,j));
375 unsigned particle_a,
unsigned particle_b,
378 unsigned N(xlist.size());
379 Eigen::MatrixXd ret(N,N);
381 IMP_THROW(
"Invalid particle 1 number", ModelException);
383 IMP_THROW(
"Invalid particle 2 number", ModelException);
385 if (particle_a == 0 && particle_b == 0)
387 for (
unsigned i=0; i<N; i++)
389 for (
unsigned j=i; j<N; j++)
391 double dist = std::abs(xlist[i][0]-xlist[j][0]);
392 double exponent = std::pow( dist/lambda_val_ , alpha_);
393 double expterm = std::exp(-0.5*exponent);
394 ret(i,j) = 2*expterm;
395 if (i!=j) ret(j,i) = ret(i,j);
398 }
else if (particle_a == 1 && particle_b == 1) {
399 for (
unsigned i=0; i<N; i++)
401 for (
unsigned j=i; j<N; j++)
403 double dist = std::abs(xlist[i][0]-xlist[j][0]);
404 double exponent = std::pow( dist/lambda_val_ , alpha_);
405 double expterm = std::exp(-0.5*exponent);
406 ret(i,j) = tau_val_*tau_val_*expterm
407 *exponent/(lambda_val_*lambda_val_)*alpha_/2
408 * (alpha_/2 * exponent - (alpha_+1));
409 if (i!=j) ret(j,i) = ret(i,j);
413 for (
unsigned i=0; i<N; i++)
415 for (
unsigned j=i; j<N; j++)
417 double dist = std::abs(xlist[i][0]-xlist[j][0]);
418 double exponent = std::pow( dist/lambda_val_ , alpha_);
419 double expterm = std::exp(-0.5*exponent);
420 ret(i,j) = tau_val_ * alpha_ * expterm / lambda_val_
422 if (i!=j) ret(j,i) = ret(i,j);
430 unsigned particle_a,
unsigned particle_b,
434 particle_a, particle_b, xlist));
436 for (
int i=0; i<mat.rows(); i++)
439 for (
int j=0; j<mat.cols(); j++)
440 line.push_back(mat(i,j));
447 unsigned get_ndims_x2()
const {
return 1;}
457 return Scale(tau_).get_nuisance_is_optimized();
459 return Scale(lambda_).get_nuisance_is_optimized();
461 IMP_THROW(
"Invalid particle number", ModelException);
468 if (
Scale(tau_).get_nuisance_is_optimized()) count++;
469 if (
Scale(lambda_).get_nuisance_is_optimized()) count++;
477 ret.push_back(lambda_);
489 out <<
"covariance function with alpha = "
490 << alpha_ << std::endl, {});
495 inline double get_value(
double x1,
double x2)
const
497 double dist = std::abs(x1-x2);
498 double ret = dist /lambda_val_ ;
503 ret = std::pow(ret, alpha_);
505 ret = IMP::square(tau_val_) *std::exp(-0.5*ret);
506 if (do_jitter && dist<IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM)
511 "function value is nan. tau = "
512 << tau_val_ <<
" lambda = " << lambda_val_
513 <<
" q1 = " << x1 <<
" q2 = " << x2);
519 Pointer<Particle> tau_,lambda_;
520 double tau_val_,lambda_val_,J_,cutoff_,alpha_square_;