def execute(self, solution: IntegerSolution) -> IntegerSolution: Check.that(issubclass(type(solution), IntegerSolution), "Solution type invalid") for i in range(solution.number_of_variables): if random.random() <= self.probability: y = solution.variables[i] yl, yu = solution.lower_bound[i], solution.upper_bound[i] if yl == yu: y = yl else: delta1 = (y - yl) / (yu - yl) delta2 = (yu - y) / (yu - yl) mut_pow = 1.0 / (self.distribution_index + 1.0) rnd = random.random() if rnd <= 0.5: xy = 1.0 - delta1 val = 2.0 * rnd + (1.0 - 2.0 * rnd) * (xy**( self.distribution_index + 1.0)) deltaq = val**mut_pow - 1.0 else: xy = 1.0 - delta2 val = 2.0 * (1.0 - rnd) + 2.0 * (rnd - 0.5) * (xy**( self.distribution_index + 1.0)) deltaq = 1.0 - val**mut_pow y += deltaq * (yu - yl) if y < solution.lower_bound[i]: y = solution.lower_bound[i] if y > solution.upper_bound[i]: y = solution.upper_bound[i] solution.variables[i] = int(round(y)) return solution
def execute(self, solution: FloatSolution) -> FloatSolution: Check.that(issubclass(type(solution), FloatSolution), "Solution type invalid") for i in range(solution.number_of_variables): rand = random.random() if rand <= self.probability: y = solution.variables[i] yl, yu = solution.lower_bound[i], solution.upper_bound[i] if yl == yu: y = yl else: delta1 = (y - yl) / (yu - yl) delta2 = (yu - y) / (yu - yl) rnd = random.random() mut_pow = 1.0 / (self.distribution_index + 1.0) if rnd <= 0.5: xy = 1.0 - delta1 val = 2.0 * rnd + (1.0 - 2.0 * rnd) * (pow(xy, self.distribution_index + 1.0)) deltaq = pow(val, mut_pow) - 1.0 else: xy = 1.0 - delta2 val = 2.0 * (1.0 - rnd) + 2.0 * (rnd - 0.5) * (pow(xy, self.distribution_index + 1.0)) deltaq = 1.0 - pow(val, mut_pow) y += deltaq * (yu - yl) if y < solution.lower_bound[i]: y = solution.lower_bound[i] if y > solution.upper_bound[i]: y = solution.upper_bound[i] solution.variables[i] = y return solution
def execute(self, solution: FloatSolution) -> FloatSolution: Check.that(type(solution) is FloatSolution, "Solution type invalid") for i in range(solution.number_of_variables): if random.random() <= self.probability: rand = random.random() if rand <= 0.5: tmp = self.__delta( solution.upper_bound[i] - solution.variables[i], self.perturbation) else: tmp = self.__delta( solution.lower_bound[i] - solution.variables[i], self.perturbation) tmp += solution.variables[i] if tmp < solution.lower_bound[i]: tmp = solution.lower_bound[i] elif tmp > solution.upper_bound[i]: tmp = solution.upper_bound[i] solution.variables[i] = tmp return solution
def execute(self, solution: FloatSolution) -> FloatSolution: Check.that(type(solution) is FloatSolution, "Solution type invalid") for i in range(solution.number_of_variables): rand = random.random() if rand <= self.probability: solution.variables[i] = solution.lower_bound[i] + \ (solution.upper_bound[i] - solution.lower_bound[i]) * random.random() return solution
def feasibility_ratio(solutions: [Solution]): """ Returns the percentage of feasible solutions in a solution list :param solutions: :return: """ Check.that(len(solutions) > 0, "The solution list is empty") return sum(1 for solution in solutions if is_feasible(solution)) / len(solutions)
def __init__(self, mutation_operator_list:[Mutation]): super(CompositeMutation,self).__init__(probability=1.0) Check.is_not_none(mutation_operator_list) Check.collection_is_not_empty(mutation_operator_list) self.mutation_operators_list = [] for operator in mutation_operator_list: Check.that(issubclass(operator.__class__, Mutation), "Object is not a subclass of Mutation") self.mutation_operators_list.append(operator)
def execute(self, solution: BinarySolution) -> BinarySolution: Check.that(type(solution) is BinarySolution, "Solution type invalid") for i in range(solution.number_of_variables): for j in range(len(solution.variables[i])): rand = random.random() if rand <= self.probability: solution.variables[i][j] = True if solution.variables[i][j] is False else False return solution
def __init__(self, crossover_operator_list:[Crossover]): super(CompositeCrossover, self).__init__(probability=1.0) Check.is_not_none(crossover_operator_list) Check.collection_is_not_empty(crossover_operator_list) self.crossover_operators_list = [] for operator in crossover_operator_list: Check.that(issubclass(operator.__class__, Crossover), "Object is not a subclass of Crossover") self.crossover_operators_list.append(operator)
def execute(self, solution: PermutationSolution) -> PermutationSolution: Check.that(type(solution) is PermutationSolution, "Solution type invalid") rand = random.random() if rand <= self.probability: pos_one, pos_two = random.sample(range(solution.number_of_variables - 1), 2) solution.variables[pos_one], solution.variables[pos_two] = \ solution.variables[pos_two], solution.variables[pos_one] return solution
def execute(self, solutions: List[CompositeSolution]) -> List[CompositeSolution]: Check.is_not_none(solutions) Check.that(len(solutions) == 2, "The number of parents is not two: " + str(len(solutions))) offspring1 = [] offspring2 = [] number_of_solutions_in_composite_solution = solutions[0].number_of_variables for i in range(number_of_solutions_in_composite_solution): parents = [solutions[0].variables[i], solutions[1].variables[i]] children = self.crossover_operators_list[i].execute(parents) offspring1.append(children[0]) offspring2.append(children[1]) return [CompositeSolution(offspring1), CompositeSolution(offspring2)]
def __init__(self, solutions: List[Solution]): super(CompositeSolution, self).__init__(len(solutions), solutions[0].number_of_objectives, solutions[0].number_of_constraints) Check.is_not_none(solutions) Check.collection_is_not_empty(solutions) for solution in solutions: Check.that( solution.number_of_objectives == solutions[0].number_of_objectives, "The solutions in the list must have the same number of objectives: " + str(solutions[0].number_of_objectives)) Check.that( solution.number_of_constraints == solutions[0].number_of_constraints, "The solutions in the list must have the same number of constraints: " + str(solutions[0].number_of_constraints)) self.variables = solutions
def execute(self, solution: PermutationSolution) -> PermutationSolution: Check.that( type(solution) is PermutationSolution, "Solution type invalid") rand = random.random() if rand <= self.probability: if self.randMut == 1: # pos_one, pos_two = random.sample(range(solution.number_of_variables - 1), 2) # there is no use for the -1 above in the original algorithm pos_one, pos_two = random.sample( range(solution.number_of_variables), 2) elif self.randMut == 2: path = solution.variables pos_one, pos_two, length = bestMutation2( self.D, self.n, path, self.first) solution.variables[pos_one], solution.variables[ pos_two] = solution.variables[pos_two], solution.variables[ pos_one] return solution
def execute(self, parents: List[BinarySolution]) -> List[BinarySolution]: Check.that(type(parents[0]) is BinarySolution, "Solution type invalid") Check.that(type(parents[1]) is BinarySolution, "Solution type invalid") Check.that( len(parents) == 2, 'The number of parents is not two: {}'.format(len(parents))) offspring = [copy.deepcopy(parents[0]), copy.deepcopy(parents[1])] rand = random.random() if rand <= self.probability: # 1. Get the total number of bits total_number_of_bits = parents[0].get_total_number_of_bits() # 2. Calculate the point to make the crossover crossover_point = random.randrange(0, total_number_of_bits) # 3. Compute the variable containing the crossover bit variable_to_cut = 0 bits_count = len(parents[1].variables[variable_to_cut]) while bits_count < (crossover_point + 1): variable_to_cut += 1 bits_count += len(parents[1].variables[variable_to_cut]) # 4. Compute the bit into the selected variable diff = bits_count - crossover_point crossover_point_in_variable = len( parents[1].variables[variable_to_cut]) - diff # 5. Apply the crossover to the variable bitset1 = copy.copy(parents[0].variables[variable_to_cut]) bitset2 = copy.copy(parents[1].variables[variable_to_cut]) for i in range(crossover_point_in_variable, len(bitset1)): swap = bitset1[i] bitset1[i] = bitset2[i] bitset2[i] = swap offspring[0].variables[variable_to_cut] = bitset1 offspring[1].variables[variable_to_cut] = bitset2 # 6. Apply the crossover to the other variables for i in range(variable_to_cut + 1, parents[0].number_of_variables): offspring[0].variables[i] = copy.deepcopy( parents[1].variables[i]) offspring[1].variables[i] = copy.deepcopy( parents[0].variables[i]) return offspring
def execute(self, solution: FloatSolution) -> FloatSolution: Check.that(issubclass(type(solution), FloatSolution), "Solution type invalid") copied_solution = solution.__copy__() if copied_solution not in self.follow_solutions: self.follow_solutions.append(copied_solution) self.follow_solutions.sort(key=lambda x: x.objectives[0], reverse=False) self.follow_solutions = self.follow_solutions[:self.others_number] if (self.avg_counter % self.others_number == 0): self.avg_counter = 0 self.avg = (self.avg * self.avg_counter + copied_solution.objectives[0]) / (self.avg_counter + 1) self.avg_counter += 1 self.steps += 1 vector = self.get_follow_vector() for i in range(solution.number_of_variables): rand = random.random() # v not enough solutions to calculate avg if rand <= self.probability or self.steps < self.others_number: y = solution.variables[i] yl, yu = solution.lower_bound[i], solution.upper_bound[i] if yl == yu: y = yl else: delta1 = (y - yl) / (yu - yl) delta2 = (yu - y) / (yu - yl) rnd = random.random() mut_pow = 1.0 / (self.distribution_index + 1.0) if rnd <= 0.5: xy = 1.0 - delta1 val = 2.0 * rnd + (1.0 - 2.0 * rnd) * (pow( xy, self.distribution_index + 1.0)) deltaq = pow(val, mut_pow) - 1.0 else: xy = 1.0 - delta2 val = 2.0 * (1.0 - rnd) + 2.0 * (rnd - 0.5) * (pow( xy, self.distribution_index + 1.0)) deltaq = 1.0 - pow(val, mut_pow) y += deltaq * (yu - yl) if y < solution.lower_bound[i]: y = solution.lower_bound[i] if y > solution.upper_bound[i]: y = solution.upper_bound[i] solution.variables[i] = y elif rand <= self.probability + self.look_at_others_probability: diff = vector[i] - solution.variables[i] calculated_value = solution.variables[i] + 0.1 * diff solution.variables[i] = max( min(calculated_value, solution.upper_bound[i]), solution.lower_bound[i]) return solution
def test_should_that_raise_an_exception_if_the_expression_is_false( self) -> None: with self.assertRaises(InvalidConditionException): Check.that(False, "The expression is false")
def execute(self, parents: List[IntegerSolution]) -> List[IntegerSolution]: Check.that( type(parents[0]) is IntegerSolution, "Solution type invalid") Check.that( type(parents[1]) is IntegerSolution, "Solution type invalid") Check.that( len(parents) == 2, 'The number of parents is not two: {}'.format(len(parents))) offspring = [copy.deepcopy(parents[0]), copy.deepcopy(parents[1])] rand = random.random() if rand <= self.probability: for i in range(parents[0].number_of_variables): value_x1, value_x2 = parents[0].variables[i], parents[ 1].variables[i] if random.random() <= 0.5: if abs(value_x1 - value_x2) > self.__EPS: if value_x1 < value_x2: y1, y2 = value_x1, value_x2 else: y1, y2 = value_x2, value_x1 lower_bound, upper_bound = parents[0].lower_bound[ i], parents[1].upper_bound[i] beta = 1.0 + (2.0 * (y1 - lower_bound) / (y2 - y1)) alpha = 2.0 - pow(beta, -(self.distribution_index + 1.0)) rand = random.random() if rand <= (1.0 / alpha): betaq = pow(rand * alpha, (1.0 / (self.distribution_index + 1.0))) else: betaq = pow(1.0 / (2.0 - rand * alpha), 1.0 / (self.distribution_index + 1.0)) c1 = 0.5 * (y1 + y2 - betaq * (y2 - y1)) beta = 1.0 + (2.0 * (upper_bound - y2) / (y2 - y1)) alpha = 2.0 - pow(beta, -(self.distribution_index + 1.0)) if rand <= (1.0 / alpha): betaq = pow( (rand * alpha), (1.0 / (self.distribution_index + 1.0))) else: betaq = pow(1.0 / (2.0 - rand * alpha), 1.0 / (self.distribution_index + 1.0)) c2 = 0.5 * (y1 + y2 + betaq * (y2 - y1)) if c1 < lower_bound: c1 = lower_bound if c2 < lower_bound: c2 = lower_bound if c1 > upper_bound: c1 = upper_bound if c2 > upper_bound: c2 = upper_bound if random.random() <= 0.5: offspring[0].variables[i] = int(c2) offspring[1].variables[i] = int(c1) else: offspring[0].variables[i] = int(c1) offspring[1].variables[i] = int(c2) else: offspring[0].variables[i] = value_x1 offspring[1].variables[i] = value_x2 else: offspring[0].variables[i] = value_x1 offspring[1].variables[i] = value_x2 return offspring
def get_neighbors(self, index: int, solution_list: List[Solution]) -> List[Solution]: Check.is_not_null(solution_list) Check.that(len(solution_list) != 0, "The list of solutions is empty") return self.__find_neighbors(solution_list, index, self.neighborhood)