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);
147 double tmpt =
Scale(tau_).get_nuisance();
148 double tmpl =
Scale(lambda_).get_nuisance();
152 if ((std::abs(tmpt - tau_val_) >
153 IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM)
154 || (std::abs(tmpl - lambda_val_) >
155 IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM))
166 lambda_val_=
Scale(lambda_).get_nuisance();
167 tau_val_=
Scale(tau_).get_nuisance();
169 << tau_val_ <<
" lambda:=" << lambda_val_
185 Floats ret(1, get_value(x1[0],x2[0]));
191 const unsigned M=xlist.size();
192 Eigen::MatrixXd Mret(M,M);
193 for (
unsigned i=0; i<M; i++)
195 for (
unsigned j=i; j<M; j++)
198 "expecting a 1-D vector");
200 "expecting a 1-D vector");
201 double x1 = xlist[i][0];
202 double x2 = xlist[j][0];
203 double ret = get_value(x1,x2);
205 if (i != j) Mret(j,i) = ret;
213 Eigen::MatrixXd mat((*
this)(xlist));
215 for (
unsigned i=0; i<xlist.size(); i++)
216 for (
unsigned j=0; j<xlist.size(); j++)
217 ret.push_back(
Floats(1,mat(i,j)));
226 double val = get_value(x1[0],x2[0]);
227 double tauderiv = 2./tau_val_ * val;
229 "tau derivative is nan.");
230 Scale(tau_).add_to_nuisance_derivative(tauderiv, accum);
235 std::pow((std::abs(x1[0]-x2[0])/lambda_val_),alpha_)
238 "lambda derivative is nan.");
239 Scale(lambda_).add_to_nuisance_derivative(lambdaderiv, accum);
249 "tau derivative is nan.");
250 Scale(tau_).add_to_nuisance_derivative(value, accum);
254 "lambda derivative is nan.");
255 Scale(lambda_).add_to_nuisance_derivative(value, accum);
258 IMP_THROW(
"Invalid particle number", ModelException);
263 unsigned particle_no,
269 unsigned N=xlist.size();
270 Eigen::MatrixXd ret(N,N);
277 diag = get_value(xlist[0][0],xlist[0][0]);
291 "derivative matrix is nan on the diagonal.");
292 for (
unsigned i=0; i<N; i++) ret(i,i) = diag;
294 bool initial_loop=
true;
295 double abs_cutoff = cutoff_*diag;
297 for (
unsigned i=0; i<N; i++)
299 for (
unsigned j=i+1; j<N; j++)
301 double x1(xlist[i][0]), x2(xlist[j][0]);
303 double dist(std::abs(x1-x2));
307 if (initial_loop || dist <= dmax)
314 val = get_value(xlist[i][0],xlist[j][0]);
321 if (dist<IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM) {
324 val = get_value(xlist[i][0],xlist[j][0]);
327 (dist/lambda_val_), alpha_)
338 if (std::abs(val) <= abs_cutoff)
342 initial_loop =
false;
344 }
else if (dist < dmax)
353 "derivative matrix is nan at position("
354 << i <<
"," << j <<
").");
363 unsigned particle_no,
368 for (
int i=0; i<mat.rows(); i++)
371 for (
int j=0; j<mat.cols(); j++)
372 line.push_back(mat(i,j));
379 unsigned particle_a,
unsigned particle_b,
382 unsigned N(xlist.size());
383 Eigen::MatrixXd ret(N,N);
385 IMP_THROW(
"Invalid particle 1 number", ModelException);
387 IMP_THROW(
"Invalid particle 2 number", ModelException);
389 if (particle_a == 0 && particle_b == 0)
391 for (
unsigned i=0; i<N; i++)
393 for (
unsigned j=i; j<N; j++)
395 double dist = std::abs(xlist[i][0]-xlist[j][0]);
396 double exponent = std::pow( dist/lambda_val_ , alpha_);
397 double expterm = std::exp(-0.5*exponent);
398 ret(i,j) = 2*expterm;
399 if (i!=j) ret(j,i) = ret(i,j);
402 }
else if (particle_a == 1 && particle_b == 1) {
403 for (
unsigned i=0; i<N; i++)
405 for (
unsigned j=i; j<N; j++)
407 double dist = std::abs(xlist[i][0]-xlist[j][0]);
408 double exponent = std::pow( dist/lambda_val_ , alpha_);
409 double expterm = std::exp(-0.5*exponent);
410 ret(i,j) = tau_val_*tau_val_*expterm
411 *exponent/(lambda_val_*lambda_val_)*alpha_/2
412 * (alpha_/2 * exponent - (alpha_+1));
413 if (i!=j) ret(j,i) = ret(i,j);
417 for (
unsigned i=0; i<N; i++)
419 for (
unsigned j=i; j<N; j++)
421 double dist = std::abs(xlist[i][0]-xlist[j][0]);
422 double exponent = std::pow( dist/lambda_val_ , alpha_);
423 double expterm = std::exp(-0.5*exponent);
424 ret(i,j) = tau_val_ * alpha_ * expterm / lambda_val_
426 if (i!=j) ret(j,i) = ret(i,j);
434 unsigned particle_a,
unsigned particle_b,
438 particle_a, particle_b, xlist));
440 for (
int i=0; i<mat.rows(); i++)
443 for (
int j=0; j<mat.cols(); j++)
444 line.push_back(mat(i,j));
451 unsigned get_ndims_x2()
const {
return 1;}
461 return Scale(tau_).get_nuisance_is_optimized();
463 return Scale(lambda_).get_nuisance_is_optimized();
465 IMP_THROW(
"Invalid particle number", ModelException);
472 if (
Scale(tau_).get_nuisance_is_optimized()) count++;
473 if (
Scale(lambda_).get_nuisance_is_optimized()) count++;
481 ret.push_back(lambda_);
500 inline double get_value(
double x1,
double x2)
const
502 double dist = std::abs(x1-x2);
503 double ret = dist /lambda_val_ ;
508 ret = std::pow(ret, alpha_);
510 ret = IMP::square(tau_val_) *std::exp(-0.5*ret);
511 if (do_jitter && dist<IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM)
513 ret +=IMP::square(tau_val_) * J_;
516 "function value is nan. tau = "
517 << tau_val_ <<
" lambda = " << lambda_val_
518 <<
" q1 = " << x1 <<
" q2 = " << x2);
524 base::Pointer<kernel::Particle> tau_,lambda_;
525 double tau_val_,lambda_val_,J_,cutoff_,alpha_square_;
Class for adding derivatives from restraints to the model.
bool has_changed() const
return true if internal parameters have changed.
unsigned get_number_of_optimized_particles() const
returns the number of particles that are optimized
A decorator for switching parameters particles.
void update()
update internal parameters
unsigned get_ndims_y() const
returns the number of output dimensions
A decorator for scale parameters particles.
#define IMP_REF_COUNTED_DESTRUCTOR(Name)
Ref counted objects should have private destructors.
ParticlesTemp get_input_particles(const ModelObjectsTemp &mos)
A decorator for nuisance parameters particles.
Add scale parameter to particle.
static Scale decorate_particle(::IMP::kernel::Particle *p)
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Eigen::MatrixXd operator()(const IMP::FloatsList &xlist) const
evaluate the function at a list of points
#define IMP_LOG_TERSE(expr)
ContainersTemp get_input_containers(const ModelObjectsTemp &mos)
void add_to_particle_derivative(unsigned particle_no, double value, DerivativeAccumulator &accum) const
update derivatives of particles
virtual Eigen::MatrixXd get_second_derivative_matrix(unsigned particle_a, unsigned particle_b, const FloatsList &xlist) const =0
return second derivative matrix
unsigned get_ndims_x1() const
returns the number of input dimensions
virtual void update()=0
update internal parameters
Eigen::MatrixXd get_derivative_matrix(unsigned particle_no, const FloatsList &xlist) const
return derivative matrix
#define IMP_INTERNAL_CHECK(expr, message)
An assertion to check for internal errors in IMP. An IMP::ErrorException will be thrown.
IMP::base::Vector< IMP::base::WeakPointer< Container > > ContainersTemp
void add_to_derivatives(const Floats &x1, const Floats &x2, DerivativeAccumulator &accum) const
update derivatives of particles
FloatsList operator()(const IMP::FloatsList &xlist, bool) const
used for testing only
#define IMP_IF_CHECK(level)
Execute the code block if a certain level checks are on.
Base class for functions of two variables.
#define IMP_OBJECT_METHODS(Name)
Define the basic things needed by any Object.
Eigen::MatrixXd get_second_derivative_matrix(unsigned particle_a, unsigned particle_b, const FloatsList &xlist) const
return second derivative matrix
bool get_particle_is_optimized(unsigned particle_no) const
returns true if the particle whose index is provided is optimized
Class to handle individual model particles.
Common base class for heavy weight IMP objects.
Classes to handle individual model particles.
bool isnan(const T &a)
Return true if a number is NaN.
unsigned get_number_of_particles() const
returns the number of particles that this function uses
#define IMP_THROW(message, exception_name)
Throw an exception with a message.
Floats operator()(const Floats &x1, const Floats &x2) const
evaluate the function at a certain point
A shared base class to help in debugging and things.
kernel::ParticlesTemp get_input_particles() const
particle manipulation
#define IMP_LOG_VERBOSE(expr)
virtual Eigen::MatrixXd get_derivative_matrix(unsigned particle_no, const FloatsList &xlist) const =0
return derivative matrix