<s> """<STR_LIT>""" <EOL> from __future__ import division , print_function , absolute_import <EOL> import numpy as np <EOL> from scipy . optimize import OptimizeResult , minimize <EOL> from scipy . optimize . optimize import _status_message <EOL> import numbers <EOL> __all__ = [ '<STR_LIT>' ] <EOL> _MACHEPS = np . finfo ( np . float64 ) . eps <EOL> def differential_evolution ( func , bounds , args = ( ) , strategy = '<STR_LIT>' , <EOL> maxiter = <NUM_LIT:1000> , popsize = <NUM_LIT:15> , tol = <NUM_LIT> , <EOL> mutation = ( <NUM_LIT:0.5> , <NUM_LIT:1> ) , recombination = <NUM_LIT> , seed = None , <EOL> callback = None , disp = False , polish = True , <EOL> init = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> solver = DifferentialEvolutionSolver ( func , bounds , args = args , <EOL> strategy = strategy , maxiter = maxiter , <EOL> popsize = popsize , tol = tol , <EOL> mutation = mutation , <EOL> recombination = recombination , <EOL> seed = seed , polish = polish , <EOL> callback = callback , <EOL> disp = disp , <EOL> init = init ) <EOL> return solver . solve ( ) <EOL> class DifferentialEvolutionSolver ( object ) : <EOL> """<STR_LIT>""" <EOL> _binomial = { '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' } <EOL> _exponential = { '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' } <EOL> def __init__ ( self , func , bounds , args = ( ) , <EOL> strategy = '<STR_LIT>' , maxiter = <NUM_LIT:1000> , popsize = <NUM_LIT:15> , <EOL> tol = <NUM_LIT> , mutation = ( <NUM_LIT:0.5> , <NUM_LIT:1> ) , recombination = <NUM_LIT> , seed = None , <EOL> maxfun = np . inf , callback = None , disp = False , polish = True , <EOL> init = '<STR_LIT>' ) : <EOL> if strategy in self . _binomial : <EOL> self . mutation_func = getattr ( self , self . _binomial [ strategy ] ) <EOL> elif strategy in self . _exponential : <EOL> self . mutation_func = getattr ( self , self . _exponential [ strategy ] ) <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> self . strategy = strategy <EOL> self . callback = callback <EOL> self . polish = polish <EOL> self . tol = tol <EOL> self . scale = mutation <EOL> if ( not np . all ( np . isfinite ( mutation ) ) or <EOL> np . any ( np . array ( mutation ) >= <NUM_LIT:2> ) or <EOL> np . any ( np . array ( mutation ) < <NUM_LIT:0> ) ) : <EOL> raise ValueError ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> self . dither = None <EOL> if hasattr ( mutation , '<STR_LIT>' ) and len ( mutation ) > <NUM_LIT:1> : <EOL> self . dither = [ mutation [ <NUM_LIT:0> ] , mutation [ <NUM_LIT:1> ] ] <EOL> self . dither . sort ( ) <EOL> self . cross_over_probability = recombination <EOL> self . func = func <EOL> self . args = args <EOL> self . limits = np . array ( bounds , dtype = '<STR_LIT:float>' ) . T <EOL> if ( np . size ( self . limits , <NUM_LIT:0> ) != <NUM_LIT:2> or not <EOL> np . all ( np . isfinite ( self . limits ) ) ) : <EOL> raise ValueError ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> if maxiter is None : <EOL> maxiter = <NUM_LIT:1000> <EOL> self . maxiter = maxiter <EOL> if maxfun is None : <EOL> maxfun = np . inf <EOL> self . maxfun = maxfun <EOL> self . __scale_arg1 = <NUM_LIT:0.5> * ( self . limits [ <NUM_LIT:0> ] + self . limits [ <NUM_LIT:1> ] ) <EOL> self . __scale_arg2 = np . fabs ( self . limits [ <NUM_LIT:0> ] - self . limits [ <NUM_LIT:1> ] ) <EOL> self . parameter_count = np . size ( self . limits , <NUM_LIT:1> ) <EOL> self . random_number_generator = _make_random_gen ( seed ) <EOL> self . num_population_members = popsize * self . parameter_count <EOL> self . population_shape = ( self . num_population_members , <EOL> self . parameter_count ) <EOL> self . _nfev = <NUM_LIT:0> <EOL> if init == '<STR_LIT>' : <EOL> self . init_population_lhs ( ) <EOL> elif init == '<STR_LIT>' : <EOL> self . init_population_random ( ) <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> self . disp = disp <EOL> def init_population_lhs ( self ) : <EOL> """<STR_LIT>""" <EOL> rng = self . random_number_generator <EOL> segsize = <NUM_LIT:1.0> / self . num_population_members <EOL> samples = ( segsize * rng . random_sample ( self . population_shape ) <EOL> + np . linspace ( <NUM_LIT:0.> , <NUM_LIT:1.> , self . num_population_members , <EOL> endpoint = False ) [ : , np . newaxis ] ) <EOL> self . population = np . zeros_like ( samples ) <EOL> for j in range ( self . parameter_count ) : <EOL> order = rng . permutation ( range ( self . num_population_members ) ) <EOL> self . population [ : , j ] = samples [ order , j ] <EOL> self . population_energies = ( np . ones ( self . num_population_members ) * <EOL> np . inf ) <EOL> self . _nfev = <NUM_LIT:0> <EOL> def init_population_random ( self ) : <EOL> """<STR_LIT>""" <EOL> rng = self . random_number_generator <EOL> self . population = rng . random_sample ( self . population_shape ) <EOL> self . population_energies = ( np . ones ( self . num_population_members ) * <EOL> np . inf ) <EOL> self . _nfev = <NUM_LIT:0> <EOL> @ property <EOL> def x ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _scale_parameters ( self . population [ <NUM_LIT:0> ] ) <EOL> @ property <EOL> def convergence ( self ) : <EOL> """<STR_LIT>""" <EOL> return ( np . std ( self . population_energies ) / <EOL> np . abs ( np . mean ( self . population_energies ) + _MACHEPS ) ) <EOL> def solve ( self ) : <EOL> """<STR_LIT>""" <EOL> nit , warning_flag = <NUM_LIT:0> , False <EOL> status_message = _status_message [ '<STR_LIT:success>' ] <EOL> if np . all ( np . isinf ( self . population_energies ) ) : <EOL> self . _calculate_population_energies ( ) <EOL> for nit in range ( <NUM_LIT:1> , self . maxiter + <NUM_LIT:1> ) : <EOL> try : <EOL> next ( self ) <EOL> except StopIteration : <EOL> warning_flag = True <EOL> status_message = _status_message [ '<STR_LIT>' ] <EOL> break <EOL> if self . disp : <EOL> print ( "<STR_LIT>" <EOL> % ( nit , <EOL> self . population_energies [ <NUM_LIT:0> ] ) ) <EOL> convergence = self . convergence <EOL> if ( self . callback and <EOL> self . callback ( self . _scale_parameters ( self . population [ <NUM_LIT:0> ] ) , <EOL> convergence = self . tol / convergence ) is True ) : <EOL> warning_flag = True <EOL> status_message = ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> break <EOL> if convergence < self . tol or warning_flag : <EOL> break <EOL> else : <EOL> status_message = _status_message [ '<STR_LIT>' ] <EOL> warning_flag = True <EOL> DE_result = OptimizeResult ( <EOL> x = self . x , <EOL> fun = self . population_energies [ <NUM_LIT:0> ] , <EOL> nfev = self . _nfev , <EOL> nit = nit , <EOL> message = status_message , <EOL> success = ( warning_flag is not True ) ) <EOL> if self . polish : <EOL> result = minimize ( self . func , <EOL> np . copy ( DE_result . x ) , <EOL> method = '<STR_LIT>' , <EOL> bounds = self . limits . T , <EOL> args = self . args ) <EOL> self . _nfev += result . nfev <EOL> DE_result . nfev = self . _nfev <EOL> if result . fun < DE_result . fun : <EOL> DE_result . fun = result . fun <EOL> DE_result . x = result . x <EOL> DE_result . jac = result . jac <EOL> self . population_energies [ <NUM_LIT:0> ] = result . fun <EOL> self . population [ <NUM_LIT:0> ] = self . _unscale_parameters ( result . x ) <EOL> return DE_result <EOL> def _calculate_population_energies ( self ) : <EOL> """<STR_LIT>""" <EOL> for index , candidate in enumerate ( self . population ) : <EOL> if self . _nfev > self . maxfun : <EOL> break <EOL> parameters = self . _scale_parameters ( candidate ) <EOL> self . population_energies [ index ] = self . func ( parameters , <EOL> * self . args ) <EOL> self . _nfev += <NUM_LIT:1> <EOL> minval = np . argmin ( self . population_energies ) <EOL> lowest_energy = self . population_energies [ minval ] <EOL> self . population_energies [ minval ] = self . population_energies [ <NUM_LIT:0> ] <EOL> self . population_energies [ <NUM_LIT:0> ] = lowest_energy <EOL> self . population [ [ <NUM_LIT:0> , minval ] , : ] = self . population [ [ minval , <NUM_LIT:0> ] , : ] <EOL> def __iter__ ( self ) : <EOL> return self <EOL> def __next__ ( self ) : <EOL> """<STR_LIT>""" <EOL> if np . all ( np . isinf ( self . population_energies ) ) : <EOL> self . _calculate_population_energies ( ) <EOL> if self . dither is not None : <EOL> self . scale = ( self . random_number_generator . rand ( ) <EOL> * ( self . dither [ <NUM_LIT:1> ] - self . dither [ <NUM_LIT:0> ] ) + self . dither [ <NUM_LIT:0> ] ) <EOL> for candidate in range ( self . num_population_members ) : <EOL> if self . _nfev > self . maxfun : <EOL> raise StopIteration <EOL> trial = self . _mutate ( candidate ) <EOL> self . _ensure_constraint ( trial ) <EOL> parameters = self . _scale_parameters ( trial ) <EOL> energy = self . func ( parameters , * self . args ) <EOL> self . _nfev += <NUM_LIT:1> <EOL> if energy < self . population_energies [ candidate ] : <EOL> self . population [ candidate ] = trial <EOL> self . population_energies [ candidate ] = energy <EOL> if energy < self . population_energies [ <NUM_LIT:0> ] : <EOL> self . population_energies [ <NUM_LIT:0> ] = energy <EOL> self . population [ <NUM_LIT:0> ] = trial <EOL> return self . x , self . population_energies [ <NUM_LIT:0> ] <EOL> def next ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . __next__ ( ) <EOL> def _scale_parameters ( self , trial ) : <EOL> """<STR_LIT>""" <EOL> return self . __scale_arg1 + ( trial - <NUM_LIT:0.5> ) * self . __scale_arg2 <EOL> def _unscale_parameters ( self , parameters ) : <EOL> """<STR_LIT>""" <EOL> return ( parameters - self . __scale_arg1 ) / self . __scale_arg2 + <NUM_LIT:0.5> <EOL> def _ensure_constraint ( self , trial ) : <EOL> """<STR_LIT>""" <EOL> for index , param in enumerate ( trial ) : <EOL> if param > <NUM_LIT:1> or param < <NUM_LIT:0> : <EOL> trial [ index ] = self . random_number_generator . rand ( ) <EOL> def _mutate ( self , candidate ) : <EOL> """<STR_LIT>""" <EOL> trial = np . copy ( self . population [ candidate ] ) <EOL> rng = self . random_number_generator <EOL> fill_point = rng . randint ( <NUM_LIT:0> , self . parameter_count ) <EOL> if ( self . strategy == '<STR_LIT>' or <EOL> self . strategy == '<STR_LIT>' ) : <EOL> bprime = self . mutation_func ( candidate , <EOL> self . _select_samples ( candidate , <NUM_LIT:5> ) ) <EOL> else : <EOL> bprime = self . mutation_func ( self . _select_samples ( candidate , <NUM_LIT:5> ) ) <EOL> if self . strategy in self . _binomial : <EOL> crossovers = rng . rand ( self . parameter_count ) <EOL> crossovers = crossovers < self . cross_over_probability <EOL> crossovers [ fill_point ] = True <EOL> trial = np . where ( crossovers , bprime , trial ) <EOL> return trial <EOL> elif self . strategy in self . _exponential : <EOL> i = <NUM_LIT:0> <EOL> while ( i < self . parameter_count and <EOL> rng . rand ( ) < self . cross_over_probability ) : <EOL> trial [ fill_point ] = bprime [ fill_point ] <EOL> fill_point = ( fill_point + <NUM_LIT:1> ) % self . parameter_count <EOL> i += <NUM_LIT:1> <EOL> return trial <EOL> def _best1 ( self , samples ) : <EOL> """<STR_LIT>""" <EOL> r0 , r1 = samples [ : <NUM_LIT:2> ] <EOL> return ( self . population [ <NUM_LIT:0> ] + self . scale * <EOL> ( self . population [ r0 ] - self . population [ r1 ] ) ) <EOL> def _rand1 ( self , samples ) : <EOL> """<STR_LIT>""" <EOL> r0 , r1 , r2 = samples [ : <NUM_LIT:3> ] <EOL> return ( self . population [ r0 ] + self . scale * <EOL> ( self . population [ r1 ] - self . population [ r2 ] ) ) <EOL> def _randtobest1 ( self , candidate , samples ) : <EOL> """<STR_LIT>""" <EOL> r0 , r1 = samples [ : <NUM_LIT:2> ] <EOL> bprime = np . copy ( self . population [ candidate ] ) <EOL> bprime += self . scale * ( self . population [ <NUM_LIT:0> ] - bprime ) <EOL> bprime += self . scale * ( self . population [ r0 ] - <EOL> self . population [ r1 ] ) <EOL> return bprime <EOL> def _best2 ( self , samples ) : <EOL> """<STR_LIT>""" <EOL> r0 , r1 , r2 , r3 = samples [ : <NUM_LIT:4> ] <EOL> bprime = ( self . population [ <NUM_LIT:0> ] + self . scale * <EOL> ( self . population [ r0 ] + self . population [ r1 ] - <EOL> self . population [ r2 ] - self . population [ r3 ] ) ) <EOL> return bprime <EOL> def _rand2 ( self , samples ) : <EOL> """<STR_LIT>""" <EOL> r0 , r1 , r2 , r3 , r4 = samples <EOL> bprime = ( self . population [ r0 ] + self . scale * <EOL> ( self . population [ r1 ] + self . population [ r2 ] - <EOL> self . population [ r3 ] - self . population [ r4 ] ) ) <EOL> return bprime <EOL> def _select_samples ( self , candidate , number_samples ) : <EOL> """<STR_LIT>""" <EOL> idxs = list ( range ( self . num_population_members ) ) <EOL> idxs . remove ( candidate ) <EOL> self . random_number_generator . shuffle ( idxs ) <EOL> idxs = idxs [ : number_samples ] <EOL> return idxs <EOL> def _make_random_gen ( seed ) : <EOL> """<STR_LIT>""" <EOL> if seed is None or seed is np . random : <EOL> return np . random . mtrand . _rand <EOL> if isinstance ( seed , ( numbers . Integral , np . integer ) ) : <EOL> return np . random . RandomState ( seed ) <EOL> if isinstance ( seed , np . random . RandomState ) : <EOL> return seed <EOL> raise ValueError ( '<STR_LIT>' <EOL> '<STR_LIT>' % seed ) </s>
