def add_v(self, cfg, v): """ Add a velocity to the position """ new = self.copy(cfg) for p in self.params: if isinstance(p, manipulator.PermutationParameter): p.apply_swaps(v[p.name], new) else: p.sum(new, v, cfg) return new def crossover(self, cfg1, cfg2): for p in self.params: if p.is_permutation() and p.size>6: # Select crossover operator new = getattr(p, self.crossover_choice)(cfg1, cfg2)[0] else: # crossover undefined for non-permutations pass return new technique.register(PSO(crossover = 'OX3')) technique.register(PSO(crossover = 'OX1')) technique.register(PSO(crossover = 'PMX')) technique.register(PSO(crossover = 'PX')) technique.register(PSO(crossover = 'CX'))
}, 'loggers': { '': { 'handlers': ['console', 'file'], 'level': 'INFO', 'propagate': True } } }) # Avoid initializing the logging again. opentuner.tuningrunmain.init_logging = lambda: None ####################################################################################################################### register( BayesianOptimization([ CumulativeModel(SimpleLatencyModel(), GaussianProcess(), "run_time"), CumulativeModel(SimpleLutCountModel(), GaussianProcess(), "luts"), CumulativeModel(SimpleRegisterCountModel(), GaussianProcess(), "regs"), CumulativeModel(SimpleDspCountModel(), GaussianProcess(), "dsps"), CumulativeModel(SimpleBramCountModel(), GaussianProcess(), "brams") ], name="CombinedModel")) ####################################################################################################################### if __name__ == '__main__': HLSTuner().main()
phi_g: influence of the particle's distance to the global best position, a float in range [0,1] """ self.manipulator = m self.position = self.manipulator.random() self.best = self.position self.omega = omega self.phi_l = phi_l self.phi_g = phi_g self.crossover_choice = crossover_choice self.velocity = {} for p in self.manipulator.params: # Velocity as a continous value self.velocity[p.name]=0 def move(self, global_best): """ Update parameter values using corresponding operators. TODO: introduce operator choice map """ m = self.manipulator for p in m.params: self.velocity[p.name] = p.op3_swarm(self.position, global_best, self.best, c=self.omega, c1=self.phi_g, c2=self.phi_l, xchoice=self.crossover_choice, velocity=self.velocity[p.name]) technique.register(PSO(crossover = 'op3_cross_OX3')) technique.register(PSO(crossover = 'op3_cross_OX1')) technique.register(PSO(crossover = 'op3_cross_PMX')) technique.register(PSO(crossover = 'op3_cross_PX')) technique.register(PSO(crossover = 'op3_cross_CX'))
params = self.manipulator.parameters(cfg1) for param in params: if param.is_permutation() and param.size>6: getattr(param, self.crossover_op)(new, cfg1, cfg2, d=param.size/3) return new class UniformGreedyMutation(GreedySelectionMixin, EvolutionaryTechnique): pass class NormalGreedyMutation(NormalMutationMixin, GreedySelectionMixin, EvolutionaryTechnique): pass class GA(CrossoverMixin, UniformGreedyMutation): pass technique.register(GA(crossover = 'OX3', mutation_rate=0.10, crossover_rate=0.8)) technique.register(GA(crossover = 'OX1', mutation_rate=0.10,crossover_rate=0.8)) technique.register(GA(crossover = 'PX', mutation_rate=0.10, crossover_rate=0.8)) technique.register(GA(crossover = 'CX', mutation_rate=0.10, crossover_rate=0.8)) technique.register(GA(crossover = 'PMX', mutation_rate=0.10, crossover_rate=0.8)) technique.register(UniformGreedyMutation(name='ga-base', mutation_rate=0.10)) technique.register(UniformGreedyMutation(name='UniformGreedyMutation05', mutation_rate=0.05)) technique.register(UniformGreedyMutation(name='UniformGreedyMutation10', mutation_rate=0.10)) technique.register(UniformGreedyMutation(name='UniformGreedyMutation20', mutation_rate=0.20)) technique.register(NormalGreedyMutation(name='NormalGreedyMutation05', mutation_rate=0.05)) technique.register(NormalGreedyMutation(name='NormalGreedyMutation10', mutation_rate=0.10)) technique.register(NormalGreedyMutation(name='NormalGreedyMutation20', mutation_rate=0.20))
# Return the configuration. return dr def select_technique_order(self): """ Select the next technique to use. """ # We have only one technique, so the order is obvious. return self.techniques def on_technique_result(self, technique, result): """ This callback is invoked by the search driver to report the results of the sub-technique. """ # Check if synthesis ended in a state that indicates that too many resources are used. There are probably more # applicable errors, but I haven't observed them yet. if result.state == "PE3" or result.state == "PE4" or result.state == "IE3" or result.state == "IE6": # Keep the user in the loop. log.info("Added constraint to space contractor.") # Add the configuration of the result to the list. self.constraints.append(result.configuration.data) # Add the space contractor technique to the list such that we can use it. register( SpaceContractorMetaTechnique(GreedyLearningTechnique(RandomForest()), name="SpaceContractorRandomForest"))
if unit_value < 1.0: # produce new config with param set step_size higher up_cfg = manipulator.copy(center.data) param.set_unit_value(up_cfg, min(1.0, unit_value + step_size)) up_cfg = driver.get_configuration(up_cfg) self.yield_nonblocking(up_cfg) points.append(up_cfg) else: # ComplexParameter for mutate_function in param.manipulators(center.data): cfg = manipulator.copy(center.data) mutate_function(cfg) cfg = driver.get_configuration(cfg) self.yield_nonblocking(cfg) points.append(cfg) yield None # wait for all results if objective.lt(driver.best_result.configuration, center): # a new global best switch to that center = driver.best_result.configuration else: # no better point, shrink the pattern step_size /= 2.0 # register our new technique in global list technique.register(PatternSearch())
getattr(param, self.crossover_op)(new, cfg1, cfg2, d=param.size / 3) break return new class UniformGreedyMutation(GreedySelectionMixin, EvolutionaryTechnique): pass class NormalGreedyMutation(NormalMutationMixin, GreedySelectionMixin, EvolutionaryTechnique): pass class GA(CrossoverMixin, UniformGreedyMutation): pass technique.register(GA(crossover="OX3", mutation_rate=0.10, crossover_rate=0.8)) technique.register(GA(crossover="OX1", mutation_rate=0.10, crossover_rate=0.8)) technique.register(GA(crossover="PX", mutation_rate=0.10, crossover_rate=0.8)) technique.register(GA(crossover="CX", mutation_rate=0.10, crossover_rate=0.8)) technique.register(GA(crossover="PMX", mutation_rate=0.10, crossover_rate=0.8)) technique.register(UniformGreedyMutation(name="ga-base", mutation_rate=0.10)) technique.register(UniformGreedyMutation(name="UniformGreedyMutation05", mutation_rate=0.05)) technique.register(UniformGreedyMutation(name="UniformGreedyMutation10", mutation_rate=0.10)) technique.register(UniformGreedyMutation(name="UniformGreedyMutation20", mutation_rate=0.20)) technique.register(NormalGreedyMutation(name="NormalGreedyMutation05", mutation_rate=0.05)) technique.register(NormalGreedyMutation(name="NormalGreedyMutation10", mutation_rate=0.10)) technique.register(NormalGreedyMutation(name="NormalGreedyMutation20", mutation_rate=0.20))
# print "unit:", unit_value # manipulate complex parameter else: # print "name:", param.name param.set_value(new_cfg, row[names.index(param.name)]) yield driver.get_configuration(new_cfg) # for row in data: # for index, key in enumerate(center): # idx = names.index(key) # center[key] = row[idx] # yield driver.get_configuration(center) # default in random fashion while True: print('[WARNING] random for readHistory') yield driver.get_configuration(manipulator.random()) # read database and history import os, glob try: num = glob.glob('sub-db-*.db')[0].replace('.db', '').split('-')[-1] fileName = os.path.join(os.getcwd(), glob.glob('sub-db-*.db')[0]) except: num, fileName = 0, None # register our new technique in global list technique.register(BasicHistoryRead(num, fileName))
class ExhaustiveSearchTechnique(AsyncProceduralSearchTechnique): """ Exhaustive search """ def main_generator(self): """ Suggest a new configuration to evaluate. """ cfg = self.manipulator.seed_config() # Obtain a list with all parameters. params = self.manipulator.parameters(cfg) for inst in product(*[param.get_values() for param in params]): # Create a configuration. cfg = {} log.info( str([param.name for param in params]) + " = (" + ', '.join(map(repr, inst)) + ")") for i in range(len(params)): cfg[params[i].name] = inst[i] # Return the configuration. yield self.driver.get_configuration(cfg) register(ExhaustiveSearchTechnique(name="ExhaustiveSearch"))
while True: points = list() # get current value of param, scaled to be in range [0.0, 1.0] unit_value = param.get_unit_value(current_cfg.data) print unit_value points.append(current_cfg) if unit_value < 1.0: # produce new config with param set step_size higher up_cfg = manipulator.copy(current_cfg.data) param.set_unit_value(up_cfg, min(1.0, unit_value + step_size)) up_cfg = driver.get_configuration(up_cfg) yield up_cfg points.append(up_cfg) #sort points by quality, best point will be points[0], worst is points[-1] # points.sort(cmp=objective.compare) current_cfg = points[-1] # if objective.lt(points[0], center): # # we found a better point, move there # center = points[0] # else: # # no better point, shrink the pattern # step_size /= 2.0 # register our new technique in global list technique.register(RegularStepSearch())
if unit_value > 0.0: down_cfg = manipulator.copy(center.data) param.set_unit_value(down_cfg, max(0.0, unit_value - step_size)) down_cfg = driver.get_configuration(down_cfg) yield down_cfg points.append(down_cfg) if unit_value < 1.0: up_cfg = manipulator.copy(center.data) param.set_unit_value(up_cfg, min(1.0, unit_value + step_size)) up_cfg = driver.get_configuration(up_cfg) yield up_cfg points.append(up_cfg) points.sort(key=cmp_to_key(objective.compare)) if objective.lt(points[0], center): center = points[0] else: step_size /= 2.0 # register our new technique in global list technique.register(BasicPatternSearch())
if isinstance(p, sjparameters.sjCompositionParameter): p.equal_division(seed_config) elif isinstance(p, sjparameters.sjPermutationParameter): pass #p.set_value(config, p.seed_value()) else: seed_config[p.name] = p.value seed_config['multiplier'] = m seed_configs.append(seed_config) # The default bandit, plus our custom techniques. from opentuner.search import technique, bandittechniques, differentialevolution, evolutionarytechniques, simplextechniques technique.register( bandittechniques.AUCBanditMetaTechnique([ sjtechniques.FixedTechnique(seed_configs), differentialevolution.DifferentialEvolutionAlt(), evolutionarytechniques.UniformGreedyMutation(), evolutionarytechniques.NormalGreedyMutation(mutation_rate=0.3), simplextechniques.RandomNelderMead(), sjtechniques.ForceRemove(), sjtechniques.ForceFuse(), sjtechniques.ForceUnbox(), sjtechniques.ForceEqualDivision(), sjtechniques.CrossSocketBeforeHyperthreadingAffinity(), ], name="StreamJITBandit")) mi = StreamJITMI(args, cfg, jvm_options, manipulator, FixedInputManager(), MinimizeTime()) m = TuningRunMain(mi, args) m.main()
else: # crossover undefined for non-permutations pass if len(new)>1: # the offspring from cfg1 new = new[0] return new class OXMixin(object): def crossover(self, cfgs): ''' Crossover the first permtation parameter, if found, of two parents and return one offspring cfg ''' cfg1, cfg2, = cfgs params = self.manipulator.parameters(cfg) for param in params: if param.is_permutation(): new = param.OX3(cfg1, cfg2)[0] # TODO: take both offsprings return new return cfg1 technique.register(PSO(name='pso-ox'))
for mutate_function in param.manipulators(center.data): cfg = manipulator.copy(center.data) mutate_function(cfg) cfg = driver.get_configuration(cfg) self.yield_nonblocking(cfg) points.append(cfg) yield None # wait for all results #sort points by quality, best point will be points[0], worst is points[-1] points.sort(cmp=objective.compare) if (objective.lt(driver.best_result.configuration, center) and driver.best_result.configuration != points[0]): # another technique found a new global best, switch to that center = driver.best_result.configuration elif objective.lt(points[0], center): # we found a better point, move there center = points[0] else: # no better point, shrink the pattern step_size /= 2.0 # register our new technique in global list technique.register(PatternSearch())
for m in seed_multipliers: seed_config = manipulator.seed_config() for p in cfg.getAllParameters().values() + jvm_options.values(): if isinstance(p, sjparameters.sjCompositionParameter): p.equal_division(seed_config) elif isinstance(p, sjparameters.sjPermutationParameter): pass #p.set_value(config, p.seed_value()) else: seed_config[p.name] = p.value seed_config['multiplier'] = m seed_configs.append(seed_config) # The default bandit, plus our custom techniques. from opentuner.search import technique, bandittechniques, differentialevolution, evolutionarytechniques, simplextechniques technique.register(bandittechniques.AUCBanditMetaTechnique([ sjtechniques.FixedTechnique(seed_configs), differentialevolution.DifferentialEvolutionAlt(), evolutionarytechniques.UniformGreedyMutation(), evolutionarytechniques.NormalGreedyMutation(mutation_rate=0.3), simplextechniques.RandomNelderMead(), sjtechniques.ForceRemove(), sjtechniques.ForceFuse(), sjtechniques.ForceUnbox(), sjtechniques.ForceEqualDivision(), sjtechniques.CrossSocketBeforeHyperthreadingAffinity(), ], name = "StreamJITBandit")) mi = StreamJITMI(args, cfg, jvm_options, manipulator, FixedInputManager(), MinimizeTime()) m = TuningRunMain(mi, args) m.main()
class UniformGreedyMutation(GreedySelectionMixin, EvolutionaryTechnique): pass class NormalGreedyMutation(NormalMutationMixin, GreedySelectionMixin, EvolutionaryTechnique): pass class GA(CrossoverMixin, UniformGreedyMutation): pass technique.register(GA(crossover='OX3', mutation_rate=0.10, crossover_rate=0.8)) technique.register(GA(crossover='OX1', mutation_rate=0.10, crossover_rate=0.8)) technique.register(GA(crossover='PX', mutation_rate=0.10, crossover_rate=0.8)) technique.register(GA(crossover='CX', mutation_rate=0.10, crossover_rate=0.8)) technique.register(GA(crossover='PMX', mutation_rate=0.10, crossover_rate=0.8)) technique.register(UniformGreedyMutation(name='ga-base', mutation_rate=0.10)) technique.register( UniformGreedyMutation(name='UniformGreedyMutation05', mutation_rate=0.05)) technique.register( UniformGreedyMutation(name='UniformGreedyMutation10', mutation_rate=0.10)) technique.register( UniformGreedyMutation(name='UniformGreedyMutation20', mutation_rate=0.20)) technique.register( NormalGreedyMutation(name='NormalGreedyMutation05', mutation_rate=0.05)) technique.register(
return self.driver.best_result.configuration.data else: return self.manipulator.random() class NormalMutationMixin(object): """ Mutate primitive parameters according to normal distribution """ def __init__(self, sigma = 0.1, *pargs, **kwargs): super(NormalMutationMixin, self).__init__(*pargs, **kwargs) self.sigma = sigma def mutate_param(self, cfg, param): """ mutate single parameter of cfg in place """ if param.is_primitive(): param.op1_normal_mutation(cfg, self.sigma) else: random.choice(param.manipulators(cfg))(cfg) class UniformGreedyMutation(GreedySelectionMixin, GlobalEvolutionaryTechnique): pass class NormalGreedyMutation(NormalMutationMixin, GreedySelectionMixin, GlobalEvolutionaryTechnique): pass technique.register(NormalGreedyMutation( crossover_rate=0.5, crossover_strength=0.2, name='GGA'))
""" Mutate primitive parameters according to normal distribution """ def __init__(self, sigma=0.1, *pargs, **kwargs): super(NormalMutationMixin, self).__init__(*pargs, **kwargs) self.sigma = sigma def mutate_param(self, cfg, param): """ mutate single parameter of cfg in place """ if param.is_primitive(): param.op1_normal_mutation(cfg, self.sigma) else: random.choice(param.manipulators(cfg))(cfg) class UniformGreedyMutation(GreedySelectionMixin, GlobalEvolutionaryTechnique): pass class NormalGreedyMutation(NormalMutationMixin, GreedySelectionMixin, GlobalEvolutionaryTechnique): pass technique.register( NormalGreedyMutation(crossover_rate=0.5, crossover_strength=0.2, name='GGA'))
return one offspring cfg ''' cfg1, cfg2, = cfgs params = self.manipulator.parameters(cfg) for param in params: if param.is_permutation(): new = param.OX3(cfg1, cfg2)[0] # TODO: take both offsprings return new return cfg1 class UniformGreedyMutation(GreedySelectionMixin, EvolutionaryTechnique): pass class NormalGreedyMutation(NormalMutationMixin, GreedySelectionMixin, EvolutionaryTechnique): pass class OXGA(OXMixin, UniformGreedyMutation): pass technique.register(OXGA(name='ga-ox', mutation_rate=0.01)) technique.register(UniformGreedyMutation(name='UniformGreedyMutation05', mutation_rate=0.05)) technique.register(UniformGreedyMutation(name='UniformGreedyMutation10', mutation_rate=0.10)) technique.register(UniformGreedyMutation(name='UniformGreedyMutation20', mutation_rate=0.20)) technique.register(NormalGreedyMutation(name='NormalGreedyMutation05', mutation_rate=0.05)) technique.register(NormalGreedyMutation(name='NormalGreedyMutation10', mutation_rate=0.10)) technique.register(NormalGreedyMutation(name='NormalGreedyMutation20', mutation_rate=0.20))
start = time.time() # Retrain the regressor. self.regressor.fit(X, Y) # Compute the training time. training_time = time.time() - start # Compute the number of trees that we need to spend the desired amount of time on training. trees = self.trees * TRAINING_TIME / training_time # Update the number of trees slowly to avoid instabilities due to measurement inaccuracies. self.trees = int((1 - UPDATE_FACTOR) * self.trees + UPDATE_FACTOR * trees) # Update the size of the data set. self.data_size = len(self.data_set) # Make a prediction for the configuration. return self.regressor.predict([cfg.values()])[0] def estimate_uncertainty(self, cfg): """ Give a measure of uncertainty for the given configuration. Random forests don't give uncertainty measures. """ return 0 # Add the random forest model to the list such that we can use it. register(GreedyLearningTechnique(RandomForest(), name="RandomForest"))
# param.set_unit_value(next_cfg,unit_value) next_cfg = driver.get_configuration(next_cfg) yield next_cfg # print(type(next_cfg)) points.append(next_cfg) elif int(center.data['opt_level']) < 3: go_cfg = manipulator.copy(center.data) opt_level_next = int(go_cfg['opt_level']) + 1 go_cfg['opt_level'] = opt_level_next go_cfg['blockSize'] = str(8) # print('go_cfg',go_cfg) go_cfg = driver.get_configuration(go_cfg) yield go_cfg points.append(go_cfg) else: points.append(center) sys.exit() points.sort(key=cmp_to_key(objective.compare)) # print('points',points) # print('points[0]',points[0]) center = points[0] if objective.lt(points[0], best): best = points[0] # register our new technique in global list technique.register(GridSearch())
self.phi_l = phi_l self.phi_g = phi_g self.crossover_choice = crossover_choice self.velocity = {} for p in self.manipulator.params: # Velocity as a continous value self.velocity[p.name] = 0 def move(self, global_best): """ Update parameter values using corresponding operators. TODO: introduce operator choice map """ m = self.manipulator for p in m.params: self.velocity[p.name] = p.op3_swarm(self.position, global_best, self.best, c=self.omega, c1=self.phi_g, c2=self.phi_l, xchoice=self.crossover_choice, velocity=self.velocity[p.name]) technique.register(PSO(crossover='op3_cross_OX3')) technique.register(PSO(crossover='op3_cross_OX1')) technique.register(PSO(crossover='op3_cross_PMX')) technique.register(PSO(crossover='op3_cross_PX')) technique.register(PSO(crossover='op3_cross_CX'))
Mean of distribution std_dev : float Standard deviation of distribution Returns ------- float Probability density """ if std_dev != 0.0: return norm.cdf(value, mean, std_dev) elif value < mean: return 0.0 elif value > mean: return 1.0 else: return 0.5 ####################################################################################################################### register( BayesianOptimization([ GaussianProcess("run_time"), GaussianProcess("luts"), GaussianProcess("regs"), GaussianProcess("dsps"), GaussianProcess("brams") ], name="BayesianOptimization"))
self.phi_l = phi_l self.phi_g = phi_g self.crossover_choice = crossover_choice self.velocity = {} for p in self.manipulator.params: # Velocity as a continous value self.velocity[p.name] = 0 def move(self, global_best): """ Update parameter values using corresponding operators. TODO: introduce operator choice map """ m = self.manipulator for p in m.params: self.velocity[p.name] = p.sv_swarm(self.position, global_best, self.best, c=self.omega, c1=self.phi_g, c2=self.phi_l, c_choice=self.crossover_choice, velocity=self.velocity[p.name]) technique.register(PSO(crossover='OX3')) technique.register(PSO(crossover='OX1')) technique.register(PSO(crossover='PMX')) technique.register(PSO(crossover='PX')) technique.register(PSO(crossover='CX'))
if random.random() < self.crossover_rate: return [self.select(), self.select()] else: return [self.select()] @abc.abstractmethod def select(self): """return a single random parent configuration""" return cfg class GreedySelectionMixin(object): """ EvolutionaryTechnique mixin for greedily selecting the best known configuration """ def select(self): """return a single random parent configuration""" if self.driver.best_result is not None: return self.driver.best_result.configuration.data else: return self.manipulator.random() class GreedyMutation(GreedySelectionMixin, EvolutionaryTechnique): pass technique.register(GreedyMutation())
#print y_train.shape for p in batch_x_cfgs: down_cfg = manipulator.copy(p.data) cfg = driver.get_configuration(down_cfg) result = driver.results_query(config=cfg).one() points_vec.append(cfg.data) results_vec.append(result.extra) x_train = pd.DataFrame(points_vec) y_train = pd.DataFrame(results_vec) print pareto_points_index print len(pareto_points_index) print x_train.shape print y_train.shape #update x_test test_index = list(set(range(len(x_test))) - set(pareto_points_index)) x_test = x_test.iloc[test_index,:] x_test_cfgs = map(lambda x: x_test_cfgs[x], test_index) y_train_list=y_train.values.tolist() #print pred_df_list res_points_index = objective.result_pareto_front(y_train_list) print y_train.iloc[res_points_index,:] # register our new technique in global list technique.register(MlSearch())
while AcceptanceFunction(0, 1, temp, 1) > random.random(): sel += 1 state = points[sel % len(points)] #switch to the global best if temperature is low (i.e. we aren't moving much) if AcceptanceFunction(0, 1, temp, 1) < .0001 and objective.lt( driver.best_result.configuration, state): state = driver.best_result.configuration #update counter counter += 1 if counter > max_time and self.loop: counter = counter - max_time #Acceptance probability function for annealing def AcceptanceFunction(e, e_new, temp, scaling): #Standard acceptance probability function using relative "goodness" if e >= e_new: return 1 if temp == 0: return 0 if scaling * (e_new - e) / temp > 10: #for practical purposes, probability is too low. return 0 return math.exp(scaling * (e - e_new) / temp) #register technique technique.register(PseudoAnnealingSearch())
sel = 0 while AcceptanceFunction(0,1,temp,1)>random.random(): sel += 1 state = points[sel%len(points)] #switch to the global best if temperature is low (i.e. we aren't moving much) if AcceptanceFunction(0,1,temp,1)< .0001 and objective.lt(driver.best_result.configuration, state): state = driver.best_result.configuration #update counter counter +=1 if counter>max_time and self.loop: counter=counter-max_time #Acceptance probability function for annealing def AcceptanceFunction(e,e_new,temp,scaling): #Standard acceptance probability function using relative "goodness" if e>=e_new: return 1 if temp == 0: return 0 if scaling*(e_new-e)/temp > 10: #for practical purposes, probability is too low. return 0 return math.exp(scaling*(e-e_new)/temp) #register technique technique.register(PseudoAnnealingSearch())
points.append(down_cfg) if unit_value < 1.0: # produce new config with param set step_size higher up_cfg = manipulator.copy(center.data) param.set_unit_value(up_cfg, min(1.0, unit_value + (random.random() * max_step))) up_cfg = driver.get_configuration(up_cfg) self.yield_nonblocking(up_cfg) points.append(up_cfg) else: # ComplexParameter for mutate_function in param.manipulators(center.data): cfg = manipulator.copy(center.data) mutate_function(cfg) cfg = driver.get_configuration(cfg) self.yield_nonblocking(cfg) points.append(cfg) yield None points.sort(cmp=objective.compare) # For this iteration, move if the new point is best # than the starting point. if objective.lt(points[0], center) or random.random() <= acceptance: center = points[0] if (objective.lt(driver.best_result.configuration, center) and driver.best_result.configuration != points[0]): # another technique found a new global best, switch to that center = driver.best_result.configuration elif objective.lt(old_center, center) or random.random() <= acceptance: center = old_center technique.register(IteratedLocalSearch())