myfitter is hosted by Hepforge, IPPP Durham

### 2.1 The Model Base Class

The Model class provides the following functionality:

Constructors
The Model provides a copy constructor and an assignment operator, but no default constructor. The default constructors of derived classes should call the constructor
          Model(int npar, int nobs)


which initialises a model with npar parameters and nobs observables. The values of the parameters and observables as well as their scales and upper and lower limits (see below) are initialised to NaN. This way, if you forget to initialise a parameter correctly, you will probably notice it. Derived classes should implement a default constructor which calls Model(int, int) to initialise themselves.

Parameters
An object of type Model stores the “current” values of the parameters of the model. The number of parameters is fixed in the constructor and returned by the function nparameters(). Parameter values can be read out and set with the methods
          double parameter(int ipar)
const ParameterVector& parameters()
void parameter(int ipar, double value)


where the parameter index ipar runs from zero to nparameters()-1. The type ParameterVector is a synonym for boost::numeric::ublas::vector<double>. You can find more information about uBLAS vectors in the documentation of the Boost uBLAS library.

Observables
A Model object stores the “current” values of the observables. The number of observables is fixed in the constructor and returned by the function nobservables(). The values of the observables can be accessed with the methods
          double observable(int iobs)
const ObservableVector& observables()


where the index iobs runs from zero to nobservables()-1. The type ObservableVector is another synonym for boost::numeric::ublas::vector<double>.

Scales of Parameters
You can read and set the scale of each parameter with
          double scale(int ipar)
void scale(int ipar, double value)


The scale of a parameter should be your best guess for the size of fluctuations in that parameter, which are allowed when the model is fitted to data. You can also set the value and scale of a parameter in one go with

          void parameter(int ipar, double value, double scale)


Bounded Parameters
You can set the ranges in which parameters are allowed to float with
          void upper_limit(int ipar, double value)
void lower_limit(int ipar, double value)
void set_range(int ipar, double upper_lim, double lower_lim)


and obtain the current upper and lower limit of a parameter with

          double upper_limit(int ipar)
double lower_limit(int ipar)


Initially, all parameters are unbounded. In this case, the two functions above return NaN. Conversely, you can remove an upper or lower limit on a parameter by setting the limit to NaN. To do this, you should use the static method

          static double Model::nan()


which just returns NaN. To check if a certain parameter currently has an upper or lower limit you can use the methods

          bool has_upper_limit(int ipar)
bool has_lower_limit(int ipar)


You can set the value, scale, lower and upper limit of a parameter in one go with

          void parameter(int ipar, double value, double scale,
double lower_limit, double lower_limit)


Fixing Parameters
You can fix a parameter to its current value or release it with the methods
          void fix(int ipar)
void release(int ipar)


A fixed parameter does not float in a fit. To check if a parameter is currently fixed, use the method

          bool fixed(int ipar)


Calculating Derivatives
The derivatives at the current point in parameter space can be calculated with
          virtual int calc_deriv()


which returns zero if the calculation was successful and a non-zero value otherwise. The derivative matrix can be accessed with the method

          const Matrix& derivatives()


The type Matrix is a synonym for boost::numeric::ublas::matrix<double>. You can find more information about uBLAS matrices in the documentation of the Boost uBLAS library. To access the elements of a Matrix object, just call the object with two integer arguments. For the matrix returned by derivatives(), the first index is a parameter index and the second an observable index.

The derivatives are calculated numerically by varying the parameters by small amounts proportional to their scale (as returned by scale(ipar)). The proportionality factor can be read and modified with the methods

          double derivative_epsilon()
void derivative_epsilon(double value)


Derived classes may overload the calc_deriv() method, for example to implement analytical formulae for the derivatives with respect to some parameters. Your own implementation should assign the values of the derivatives to the protected member derivatives_, which is of type Matrix. If you do not want to implement all derivatives yourself the derivatives with respect to a certain parameter ipar can be be calculated numerically with the protected method

          int numerical_derivative_(int ipar)


This method fills the corresponding row of derivatives_ and returns zero on success and a non-zero value on failure. Finally, you can check your own implementation of derivatives with the method

          bool check_derivatives(double rel_prec, double abs_prec)


This method checks if your results for the derivatives agree with the numerical derivatives with a relative precision rel_prec. Any derivatives which are smaller than abs_prec in magnitude are regarded as exactly zero.

The smallrange Flags
You can read and set the smallrange flag for each parameter with the methods
          bool smallrange(int ipar)
void smallrange(int ipar, bool value)


When the smallrange flag is set, the parameter is considered fixed for the purpose of determining the model's hyperplane before a p-value integration (see [arXiv:1207.1446] for details), but floats in any fits performed during the p-value integration. The right combination of smallrange flags can significantly increase the efficiency of p-value integrations. The flag should be set if a parameter is only allowed to vary in a small range or if the dependence of all observables on that parameter is very weak.

Sampling the Parameter Space
You can randomly sample the parameter space and build up a dictionary of parameter values and the corresponding observable values. This dictionary can then be used by the fit functions to find good starting points for minimising the \chi^2. The ranges in which the parameters are scanned can be read with the methods
          double scan_min(int ipar)
double scan_max(int ipar)


and set with

          void scan_min(int ipar, double value)
void scan_max(int ipar, double value)
void scan_range(int ipar, double min_val, double max_val)


If you are lazy you can also set the scan ranges of all parameters at once with

          void set_scan_ranges(double factor)


which sets the scan range of each parameter i to the interval from parameter(i)-factor*scale(i) to parameter(i)+factor*scale(i). To sample the parameter space with n points, call

          void scan(int n)


If you want more sample points in specific part of the parameter space you can change the scan ranges and call scan() again. The old data will be kept. To clear the dictionary, call

          void clear()