Changeset 87


Ignore:
Timestamp:
02/05/09 20:28:35 (7 years ago)
Author:
mmckerns
Message:

added tools.wrap_bounds; added range bounds to fmin (modified from park.simplex)

Location:
python
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • python/nmtools.py

    r82 r87  
    1616         sim = inst.population 
    1717         fsim = inst.popEnergy 
    18          return (max(numpy.ravel(abs(sim[1:]-sim[0]))) <= xtol \ 
    19                 and max(abs(fsim[0]-fsim[1:])) <= ftol) 
     18         #FIXME: abs(inf - inf) will raise a warning... 
     19         errdict = numpy.seterr(invalid='ignore') #FIXME: turn off warning  
     20         answer = (max(numpy.ravel(abs(sim[1:]-sim[0]))) <= xtol \ 
     21                  and max(abs(fsim[0]-fsim[1:])) <= ftol) 
     22         numpy.seterr(invalid=errdict['invalid']) #FIXME: turn on warnings 
     23         return answer 
    2024    return _ 
    2125 
  • python/scipy_optimize_fmin.py

    r82 r87  
    55# adapted from scipy.optimize, scipy version 0.4.8 
    66# by Patrick Hung, Caltech. 
    7 # adapted to class by mmckerns@caltech.edu 
     7# adapted to class (& added bounds) 
     8# by mmckerns@caltech.edu 
    89 
    910""" 
     
    1819 
    1920from mystic.tools import Null, wrap_function 
     21from mystic.tools import wrap_bounds 
    2022 
    2123import numpy 
    2224from numpy import atleast_1d, eye, zeros, shape, \ 
    2325     asarray, absolute, sqrt, Inf, asfarray 
     26from numpy import clip 
    2427 
    2528abs = absolute 
     
    5962 
    6063    def SetStrictRanges(self, min, max): 
    61         raise NotImplementedError, "bound constraints not implemented" 
     64        self._useStrictRange = True 
     65        self._strictMin = min 
     66        self._strictMax = max 
     67        return 
     68 
     69    def setSimplexWithinRangeBoundary(self, x0, radius): 
     70        """ensure that initial simplex is set within bounds""" 
     71        #code modified from park-1.2/park/simplex.py (version 1257) 
     72        if self._useStrictRange: 
     73            lo = asarray(self._strictMin) 
     74            hi = asarray(self._strictMax) 
     75            # crop x0 at bounds 
     76            x0[x0<lo] = lo[x0<lo] 
     77            x0[x0>hi] = hi[x0>hi] 
     78 
     79        val = x0*(1+radius) 
     80        val[val==0] = radius 
     81        if not self._useStrictRange: 
     82            return x0, val 
     83 
     84        radius = clip(radius,0,0.5) 
     85        # rescale val by bounded range... 
     86        # (increases fit for tight bounds; makes worse[?] for large bounds) 
     87        bounded = ~numpy.isinf(lo) & ~numpy.isinf(hi) 
     88        val[bounded] = x0[bounded] + (hi[bounded]-lo[bounded])*radius 
     89        # crop val at bounds 
     90        val[val<lo] = lo[val<lo] 
     91        val[val>hi] = hi[val>hi] 
     92        # handle collisions (when val[i] == x0[i]) 
     93        collision = val==x0 
     94        if numpy.any(collision): 
     95            rval = x0*(1-radius) 
     96            rval[rval==0] = -radius 
     97            rval[bounded] = x0[bounded] - (hi[bounded]-lo[bounded])*radius 
     98            val[collision] = rval[collision] 
     99        # make tolerance relative for bounded parameters 
     100     #  tol = numpy.ones(x0.shape)*xtol 
     101     #  tol[bounded] = (hi[bounded]-lo[bounded])*xtol 
     102     #  xtol = tol 
     103        return x0, val 
    62104 
    63105    def UpdateGenealogyRecords(self, id, newchild): 
     
    128170        disp=0         #non-zero to print convergence messages. 
    129171        retall=0 
     172        radius=0.05    #percentage change for initial simplex values 
    130173        if kwds.has_key('disp'): disp = kwds['disp'] 
     174        if kwds.has_key('radius'): radius = kwds['radius'] 
    131175        #------------------------------------------------------------- 
    132176 
     
    136180 
    137181        fcalls, func = wrap_function(func, args, EvaluationMonitor) 
     182        if self._useStrictRange: 
     183            func = wrap_bounds(func, self._strictMin, self._strictMax) 
    138184 
    139185        def handler(signum, frame): 
     
    195241            allvecs = [sim[0]] 
    196242        fsim[0] = func(x0) 
    197         nonzdelt = 0.05 
    198         zdelt = 0.00025 
     243 
     244        #--- ensure initial simplex is within bounds --- 
     245        x0,val = self.setSimplexWithinRangeBoundary(x0,radius) 
     246        #--- end bounds code --- 
    199247        for k in range(0,N): 
    200248            y = numpy.array(x0,copy=True) 
    201             if y[k] != 0: 
    202                 y[k] = (1+nonzdelt)*y[k] 
    203             else: 
    204                 y[k] = zdelt 
    205  
     249            y[k] = val[k] 
    206250            sim[k+1] = y 
    207251            f = func(y) 
     
    209253     
    210254        ind = numpy.argsort(fsim) 
    211         fsim = numpy.take(fsim,ind)  # sort so sim[0,:] has the lowest function value 
     255        fsim = numpy.take(fsim,ind) 
     256        # sort so sim[0,:] has the lowest function value 
    212257        sim = numpy.take(sim,ind,0) 
    213         self.bestSolution = sim[0] #XXX: goes here? 
    214         self.bestEnergy = min(fsim) #XXX: goes here? 
    215         self.population = sim #XXX: OK? 
    216         self.popEnergy = fsim #XXX: OK? 
     258        self.bestSolution = sim[0] 
     259        self.bestEnergy = min(fsim) 
     260        self.population = sim 
     261        self.popEnergy = fsim 
    217262 
    218263        iterations = 1 
     
    276321                allvecs.append(sim[0]) 
    277322 
    278             self.bestSolution = sim[0] #XXX: goes here? 
    279             self.bestEnergy = min(fsim) #XXX: goes here? 
    280             self.population = sim #XXX: OK? 
    281             self.popEnergy = fsim #XXX: OK? 
     323            self.bestSolution = sim[0] 
     324            self.bestEnergy = min(fsim) 
     325            self.population = sim 
     326            self.popEnergy = fsim 
    282327            self.energy_history.append(self.bestEnergy) 
    283328 
     
    326371    stepmon = Sow() 
    327372    evalmon = Sow() 
    328     from nmtools import IterationRelativeError as IRE 
     373    from mystic.nmtools import IterationRelativeError as IRE 
    329374 
    330375    solver = NelderMeadSimplexSolver(len(x0)) 
     
    375420    algor = [] 
    376421    x0 = [0.8,1.2,0.7] 
     422   #x0 = [0.8,1.2,1.7]                  #... better when using "bad" range 
     423    min = [-0.999, -0.999, 0.999]       #XXX: behaves badly when large range 
     424    max = [200.001, 100.001, numpy.inf] #... for >=1 x0 out of bounds; (up xtol) 
     425  # min = [-0.999, -0.999, -0.999] 
     426  # max = [200.001, 100.001, numpy.inf] 
     427 #  min = [-0.999, -0.999, 0.999] 
     428 #  max = [2.001, 1.001, 1.001] 
    377429    print "Nelder-Mead Simplex" 
    378430    print "===================" 
    379431    start = time.time() 
    380     from tools import VerboseSow 
     432    from mystic.tools import VerboseSow 
    381433    stepmon = VerboseSow(10) 
    382     from nmtools import IterationRelativeError as IRE 
     434    from mystic.nmtools import IterationRelativeError as IRE 
    383435 
    384436   #print fmin(__rosen,x0,retall=0,full_output=0) 
    385437    solver = NelderMeadSimplexSolver(len(x0)) 
    386438    solver.SetInitialPoints(x0) 
     439    solver.SetStrictRanges(min,max) 
    387440    solver.enable_signal_handler() 
    388     solver.Solve(__rosen,termination=IRE(),StepMonitor=stepmon) 
     441    solver.Solve(__rosen,termination=IRE(xtol=1e-5),StepMonitor=stepmon) 
    389442    print solver.Solution() 
    390443 
  • python/tools.py

    r82 r87  
    189189    return ncalls, function_wrapper 
    190190 
     191def wrap_bounds(function, min=None, max=None): 
     192    from numpy import asarray, any, inf 
     193    bounds = True 
     194    if min is not None and max is not None: #has upper & lower bound 
     195        min = asarray(min) 
     196        max = asarray(max) 
     197    elif min is not None: #has lower bound 
     198        min = asarray(min) 
     199        max = asarray([inf for i in min]) 
     200    elif max is not None: #has upper bound 
     201        max = asarray(max) 
     202        min = asarray([-inf for i in max]) 
     203    else: #not bounded 
     204        bounds = False 
     205    if bounds: 
     206        def function_wrapper(x): 
     207            if any((x<min)|(x>max)): #if violate bounds, evaluate as inf 
     208                return inf 
     209            return function(x) 
     210    else: 
     211        def function_wrapper(x): 
     212            return function(x) 
     213    return function_wrapper 
     214 
    191215def wrap_cf(CF, REG=None, cfmult = 1.0, regmult = 0.0): 
    192216    def _(*args, **kwargs): 
Note: See TracChangeset for help on using the changeset viewer.