8 #ifndef IMPISD_BIVARIATE_FUNCTIONS_H
9 #define IMPISD_BIVARIATE_FUNCTIONS_H
11 #include <IMP/isd/isd_config.h>
17 #include <IMP/algebra/eigen3/Eigen/Dense>
19 #define IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM 1e-7
21 IMPISD_BEGIN_NAMESPACE
40 bool stupid)
const = 0;
43 virtual bool has_changed()
const = 0;
46 virtual void update() = 0;
49 virtual void add_to_derivatives(
const Floats& x1,
const Floats& x2,
57 virtual void add_to_particle_derivative(
unsigned particle_no,
double value,
65 virtual IMP_Eigen::MatrixXd get_derivative_matrix(
66 unsigned particle_no,
const FloatsList& xlist)
const = 0;
69 virtual FloatsList get_derivative_matrix(
unsigned particle_no,
71 bool stupid)
const = 0;
74 virtual IMP_Eigen::MatrixXd get_second_derivative_matrix(
75 unsigned particle_a,
unsigned particle_b,
79 virtual FloatsList get_second_derivative_matrix(
unsigned particle_a,
82 bool stupid)
const = 0;
85 virtual unsigned get_ndims_x1()
const = 0;
86 virtual unsigned get_ndims_x2()
const = 0;
89 virtual unsigned get_ndims_y()
const = 0;
92 virtual unsigned get_number_of_particles()
const = 0;
95 virtual bool get_particle_is_optimized(
unsigned particle_no)
const = 0;
98 virtual unsigned get_number_of_optimized_particles()
const = 0;
122 double alpha = 2.0,
double jitter = 0.0,
123 double cutoff = 1e-7)
130 IMP_LOG_TERSE(
"Covariance1DFunction: constructor" << std::endl);
133 lambda_val_ =
Scale(ilambda).get_nuisance();
134 tau_val_ =
Scale(tau).get_nuisance();
135 do_jitter = (jitter > IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM);
136 alpha_square_ = (std::abs(alpha - 2) < IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM);
141 double tmpt =
Scale(tau_).get_nuisance();
142 double tmpl =
Scale(lambda_).get_nuisance();
146 if ((std::abs(tmpt - tau_val_) > IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM) ||
147 (std::abs(tmpl - lambda_val_) > IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM)) {
157 lambda_val_ =
Scale(lambda_).get_nuisance();
158 tau_val_ =
Scale(tau_).get_nuisance();
160 << tau_val_ <<
" lambda:=" << lambda_val_ << std::endl);
171 Floats ret(1, get_value(x1[0], x2[0]));
176 const unsigned M = xlist.size();
177 IMP_Eigen::MatrixXd Mret(M, M);
178 for (
unsigned i = 0; i < M; i++) {
179 for (
unsigned j = i; j < M; j++) {
182 double x1 = xlist[i][0];
183 double x2 = xlist[j][0];
184 double ret = get_value(x1, x2);
186 if (i != j) Mret(j, i) = ret;
193 IMP_Eigen::MatrixXd mat((*
this)(xlist));
195 for (
unsigned i = 0; i < xlist.size(); i++)
196 for (
unsigned j = 0; j < xlist.size(); j++)
197 ret.push_back(
Floats(1, mat(i, j)));
204 double val = get_value(x1[0], x2[0]);
205 double tauderiv = 2. / tau_val_ * val;
207 Scale(tau_).add_to_nuisance_derivative(tauderiv, accum);
212 (alpha_ * std::pow((std::abs(x1[0] - x2[0]) / lambda_val_), alpha_) /
215 Scale(lambda_).add_to_nuisance_derivative(lambdaderiv, accum);
220 switch (particle_no) {
223 Scale(tau_).add_to_nuisance_derivative(value, accum);
227 Scale(lambda_).add_to_nuisance_derivative(value, accum);
230 IMP_THROW(
"Invalid particle number", ModelException);
239 unsigned N = xlist.size();
240 IMP_Eigen::MatrixXd ret(N, N);
242 switch (particle_no) {
246 diag = get_value(xlist[0][0], xlist[0][0]);
247 diag *= 2. / tau_val_;
256 IMP_THROW(
"Invalid particle number", ModelException);
259 "derivative matrix is nan on the diagonal.");
260 for (
unsigned i = 0; i < N; i++) ret(i, i) = diag;
262 bool initial_loop =
true;
263 double abs_cutoff = cutoff_ * diag;
265 for (
unsigned i = 0; i < N; i++) {
266 for (
unsigned j = i + 1; j < N; j++) {
267 double x1(xlist[i][0]), x2(xlist[j][0]);
269 double dist(std::abs(x1 - x2));
273 if (initial_loop || dist <= dmax) {
274 switch (particle_no) {
278 val = get_value(xlist[i][0], xlist[j][0]);
279 val *= 2. / tau_val_;
285 if (dist < IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM) {
288 val = get_value(xlist[i][0], xlist[j][0]);
289 val *= alpha_ * std::pow((dist / lambda_val_), alpha_) /
294 IMP_THROW(
"Invalid particle number", ModelException);
299 if (std::abs(val) <= abs_cutoff) {
301 initial_loop =
false;
303 }
else if (dist < dmax) {
311 "derivative matrix is nan at position("
312 << i <<
"," << j <<
").");
324 for (
int i = 0; i < mat.rows(); i++) {
326 for (
int j = 0; j < mat.cols(); j++) line.push_back(mat(i, j));
333 unsigned particle_a,
unsigned particle_b,
const FloatsList& xlist)
const {
334 unsigned N(xlist.size());
335 IMP_Eigen::MatrixXd ret(N, N);
336 if (particle_a > 1)
IMP_THROW(
"Invalid particle 1 number", ModelException);
337 if (particle_b > 1)
IMP_THROW(
"Invalid particle 2 number", ModelException);
339 if (particle_a == 0 && particle_b == 0) {
340 for (
unsigned i = 0; i < N; i++) {
341 for (
unsigned j = i; j < N; j++) {
342 double dist = std::abs(xlist[i][0] - xlist[j][0]);
343 double exponent = std::pow(dist / lambda_val_, alpha_);
344 double expterm = std::exp(-0.5 * exponent);
345 ret(i, j) = 2 * expterm;
346 if (i != j) ret(j, i) = ret(i, j);
349 }
else if (particle_a == 1 && particle_b == 1) {
350 for (
unsigned i = 0; i < N; i++) {
351 for (
unsigned j = i; j < N; j++) {
352 double dist = std::abs(xlist[i][0] - xlist[j][0]);
353 double exponent = std::pow(dist / lambda_val_, alpha_);
354 double expterm = std::exp(-0.5 * exponent);
355 ret(i, j) = tau_val_ * tau_val_ * expterm * exponent /
356 (lambda_val_ * lambda_val_) * alpha_ / 2 *
357 (alpha_ / 2 * exponent - (alpha_ + 1));
358 if (i != j) ret(j, i) = ret(i, j);
362 for (
unsigned i = 0; i < N; i++) {
363 for (
unsigned j = i; j < N; j++) {
364 double dist = std::abs(xlist[i][0] - xlist[j][0]);
365 double exponent = std::pow(dist / lambda_val_, alpha_);
366 double expterm = std::exp(-0.5 * exponent);
367 ret(i, j) = tau_val_ * alpha_ * expterm / lambda_val_ * exponent;
368 if (i != j) ret(j, i) = ret(i, j);
378 IMP_Eigen::MatrixXd mat(
381 for (
int i = 0; i < mat.rows(); i++) {
383 for (
int j = 0; j < mat.cols(); j++) line.push_back(mat(i, j));
390 unsigned get_ndims_x2()
const {
return 1; }
396 switch (particle_no) {
398 return Scale(tau_).get_nuisance_is_optimized();
400 return Scale(lambda_).get_nuisance_is_optimized();
402 IMP_THROW(
"Invalid particle number", ModelException);
408 if (
Scale(tau_).get_nuisance_is_optimized()) count++;
409 if (
Scale(lambda_).get_nuisance_is_optimized()) count++;
416 ret.push_back(lambda_);
431 inline double get_value(
double x1,
double x2)
const {
432 double dist = std::abs(x1 - x2);
433 double ret = dist / lambda_val_;
437 ret = std::pow(ret, alpha_);
439 ret = IMP::square(tau_val_) * std::exp(-0.5 * ret);
440 if (do_jitter && dist < IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM) {
441 ret += IMP::square(tau_val_) * J_;
444 "function value is nan. tau = "
445 << tau_val_ <<
" lambda = " << lambda_val_
446 <<
" q1 = " << x1 <<
" q2 = " << x2);
452 base::Pointer<kernel::Particle> tau_, lambda_;
453 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.
IMP_Eigen::MatrixXd get_derivative_matrix(unsigned particle_no, const FloatsList &xlist) const
return derivative matrix
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.
virtual IMP_Eigen::MatrixXd get_derivative_matrix(unsigned particle_no, const FloatsList &xlist) const =0
return derivative matrix
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.
#define IMP_LOG_TERSE(expr)
IMP_Eigen::MatrixXd get_second_derivative_matrix(unsigned particle_a, unsigned particle_b, const FloatsList &xlist) const
return second derivative matrix
ContainersTemp get_input_containers(const ModelObjectsTemp &mos)
void add_to_particle_derivative(unsigned particle_no, double value, DerivativeAccumulator &accum) const
update derivatives of particles
unsigned get_ndims_x1() const
returns the number of input dimensions
Object(std::string name)
Construct an object with the given name.
virtual void update()=0
update internal parameters
#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
IMP_Eigen::MatrixXd operator()(const IMP::FloatsList &xlist) const
evaluate the function at a list of points
#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.
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
virtual IMP_Eigen::MatrixXd get_second_derivative_matrix(unsigned particle_a, unsigned particle_b, const FloatsList &xlist) const =0
return second derivative matrix
#define IMP_LOG_VERBOSE(expr)