Changeset 110


Ignore:
Timestamp:
03/11/09 00:40:03 (7 years ago)
Author:
mmckerns
Message:

added maxfun & scipy's callback to DE;
maxiter, maxfun are now kwds, with default=None (i.e. a large value);
move unroll from DE to tools.unpair

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • DEV_NOTES

    r109 r110  
    77 - use wrap_bounds instead of existing method (?) 
    88 - fix bug: DESolver throws error when given numpy.inf as a bound (!) 
    9  - add maxfun, disp, and scipy's callback to DESolver 
    109 - enable signal_handler & sigint_callback (?) for all 'one-liner' interfaces 
    1110 - DESolver needs documentation 
  • DEV_TODO

    r109 r110  
    77* Allow sigint_callback to take a list (i.e. provide call[i]) 
    88* Add "constraints" to models (design similar to pyre.inventory and validators) 
     9* Extend parallel launcher and communication to distributed services (gsl & idd) 
    910 
    1011INDIRECT: 
  • mystic/examples/test_ffitB.py

    r109 r110  
    2828    solver.Solve(ChebyshevCost, strategy, termination = VTR(0.01) , \ 
    2929                 maxiter= MAX_GENERATIONS, CrossProbability=1.0, ScalingFactor=0.9 , \ 
    30                  sigint_callback = plot_solution \ 
     30                 StepMonitor=VerboseSow(30), sigint_callback = plot_solution \ 
    3131                 ) 
    3232 
  • mystic/mystic/differential_evolution.py

    r109 r110  
    4545           'diffev'] 
    4646 
    47 from mystic.tools import Null, wrap_function 
     47from mystic.tools import Null, wrap_function, unpair 
    4848 
    4949from abstract_solver import AbstractSolver 
     
    9090 
    9191    def Solve(self, costfunction, strategy, termination, 
    92               maxiter, CrossProbability = 0.5, ScalingFactor = 0.7, 
    93               sigint_callback = None, 
    94               EvaluationMonitor=Null, StepMonitor=Null, ExtraArgs=()): 
     92              maxiter=None, maxfun=None, sigint_callback=None, 
     93              CrossProbability = 0.5, ScalingFactor = 0.7, 
     94              EvaluationMonitor=Null, StepMonitor=Null, ExtraArgs=(), **kwds): 
    9595        """Minimize a function using differential evolution. 
    9696 
     
    113113        """ 
    114114        #FIXME: Solve() interface does not conform to AbstractSolver interface 
     115        callback=None  #user-supplied function, called after each step 
     116        if kwds.has_key('callback'): callback = kwds['callback'] 
     117        #------------------------------------------------------------- 
     118 
    115119        import signal 
    116120        import mystic.termination as detools 
     
    159163        self.bestEnergy = 1.0E20 
    160164          
     165        if maxiter is None: 
     166            maxiter = self.nDim * self.nPop * 10  #XXX: set better defaults? 
     167        if maxfun is None: 
     168            maxfun = self.nDim * self.nPop * 1000 #XXX: set better defaults? 
     169        self._maxiter = maxiter 
     170        self._maxfun = maxfun 
     171 
    161172        generation = 0 
    162173        for generation in range(maxiter): 
    163174            StepMonitor(self.bestSolution[:], self.bestEnergy) 
     175            if fcalls[0] >= maxfun: break 
    164176            for candidate in range(self.nPop): 
    165177                # generate trialSolution (within valid range) 
     
    181193            #print "Generation %d has best cost function : %f" % (generation, self.bestEnergy) 
    182194            self.energy_history.append(self.bestEnergy) 
     195 
     196            if callback is not None: 
     197                callback(self.bestSolution) 
    183198             
    184199            if detools.EARLYEXIT or termination(self): 
     
    207222    """ 
    208223    def Solve(self, costfunction, strategy, termination, 
    209               maxiter, CrossProbability = 0.5, ScalingFactor = 0.7, 
    210               sigint_callback = None, 
    211               EvaluationMonitor=Null, StepMonitor=Null, ExtraArgs=()): 
     224              maxiter=None, maxfun=None, sigint_callback=None, 
     225              CrossProbability = 0.5, ScalingFactor = 0.7, 
     226              EvaluationMonitor=Null, StepMonitor=Null, ExtraArgs=(), **kwds): 
    212227        """Minimize a function using differential evolution. 
    213228 
     
    230245        """ 
    231246        #FIXME: Solve() interface does not conform to AbstractSolver interface 
     247        callback=None  #user-supplied function, called after each step 
     248        if kwds.has_key('callback'): callback = kwds['callback'] 
     249        #------------------------------------------------------------- 
     250 
    232251        import signal 
    233252        import mystic.termination as detools 
     
    274293        self.bestEnergy = 1.0E20 
    275294          
     295        if maxiter is None: 
     296            maxiter = self.nDim * self.nPop * 10  #XXX: set better defaults? 
     297        if maxfun is None: 
     298            maxfun = self.nDim * self.nPop * 1000 #XXX: set better defaults? 
     299        self._maxiter = maxiter 
     300        self._maxfun = maxfun 
     301 
    276302        trialPop = [[0.0 for i in range(self.nDim)] for j in range(self.nPop)] 
    277303 
     
    279305        for generation in range(maxiter): 
    280306            StepMonitor(self.bestSolution[:], self.bestEnergy) 
     307            if fcalls[0] >= maxfun: break 
    281308            for candidate in range(self.nPop): 
    282309                # generate trialSolution (within valid range) 
     
    301328            #print "Generation %d has best cost function : %f" % (generation, self.bestEnergy) 
    302329            self.energy_history.append(self.bestEnergy) 
     330 
     331            if callback is not None: 
     332                callback(self.bestSolution) 
    303333             
    304334            if detools.EARLYEXIT or termination(self): 
     
    313343 
    314344def diffev(func,x0,npop,args=(),bounds=None,ftol=5e-3,gtol=None, 
    315            maxiter=None,cross=1.0,scale=0.9, #maxfun=None, 
    316            full_output=0,disp=1,retall=0):   #,callback=None): 
     345           maxiter=None,maxfun=None,cross=1.0,scale=0.9, 
     346           full_output=0,disp=1,retall=0,callback=None): 
    317347    """interface for differential evolution that mimics scipy.optimize.fmin""" 
    318348 
     
    322352    from mystic.strategy import Best1Exp #, Best1Bin, Rand1Exp 
    323353    strategy = Best1Exp 
    324     if gtol: 
     354    if gtol: #if number of generations provided, use ChangeOverGeneration  
    325355        from mystic.termination import ChangeOverGeneration 
    326356        termination = ChangeOverGeneration(ftol,gtol) 
     
    329359        termination = VTR(ftol) 
    330360 
    331     def unroll(bounds): #TODO: move to tools? 
    332         from numpy import asarray 
    333         boundsT = asarray(bounds).transpose() 
    334         return [i.tolist() for i in boundsT] 
    335  
    336361    ND = len(x0) 
    337362    solver = DifferentialEvolutionSolver2(ND,npop) 
    338363    if bounds: 
    339         minb,maxb = unroll(bounds) 
     364        minb,maxb = unpair(bounds) 
    340365        solver.SetStrictRanges(minb,maxb) 
    341     try: 
    342         minb,maxb = unroll(x0) 
     366 
     367    try: #x0 passed as 1D array of (min,max) pairs 
     368        minb,maxb = unpair(x0) 
    343369        solver.SetRandomInitialPoints(minb,maxb) 
    344     except: 
     370    except: #x0 passed as 1D array of initial parameter values 
    345371        solver.SetInitialPoints(x0) 
    346372 
    347373   #solver.enable_signal_handler() 
    348     #TODO: add maxfun & disp to DESolve 
    349     #TODO: add scipy's (end-of-iteration) callback to DESolve 
     374    #XXX: move maxiter & maxfun kwds from Solve() to solver.SetLimits() ? 
    350375    #TODO: enable signal handlers & sigint_callbacks? for all minimal interfaces 
    351376    #FIXME: DESolve can't handle bounds of numpy.inf 
    352377    solver.Solve(func,strategy=strategy,termination=termination,\ 
    353                  maxiter=maxiter,\ 
    354                 #maxfun=maxfun,\ 
     378                 maxiter=maxiter,maxfun=maxfun,\ 
    355379                 CrossProbability=cross,ScalingFactor=scale,\ 
    356380                 EvaluationMonitor=evalmon,StepMonitor=stepmon,\ 
    357                 #sigint_callback=callback,\ 
    358                  ExtraArgs=args) 
     381                #sigint_callback=other_callback,\ 
     382                 ExtraArgs=args,callback=callback) 
    359383    solution = solver.Solution() 
    360384 
     
    368392    allvecs = stepmon.x 
    369393 
    370     from numpy import inf 
    371     maxfun=inf #XXX: maxfun not implemented for DESolvers 
    372     if fcalls >= maxfun: 
     394    if fcalls >= solver._maxfun: 
    373395        warnflag = 1 
    374396        if disp: 
    375397            print "Warning: Maximum number of function evaluations has "\ 
    376398                  "been exceeded." 
    377     elif iterations >= maxiter: 
     399    elif iterations >= solver._maxiter: 
    378400        warnflag = 2 
    379401        if disp: 
  • mystic/mystic/tools.py

    r107 r110  
    3333 
    3434 -- wrap_bounds : impose bounds on a funciton object 
     35 
     36 -- unpair : convert a 1D array of N pairs to two 1D arrays of N values 
    3537 
    3638""" 
     
    242244    return _ 
    243245 
     246 
     247def unpair(pairs): 
     248    '''convert a 1D array of N pairs to two 1D arrays of N values 
     249For example: 
     250    [a0,a1,a2],[b0,b1,b2] = unpair([(a0,b0),(a1,b1),(a2,b2)])''' 
     251    from numpy import asarray 
     252    pairsT = asarray(pairs).transpose() 
     253    return [i.tolist() for i in pairsT] 
     254 
     255 
    244256if __name__=='__main__': 
    245257    import doctest 
Note: See TracChangeset for help on using the changeset viewer.