async def evaluate_individual(current_population, individual_id, environment, iteration):
    """
    This method obtains an overall value for an individual in an environment
    :param current_population: set of individuals to test against the environment
    :type current_population: list or DBWrapper
    :param individual_id: id of the individual to evaluate
    :type individual_id: int
    :param environment: the current parameters against which the individuals are being tested
    :type environment: Environment
    :param iteration: current iteration
    :type iteration: int
    :return: pair of individual with its value
    :rtype: tuple
    """
    base_coll_name = f'{environment.name}_{iteration}'
    individual = current_population[base_coll_name][individual_id]
    if not is_generic():
        individual_value = human_value_function(individual, environment.data)
        if not is_food_accessible(individual, environment.data):
            individual_value = individual_value * 0.5
        individual_value = human_penalize_extremes(individual, individual_value, environment.data)
    else:
        individual_value = generic_value_function(individual, environment.data)
        individual_value = generic_penalize_extremes(individual, individual_value, environment.data)
    individual['value'] = individual_value
    current_population[f'{environment.name}_{iteration}_{"filtered"}'].append(individual)
    return individual_value
 def add_limits(self, environment):
     """
     This method is used to add some horizontal axis's to the plots to understand better if the results
     make sens.
     :param environment: the current parameters against which the individuals are being tested
     :type environment: dict
     """
     if not is_generic():
         temp_threshold = 0.05 + (abs(environment['temperature'] - 20) *
                                  (0.30 / 30))
         self.ax1.axhline(y=environment['predators_speed'],
                          c="red",
                          linewidth=0.5,
                          zorder=0)
         self.ax1.axhline(y=environment['food_animals_speed'],
                          c="blue",
                          linewidth=0.5,
                          zorder=0)
         self.ax2.axhline(y=environment['food_animals_strength'],
                          c="blue",
                          linewidth=0.5,
                          zorder=0)
         self.ax3.axhline(y=temp_threshold,
                          c="blue",
                          linewidth=0.5,
                          zorder=0)
         self.ax4.axhline(y=environment['tree_height'],
                          c="blue",
                          linewidth=0.5,
                          zorder=0)
         environment_params = '\n'.join(
             [f'{key}: {value}' for key, value in environment.items()])
         self.ax6.text(0.2,
                       0.5,
                       environment_params,
                       horizontalalignment='left',
                       verticalalignment='center',
                       size=15)
         self.ax6.axis('off')
     else:
         for key in environment.keys():
             self.__getattribute__(key).axhline(y=environment[key],
                                                c="red",
                                                linewidth=0.5,
                                                zorder=0)
         environment_params = '\n'.join(
             [f'{key}: {value}' for key, value in environment.items()])
         self.data.text(0.2,
                        0.5,
                        environment_params,
                        horizontalalignment='left',
                        verticalalignment='center',
                        size=15)
         self.data.axis('off')
    def set_plots(self, environment):
        if not is_generic():
            self.ax1 = self.fig.add_subplot(3, 2, 1)
            self.ax1.set_title('Average Speed')
            self.ax1.set_ylim([
                HUMAN_PARAMS['speed'][0] * 0.8, HUMAN_PARAMS['speed'][1] * 1.2
            ])
            self.ax2 = self.fig.add_subplot(3, 2, 2)
            self.ax2.set_title('Average Strength')
            self.ax2.set_ylim([
                HUMAN_PARAMS['strength'][0] * 0.8,
                HUMAN_PARAMS['strength'][1] * 1.2
            ])
            self.ax3 = self.fig.add_subplot(3, 2, 3)
            self.ax3.set_title('Average Skin thickness')
            self.ax3.set_ylim([
                HUMAN_PARAMS['skin_thickness'][0] * 0.8,
                HUMAN_PARAMS['skin_thickness'][1] * 1.2
            ])
            self.ax4 = self.fig.add_subplot(3, 2, 4)
            self.ax4.set_title('Average Total Reach')
            self.ax4.set_ylim([1 * 0.8, 2.5 * 1.2])
            self.ax5 = self.fig.add_subplot(3, 2, 5)
            self.ax5.set_title('Individuals fitting')
            self.ax5.set_ylim([
                (get_population_size() * 0.9) - get_population_size(),
                get_population_size() * 1.1
            ])
            self.ax6 = self.fig.add_subplot(3, 2, 6)
        else:
            ind = 1
            num_attrs = len(environment.data.keys())
            num_rows = int((num_attrs + 2) / 2) + 1
            num_cols = 2
            for key, val in environment.data.items():
                self.__setattr__(key,
                                 self.fig.add_subplot(num_rows, num_cols, ind))
                self.__getattribute__(key).set_title(key)
                self.__getattribute__(key).set_ylim([
                    GENERIC_PARAMS[key][0] * 0.8, GENERIC_PARAMS[key][1] * 1.2
                ])
                ind += 1
            self.fitting = self.fig.add_subplot(num_rows, num_cols, ind)
            self.fitting.set_title('Individuals fitting')
            self.fitting.set_ylim([
                (get_population_size() * 0.9) - get_population_size(),
                get_population_size() * 1.1
            ])
            self.data = self.fig.add_subplot(num_rows, num_cols, ind + 1)

        plt.xlabel("Iterations")
        plt.tight_layout()
        plt.gcf().subplots_adjust(bottom=0.08, right=0.9, left=0.1, top=0.9)
Exemple #4
0
 def __init__(self, environment, iteration):
     if is_generic():
         self.averages = {}
         for param, _ in GENERIC_PARAMS.items():
             self.averages[param] = 0
         self.averages['fitting'] = 0
         self.averages['value'] = 0
     else:
         self.averages = {
             'speed': 0,
             'strength': 0,
             'skin': 0,
             'total_reach': 0,
             'fitting': 0,
             'value': 0
         }
     self.environment = environment
     self.iteration = iteration
def obtain_params(index):
    """
    This method creates an individual for the first iteration, by randomly obtaining values in a defined range for
    each parameters, and assigning an age and initial iteration
    :param index: individual index
    :type index: int
    :return: the individual containing all its parameters
    :rtype: dict
    """
    params = {
        '_id': index,
        'age': int(index / (get_population_size() / 5)) + 1,
        'value': 0
    }
    individual_params = dict(GENERIC_PARAMS) if is_generic() else dict(
        HUMAN_PARAMS)
    for k, v in individual_params.items():
        params[k] = round(random.uniform(v[0], v[1]), 3)
    return params
async def obtain_children(index, iteration, individual1_ind, individual2_ind, current_population, filtered_coll):
    """
    This method takes the indexes of the new child parents, obtains the parents parameters, and creates the
    new child parameters from the average of each of the parents parameters, adding a small mutation factor
    :param index: _id of the new children
    :type index: int
    :param iteration: current iteration
    :type iteration: int
    :param individual1_ind: parent 1 _id
    :type individual1_ind: int
    :param individual2_ind: parent 1 _id
    :type individual2_ind: int
    :param current_population: individuals to reproduce
    :type current_population: list or DBWrapper
    :param filtered_coll: name of the filtered collection
    :type filtered_coll: str
    :return: obtained child or _id of the new child
    :rtype: dict or int
    """
    ind1 = current_population[filtered_coll][individual1_ind]
    ind2 = current_population[filtered_coll][individual2_ind]
    child = dict()
    child['_id'] = index
    child['age'] = int((index - int(get_population_size()*0.6)) / int(get_population_size()*0.6 / 5)) \
        + iteration \
        + 1
    mutation_factor = get_mutation_factor()
    PARAMS_TO_READ = GENERIC_PARAMS if is_generic() else HUMAN_PARAMS
    for parameter, value in ind1.items():
        if parameter != '_id' and parameter != 'age' and parameter != 'value':
            child[parameter] = round(
                float(np.clip(
                    (ind1[parameter] + ind2[parameter]) / 2 * random.uniform(1 - mutation_factor,
                                                                             1 + mutation_factor),
                    PARAMS_TO_READ[parameter][0] * 0.8,
                    PARAMS_TO_READ[parameter][1] * 1.2)),
                3
            )
    child['value'] = 0
    reproduction_collection = f'{"_".join(filtered_coll.split("_")[:-1])}_{"reproduction"}'
    current_population[reproduction_collection].append(child)
    return index
 def add_data(self, results, iteration):
     """
     This method adds the points to plot for the current iteration
     :param results: object containing the iteration average results
     :type results: dict
     :param iteration: current iteration
     :type iteration: int
     """
     if not is_generic():
         self.ax1.scatter(iteration, results['speed'], color='r', s=3)
         self.ax2.scatter(iteration, results['strength'], color='g', s=3)
         self.ax3.scatter(iteration, results['skin'], color='b', s=3)
         self.ax4.scatter(iteration, results['total_reach'], color='c', s=3)
         self.ax5.scatter(iteration, results['fitting'], color='k', s=3)
     else:
         for key, val in results.items():
             if key != 'value' and key != 'age' and key != '_id':
                 self.__getattribute__(key).scatter(iteration,
                                                    results[key],
                                                    color='r',
                                                    s=3)
         self.fitting.scatter(iteration, results['fitting'], color='k', s=3)
Exemple #8
0
 def analyze_population(self, current_population, environment_name, iteration):
     """
     This method obtains the averages for the current iteration individuals and saves the results to be plot
     :param current_population: current set of individuals
     :type current_population: list or DBWrapper
     :param environment_name: the current parameters against which the individuals are being tested
     :type environment_name: str
     :param iteration: current iteration
     :type iteration: int
     """
     coll_name = f'{environment_name}_{iteration + 1}'
     if not is_generic():
         total_speed = 0
         total_strength = 0
         total_skin = 0
         total_reach = 0
         total_value = 0
         to_evaluate = 0
         total_fitting = 0
         for individual in current_population[coll_name]:
             total_speed += individual['speed']
             total_strength += individual['strength']
             total_skin += individual['skin_thickness']
             if 'value' in individual:
                 total_value += individual['value']
                 to_evaluate += 1
             reach = individual['height'] + individual['arm_length'] + individual['jump']
             total_reach += reach
             if (reach > self.environment['tree_height'] or
                 (individual['speed'] > self.environment['food_animals_speed'] and
                  individual['strength'] > self.environment['food_animals_strength'])) and \
                     is_fast_enough(individual, self.environment) and \
                     is_warm_enough(individual, self.environment):
                 total_fitting += 1
         self.averages = {
             'speed': total_speed / get_population_size(),
             'strength': total_strength / get_population_size(),
             'skin': total_skin / get_population_size(),
             'total_reach': total_reach / get_population_size(),
             'value': total_value / to_evaluate,
             'fitting': total_fitting
         }
     else:
         total_value = 0
         evaluated = 0
         for individual in current_population[coll_name]:
             fits = True
             for param, value in individual.items():
                 if param != '_id' and param != 'age' and param != 'value':
                     self.averages[param] += value
                     if fits and \
                        not (GENERIC_ENVIRONMENT_DEFAULT[param]-2 < value < GENERIC_ENVIRONMENT_DEFAULT[param]+2):
                         fits = False
                 if param == 'value':
                     total_value += value
                     evaluated += 1
             if fits:
                 self.averages['fitting'] += 1
         self.averages['value'] = total_value / max(evaluated, 1)
         for param, value in GENERIC_PARAMS.items():
             self.averages[param] = self.averages[param] / get_population_size()
     my_plot.add_data(self.averages, self.iteration)