LSQFit.h

Classes

LSQFit -- Basic class for the least squares fitting (full description)

class LSQFit

Types

enum ReadyCode

NONREADY = 0
SOLINCREMENT
DERIVLEVEL
MAXITER
NOREDUCTION
SINGULAR
N_ReadyCode

enum ErrorField

NC
Number of condition equations
SUMWEIGHT
Sum weights of condition equations
SUMLL
Sum known terms squared
CHI2
Calculated chi^2
N_ErrorField
Number of error fields

enum StateBit

INVERTED = 1
Inverted matrix present
TRIANGLE = 2*INVERTED,
Triangularised
NONLIN = 2*TRIANGLE,
Non-linear solution Non-linear solution
N_StateBit
Filler for cxx2html Filler for cxx2html

Interface

Public Members
explicit LSQFit(uInt nUnknowns, uInt nConstraints=0)
LSQFit(uInt nUnknowns, const LSQReal &, uInt nConstraints=0)
LSQFit(uInt nUnknowns, const LSQComplex &, uInt nConstraints=0)
LSQFit()
LSQFit(const LSQFit &other)
LSQFit &operator=(const LSQFit &other)
~LSQFit()
Bool invert(uInt &nRank, Bool doSVD=False)
template <class U> void copy(const Double *beg, const Double *end, U &sol, U)
template <class U> void copy(const Double *beg, const Double *end, U &sol, U)
template <class U> void copy(const Double *beg, const Double *end, U *sol, U)
template <class U> void copy(const Double *beg, const Double *end, U *sol, U)
template <class U> void uncopy(Double *beg, const Double *end, U &sol, U)
template <class U> void uncopy(Double *beg, const Double *end, U &sol, U)
template <class U> void uncopy(Double *beg, const Double *end, U *sol, U)
template <class U> void uncopy(Double *beg, const Double *end, U *sol, U)
template <class U> void copyDiagonal(U &errors, U)
template <class U> void copyDiagonal(U &errors, U)
template <class U> void solve(U *sol)
template <class U> void solve(std::complex<U> *sol)
template <class U> void solve(U &sol)
template <class U> Bool solveLoop(uInt &nRank, U *sol, Bool doSVD=False)
template <class U> Bool solveLoop(uInt &nRank, std::complex<U> *sol, Bool doSVD=False)
template <class U> Bool solveLoop(uInt &nRank, U &sol, Bool doSVD=False)
template <class U> Bool solveLoop(Double &fit, uInt &nRank, U *sol, Bool doSVD=False)
template <class U> Bool solveLoop(Double &fit, uInt &nRank, std::complex<U> *sol, Bool doSVD=False)
template <class U> Bool solveLoop(Double &fit, uInt &nRank, U &sol, Bool doSVD=False)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const U &obs, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const U &obs, LSQFit::Real, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const std::complex<U> &obs, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Complex, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Separable, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::AsReal, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Conjugate, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const U &obs, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const U &obs, LSQFit::Real, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const std::complex<U> &obs, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Complex, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Separable, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::AsReal, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Conjugate, Bool doNorm=True, Bool doKnown=True)
template <class U> Bool getConstraint(uInt n, U *cEq) const
template <class U> Bool getConstraint(uInt n, std::complex<U> *cEq) const
template <class U> Bool getConstraint(uInt n, U &cEq) const
template <class U, class V> Bool setConstraint(uInt n, const V &cEq, const U &obs)
template <class U, class V> Bool setConstraint(uInt n, const V &cEq, const std::complex<U> &obs)
template <class U, class V, class W> Bool setConstraint(uInt n, uInt nIndex, const W &cEqIndex, const V &cEq, const U &obs)
template <class U, class V, class W> Bool setConstraint(uInt n, uInt nIndex, const W &cEqIndex, const V &cEq, const std::complex<U> &obs)
template <class U, class V> Bool addConstraint(const V &cEq, const U &obs)
template <class U, class V> Bool addConstraint(const V &cEq, const std::complex<U> &obs)
template <class U, class V, class W> Bool addConstraint(uInt nIndex, const W &cEqIndex, const V &cEq, const U &obs)
template <class U, class V, class W> Bool addConstraint(uInt nIndex, const W &cEqIndex, const V &cEq, const std::complex<U> &obs)
Bool merge(const LSQFit &other)
Bool merge(const LSQFit &other, uInt nIndex, uInt *nEqIndex)
template <class W> Bool merge(const LSQFit &other, uInt nIndex, const W &nEqIndex)
void reset()
void set(uInt nUnknowns, uInt nConstraints=0)
void set(Int nUnknowns, Int nConstraints=0)
void set(uInt nUnknowns, const LSQReal &, uInt nConstraints=0)
void set(Int nUnknowns, const LSQReal &, Int nConstraints=0)
void set(uInt nUnknowns, const LSQComplex &, uInt nConstraints=0)
void set(Int nUnknowns, const LSQComplex &, Int nConstraints=0)
void set(Double factor=1e-6, Double LMFactor=1e-3)
void setEpsValue(Double epsval=1e-8)
void setEpsDerivative(Double epsder=1e-8)
void setMaxIter(uInt maxiter=0)
uInt nIterations()
void setBalanced(Bool balanced=False)
LSQFit::ReadyCode isReady()
const std::string &readyText()
template <class U> Bool getCovariance(U *covar)
template <class U> Bool getCovariance(std::complex<U> *covar)
template <class U> Bool getErrors(U *errors)
template <class U> Bool getErrors(std::complex<U> *errors)
template <class U> Bool getErrors(U &errors)
uInt nUnknowns() const
uInt nConstraints() const
uInt getDeficiency() const
Double getChi() const
Double getChi2() const
Double getSD() const
Double getWeightedSD() const
void debugIt(uInt &nun, uInt &np, uInt &ncon, uInt &ner, uInt &rank, Double *&nEq, Double *&known, Double *&constr, Double *&er, uInt *&piv, Double *&sEq, Double *&sol, Double &prec, Double &nonlin) const
Bool fromRecord(String &error, const RecordInterface &in)
Bool toRecord(String &error, RecordInterface &out) const
const String &ident() const
void toAipsIO (AipsIO&) const
void fromAipsIO (AipsIO&)
Protected Members
Double *rowrt(uInt i) const
Double *rowru(uInt i) const
static Double realMC(const std::complex<Double> &x, const std::complex<Double> &y)
static Double imagMC(const std::complex<Double> &x, const std::complex<Double> &y)
static Float realMC(const std::complex<Float> &x, const std::complex<Float> &y)
static Float imagMC(const std::complex<Float> &x, const std::complex<Float> &y)
void init()
void clear()
void deinit()
void solveIt()
Bool solveItLoop(Double &fit, uInt &nRank, Bool doSVD=False)
void solveMR(uInt nin)
Bool invertRect()
Double normSolution(const Double *sol) const
Double normInfKnown(const Double *known) const
void save(Bool all=True)
void restore(Bool all=True)
void copy(const LSQFit &other, Bool all=True)
void extendConstraints(uInt n)
void createNCEQ()
void getWorkSOL()
void getWorkCOV()

Description

Prerequisite

Etymology

From Least SQuares and Fitting

Synopsis

The LSQFit class contains the basic functions to do all the fitting described in the Note about fitting. It handles real, and complex equations;
linear and non-linear (Levenberg-Marquardt) solutions;
regular (with optional constraints) or Singular Value Decomposition (SVD).
In essence they are a set of routines to generate normal equations (makeNorm()) in triangular form from a set of condition equations;
to do a Cholesky-type decomposition of the normal equations (either regular or SVD) and test its rank (invert());
to do a quasi inversion of the decomposed equations (solve()) to obtain the solution and/or the errors.

All calculations are done in place. Methods to obtain additional information about the fitting process are available.

This class can be used as a stand-alone class outside of the aips++ environment. In that case the aips.h include file can be replaced if necessary by appropriate typedefs for Double, Float and uInt.
The interface to the methods have standard data or standard STL iterator arguments only. They can be used with any container having an STL random-access iterator interface. Especially they can be used with carrays (necessary templates provided), aips++ Vectors (necessary templates provided in LSQaips), standard random access STL containers (like std::vector).

The normal operation of the class consists of the following steps:

An LSQFit object can be re-used by issuing the reset() command, or set() of new values. If an unknown has not been used in the condition equations at all, the doDiagonal() will make sure a proper solution is obtained, with missing unknowns zeroed.

Most of the calculations are done in place; however, enough data is saved that it is possible to continue with the same (partial) normal equations after e.g. an interim solution.

If the normal equations are produced in separate partial sets (e.g. in a multi-processor environment) a merge() method can combine them.

Tip It is suggested to add any possible constraint equations after the merge.

A debugIt() method provides read access to all internal information.

The member definitions are split over three files. The second one contains the templated member function definitions, to bypass the problem of duplicate definitions of non-templated members when pre-compiling them. The third contains methods for saving objects as Records or through AipsIO.

Warning No boundary checks on input and output containers is done for faster execution. In general these tests should be done at the higher level routines, like the LinearFit and NonLinearFit classes which should be checked for usage of LSQFit.

The contents can be saved in a record (toRecord<src>), and an object can be created from a record (<src>fromRecord). The record identifier is 'lfit'.
The object can also be saved or restored using AipsIO.

Example

See the tLSQFit.cc and tLSQaips.cc program for extensive examples.

The following example will first create 2 condition equations for 3 unknowns (the third is degenerate). It will first create normal equations for a 2 unknown solution and solve; then it will create normal equations for a 3 unknown solution, and solve (note that the degenerate will be set to 0. The last one will use SVD and one condition equation.r

   #include <casa/aips.h>
   #include <scimath/Fitting/LSQFit.h>
   #include <iostream>
   
   int main() {
     // Condition equations for x+y=2; x-y=4;
     Double ce[2][3] = {{1, 1, 0}, {1, -1, 0}};
     Double m[2] = {2, 4};
     // Solution and error area
     Double sol[3];
     Double sd, mu;
     uInt rank;
     Bool ok;
   
     // LSQ object
     LSQFit fit(2);
   
     // Make normal equation
     for (uInt i=0; i<2; i++) fit.makeNorm(ce[i], 1.0, m[i]);
     // Invert(decompose) and show
     ok = fit.invert(rank);
     cout << "ok? " << ok << "; rank: " << rank << endl;
     // Solve and show
     if (ok) {
       fit.solve(sol, &sd, &mu);
       for (uInt i=0; i<2; i++) cout << "Sol" << i << ": " << sol[i] << endl;
       cout << "sd: "<< sd << "; mu: " << mu << endl;
     };
     cout << "----------" << endl; 
   
     // Retry with 3 unknowns: note auto fill of unmentioned one
     fit.set(uInt(3));
     for (uInt i=0; i<2; i++) fit.makeNorm(ce[i], 1.0, m[i]);
     ok = fit.invert(rank);
     cout << "ok? " << ok << "; rank: " << rank << endl;
     if (ok) {
       fit.solve(sol, &sd, &mu);
       for (uInt i=0; i<3; i++) cout << "Sol" << i << ": " << sol[i] << endl;
       cout << "sd: "<< sd << "; mu: " << mu << endl; 
     };
     cout << "----------" << endl; 
   
     // Retry with 3 unknowns; but 1 condition equation and use SVD
     fit.reset();
     for (uInt i=0; i<1; i++) fit.makeNorm(ce[i], 1.0, m[i]);
     ok = fit.invert(rank, True);
     cout << "ok? " << ok << "; rank: " << rank << endl;
     if (ok) {
       fit.solve(sol, &sd, &mu);
       for (uInt i=0; i<3; i++) cout << "Sol" << i << ": " << sol[i] << endl;
       cout << "sd: "<< sd << "; mu: " << mu << endl; 
     };
     cout << "----------" << endl; 
   
     // Without SVD it would be:
     fit.reset();
     for (uInt i=0; i<1; i++) fit.makeNorm(ce[i], 1.0, m[i]);
     ok = fit.invert(rank);
     cout << "ok? " << ok << "; rank: " << rank << endl;
     if (ok) {
       fit.solve(sol, &sd, &mu);
       for (uInt i=0; i<3; i++) cout << "Sol" << i << ": " << sol[i] << endl;
       cout << "sd: "<< sd << "; mu: " << mu << endl; 
     };
     cout << "----------" << endl; 
   
     exit(0);
   }
Which will produce the output:
   ok? 1; rank: 2
   Sol0: 3
   Sol1: -1
   sd: 0; mu: 0
   ----------
   ok? 1; rank: 3
   Sol0: 3
   Sol1: -1
   Sol2: 0
   sd: 0; mu: 0
   ----------
   ok? 1; rank: 2
   Sol0: 1
   Sol1: 1
   Sol2: 0
   sd: 0; mu: 0
   ----------
   ok? 0; rank: 2
   ----------

Motivation

The class was written to be able to do complex, real standard and SVD solutions in a simple and fast way.

To Do

Member Description

enum ReadyCode

State of the non-linear solution

explicit LSQFit(uInt nUnknowns, uInt nConstraints=0)

Construct an object with the number of unknowns and constraints, using the default collinearity factor and the default Levenberg-Marquardt adjustment factor.

Assume real

LSQFit(uInt nUnknowns, const LSQReal &, uInt nConstraints=0)

Construct an object with the number of unknowns and constraints, using the default collinearity factor and the default Levenberg-Marquardt adjustment factor.

Allow explicit Real specification

LSQFit(uInt nUnknowns, const LSQComplex &, uInt nConstraints=0)

Construct an object with the number of unknowns and constraints, using the default collinearity factor and the default Levenberg-Marquardt adjustment factor.

Allow explicit Complex specification

LSQFit()

Default constructor (empty, only usable after a set(nUnknowns))

LSQFit(const LSQFit &other)

Copy constructor (deep copy)

LSQFit &operator=(const LSQFit &other)

Assignment (deep copy)

~LSQFit()

Bool invert(uInt &nRank, Bool doSVD=False)

Triangularize the normal equations and determine the rank nRank of the normal equations and, in the case of an SVD solution, the constraint equations. The collinearity factor is used to determine if the system can be solved (in essence it is the square of the sine of the angle between a column in the normal equations and the plane suspended by the other columns: if too parallel, the equations are degenerate). If doSVD is given as False, False is returned if rank not maximal, else an SVD solution is done.

template <class U> void copy(const Double *beg, const Double *end, U &sol, U)
template <class U> void copy(const Double *beg, const Double *end, U &sol, U)
template <class U> void copy(const Double *beg, const Double *end, U *sol, U)
template <class U> void copy(const Double *beg, const Double *end, U *sol, U)
template <class U> void uncopy(Double *beg, const Double *end, U &sol, U)
template <class U> void uncopy(Double *beg, const Double *end, U &sol, U)
template <class U> void uncopy(Double *beg, const Double *end, U *sol, U)
template <class U> void uncopy(Double *beg, const Double *end, U *sol, U)
template <class U> void copyDiagonal(U &errors, U)
template <class U> void copyDiagonal(U &errors, U)

Copy date from beg to end; converting if necessary to complex data

template <class U> void solve(U *sol)
template <class U> void solve(std::complex<U> *sol)
template <class U> void solve(U &sol)

Solve normal equations. The solution will be given in sol.

template <class U> Bool solveLoop(uInt &nRank, U *sol, Bool doSVD=False)
template <class U> Bool solveLoop(uInt &nRank, std::complex<U> *sol, Bool doSVD=False)
template <class U> Bool solveLoop(uInt &nRank, U &sol, Bool doSVD=False)
template <class U> Bool solveLoop(Double &fit, uInt &nRank, U *sol, Bool doSVD=False)
template <class U> Bool solveLoop(Double &fit, uInt &nRank, std::complex<U> *sol, Bool doSVD=False)
template <class U> Bool solveLoop(Double &fit, uInt &nRank, U &sol, Bool doSVD=False)

Solve a loop in a non-linear set. The methods with the fit argument are deprecated. Use the combination without the 'fit' parameter, and the isReady() call. The 'fit' parameter returns for each loop a goodness of fit indicator. If it is >0; more loops are necessary. If it is negative, and has an absolute value of say less than .001, it is probably ok, and the iterations can be stopped. Other arguments are as for solve() and invert(). The sol is used for both input (parameter guess) and output.

template <class U, class V> void makeNorm(const V &cEq, const U &weight, const U &obs, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const U &obs, LSQFit::Real, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const std::complex<U> &obs, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Complex, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Separable, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::AsReal, Bool doNorm=True, Bool doKnown=True)
template <class U, class V> void makeNorm(const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Conjugate, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const U &obs, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const U &obs, LSQFit::Real, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const std::complex<U> &obs, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Complex, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Separable, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::AsReal, Bool doNorm=True, Bool doKnown=True)
template <class U, class V, class W> void makeNorm(uInt nIndex, const W &cEqIndex, const V &cEq, const U &weight, const std::complex<U> &obs, LSQFit::Conjugate, Bool doNorm=True, Bool doKnown=True)

Make normal equations using the cEq condition equation (with nUnknowns elements) and a weight weight, given the known observed value obs.

doNorm and doKnown can be used to e.g. re-use existing normal equations, i.e. the condition equations, but make a new known side (i.e. new observations).

The versions with cEqIndex[] indicate which of the nUnknowns are actually present in the condition equation (starting indexing at 0); the other terms are supposed to be zero. E.g. if a 12-telescope array has an equation only using telescopes 2 and 4, the lengths of cEqIndex and cEq will be both 2, and the index will contain 1 and 3 (when telescope numbering starts at 1) or 2 and 4 (when telescope numbering starts at 0. The index is given as an iterator (and hence can be a raw pointer)

Note that the use of const U & is due to a Float->Double conversion problem on Solaris. Linux was ok.

template <class U> Bool getConstraint(uInt n, U *cEq) const
template <class U> Bool getConstraint(uInt n, std::complex<U> *cEq) const
template <class U> Bool getConstraint(uInt n, U &cEq) const

Get the n-th (from 0 to the rank deficiency, or missing rank, see e.g. getDeficiency()) constraint equation as determined by invert() in SVD-mode in cEq[nUnknown]. False returned for illegal n. Note that nMissing will be equal to the number of unknowns (nUnknowns, or double that for the complex case) minus the rank as returned from the invert() method.

template <class U, class V> Bool setConstraint(uInt n, const V &cEq, const U &obs)
template <class U, class V> Bool setConstraint(uInt n, const V &cEq, const std::complex<U> &obs)
template <class U, class V, class W> Bool setConstraint(uInt n, uInt nIndex, const W &cEqIndex, const V &cEq, const U &obs)
template <class U, class V, class W> Bool setConstraint(uInt n, uInt nIndex, const W &cEqIndex, const V &cEq, const std::complex<U> &obs)
template <class U, class V> Bool addConstraint(const V &cEq, const U &obs)
template <class U, class V> Bool addConstraint(const V &cEq, const std::complex<U> &obs)
template <class U, class V, class W> Bool addConstraint(uInt nIndex, const W &cEqIndex, const V &cEq, const U &obs)
template <class U, class V, class W> Bool addConstraint(uInt nIndex, const W &cEqIndex, const V &cEq, const std::complex<U> &obs)

Add a new constraint equation (updating nConstraints); or set a numbered constraint equation (0..nConstraints-1). False if illegal number n. The constraints are equations with nUnknowns terms, and a constant value. E.g. measuring three angles of a triangle could lead to equation [1,1,1] with obs as 3.1415. Note that each complex constraint will be converted into two real constraints (see Note 224).

Bool merge(const LSQFit &other)
Bool merge(const LSQFit &other, uInt nIndex, uInt *nEqIndex)
template <class W> Bool merge(const LSQFit &other, uInt nIndex, const W &nEqIndex)

Merge other LSQFit object (i.e. the normal equation and related information) into this. Both objects must have the same number of unknowns, and be pure normal equations (i.e. no invert(), solve(), solveLoop() or statistics calls// should have been made). If merging cannot be done, False is returned. The index case (the index is an iterator) assumes that the normal equations to be merged are a sparse subset of the complete matrix. The index 'vector' specifies which unknown are present. An index outside the scope of the final equations will be skipped.
Tip For highest numerical precision in the case of a larger number of partial normal equations to be merged, it is best to merge them in pairs (and repeat).

void reset()

Reset status to empty

void set(uInt nUnknowns, uInt nConstraints=0)
void set(Int nUnknowns, Int nConstraints=0)
void set(uInt nUnknowns, const LSQReal &, uInt nConstraints=0)
void set(Int nUnknowns, const LSQReal &, Int nConstraints=0)
void set(uInt nUnknowns, const LSQComplex &, uInt nConstraints=0)
void set(Int nUnknowns, const LSQComplex &, Int nConstraints=0)

Set new sizes (default is for Real)

void set(Double factor=1e-6, Double LMFactor=1e-3)

Set new factors (collinearity factor, and Levenberg-Marquardt LMFactor)

void setEpsValue(Double epsval=1e-8)

Set new value solution test

void setEpsDerivative(Double epsder=1e-8)

Set new derivative test

void setMaxIter(uInt maxiter=0)

Set maximum number of iterations

uInt nIterations()

Get number of iterations done

void setBalanced(Bool balanced=False)

Set the expected form of the normal equations

LSQFit::ReadyCode isReady()
const std::string &readyText()

Ask the state of the non-linear solutions

template <class U> Bool getCovariance(U *covar)
template <class U> Bool getCovariance(std::complex<U> *covar)

Get the covariance matrix (of size nUnknowns * nUnknowns)

template <class U> Bool getErrors(U *errors)
template <class U> Bool getErrors(std::complex<U> *errors)
template <class U> Bool getErrors(U &errors)

Get main diagonal of covariance function (of size nUnknowns)

uInt nUnknowns() const

Get the number of unknowns

uInt nConstraints() const

Get the number of constraints

uInt getDeficiency() const

Get the rank deficiency
WarningNote that the number is returned assuming real values. For complex values it has to be halved

Double getChi() const
Double getChi2() const
Double getSD() const
Double getWeightedSD() const

Get chi^2 (both are identical); the standard deviation (per observation) and the standard deviation per weight unit.

void debugIt(uInt &nun, uInt &np, uInt &ncon, uInt &ner, uInt &rank, Double *&nEq, Double *&known, Double *&constr, Double *&er, uInt *&piv, Double *&sEq, Double *&sol, Double &prec, Double &nonlin) const

Debug: Note that all pointers may be 0.

Bool fromRecord(String &error, const RecordInterface &in)

Create an LSQFit object from a record. An error message is generated, and False returned if an invalid record is given. A valid record will return True. Error messages are postfixed to error.

Bool toRecord(String &error, RecordInterface &out) const

Create a record from an LSQFit object. The return will be False and an error message generated only if the object does not contain a valid object. Error messages are postfixed to error.

const String &ident() const

Get identification of record

enum ErrorField

Offset of fields in error_p data area.

enum StateBit

Bits that can be set/referenced

void toAipsIO (AipsIO&) const
void fromAipsIO (AipsIO&)

Work areas for interim solutions and covariance

Double *rowrt(uInt i) const
Double *rowru(uInt i) const

Get pointer in rectangular array

static Double realMC(const std::complex<Double> &x, const std::complex<Double> &y)
static Double imagMC(const std::complex<Double> &x, const std::complex<Double> &y)
static Float realMC(const std::complex<Float> &x, const std::complex<Float> &y)
static Float imagMC(const std::complex<Float> &x, const std::complex<Float> &y)

Calculate the real or imag part of x*conj(y)

void init()

Initialise areas

void clear()

Clear areas

void deinit()

De-initialise area

void solveIt()

Solve normal equations

Bool solveItLoop(Double &fit, uInt &nRank, Bool doSVD=False)

One non-linear LM loop

void solveMR(uInt nin)

Solve missing rank part

Bool invertRect()

Invert rectangular matrix (i.e. when constraints present)

Double normSolution(const Double *sol) const

Get the norm of the current solution vector

Double normInfKnown(const Double *known) const

Get the infinite norm of the known vector

void save(Bool all=True)

Save current status (or part)

void restore(Bool all=True)

Restore current status

void copy(const LSQFit &other, Bool all=True)

Copy data. If all False, only the relevant data for non-linear solution are copied (normal equations, knows and errors).

void extendConstraints(uInt n)

Extend the constraint equation area to the specify number of equations.

void createNCEQ()

Create the solution equation area nceq_p and fill it.

void getWorkSOL()
void getWorkCOV()

Get work areas for solutions, covariance