| | 5 | There should be a very simple interface with default options and methods specified to get code working. One should then be able to refine the method to suit the particular problem. Ultimately, it might be nice to provide tools that could try different methods and parameter values to determine the "optimum" solver for a given problem. |
| | 6 | |
| | 7 | Here is an example of a paradigm where a class is used to return a new functor which returns the zeros of a function |
| | 8 | {{{ |
| | 9 | #!python |
| | 10 | from optimize import Zeros |
| | 11 | |
| | 12 | def f(x,n): |
| | 13 | """Return x**2 - n. Zero is at sqrt(n).""" |
| | 14 | return x*x - n |
| | 15 | |
| | 16 | zeros = Zeros(f=f,x0=0) |
| | 17 | |
| | 18 | sqrt4 = zeros(4.0) |
| | 19 | }}} |
| | 20 | The idea here is that the `Zeros` class will perform any initializations (that could be somewhat costly) and checks, then return an optimized function (functor) `zeros` that actually performs the calculation. The argument `f` could be a simple function or a more complex functor with instructions, for example, about how to compute the Jacobian. The initializer for the `Zeros` class would query `f` to see its capabilities. |
| | 21 | |
| | 22 | If you want to use a specific algorithm, then you could specify it at this point. For example: |
| | 23 | {{{ |
| | 24 | #!python |
| | 25 | from optimize.methods import Broyden |
| | 26 | from optimize import Zeros |
| | 27 | ... |
| | 28 | method = Broyden(ftol=1e-10,xtol=1e-12) |
| | 29 | zeros = Zeros(f=f,x0=0,method=method) |
| | 30 | }}} |
| | 31 | `Broyden` would be a convenience wrapper of a modularized optimization method specifying the step type, line search method, etc. One could also build ones own custom method using the components. The `Broyden` class should be able to provide a list of options that can easily be selected to customize the method (either by the user or by an automatic performance tuner) as a starting point for a custom optimizer for example. One could subclass: |
| | 32 | {{{ |
| | 33 | #!python |
| | 34 | from optimize.method import Broyden |
| | 35 | from optimize.method.criteria import RelativeValueCriterion |
| | 36 | |
| | 37 | class MyMethod(Broyden): |
| | 38 | criterion = RelativeValueCriterion |
| | 39 | |
| | 40 | method = MyMethod |
| | 41 | }}} |
| | 42 | or one could build from options: |
| | 43 | {{{ |
| | 44 | #!python |
| | 45 | from optimize.method import Broyden |
| | 46 | from optimize.method.criteria import RelativeValueCriterion |
| | 47 | method = Broyden(criterion=RelativeValueCriterion()) |
| | 48 | }}} |
| | 49 | It would also be nice if there was a unified method for passing keyword arguments in at various stages, so one could change individual paremeters at any stage, i.e. the tolerance could be specified when constructing the method, or when calling the actual optimizer: |
| | 50 | {{{ |
| | 51 | #!python |
| | 52 | zeros = Zeros(f=f,x0=x0,ftol=0.001) |
| | 53 | approx2 = zeros(4.0) |
| | 54 | better2 = zeros(4.0,ftol=1e-16) |
| | 55 | }}} |