Source code for pyec.distribution.ec.evoanneal

from pyec.distribution.convolution import Convolution
from pyec.distribution import Gaussian as SimpleGaussian
from pyec.distribution import BernoulliTernary as SimpleBernoulli
from pyec.distribution import FixedCube
from pyec.distribution.bayes.mutators import *
from pyec.distribution.bayes.structure.proposal import StructureProposal
from pyec.distribution.bayes.sample import DAGSampler
from pyec.distribution.ec.mutators import *
from pyec.distribution.ec.selectors import *
from pyec.config import Config, ConfigBuilder
from pyec.util.combinatorics import factorial

from scipy.special import erf

import logging
log = logging.getLogger(__file__)  

[docs]class REAConfigurator(ConfigBuilder): def __init__(self): super(REAConfigurator, self).__init__(EvolutionaryAnnealing) self.cfg.shiftToDb = True self.cfg.taylorDepth = 10 self.cfg.selection = "tournament" self.cfg.varInit = 1.0 self.cfg.varDecay = 2.5 self.cfg.varExp = 0.25 self.cfg.learningRate = 1.0 self.cfg.pressure = 0.025 self.cfg.crossover = "none" self.cfg.mutation = "gauss" self.cfg.activeField = "point" self.cfg.partition = True self.cfg.passArea = True def setTournament(self, pressure=0.025): self.cfg.selection = "tournament" self.cfg.taylorDepth = 0 self.cfg.pressure = pressure def setProportional(self, taylorDepth=100): self.cfg.taylorDepth = taylorDepth self.cfg.selection = "proportional" def setGaussian(self): self.cfg.mutation = "gauss" def setCauchy(self): self.cfg.mutation = "cauchy" def setCrossover(self, enable=True): if enable: self.cfg.crossover = "uniform" else: self.cfg.crossover = "none" def postConfigure(self, cfg): if cfg.bounded: cfg.initialDistribution = FixedCube(cfg) else: cfg.initialDistribution = SimpleGaussian(cfg)
[docs]class BEAConfigurator(REAConfigurator): def __init__(self): super(BEAConfigurator, self).__init__() self.setTournament() self.setCrossover() self.cfg.mutation = "bernoulli" self.cfg.binaryDepth=16 self.cfg.activeField="binary" def postConfigure(self, cfg): cfg.rawdim = cfg.dim cfg.rawscale = cfg.scale cfg.rawcenter = cfg.center cfg.dim = cfg.dim * cfg.binaryDepth cfg.center = .5 cfg.scale = .5 cfg.initialDistribution = SimpleBernoulli(cfg)
[docs]class BayesEAConfigurator(REAConfigurator): def __init__(self): super(BayesEAConfigurator, self).__init__() self.setTournament() self.cfg.varInit = 1.0 self.cfg.varDecay = 1.0 self.cfg.varExp = 0.25 self.cfg.bounded = False self.cfg.initialDistribution = None self.cfg.data = None self.cfg.randomizer = None self.cfg.sampler = DAGSampler() self.cfg.numVariables = None self.cfg.variableGenerator = None self.cfg.crossoverProb = 0.50 self.cfg.mutation = "structure" self.cfg.crossover = "none" self.cfg.activeField = "bayes" self.cfg.passArea = True self.cfg.learningRate = 0.005 self.cfg.branchFactor = 1000000 def setCrossover(self, merge=True, enable=True): if enable and merge: self.cfg.crossover = "merge" elif enable and not merge: self.cfg.crossover = "crossbayes" else: self.cfg.crossover = "none"
[docs]class EvolutionaryAnnealing(Convolution): """ Run the evolutionary annealing algorithm of Lockett and Miikkulainen (2011). """ def __init__(self, config): self.config = config self.binary = False if hasattr(config, 'varInit'): config.stddev = config.varInit self.selectors = [] if config.selection == "proportional": self.selectors.append(ProportionalAnnealing(config)) elif config.selection == "tournament": self.selectors.append(TournamentAnnealing(config)) else: raise Exception, "Unknown Selection" if len(self.selectors) == 1: self.selector = self.selectors[0] else: self.selector = Convolution(self.selectors, passScores = True) self.mutators = [] if hasattr(config, 'crossover') and config.crossover != "none": selector = self.selector if config.crossover == 'uniform': crosser = UniformCrosser(config) elif config.crossover == 'onePoint': crosser = OnePointCrosser(config) elif config.crossover == 'twoPoint': crosser = TwoPointCrosser(config) elif config.crossover == 'intermediate': crosser = IntermediateCrosser(config) elif config.crossover == 'merge': crosser = Merger() elif config.crossover == 'crossbayes': crosser = UniformBayesCrosser(config) else: raise Exception, "Unknown crossover method" order = 2 if hasattr(config, 'crossoverOrder'): order = int(config.crossoverOrder) else: config.crossoverOrder = order self.mutators.append(Crossover(selector, crosser, order)) if config.mutation == "gauss": if config.passArea: self.mutators.append(AreaSensitiveGaussian(config)) else: self.mutators.append(DecayedGaussian(config)) elif config.mutation == "uniform": config.passArea = False self.mutators.append(UniformArea(config)) elif config.mutation == "uniformBinary": self.binary = not self.config.binaryPartition config.passArea = True self.mutators.append(UniformAreaBernoulli(config)) elif config.mutation == "cauchy": self.mutators.append(DecayedCauchy(config)) elif config.mutation == "bernoulli": self.binary = not self.config.binaryPartition if config.passArea: self.mutators.append(AreaSensitiveBernoulli(config)) else: self.mutators.append(DecayedBernoulli(config)) elif config.mutation == "structure": if config.passArea: self.mutators.append(AreaSensitiveStructureMutator(config)) else: self.mutators.append(StructureMutator(config)) config.initialDistribution = StructureProposal(config) config.structureGenerator = config.initialDistribution self.mutator = Convolution(self.mutators) passScores = len(self.selectors) > 1 super(EvolutionaryAnnealing, self).__init__(self.selectors + self.mutators, config.initialDistribution, passScores) def convert(self, x): if self.binary: ns = array([i+1 for i in xrange(self.config.binaryDepth)] * self.config.rawdim) ms = .5 ** ns y = reshape(x.__mult__(ms), (self.config.binaryDepth, self.config.rawdim)) y = y.sum(axis=0).reshape(self.config.rawdim) return y * self.config.rawscale + self.config.rawcenter elif hasattr(self.config, 'convert') and self.config.convert: return x[:self.config.dim] return x @property def var(self): try: return self.mutators[-1].sd except: try: return self.mutators[-1].bitFlipProbs except: try: return self.mutators[-1].decay except: return 0.0 @classmethod def configurator(cls): return REAConfigurator(cls)