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);
131 lambda_val_ =
Scale(ilambda).get_nuisance();
132 tau_val_ =
Scale(tau).get_nuisance();
133 do_jitter = (jitter > IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM);
134 alpha_square_ = (std::abs(alpha - 2) < IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM);
139 double tmpt =
Scale(tau_).get_nuisance();
140 double tmpl =
Scale(lambda_).get_nuisance();
144 if ((std::abs(tmpt - tau_val_) > IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM) ||
145 (std::abs(tmpl - lambda_val_) > IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM)) {
155 lambda_val_ =
Scale(lambda_).get_nuisance();
156 tau_val_ =
Scale(tau_).get_nuisance();
158 << tau_val_ <<
" lambda:=" << lambda_val_ << std::endl);
169 Floats ret(1, get_value(x1[0], x2[0]));
174 const unsigned M = xlist.size();
175 IMP_Eigen::MatrixXd Mret(M, M);
176 for (
unsigned i = 0; i < M; i++) {
177 for (
unsigned j = i; j < M; j++) {
180 double x1 = xlist[i][0];
181 double x2 = xlist[j][0];
182 double ret = get_value(x1, x2);
184 if (i != j) Mret(j, i) = ret;
191 IMP_Eigen::MatrixXd mat((*
this)(xlist));
193 for (
unsigned i = 0; i < xlist.size(); i++)
194 for (
unsigned j = 0; j < xlist.size(); j++)
195 ret.push_back(
Floats(1, mat(i, j)));
202 double val = get_value(x1[0], x2[0]);
203 double tauderiv = 2. / tau_val_ * val;
205 Scale(tau_).add_to_nuisance_derivative(tauderiv, accum);
210 (alpha_ * std::pow((std::abs(x1[0] - x2[0]) / lambda_val_), alpha_) /
213 Scale(lambda_).add_to_nuisance_derivative(lambdaderiv, accum);
218 switch (particle_no) {
221 Scale(tau_).add_to_nuisance_derivative(value, accum);
225 Scale(lambda_).add_to_nuisance_derivative(value, accum);
228 IMP_THROW(
"Invalid particle number", ModelException);
237 unsigned N = xlist.size();
238 IMP_Eigen::MatrixXd ret(N, N);
240 switch (particle_no) {
244 diag = get_value(xlist[0][0], xlist[0][0]);
245 diag *= 2. / tau_val_;
254 IMP_THROW(
"Invalid particle number", ModelException);
257 "derivative matrix is nan on the diagonal.");
258 for (
unsigned i = 0; i < N; i++) ret(i, i) = diag;
260 bool initial_loop =
true;
261 double abs_cutoff = cutoff_ * diag;
263 for (
unsigned i = 0; i < N; i++) {
264 for (
unsigned j = i + 1; j < N; j++) {
265 double x1(xlist[i][0]), x2(xlist[j][0]);
267 double dist(std::abs(x1 - x2));
271 if (initial_loop || dist <= dmax) {
272 switch (particle_no) {
276 val = get_value(xlist[i][0], xlist[j][0]);
277 val *= 2. / tau_val_;
283 if (dist < IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM) {
286 val = get_value(xlist[i][0], xlist[j][0]);
287 val *= alpha_ * std::pow((dist / lambda_val_), alpha_) /
292 IMP_THROW(
"Invalid particle number", ModelException);
297 if (std::abs(val) <= abs_cutoff) {
299 initial_loop =
false;
301 }
else if (dist < dmax) {
309 "derivative matrix is nan at position("
310 << i <<
"," << j <<
").");
322 for (
int i = 0; i < mat.rows(); i++) {
324 for (
int j = 0; j < mat.cols(); j++) line.push_back(mat(i, j));
331 unsigned particle_a,
unsigned particle_b,
const FloatsList& xlist)
const {
332 unsigned N(xlist.size());
333 IMP_Eigen::MatrixXd ret(N, N);
334 if (particle_a > 1)
IMP_THROW(
"Invalid particle 1 number", ModelException);
335 if (particle_b > 1)
IMP_THROW(
"Invalid particle 2 number", ModelException);
337 if (particle_a == 0 && particle_b == 0) {
338 for (
unsigned i = 0; i < N; i++) {
339 for (
unsigned j = i; j < N; j++) {
340 double dist = std::abs(xlist[i][0] - xlist[j][0]);
341 double exponent = std::pow(dist / lambda_val_, alpha_);
342 double expterm = std::exp(-0.5 * exponent);
343 ret(i, j) = 2 * expterm;
344 if (i != j) ret(j, i) = ret(i, j);
347 }
else if (particle_a == 1 && particle_b == 1) {
348 for (
unsigned i = 0; i < N; i++) {
349 for (
unsigned j = i; j < N; j++) {
350 double dist = std::abs(xlist[i][0] - xlist[j][0]);
351 double exponent = std::pow(dist / lambda_val_, alpha_);
352 double expterm = std::exp(-0.5 * exponent);
353 ret(i, j) = tau_val_ * tau_val_ * expterm * exponent /
354 (lambda_val_ * lambda_val_) * alpha_ / 2 *
355 (alpha_ / 2 * exponent - (alpha_ + 1));
356 if (i != j) ret(j, i) = ret(i, j);
360 for (
unsigned i = 0; i < N; i++) {
361 for (
unsigned j = i; j < N; j++) {
362 double dist = std::abs(xlist[i][0] - xlist[j][0]);
363 double exponent = std::pow(dist / lambda_val_, alpha_);
364 double expterm = std::exp(-0.5 * exponent);
365 ret(i, j) = tau_val_ * alpha_ * expterm / lambda_val_ * exponent;
366 if (i != j) ret(j, i) = ret(i, j);
376 IMP_Eigen::MatrixXd mat(
379 for (
int i = 0; i < mat.rows(); i++) {
381 for (
int j = 0; j < mat.cols(); j++) line.push_back(mat(i, j));
388 unsigned get_ndims_x2()
const {
return 1; }
394 switch (particle_no) {
396 return Scale(tau_).get_nuisance_is_optimized();
398 return Scale(lambda_).get_nuisance_is_optimized();
400 IMP_THROW(
"Invalid particle number", ModelException);
406 if (
Scale(tau_).get_nuisance_is_optimized()) count++;
407 if (
Scale(lambda_).get_nuisance_is_optimized()) count++;
414 ret.push_back(lambda_);
429 inline double get_value(
double x1,
double x2)
const {
430 double dist = std::abs(x1 - x2);
431 double ret = dist / lambda_val_;
435 ret = std::pow(ret, alpha_);
437 ret = IMP::square(tau_val_) * std::exp(-0.5 * ret);
438 if (do_jitter && dist < IMP_ISD_BIVARIATE_FUNCTIONS_MINIMUM) {
439 ret += IMP::square(tau_val_) * J_;
442 "function value is nan. tau = "
443 << tau_val_ <<
" lambda = " << lambda_val_
444 <<
" q1 = " << x1 <<
" q2 = " << x2);
450 base::Pointer<kernel::Particle> tau_, lambda_;
451 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
#define IMP_OBJECT_METHODS(Name)
Define the basic things needed by any Object.
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.
ParticlesTemp get_input_particles(const ModelObjectsTemp &mos)
Return all the input particles for a given ModelObject.
A decorator for nuisance parameters particles.
Add scale parameter to particle.
#define IMP_LOG_VERBOSE(expr)
#define IMP_REF_COUNTED_DESTRUCTOR(Name)
Ref counted objects should have private destructors.
virtual IMP_Eigen::MatrixXd get_derivative_matrix(unsigned particle_no, const FloatsList &xlist) const =0
return derivative matrix
#define IMP_LOG_TERSE(expr)
#define IMP_INTERNAL_CHECK(expr, message)
An assertion to check for internal errors in IMP. An IMP::ErrorException will be thrown.
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)
Return all the input particles for a given ModelObject.
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
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
Base class for functions of two variables.
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. (Note that implementation of inline functions in in int...
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.
A shared base class to help in debugging and things.
Floats operator()(const Floats &x1, const Floats &x2) const
evaluate the function at a certain point
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
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