/[escript]/trunk/downunder/py_src/costfunctions.py
ViewVC logotype

Contents of /trunk/downunder/py_src/costfunctions.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4178 - (show annotations)
Thu Jan 31 03:18:56 2013 UTC (6 years, 8 months ago) by caltinay
File MIME type: text/x-python
File size: 10752 byte(s)
Some more doco.

1
2 ##############################################################################
3 #
4 # Copyright (c) 2003-2013 by University of Queensland
5 # http://www.uq.edu.au
6 #
7 # Primary Business: Queensland, Australia
8 # Licensed under the Open Software License version 3.0
9 # http://www.opensource.org/licenses/osl-3.0.php
10 #
11 # Development until 2012 by Earth Systems Science Computational Center (ESSCC)
12 # Development since 2012 by School of Earth Sciences
13 #
14 ##############################################################################
15
16 """General cost functions for minimization"""
17
18 __copyright__="""Copyright (c) 2003-2013 by University of Queensland
19 http://www.uq.edu.au
20 Primary Business: Queensland, Australia"""
21 __license__="""Licensed under the Open Software License version 3.0
22 http://www.opensource.org/licenses/osl-3.0.php"""
23 __url__="https://launchpad.net/escript-finley"
24
25 __all__ = [ 'CostFunction', 'MeteredCostFunction' ]
26
27 import logging
28
29 class CostFunction(object):
30 """
31 A function *f(x)* that can be minimized (base class).
32
33 Example of usage::
34
35 cf=DerivedCostFunction()
36 # ... calculate x ...
37 args=cf.getArguments(x) # this could be potentially expensive!
38 f=cf.getValue(x, *args)
39 # ... it could be required to update x without using the gradient...
40 # ... but then ...
41 gf=cf.getGradient(x, *args)
42
43 The class distinguishes between the representation of the solution
44 x (x-type) and the gradients (r-type).
45
46 :cvar provides_inverse_Hessian_approximation: This member should be set
47 to ``True`` in subclasses that provide a valid implementation of
48 `getInverseHessianApproximation()`
49 """
50
51 provides_inverse_Hessian_approximation=False
52
53 def __init__(self):
54 """
55 Constructor. Initializes logger.
56 """
57 self.logger = logging.getLogger('inv.%s'%self.__class__.__name__)
58
59 def __call__(self, x, *args):
60 """
61 short for `getValue(x, *args)`.
62 """
63 return self.getValue(x, *args)
64
65 def getArguments(self, x):
66 """
67 returns precalculated values that are shared in the calculation of
68 *f(x)* and *grad f(x)* and the Hessian operator. The default
69 implementation returns an empty tuple.
70
71 :param x: location of derivative
72 :type x: x-type
73 :rtype: ``tuple``
74 """
75 return ()
76
77 def getDualProduct(self, x, r):
78 """
79 returns the dual product of ``x`` and ``r``
80
81 :type x: x-type
82 :type r: r-type
83 :rtype: ``float``
84 """
85 raise NotImplementedError
86
87 def getGradient(self, x, *args):
88 """
89 returns the gradient of *f* at *x* using the precalculated values for
90 *x*.
91
92 :param x: location of derivative
93 :type x: x-type
94 :param args: pre-calculated values for ``x`` from `getArguments()`
95 :rtype: r-type
96 """
97 raise NotImplementedError
98
99 def getInverseHessianApproximation(self, x, r, *args):
100 """
101 returns an approximative evaluation *p* of the inverse of the Hessian
102 operator of the cost function for a given gradient *r* at a given
103 location *x*: *H(x) p = r*
104
105 :param x: location of Hessian operator to be evaluated
106 :type x: x-type
107 :param r: a given gradient
108 :type r: r-type
109 :param args: pre-calculated values for ``x`` from `getArguments()`
110 :rtype: x-type
111 :note: In general it is assumed that the Hessian *H(x)* needs to be
112 calculated in each call for a new location *x*. However, the
113 solver may suggest that this is not required, typically when
114 the iteration is close to completeness.
115 :note: Subclasses that implement this method should set the class
116 variable `provides_inverse_Hessian_approximation` to ``True`` to
117 enable the solver to call this method.
118 """
119 raise NotImplementedError
120
121 def getValue(self, x, *args):
122 """
123 returns the value *f(x)* using the precalculated values for *x*.
124
125 :param x: a solution approximation
126 :type x: x-type
127 :rtype: ``float``
128 """
129 raise NotImplementedError
130
131 def updateHessian(self):
132 """
133 notifies the class that the Hessian operator needs to be updated.
134 This method is called by the solver class.
135 """
136 pass
137
138 def getNorm(self, x):
139 """
140 returns the norm of ``x``
141
142 :type x: x-type
143 :rtype: ``float``
144 """
145 raise NotImplementedError
146
147
148 class MeteredCostFunction(CostFunction):
149 """
150 This an intrumented version of the `CostFunction` class. The function
151 calls update statistical information.
152 The actual work is done by the methods with corresponding name and a
153 leading underscore. These functions need to be overwritten for a particular
154 cost function implementation.
155 """
156
157 def __init__(self):
158 """
159 the base constructor initializes the counters so subclasses should
160 ensure the super class constructor is called.
161 """
162 super(MeteredCostFunction, self).__init__()
163 self.resetCounters()
164
165 def resetCounters(self):
166 """
167 resets all statistical counters
168 """
169 self.DualProduct_calls=0
170 self.Value_calls=0
171 self.Gradient_calls=0
172 self.Arguments_calls=0
173 self.InverseHessianApproximation_calls=0
174 self.Norm_calls=0
175
176 def getDualProduct(self, x, r):
177 """
178 returns the dual product of ``x`` and ``r``
179
180 :type x: x-type
181 :type r: r-type
182 :rtype: ``float``
183 """
184 self.DualProduct_calls+=1
185 return self._getDualProduct(x, r)
186
187 def _getDualProduct(self, x, r):
188 """
189 returns the dual product of ``x`` and ``r``
190
191 :type x: x-type
192 :type r: r-type
193 :rtype: ``float``
194 :note: This is the worker for `getDualProduct()`, needs to be overwritten.
195 """
196 raise NotImplementedError
197
198 def getNorm(self, x):
199 """
200 returns the norm of ``x``
201
202 :type x: x-type
203 :rtype: ``float``
204 """
205 self.Norm_calls+=1
206 return self._getNorm(x)
207
208 def _getNorm(self, x):
209 """
210 returns the norm of ``x``
211
212 :type x: x-type
213 :rtype: ``float``
214 :note: This is the worker for `getNorm()`, needs to be overwritten.
215 """
216 raise NotImplementedError
217
218 def getValue(self, x, *args):
219 """
220 returns the value *f(x)* using the precalculated values for *x*.
221
222 :param x: a solution approximation
223 :type x: x-type
224 :rtype: ``float``
225 """
226 self.Value_calls+=1
227 return self._getValue(x, *args)
228
229 def _getValue(self, x, *args):
230 """
231 returns the value *f(x)* using the precalculated values for *x*.
232
233 :param x: a solution approximation
234 :type x: x-type
235 :rtype: ``float``
236 :note: This is the worker for ``getValue()``, needs to be overwritten.
237 """
238 raise NotImplementedError
239
240 def getGradient(self, x, *args):
241 """
242 returns the gradient of *f* at *x* using the precalculated values for
243 *x*.
244
245 :param x: location of derivative
246 :type x: x-type
247 :param args: pre-calculated values for ``x`` from `getArguments()`
248 :rtype: r-type
249 """
250 self.Gradient_calls+=1
251 return self._getGradient(x, *args)
252
253 def _getGradient(self, x, *args):
254 """
255 returns the gradient of *f* at *x* using the precalculated values for
256 *x*.
257
258 :param x: location of derivative
259 :type x: x-type
260 :param args: pre-calculated values for ``x`` from `getArguments()`
261 :rtype: r-type
262 :note: This is the worker for `getGradient()`, needs to be overwritten.
263 """
264 raise NotImplementedError
265
266
267 def getArguments(self, x):
268 """
269 returns precalculated values that are shared in the calculation of
270 *f(x)* and *grad f(x)* and the Hessian operator
271
272 :param x: location of derivative
273 :type x: x-type
274 """
275 self.Arguments_calls+=1
276 return self._getArguments(x)
277
278 def _getArguments(self, x):
279 """
280 returns precalculated values that are shared in the calculation of
281 *f(x)* and *grad f(x)* and the Hessian operator
282
283 :param x: location of derivative
284 :type x: x-type
285 :note: Overwrite this function to implement a specific cost function
286 """
287 return ()
288
289 def getInverseHessianApproximation(self, x, r,*args):
290 """
291 returns an approximative evaluation *p* of the inverse of the Hessian
292 operator of the cost function for a given gradient *r* at a given
293 location *x*: *H(x) p = r*
294
295 :param x: location of Hessian operator to be evaluated.
296 :type x: x-type
297 :param r: a given gradient
298 :type r: r-type
299 :param args: pre-calculated values for ``x`` from `getArguments()`
300 :rtype: x-type
301 :note: In general it is assumed that the Hessian *H(x)* needs to be
302 calculate in each call for a new location *x*. However, the
303 solver may suggest that this is not required, typically when
304 the iteration is close to completeness.
305 """
306 self.InverseHessianApproximation_calls+=1
307 return self._getInverseHessianApproximation(x, r, *args)
308
309 def _getInverseHessianApproximation(self, x, r, *args):
310 """
311 returns an approximative evaluation *p* of the inverse of the Hessian
312 operator of the cost function for a given gradient *r* at a given
313 location *x*: *H(x) p = r*
314
315 :param x: location of Hessian operator to be evaluated
316 :type x: x-type
317 :param r: a given gradient
318 :type r: r-type
319 :param args: pre-calculated values for ``x`` from `getArguments()`
320 :rtype: x-type
321 :note: In general it is assumed that the Hessian *H(x)* needs to be
322 calculate in each call for a new location *x*. However, the
323 solver may suggest that this is not required, typically when
324 the iteration is close to completeness.
325 :note: This is the worker for getInverseHessianApproximation()`, needs
326 to be overwritten.
327 :note: Subclasses that implement this method should set the class
328 variable `provides_inverse_Hessian_approximation` to ``True`` to
329 enable the solver to call this method.
330 """
331 raise NotImplementedError
332

  ViewVC Help
Powered by ViewVC 1.1.26