/[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 4074 - (show annotations)
Thu Nov 15 03:30:59 2012 UTC (7 years ago) by gross
File MIME type: text/x-python
File size: 11617 byte(s)
this will break the downundermodule: major revision of the classes.
1
2 ##############################################################################
3 #
4 # Copyright (c) 2003-2012 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-2012 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
28 class CostFunction(object):
29 """
30 A function *f(x)* that can be minimized (base class).
31
32 Example of usage::
33
34 cf=DerivedCostFunction()
35 # ... calculate x ...
36 args=cf.getArguments(x) # this could be potentially expensive!
37 f=cf.getValue(x, *args)
38 # ... it could be required to update x without using the gradient...
39 # ... but then ...
40 gf=cf.getGradient(x, *args)
41
42
43 The class makes a difference for the representation of the solution x (x-type) and
44 the gradients (r-type).
45 """
46
47 def __init__(self):
48 """
49 the base constructor initializes the counters so subclasses should
50 ensure the super class constructor is called.
51 """
52 self.provides_inverse_Hessian_approximation=True
53
54 def getDualProduct(self, x, r):
55 """
56 returns the dual product of ``x`` and ``r``
57
58 :type x: x-type
59 :type r: r-type
60 :rtype: ```float```
61 """
62 raise NotImplementedError
63
64 def getValue(self, x, *args):
65 """
66 returns the value *f(x)* using the precalculated values for *x*.
67
68 :param x: a solution approximation
69 :type x: x-type
70 :rtype: ```float```
71 """
72 raise NotImplementedError
73
74 def __call__(self, x, *args):
75 """
76 short for ``getValue(x, *args)``.
77 """
78 return self.getValue(x, *args)
79
80 def getGradient(self, x, *args):
81 """
82 returns the gradient of *f* at *x* using the precalculated values for
83 *x*.
84
85 :param x: location of derivative
86 :type x: x-type
87 :param args: pre-calculated values for ``x`` from ``getArguments()``
88 :rtype r: r-type
89 """
90 raise NotImplementedError
91
92 def getDirectionalDerivative(self, x, d, *args):
93 """
94 return the directional derivative of *f(x)* in direction of *d*
95
96 :note: this returns ``dualProduct(d, grad f(x))`` but the method can be overwritten
97 to use a more efficient evalautaion.
98
99 :param x: location of derivative
100 :type x: x-type
101 :param d: direction
102 :type d: x-type
103 :param args: pre-calculated values for ``x`` from ``getArguments()``
104 :rtype: ``float``
105 """
106 return self.getDualProduct(d, self.getGradient(x, *args))
107
108 def getArguments(self, x):
109 """
110 returns precalculated values that are shared in the calculation of
111 *f(x)* and *grad f(x)* and the Hessian operator
112
113 :param x: location of derivative
114 :type x: x-type
115 """
116 return ()
117
118 def getInverseHessianApproximation(self, x, r, *args):
119 """
120 returns an approximative evaluation *p* of the inverse of the Hessian operator of the costfunction
121 for a given gradient type *r* at a given location *x*: *H(x) p = r*
122
123 :param x: location of Hessian operator to be evaluated.
124 :type x: x-type
125 :param r: a given gradient
126 :type r: r-type
127 :param args: pre-calculated values for ``x`` from ``getArguments()``
128 :rtype x: x-type
129 :note: In general it is assumed that the Hessian *H(x)* needs to be calculate in each call for a new
130 location *x*. However, the solver may suggest that this is not required, typically when the iteration
131 is close to completeness.
132 :note: class attribute provides_inverse_Hessian_approximation need to be set to True to encourage
133 the solver to call this method.
134
135 """
136 raise NotImplementedError
137
138 def updateHessian(self):
139 """
140 notifies the class that the Hessian operator needs to be updated. This method is
141 called by the solver method.
142 """
143 pass
144
145 class MeteredCostFunction(CostFunction):
146 """
147 This an intrumented version of the ``CostFunction`` class. The function calls update statistical information.
148 The actual work is done by the methods with corresponding name and a leading underscore. These functions
149 need to be overwritten for a particular cost function implementation.
150 """
151
152 def __init__(self):
153 """
154 the base constructor initializes the counters so subclasses should
155 ensure the super class constructor is called.
156 """
157 super(MeteredCostFunction, self).__init__()
158 self.resetCounters()
159
160 def resetCounters(self):
161 """
162 resets all statistical counters
163 """
164 self.DualProduct_calls=0
165 self.Value_calls=0
166 self.Gradient_calls=0
167 self.DirectionalDerivative_calls=0
168 self.Arguments_calls=0
169 self.InverseHessianApproximation_calls=0
170
171 def getDualProduct(self, x, r):
172 """
173 returns the dual product of ``x`` and ``r``
174
175 :type x: x-type
176 :type r: r-type
177 :rtype: ```float```
178 """
179 self.DualProduct_calls+=1
180 return self._getDualProduct(x, r)
181
182 def _getDualProduct(self, x, r):
183 """
184 returns the dual product of ``x`` and ``r``
185
186 :type x: x-type
187 :type r: r-type
188 :rtype: ```float```
189 :note: This is the worker for `getDualProduct()`, needs to be overwritten.
190 """
191 raise NotImplementedError
192
193 def getValue(self, x, *args):
194 """
195 returns the value *f(x)* using the precalculated values for *x*.
196
197 :param x: a solution approximation
198 :type x: x-type
199 :rtype: ```float```
200 """
201 self.Value_calls+=1
202 return self._getValue(x, *args)
203
204 def _getValue(self, x, *args):
205 """
206 returns the value *f(x)* using the precalculated values for *x*.
207
208 :param x: a solution approximation
209 :type x: x-type
210 :rtype: ```float```
211 :note: This is the worker for ``getValue()`, needs to be overwritten.
212 """
213 raise NotImplementedError
214
215 def getGradient(self, x, *args):
216 """
217 returns the gradient of *f* at *x* using the precalculated values for
218 *x*.
219
220 :param x: location of derivative
221 :type x: x-type
222 :param args: pre-calculated values for ``x`` from ``getArguments()``
223 :rtype r: r-type
224 """
225 self.Gradient_calls+=1
226 return self._getGradient(x, *args)
227 def _getGradient(self, x, *args):
228 """
229 returns the gradient of *f* at *x* using the precalculated values for
230 *x*.
231
232 :param x: location of derivative
233 :type x: x-type
234 :param args: pre-calculated values for ``x`` from ``getArguments()``
235 :rtype r: r-type
236 :note: This is the worker for `getGradient()`, needs to be overwritten.
237 """
238 raise NotImplementedError
239
240 def getDirectionalDerivative(self, x, d, *args):
241 """
242 return the directional derivative of *f(x)* in direction of *d*
243
244 :note: this returns ``dualProduct(d, grad f(x))`` but the method can be overwritten
245 to use a more efficient evalautaion.
246
247 :param x: location of derivative
248 :type x: x-type
249 :param d: direction
250 :type d: x-type
251 :param args: pre-calculated values for ``x`` from ``getArguments()``
252 :rtype: ``float``
253 """
254 self.DirectionalDerivative_calls+=1
255 return self._getDirectionalDerivative(x, d, *args)
256
257 def _getDirectionalDerivative(self, x, d, *args):
258 """
259 returns the directional derivative of *f(x)* in direction of *d*
260
261 :note: this returns ``dualProduct(d, grad f(x))`` but the method can be overwritten
262 to use a more efficient evalautaion.
263
264 :param x: location of derivative
265 :type x: x-type
266 :param d: direction
267 :type d: x-type
268 :param args: pre-calculated values for ``x`` from ``getArguments()``
269 :rtype: ``float``
270 """
271 return self.getDualProduct(d, self.getGradient(x, *args))
272
273
274 def getArguments(self, x):
275 """
276 returns precalculated values that are shared in the calculation of
277 *f(x)* and *grad f(x)* and the Hessian operator
278
279 :param x: location of derivative
280 :type x: x-type
281 """
282 self.Arguments_calls+=1
283 return self._getArguments(x)
284
285 def _getArguments(self, x):
286 """
287 returns precalculated values that are shared in the calculation of
288 *f(x)* and *grad f(x)* and the Hessian operator
289
290 :param x: location of derivative
291 :type x: x-type
292 :note: Overwrite this function to implement a specific cost function
293 """
294 return ()
295
296 def getInverseHessianApproximation(self, x, r,*args):
297 """
298 returns an approximative evaluation *p* of the inverse of the Hessian operator of the costfunction
299 for a given gradient type *r* at a given location *x*: *H(x) p = r*
300
301 :param x: location of Hessian operator to be evaluated.
302 :type x: x-type
303 :param r: a given gradient
304 :type r: r-type
305 :param args: pre-calculated values for ``x`` from ``getArguments()``
306 :rtype x: x-type
307 :note: In general it is assumed that the Hessian *H(x)* needs to be calculate in each call for a new
308 location *x*. However, the solver may suggest that this is not required, typically when the iteration
309 ius close to completness.
310 """
311 self.InverseHessianApproximation_calls+=1
312 return self._getInverseHessianApproximation(x, r, *args)
313
314 def _getInverseHessianApproximation(self, x, r, *args):
315 """
316 returns an approximative evaluation *p* of the inverse of the Hessian operator of the costfunction
317 for a given gradient type *r* at a given location *x*: *H(x) p = r*
318
319 :param x: location of Hessian operator to be evaluated.
320 :type x: x-type
321 :param r: a given gradient
322 :type r: r-type
323 :param args: pre-calculated values for ``x`` from ``getArguments()``
324 :rtype x: x-type
325 :note: In general it is assumed that the Hessian *H(x)* needs to be calculate in each call for a new
326 location *x*. However, the solver may suggest that this is not required, typically when the iteration
327 ius close to completness.
328 :note: :note: This is the worker for getInverseHessianApproximation()`, needs to be overwritten.
329 """
330 raise NotImplementedError
331

  ViewVC Help
Powered by ViewVC 1.1.26