12.21.11. - Optimizing
In version 4 of the C-PLOT package, there is a second variation on the fitting algorithm. This second variation is only relevant when you do not provide analytic derivatives for all the fitted parameters. For certain fitting functions you may be able to make your calculations more efficient with this new variation (at the expense of much more memory usage). Both variations produce the same fit results.
The differences relate to the order in which the
model()
function
is called.
While doing the fit iterations in the original method,
for each data point in turn, the
model()
equation is called
once with the current parameter set and then an extra time for each
parameter that did not have analytic derivatives provided.
The new method always calls
model()
for all the data points
each time there is a change of parameter values.
During a fit iteration,
model()
will be called for each data point in turn with the
current parameter set.
Then, for each fitted parameter that does not
have analytic derivatives provided,
model()
will be called for
each data point in turn with the varied value of the fitted parameter.
For users who need to do lengthy calculations that change for each
parameter set but are the same for each data point, this new method
makes it possible to speed the fitting process.
The only drawback to the new method is that it allocates additional memory equal to
MAXPTS * MAXPAR * sizeof(double)
.
The default behavior is to use the old calling sequence. To use the new calling sequence, add the line:
#define VECTORIZE 1to your prototype before p_fitsize.h is included.
In order to take advantage of the new variation, you need to know at what point in the fitting algorithm the
model()
function
is being called.
That information can determined from the arguments
to
model()
. The
model()
function is called with four integer arguments:
model(deriv_flag, m_mode, par_num, point_num)The argument
deriv_flag
has already been described.
It is set
if
model()
must calculate the analytic derivatives during this
call.
The argument
m_mode
is set to one of the constants defined in
p_fitsize.h
to indicate from where in the code
model()
is being called.
These constants are:
/* Called from ... */ #define FIT_VALUE 2 /* ... "fi" during fitting */ #define FIT_PARTIAL 3 /* ... "fi" to calculate partial */ #define FIT_SUMSQ 4 /* ... "fc" or "ch" */ #define CALC_DATA 5 /* ... "sa" */ #define MAKE_RESIDUALS 6 /* ... "mr" */ #define MAKE_DATA 7 /* ... "md" */The argument
par_num
is normally -1.
When
model()
is called with
m_mode
equal to
FIT_PARTIAL
, the parameter
described by
fpar[par_num]
has been incremented (for calculating
the partial derivative) from its value when
model()
was last
called with
mode
equal to
FIT_VALUE
. The argument
point_num
is the index into the
f_data
array.
If the fit range does not include all the data,
point_num
will
not necessarily have a value of zero at any time.
Use code similar
to the following to check for the first point:
model(deriv_flag, m_mode, par_num, point_num) { static int prev_point = 32000; /* a large number */ int first; if (point_num < prev_point) first = 1; /* first in loop */ else first = 0; /* not so */ prev_point = point_num; ... }Note that if you can't provide analytic derivatives, you could still improve the performance of the computations by calculating the partial derivatives yourself. When
deriv_flag
is set, find the value
of the fitting function at
y0 = f(a[j] = v)and at
y1 = f(a[j] = v + del)and set the parameter's derivative to
(y1 - y0) / del
.
By calculating
the derivatives for all the parameters within
model()
, you can
avoid redundant computations and speed up the fitting substantially.