source: sasview/park-1.2.1/park/fitmc.py @ a9d5684

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since a9d5684 was 3570545, checked in by Mathieu Doucet <doucetm@…>, 13 years ago

Adding park Part 2

  • Property mode set to 100644
File size: 6.0 KB
Line 
1
2# The job queue needs to be in a transaction/rollback protected database.
3# If the server is rebooted, long running jobs should continue to work.
4#
5from __future__ import division
6import numpy
7
8import simplex
9
10import fitresult, pmap, fit
11
12__all__ = ['fitmc', 'FitMCJob']
13
14class LocalFit(object):
15    """
16    Abstract interface for a local minimizer
17
18    See `park.fitmc.FitSimplex` for a concrete implementation.
19    """
20    def fit(self, objective, x0):
21        """
22        Minimize the value of a fitness function.
23
24        See `park.fitmc.Fitness` for the definition of the goodness of fit
25        object.  x0 is a vector containing the initial value for the fit.
26        """
27    def abort(self):
28        """
29        Cancel the fit.  This will be called from a separate execution
30        thread.  The fit should terminate as soon as possible after this
31        function has been called.  Ideally this would interrupt the
32        cur
33        """
34
35class FitSimplex(LocalFit):
36    """
37    Local minimizer using Nelder-Mead simplex algorithm.
38
39    Simplex is robust and derivative free, though not very efficient.
40
41    This class wraps the bounds contrained Nelder-Mead simplex
42    implementation for `park.simplex.simplex`.
43    """
44    radius = 0.05
45    """Size of the initial simplex; this is a portion between 0 and 1"""
46    xtol = 1
47    #xtol = 1e-4
48    """Stop when simplex vertices are within xtol of each other"""
49    ftol = 1e-4
50    """Stop when vertex values are within ftol of each other"""
51    maxiter = None
52    """Maximum number of iterations before fit terminates"""
53    def fit(self, fitness, x0):
54        """Run the fit"""
55        self.cancel = False
56        pars = fitness.fit_parameters()
57        bounds = numpy.array([p.range for p in pars]).T
58        result = simplex.simplex(fitness, x0, bounds=bounds,
59                                 radius=self.radius, xtol=self.xtol,
60                                 ftol=self.ftol, maxiter=self.maxiter,
61                                 abort_test=self._iscancelled)
62        #print "calls:",result.calls
63        #print "simplex returned",result.x,result.fx
64        # Need to make our own copy of the fit results so that the
65        # values don't get stomped on by the next fit iteration.
66        fitpars = [fitresult.FitParameter(pars[i].name,pars[i].range,v)
67                   for i,v in enumerate(result.x)]
68        res = fitresult.FitResult(fitpars, result.calls, result.fx)
69        # Compute the parameter uncertainties from the jacobian
70        res.calc_cov(fitness)
71        return res
72
73    def abort(self):
74        """Cancel the fit in progress from another thread of execution"""
75        # Effectively an atomic operation; rely on GIL to protect it.
76        self.cancel = True
77        # Abort the current function evaluation if possible.
78        if hasattr(fitness,'abort'): self.fitness.abort()
79
80    def _iscancelled(self): return self.cancel
81
82class MapMC(object):
83    """
84    Evaluate a local fit at a particular start point.
85
86    This is the function to be mapped across a set of start points for the
87    monte carlo map-reduce implementation.
88
89    See `park.pmap.Mapper` for required interface.
90    """
91    def __init__(self, minimizer, fitness):
92        self.minimizer, self.fitness = minimizer, fitness
93    def __call__(self, x0):
94        return self.minimizer.fit(self.fitness,x0)
95    def abort(self):
96        self.minimizer.abort()
97
98class CollectMC(object):
99    """
100    Collect the results from multiple start points in a Monte Carlo fit engine.
101
102    See `park.pmap.Collector` for required interface.
103    """
104    def __init__(self, number_expected, handler):
105        self.number_expected = number_expected
106        """Number of starting points to check with local optimizer"""
107        self.iterations = 0
108        self.best = None
109        self.calls = 0
110        self.handler = handler
111        self.handler.done = False
112    def __call__(self, result):
113        # Keep track of the amount of work done
114        self.iterations += 1
115        self.calls += result.calls
116        if self.best is None or result.fitness < self.best.fitness:
117            self.best = result
118            self.handler.result = result
119            self.handler.improvement()
120        # Progress should go after improvement in case the fit handler
121        # wants to suppress intermediate improvements
122        self.handler.progress(self.iterations, self.number_expected)
123    def abort(self):
124        self.handler.done = True
125        self.handler.abort()
126    def finalize(self):
127        self.handler.result.calls = self.calls
128        self.handler.done = True
129        self.handler.finalize()
130    def error(self, msg):
131        self.handler.done = True
132        self.handler.error(msg)
133
134def fitmc(fitness, x0, bounds, localfit, n, handler):
135    """
136    Run a monte carlo fit.
137
138    This procedure maps a local optimizer across a set of n initial points.
139    The initial parameter value defined by the fitness parameters defines
140    one initial point.  The remainder are randomly generated within the
141    bounds of the problem.
142
143    localfit is the local optimizer to use.  It should be a bounded
144    optimizer following the `park.fitmc.LocalFit` interface.
145
146    handler accepts updates to the current best set of fit parameters.
147    See `park.fitresult.FitHandler` for details.
148    """
149    lo,hi = bounds
150    delta = hi-lo
151    delta[numpy.isinf(delta)] = 1
152    lo[numpy.isinf(lo)] = hi-1
153    lo[numpy.isinf(lo)] = 0
154    P = numpy.random.rand(n,len(x0))*delta+lo
155    #print "Population",P
156    P[0] = x0
157    pmap.pmapreduce(MapMC(localfit,fitness),
158                    CollectMC(n,handler),
159                    P)
160
161class FitMC(fit.Fitter):
162    """
163    Monte Carlo optimizer.
164
165    This implements `park.fit.Fitter`.
166    """
167    localfit = FitSimplex()
168    start_points = 10
169
170    def _fit(self, objective, x0, bounds):
171        """
172        Run a monte carlo fit.
173
174        This procedure maps a local optimizer across a set of initial points.
175        """
176        fitmc(objective, x0, bounds, self.localfit,
177              self.start_points, self.handler)
178
179if __name__ == "__main__":
180    fit.demo2(FitMC(localfit=FitSimplex(),start_points=10))
Note: See TracBrowser for help on using the repository browser.