def step(self):
        pop_size = len(self.population)
        for i in range(pop_size):
            specimen_pos = self.population[i]
            specimen_best_pos = self.bestPositions[i]
            new_speed = []
            for att_i in range(self.d):
                local_best_tend = self.c1 * rand.random() * (specimen_best_pos[att_i] - (specimen_pos[att_i]))
                global_best_tend = self.c2 * rand.random() * (self.gBest[att_i] - (specimen_pos[att_i]))
                new_speed.append(self.w * self.actualSpeed[i][att_i] + local_best_tend + global_best_tend)

            # speed validation and correction
            self.validate_speed_vector(new_speed)
            self.actualSpeed[i] = new_speed

            # new position update
            new_position = []
            for att_i in range(self.d):
                new_position.append(specimen_pos[att_i] + new_speed[att_i])

            # position validation
            PopulationUtils.validate_constrains(new_position, self.specimen_template)

            # count fitness and update new position
            new_position.append(self.fitness_function(new_position))
            self.population[i] = new_position

            # control with best local and global
            if self.gBest[self.d] > new_position[self.d]:
                self.gBest = new_position
            if self.bestPositions[i][self.d] > new_position[self.d]:
                self.bestPositions[i] = new_position
        self.iteration += 1
    def step(self):
        new_population = []
        pop_size = len(self.population)
        for i in range(pop_size):
            actual_specimen = self.population[i]
            # choose 3 random specimen from population
            random_specimens = []
            for j in range(3):
                next_spec_index = rand.randint(0, pop_size-1)
                next_spec = self.population[next_spec_index]
                # if we pick already used, we just increase index until we find unused
                while next_spec in random_specimens:
                    next_spec_index += 1
                    if next_spec_index == pop_size:
                        next_spec_index = 0
                    next_spec = self.population[next_spec_index]

                # now we have unused - use numpy arrays for easy manipulation
                random_specimens.append(np.array(next_spec[:self.d]))

            # create Differential vector
            differential_vector = np.array(random_specimens[0] - random_specimens[1])
            weighted_differential_vector = self.F * differential_vector
            noise_vector = random_specimens[2] + weighted_differential_vector

            # trial vector - MUTATION part
            trial_vector = []
            for att_index in range(len(noise_vector)):
                probability = rand.random()
                if probability <= self.CR:
                    trial_vector.append(noise_vector[att_index])
                else:
                    trial_vector.append(actual_specimen[att_index])

            # constrains
            PopulationUtils.validate_constrains(trial_vector, self.specimen_template)
            # count fitness of trial vector
            trial_vector.append(self.fitness_function(trial_vector))
            # add to new population one with better fitness
            if trial_vector[self.d] < actual_specimen[self.d]:
                new_population.append(trial_vector)
            else:
                new_population.append(actual_specimen)

        # discard old population in favour of new one
        self.population = new_population
        # or generation to be correct
        self.iteration += 1
def neighborhood(x, d, fitness_fn=None, n=10, specimen_template=None):
    """
    Generates randomly neighbourhood of specimen "x" in given diameter "d"
    :param x: specimen
    :param d: area diameter
    :param fitness_fn: fitness function
    :param specimen_template: template
    :param n: number of neighbours to generate default=10
    :return: list of neighbours
    """
    neighbours = []
    for i in range(n):
        new = []
        for dimension in x:
            # (dimension-d) to always be in parenthesis
            new.append((rand.random() * (dimension+d - (dimension-d))) + (dimension-d))
        if specimen_template is not None:
            PopulationUtils.validate_constrains(new, specimen_template)
        if fitness_fn is not None:
            new.append(fitness_fn(new))
        neighbours.append(new)
    return neighbours