def _calculate_objectives(self): assert not (self.order and self.times),\ "Pass order or times, but not both!" self.makespan = None self.min_sum = None self.local_min_sum = None if self.times: warning_printed = False self.order = calculate_order_from_times(self.times, self.graph) times, self.local_sum = calculate_times(self.order, self.graph, return_angle_sum=True) for key in times: try: assert math.isclose(times[key], self.times[key], abs_tol=10**-5) except AssertionError as e: if not warning_printed: warning_printed = True if self.solution_type == "min_sum": if hasattr(self, "obj_val") and \ not math.isclose(sum(self.local_sum), self.obj_val): print("Warning: Solution type is min_sum but minsum is mismatched: ", sum(self.local_sum), "vs:", self.obj_val) print("Warning: Times are not matching:", times[key], self.times[key]) max_times = max([times[i] for i in times]) max_self_times = max([self.times[i] for i in self.times]) if not math.isclose(max_times, max_self_times, abs_tol=10**-5): print("And max times are also mismatched. Calculated:", max_times, " passed:", max_self_times) elif self.order: self.times, self.local_sum = calculate_times(self.order, self.graph, return_angle_sum=True) else: return self.makespan = max([self.times[key] for key in self.times]) self.min_sum = sum(self.local_sum) self.local_min_sum = max(self.local_sum)
def _calculate_order(self, solutions, graph): order = [] had_duplicates = False if not self.greedy_glue: for sol in solutions: for edge in sol.order: # ToDo: DELETE THIS DEBUG LINES duplicate_edge = edge in order had_duplicates = had_duplicates or duplicate_edge # END DEBUG LINES order.extend([edge for edge in sol.order if edge not in order]) times = calculate_times(order, graph) else: best_order = None best_angles = None best_times = None for sol in solutions: order = [edge for edge in sol.order] times = calculate_times(order, graph) angles = [0 for i in range(graph.vert_amount)] remaining_solutions = { sol2 for sol2 in solutions if sol2 != sol } while remaining_solutions: next_times = None next_angles = None next_sol = None for sol2 in remaining_solutions: second_order = [ edge for edge in sol2.order if edge not in order ] orders = [ second_order, [i for i in reversed(second_order)] ] for new_order in orders: curr_times, angles = calculate_times( new_order, graph, times=times.copy(), return_angle_sum=True) if next_times is None or sum(angles) < sum( next_angles): next_times = curr_times next_angles = angles next_sol = sol2 next_order = new_order angles = next_angles times = next_times order = order + next_order remaining_solutions.remove(next_sol) if best_order is None or sum(angles) < sum(best_angles): best_angles = angles best_order = order best_times = times return best_times return times
def __call__(self, gen_algo: GeneticAlgorithm): data = [] for genome in gen_algo.genomes: arg_sorted = np.argsort(genome.order_numbers) order = self.graph.edges[arg_sorted].tolist() times, head_sum = calculate_times(self.graph.edges[arg_sorted], angles=self.graph.costs, return_angle_sum=True) min_sum = sum(head_sum) local_min_sum = max(head_sum) sol = AngularGraphSolution( self.graph, 0, gen_algo.solver, gen_algo.solution_type, is_optimal=False, order=order, error_message=None ) data.append({ "Graph": self.graph.name, "Generation": gen_algo.generation, "solution_type": sol.solution_type, "solver": sol.solver, "min_sum": sol.min_sum, "local_min_sum": sol.local_min_sum, "makespan": sol.makespan }) assert math.isclose(genome.solution, -sol.local_min_sum) or math.isclose(genome.solution, -sol.min_sum) self.dataFrame = self.dataFrame.append(DataFrame(data), ignore_index=True) update_callback(gen_algo)
def _inner_fitness_makespan(angles, edges, orders): results = np.zeros(len(orders), dtype=float) for i, order in enumerate(orders): arg_sort = np.argsort(order) times = calculate_times(edges[arg_sort], angles=angles) results[i] = -max([times[key] for key in times]) return results
def _get_candidate(self, order, remaining_edges, headings, angles): candidate_edge = None candidate_cost = None times = calculate_times(order, angles=angles) for edge in remaining_edges: new_order = order.copy() new_order.append(edge) max_time = 0 vertex_set = set(edge) for index in vertex_set: other_index = vertex_set.difference([index]).pop() curr_prev = headings[index][-1] if headings[index] else None if curr_prev is not None: angle = angles[index][(curr_prev, other_index)] sorted_key = tuple(sorted([index, curr_prev])) max_time = max([max_time, times[sorted_key] + angle]) if ((candidate_cost is None) or (max_time < candidate_cost)) or ((candidate_cost == 0) and (max_time > 0)): candidate_edge = edge candidate_cost = max_time return candidate_edge, candidate_cost
def _get_cost(self, solution: Union[AngularGraphSolution, List], angles: Optional = None): if isinstance(solution, AngularGraphSolution): return solution.makespan times = calculate_times(solution, angles=angles) return sum([times[key] for key in times])
def _get_cost(self, solution: Union[AngularGraphSolution, List], angles: Optional = None): if isinstance(solution, AngularGraphSolution): return solution.order, solution.min_sum times, heads = calculate_times(solution, return_angle_sum=True, angles=angles) return solution, sum(heads)
def _get_cost(self, solution: Union[AngularGraphSolution, List], angles: Optional = None): if isinstance(solution, AngularGraphSolution): return solution.order, solution.makespan times, heads = calculate_times(solution, return_angle_sum=True, angles=angles) return solution, max([times[key] for key in times])
def _inner_fitness_local_min_sum(angles, edges, orders): results = np.zeros(len(orders), dtype=float) for i, order in enumerate(orders): arg_sort = np.argsort(order) times, head_sum = calculate_times(edges[arg_sort], angles=angles, return_angle_sum=True) results[i] = -max(head_sum) return results
def _add_pre_solution(self, times, graph, start_solution: Union[AngularGraphSolution, List[Tuple[int, int]]]): if start_solution: if not isinstance(start_solution, AngularGraphSolution): start_times = calculate_times(start_solution, graph) else: start_times = start_solution.times for key in times: times[key].Start = start_times[key]
def _add_pre_solution(self, graph: Graph, start_solution: Union[AngularGraphSolution, List[Tuple[int, int]]]): if start_solution is None: return if not isinstance(start_solution, AngularGraphSolution): times = calculate_times(start_solution, graph) else: times = start_solution.times for key in times: self.times[key].Start = times[key]
def _calculate_cost(solver, graph, new_order): times, heads = calculate_times(graph.edges[np.argsort(new_order)], graph, return_angle_sum=True) if solver.solution_type == "makespan": cost = max(times.values()) elif solver.solution_type == "min_sum": cost = sum(heads) else: cost = max(heads) return cost
def _calc_solution(self, graph, orientations, n, k, start_time): dep_graph = self._calculate_dependecy_graph(graph, orientations) order = self._calculate_order(dep_graph) times = calculate_times(order, graph) obj_val = (n - 2) * 180 + (360 / n) * k sol = AngularGraphSolution(graph, time.time() - start_time, self.__class__.__name__, "min_sum", times=times, obj_val=obj_val, sweep_order=order) return sol
def _get_candidate(self, order, remaining_edges, headings, angles): candidate_edge = None candidate_cost = None for edge in remaining_edges: new_order = order.copy() new_order.append(edge) new_times = calculate_times(new_order, angles=angles) cost = max(new_times.values()) if ((candidate_cost is None) or (cost < candidate_cost)) or ((candidate_cost == 0) and (cost > 0)): candidate_edge = edge candidate_cost = cost return candidate_edge, candidate_cost
def _reconstruct_order(self): self.order = pickle.loads(self._sol) # This is just for older versions, where the solution was saved as multidict if isinstance(self.order, Multidict): self.times = self.order self.order = calculate_order_from_times(self.times, self.graph) else: self.times, self.local_sum = calculate_times(self.order, self.graph, return_angle_sum=True) self.makespan = None self.min_sum = None self.local_min_sum = None try: self.makespan = max(self.times.values()) self.min_sum = sum(self.local_sum) self.local_min_sum = max(self.local_sum) except (TypeError, AttributeError): pass # can happen if a solution has an error
def _greedy_order(orders, graph: Graph, solver: Solver): results = [] for orig_order in orders: arg_ordered = np.argsort(orig_order) ordered = orig_order[arg_ordered] inner_graph = Graph(graph.vertices, graph.edges[arg_ordered]) order, cost = solver.solve(inner_graph, no_sol_return=True) edge_dict = {(o[0], o[1]): i for i, o in enumerate(graph.edges)} order_translate = { edge_dict[(e1, e2)]: i for i, (e1, e2) in enumerate(order) } new_order = np.array( [ordered[order_translate[key]] for key in range(len(orig_order))]) times, heads = calculate_times(graph.edges[np.argsort(new_order)], graph, return_angle_sum=True) try: assert (graph.edges[np.argsort(new_order)] == order ).all(), "Not all edges are sorted the same" except AssertionError as ar: print(ar) results.append((new_order, -cost)) return results