def get_max_nudge(self, individuals, number_of_generations): """ Find the maximum synergistic nudge. Parameters: ---------- number_of_generations: an integer individuals: list of IndividualNudge objects Returns: ------- A numpy array which represents the maximum individual nudge for the start distribution. """ population = individuals scores = [] for timestep in range(number_of_generations): population = self.evolve(population, timestep) scores.append(population[0].score) if TEST: print("time step {} best score {} worst score {}".format( timestep, population[0].score, population[-1].score)) return ea.sort_individuals(population)[0]
def find_synergistic_nudge_with_max_impact(input_dist, cond_output, nudge_size, evolutionary_parameters): """ find the synergistic nudge with the maximum impact Parameters: ---------- input_dist: nd-array, representing the joint input distribution cond_output: nd-array, representing the output distribution conditioned on the input nudge_size: positive float evolutionary_parameters: dict with the following keys number_of_generations: integer population_size: integer number_of_children: integer, if generational larger than or equal to population size generational: Boolean, whether to replace the old generation parent_selection_mode: "rank_exponential" or None (for random selection) start_mutation_size: positive float, the mutation size at the start change_mutation_size: positive float, the upper bound on the range the change is selected from uniformly mutations_per_update_step: integer Returns: A SynergisticNudge object """ #create initial population synergistic_nudges = [] for _ in range(evolutionary_parameters["population_size"]): new_synergistic_nudge = SynergisticNudge.create_nudge( input_dist, cond_output, nudge_size, evolutionary_parameters["mutations_per_update_step"], evolutionary_parameters["start_mutation_size"], evolutionary_parameters["change_mutation_size"], timestamp=0) synergistic_nudges.append(new_synergistic_nudge) for synergistic_nudge in synergistic_nudges: synergistic_nudge.evaluate() initial_impact = ea.sort_individuals(synergistic_nudges)[0].score #evolve the population find_max_synergistic_nudge = FindMaximumSynergisticNudge( evolutionary_parameters["generational"], evolutionary_parameters["number_of_children"], evolutionary_parameters["parent_selection_mode"]) max_synergistic_nudge = find_max_synergistic_nudge.get_max_nudge( synergistic_nudges, evolutionary_parameters["number_of_generations"]) if TEST: print("synergistic nudge: intial impact {}, max impact {}".format( initial_impact, max_synergistic_nudge.score)) return max_synergistic_nudge
def find_maximum_local_nudge(input_dist, cond_output, nudge_size, evolution_params, verbose=False): """ find the synergistic nudge with the maximum impact Parameters: ---------- input_dist: nd-array, representing the joint input distribution cond_output: nd-array, representing the output distribution conditioned on the input nudge_size: positive float evolutionary_parameters: dict with the following keys number_of_generations: integer population_size: integer number_of_children: integer, if generational larger than or equal to population size generational: Boolean, whether to replace the old generation parent_selection_mode: "rank_exponential" or None (for random selection) start_mutation_size: positive float, the mutation size at the start change_mutation_size: positive float, the maximum percentage the mutation size is changed mutation_size_weights: positive float change_mutation_size_weights: positive float The maximum percentage the mutation_size for the weights is changed. Returns: A LocalNudge object """ #create initial population nudged_vars_to_states = { nudged_var: number_of_states for nudged_var, number_of_states in enumerate(input_dist.shape) } local_nudges = [] for _ in range(evolution_params["population_size"]): new_local_nudge = LocalNudge.create_local_nudge( nudged_vars_to_states, nudge_size, evolution_params["mutation_size_weights"], evolution_params["start_mutation_size"], evolution_params["change_mutation_size"], evolution_params["change_mutation_size_weights"], timestamp=0) local_nudges.append(new_local_nudge) for local_nudge in local_nudges: local_nudge.evaluate(input_dist, cond_output) initial_impact = ea.sort_individuals(local_nudges)[0].score #evolve the population find_max_local_nudge = FindMaximumLocalNudge( input_dist, cond_output, nudge_size, evolution_params["generational"], evolution_params["number_of_children"], evolution_params["parent_selection_mode"]) for timestep in range(evolution_params["number_of_generations"]): local_nudges = find_max_local_nudge.evolve(local_nudges, timestep) best_local_nudge = ea.sort_individuals(local_nudges)[0] if verbose: print("best score {}, worst score {}".format( best_local_nudge.score, local_nudges[-1].score)) if TEST: print("local nudge: intial impact {}, max impact {}".format( initial_impact, best_local_nudge.score)) return ea.sort_individuals(local_nudges)[0]
#individual nudge optimization number_of_generations = 50 population_size = 10 number_of_children = 10 generational = False mutation_size = nudge_size / 4 parent_selection_mode = "rank_exponential" #parent_selection_mode = None individuals = create_individual_nudges(population_size, number_of_states, nudge_size, "random") for individual in individuals: individual.evaluate(input_dist, cond_output) print("initial impact {}".format( ea.sort_individuals(individuals)[0].score)) find_max_nudge = FindMaximumIndividualNudge(input_dist, cond_output, nudge_size, generational, number_of_children, parent_selection_mode) # max_individual = find_max_nudge.get_max_nudge( # individuals, number_of_generations, mutation_size # ) # print("the found max impact for an individual nudge {}".format( # max_individual.score # )) print("the found max impact for a local nudge {}".format( max_local_nudge.score)) max_impact = maximum_nudges.find_max_impact_individual_nudge_exactly(
def get_best_individual(self): return ea.sort_individuals(self.individuals)[0]
def get_cond_output_with_max_distance(input_shape, number_of_output_states, goal_distance, evolutionary_parameters, input_dists, number_of_input_distributions=None): """ Create a conditional output distribution which gives as different as possible marginal for the different input distributions Parameters: ---------- input_shape: a list, the number of states of the inut variables number_of_states_output: integer input_distributions: a list of nd-arrays or None Every array representing a probability distribution number_of_input_distributions: integer The number of input distributions to generate using a Dirichlet distribution with all parameters equal to 1. evolutionary_parameters: dict with the keys number_of_generations: integer population_size: integer number_of_children: integer, if generational larger than or equal to population size generational: Boolean, whether to replace the old generation mutation_size: positive float change_mutation_size: positive float parent_selection_mode: "rank_exponential" or None (for random selection) """ if input_dists is None: number_of_input_states = reduce(lambda x, y: x * y, input_shape) input_dists = [ np.random.dirichlet([1] * number_of_input_states) for _ in range(number_of_input_distributions) ] input_dists = [np.reshape(dist, input_shape) for dist in input_dists] #create initial population conditional_outputs = create_conditonal_distributions( evolutionary_parameters["population_size"], number_of_output_states, len(input_shape)) mutation_size = evolutionary_parameters["mutation_size"] change_mutation_size = evolutionary_parameters["change_mutation_size"] conditional_outputs = [ ConditionalOutput(cond_output, mutation_size, change_mutation_size) for cond_output in conditional_outputs ] #for dist in conditional_outputs: # found_sum = np.sum(dist.cond_output) # expected_sum = reduce(lambda x,y: x*y, dist.cond_output.shape[:-1]) # if abs(found_sum-expected_sum) > 10**(-7): # raise ValueError() for conditional_output in conditional_outputs: conditional_output.evaluate(goal_distance, input_dists) initial_distance = ea.sort_individuals(conditional_outputs)[-1].score #evolve the population find_conditional_output = FindConditionalOutput( conditional_outputs, goal_distance, evolutionary_parameters["number_of_generations"], evolutionary_parameters["number_of_children"], evolutionary_parameters["parent_selection_mode"]) find_conditional_output.evolve(evolutionary_parameters["generational"], input_dists) final_distance = find_conditional_output.get_best_individual() print("initial distance {}, distance after evolution {}".format( initial_distance, final_distance.score)) return find_conditional_output.individuals[0]