casacore
Loading...
Searching...
No Matches
AutoDiff.h
Go to the documentation of this file.
1//# AutoDiff.h: An automatic differentiating class for functions
2//# Copyright (C) 1995,1998,1999,2001,2002
3//# Associated Universities, Inc. Washington DC, USA.
4//#
5//# This library is free software; you can redistribute it and/or modify it
6//# under the terms of the GNU Library General Public License as published by
7//# the Free Software Foundation; either version 2 of the License, or (at your
8//# option) any later version.
9//#
10//# This library is distributed in the hope that it will be useful, but WITHOUT
11//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13//# License for more details.
14//#
15//# You should have received a copy of the GNU Library General Public License
16//# along with this library; if not, write to the Free Software Foundation,
17//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18//#
19//# Correspondence concerning AIPS++ should be addressed as follows:
20//# Internet email: casa-feedback@nrao.edu.
21//# Postal address: AIPS++ Project Office
22//# National Radio Astronomy Observatory
23//# 520 Edgemont Road
24//# Charlottesville, VA 22903-2475 USA
25
26#ifndef SCIMATH_AUTODIFF_H
27#define SCIMATH_AUTODIFF_H
28
29//# Includes
30#include <casacore/casa/aips.h>
31#include <casacore/casa/Arrays/Vector.h>
32
33namespace casacore { //# NAMESPACE CASACORE - BEGIN
34
35// <summary>
36// Class that computes partial derivatives by automatic differentiation.
37// </summary>
38//
39// <use visibility=export>
40//
41// <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tAutoDiff.cc" demos="dAutoDiff.cc">
42// </reviewed>
43//
44// <prerequisite>
45// <li>
46// </prerequisite>
47//
48// <etymology>
49// Class that computes partial derivatives by automatic differentiation, thus
50// AutoDiff.
51// </etymology>
52//
53// <synopsis>
54// Class that computes partial derivatives by automatic differentiation.
55// It does this by storing the value of a function and the values of its first
56// derivatives with respect to its independent parameters. When a mathematical
57// operation is applied to an AutoDiff object, the derivative values of the
58// resulting new object are computed according to chain rules
59// of differentiation.
60//
61// Suppose we have a function f(x0,x1,...,xn) and its differential is
62// <srcblock>
63// df = (df/dx0)*dx0 + (df/dx1)*dx1 + ... + (df/dxn)*dxn
64// </srcblock>
65// We can build a class that has the value of the function,
66// f(x0,x1,...,xn), and the values of the derivatives, (df/dx0), (df/dx1),
67// ..., (df/dxn) at (x0,x1,...,xn), as class members.
68//
69// Now if we have another function, g(x0,x1,...,xn) and its differential is
70// dg = (dg/dx0)*dx0 + (dg/dx1)*dx1 + ... + (dg/dxn)*dxn,
71// since
72// <srcblock>
73// d(f+g) = df + dg,
74// d(f*g) = g*df + f*dg,
75// d(f/g) = df/g - fdg/g^2,
76// dsin(f) = cos(f)df,
77// ...,
78// </srcblock>
79// we can calculate
80// <srcblock>
81// d(f+g), d(f*g), ...,
82// </srcblock> based on our information on
83// <srcblock>
84// df/dx0, df/dx1, ..., dg/dx0, dg/dx1, ..., dg/dxn.
85// </srcblock>
86// All we need to do is to define the operators and derivatives of common
87// mathematical functions.
88//
89// To be able to use the class as an automatic differentiator of a function
90// object, we need a templated function object, i.e. an object with:
91// <ul>
92// <li> a <src> template <class T> T operator()(const T)</src>
93// <li> or multiple variable input like:
94// <src> template <class T> T operator()(const Vector<T> &)</src>
95// <li> all variables and constants used in the calculation of the function
96// value should have been typed with T
97// </ul>
98// A simple example of such a function object could be:
99// <srcblock>
100// template <class T> f {
101// public:
102// T operator()(const T &x, const T &a, const T &b) {
103// return a*b*x; }
104// };
105// // Instantiate the following versions:
106// template class f<Double>;
107// template class f<AutoDiff<Double> >;
108// </srcblock>
109// A call with values will produce the function value:
110// <srcblock>
111// cout << f(7.0, 2.0, 3.0) << endl;
112// // will produce the value at x=7 for a=2; b=3:
113// 42
114// // But a call indicating that we want derivatives to a and b:
115// cout << f(AutoDiff<Double>(7.0), AutoDiff<Double>(2.0, 2, 0),
116// AutoDiff<Double>(3.0, 2, 1)) << endl;
117// // will produce the value at x=7 for a=2; b=3:
118// // and the partial derivatives wrt a and b at x=7:
119// (42, [21, 14])
120// // The following will calculate the derivate wrt x:
121// cout << f(AutoDiff<Double>(7.0, 1, 0), AutoDiff<Double>(2.0),
122// AutoDiff<Double>(3.0)) << endl;
123// (42,[6])
124// </srcblock>
125// In actual practice, there are a few rules to obey for the structure of
126// the function object if you want to use the function object and its
127// derivatives in least squares fitting procedures in the Fitting
128// module. The major one is to view the function object having 'fixed' and
129// 'variable' parameters. I.e., rather than viewing the function as
130// depending on parameters <em>a, b, x</em> (<src>f(a,b,x)</src>), the
131// function is considered to be <src>f(x; a,b)</src>, where <em>a, b</em>
132// are 'fixed' parameters, and <em>x</em> a variable parameter.
133// Fixed parameters should be contained in a
134// <linkto class=FunctionParam>FunctionParam</linkto> container object;
135// while the variable parameter(s) are given in the function
136// <src>operator()</src>. See <linkto class=Function>Function</linkto> class
137// for details.
138//
139// A Gaussian spectral profile would in general have the center frequency,
140// the width and the amplitude as fixed parameters, and the frequency as
141// a variable. Given a spectrum, you would solve for the fixed parameters,
142// given spectrum values. However, in other cases the role of the
143// parameters could be reversed. An example could be a whole stack of
144// observed (in the laboratory) spectra at different temperatures at
145// one frequency. In that case the width would be the variable parameter,
146// and the frequency one of the fixed (and to be solved for)parameters.
147//
148// Since the calculation of the derivatives is done with simple overloading,
149// the calculation of second (and higher) derivatives is easy. It should be
150// noted that higher deivatives are inefficient in the current incarnation
151// (there is no knowledge e.g. about symmetry in the Jacobian). However,
152// it is a very good way to get the correct answers of the derivatives. In
153// practice actual production code will be better off with specialization
154// of the <src>f<AutoDiff<> ></src> implementation.
155//
156// The <src>AutoDiff</src> class is the class the user communicates with.
157// Alias classes (<linkto class=AutoDiffA>AutoDiffA</linkto> and
158// <linkto class=AutoDiffA>AutoDiffX</linkto>) exists
159// to make it possible to have different incarnations of a templated
160// method (e.g. a generic one and a specialized one). See the
161// <src>dAutoDiff</src> demo for an example of its use.
162//
163// All operators and functions are declared in <linkto file=AutoDiffMath.h>
164// AutoDiffMath</linkto>. The output operator in
165// <linkto file=AutoDiffIO.h>AutoDiffIO</linkto>.
166// </synopsis>
167//
168// <example>
169// <srcblock>
170// // First a simple example.
171// // We have a function of the form f(x,y,z); and want to know the
172// // value of the function for x=10; y=20; z=30; and for
173// // the derivatives at those point.
174// // Specify the values; and indicate 3 derivatives:
175// AutoDiff<Double> x(10.0, 3, 0);
176// AutoDiff<Double> y(20.0, 3, 1);
177// AutoDiff<Double> z(30.0, 3, 2);
178// // The result will be:
179// AutoDiff<Double> result = x*y + sin(z);
180// cout << result.value() << endl;
181// // 199.012
182// cout << result.derivatives() << endl;
183// // [20, 10, 0.154251]
184// // Note: sin(30) = -0.988; cos(30) = 0.154251;
185// </srcblock>
186//
187// See for an extensive example the demo program dAutoDiff. It is
188// based on the example given above, and shows also the use of second
189// derivatives (which is just using <src>AutoDiff<AutoDiff<Double> ></src>
190// as template argument).
191// <srcblock>
192// // The function, with fixed parameters a,b:
193// template <class T> class f {
194// public:
195// T operator()(const T& x) { return a_p*a_p*a_p*b_p*b_p*x; }
196// void set(const T& a, const T& b) { a_p = a; b_p = b; }
197// private:
198// T a_p;
199// T b_p;
200// };
201// // Call it with different template arguments:
202// Double a0(2), b0(3), x0(7);
203// f<Double> f0; f0.set(a0, b0);
204// cout << "Value: " << f0(x0) << endl;
205//
206// AutoDiff<Double> a1(2,2,0), b1(3,2,1), x1(7);
207// f<AutoDiff<Double> > f1; f1.set(a1, b1);
208// cout << "Diff a,b: " << f1(x1) << endl;
209//
210// AutoDiff<Double> a2(2), b2(3), x2(7,1,0);
211// f<AutoDiff<Double> > f2; f2.set(a2, b2);
212// cout << "Diff x: " << f2(x2) << endl;
213//
214// AutoDiff<AutoDiff<Double> > a3(AutoDiff<Double>(2,2,0),2,0),
215// b3(AutoDiff<Double>(3,2,1),2,1), x3(AutoDiff<Double>(7),2);
216// f<AutoDiff<AutoDiff<Double> > > f3; f3.set(a3, b3);
217// cout << "Diff2 a,b: " << f3(x3) << endl;
218//
219// AutoDiff<AutoDiff<Double> > a4(AutoDiff<Double>(2),1),
220// b4(AutoDiff<Double>(3),1),
221// x4(AutoDiff<Double>(7,1,0),1,0);
222// f<AutoDiff<AutoDiff<Double> > > f4; f4.set(a4, b4);
223// cout << "Diff2 x: " << f4(x4) << endl;
224//
225// // Result will be:
226// // Value: 504
227// // Diff a,b: (504, [756, 336])
228// // Diff x: (504, [72])
229// // Diff2 a,b: ((504, [756, 336]), [(756, [756, 504]), (336, [504, 112])])
230// // Diff2 x: ((504, [72]), [(72, [0])])
231//
232// // It needed the template instantiations definitions:
233// template class f<Double>;
234// template class f<AutoDiff<Double> >;
235// template class f<AutoDiff<AutoDiff<Double> > >;
236// </srcblock>
237// </example>
238//
239// <motivation>
240// The creation of the class was motivated by least-squares non-linear fit where
241// partial derivatives of a fitted function are needed. It would be tedious
242// to create functionals for all partial derivatives of a function.
243// </motivation>
244//
245// <templating arg=T>
246// <li> any class that has the standard mathematical and comparisons
247// defined
248// </templating>
249//
250// <todo asof="2001/06/07">
251// <li> Nothing I know
252// </todo>
253
254template <class T> class AutoDiff {
255 public:
256 //# Typedefs
257 typedef T value_type;
262
263 //# Constructors
264 // Construct a constant with a value of zero. Zero derivatives.
266
267 // Construct a constant with a value of v. Zero derivatives.
268 AutoDiff(const T &v);
269
270 // A function f(x0,x1,...,xn,...) with a value of v. The
271 // total number of derivatives is ndiffs, the nth derivative is one, and all
272 // others are zero.
273 AutoDiff(const T &v, const uInt ndiffs, const uInt n);
274
275 // A function f(x0,x1,...,xn,...) with a value of v. The
276 // total number of derivatives is ndiffs.
277 // All derivatives are zero.
278 AutoDiff(const T &v, const uInt ndiffs);
279
280 // Construct one from another
281 AutoDiff(const AutoDiff<T> &other);
282
283 // Construct a function f(x0,x1,...,xn) of a value v and a vector of
284 // derivatives derivs(0) = df/dx0, derivs(1) = df/dx1, ...
285 AutoDiff(const T &v, const Vector<T> &derivs);
286
288
289 // Assignment operator. Assign a constant to variable. All derivatives
290 // are zero.
291 AutoDiff<T> &operator=(const T &v);
292
293 // Assign one to another.
295
296 // In-place mathematical operators
297 // <group>
298 void operator*=(const AutoDiff<T> &other);
299 void operator/=(const AutoDiff<T> &other);
300 void operator+=(const AutoDiff<T> &other);
301 void operator-=(const AutoDiff<T> &other);
302 void operator*=(const T other);
303 void operator/=(const T other);
304 void operator+=(const T other);
305 void operator-=(const T other);
306 // </group>
307
308 // Returns the value of the function
309 // <group>
310 T &value() { return val_p; }
311 const T &value() const { return val_p; }
312 // </group>
313
314 // Returns a vector of the derivatives of an AutoDiff
315 // <group>
316 const Vector<T>& derivatives() const {return grad_p; }
318 void derivatives(Vector<T> &res) const;
319 // </group>
320
321 // Returns a specific derivative. The second set does not check for
322 // a valid which; the first set does through Vector addressing.
323 // <group>
324 T &derivative(uInt which) { return grad_p(which); }
325 const T &derivative(uInt which) const { return grad_p(which); }
326 T &deriv(uInt which) { return grad_p[which]; }
327 const T &deriv(uInt which) const { return grad_p[which]; }
328 // </group>
329
330 // Return total number of derivatives
331 uInt nDerivatives() const { return nd_p; }
332
333 // Is it a constant, i.e., with zero derivatives?
334 Bool isConstant() const { return nd_p == 0; }
335
336 private:
337 //# Data
338 // The function value
340 // The number of derivatives
342 // The derivatives
344};
345
346
347} //# NAMESPACE CASACORE - END
348
349#ifndef CASACORE_NO_AUTO_TEMPLATES
350#include <casacore/scimath/Mathematics/AutoDiff.tcc>
351#endif //# CASACORE_NO_AUTO_TEMPLATES
352#endif
AutoDiff< T > & operator=(const AutoDiff< T > &other)
Assign one to another.
Vector< T > grad_p
The derivatives.
Definition AutoDiff.h:343
Vector< T > & derivatives()
Definition AutoDiff.h:317
void derivatives(Vector< T > &res) const
T & deriv(uInt which)
Definition AutoDiff.h:326
const Vector< T > & derivatives() const
Returns a vector of the derivatives of an AutoDiff.
Definition AutoDiff.h:316
T & derivative(uInt which)
Returns a specific derivative.
Definition AutoDiff.h:324
AutoDiff< T > & operator=(const T &v)
Assignment operator.
void operator/=(const T other)
AutoDiff(const T &v, const uInt ndiffs)
A function f(x0,x1,...,xn,...) with a value of v.
void operator+=(const T other)
T & value()
Returns the value of the function.
Definition AutoDiff.h:310
Bool isConstant() const
Is it a constant, i.e., with zero derivatives?
Definition AutoDiff.h:334
void operator-=(const AutoDiff< T > &other)
const T & value() const
Definition AutoDiff.h:311
AutoDiff(const T &v, const Vector< T > &derivs)
Construct a function f(x0,x1,...,xn) of a value v and a vector of derivatives derivs(0) = df/dx0,...
const T & deriv(uInt which) const
Definition AutoDiff.h:327
void operator*=(const AutoDiff< T > &other)
In-place mathematical operators.
value_type * iterator
Definition AutoDiff.h:260
void operator/=(const AutoDiff< T > &other)
const value_type & const_reference
Definition AutoDiff.h:259
uInt nd_p
The number of derivatives.
Definition AutoDiff.h:341
AutoDiff(const T &v)
Construct a constant with a value of v.
value_type & reference
Definition AutoDiff.h:258
void operator+=(const AutoDiff< T > &other)
AutoDiff()
Construct a constant with a value of zero.
const T & derivative(uInt which) const
Definition AutoDiff.h:325
AutoDiff(const AutoDiff< T > &other)
Construct one from another.
uInt nDerivatives() const
Return total number of derivatives.
Definition AutoDiff.h:331
const value_type * const_iterator
Definition AutoDiff.h:261
void operator*=(const T other)
void operator-=(const T other)
T val_p
The function value.
Definition AutoDiff.h:339
AutoDiff(const T &v, const uInt ndiffs, const uInt n)
A function f(x0,x1,...,xn,...) with a value of v.
this file contains all the compiler specific defines
Definition mainpage.dox:28
unsigned int uInt
Definition aipstype.h:49
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40