Пример #1
0
    def solve(self, graph: Graph, **kwargs):
        self._build_model(graph)

        solver = cp_model.CpSolver()
        for param in self.params:
            setattr(solver.parameters, param, self.params[param])
        if "time_limit" in kwargs:
            solver.parameters.max_time_in_seconds = kwargs["time_limit"]

        status = solver.Solve(self.model)
        if status in [cp_model.FEASIBLE, cp_model.OPTIMAL]:
            obj_val = solver.ObjectiveValue()
            values = {tuple(self.abstract_graph.vertices[key]): solver.Value(self.vertices[key]) for key in self.vertices}
            order = calculate_order_from_times(values, self.graph)

            sol = AngularGraphSolution(
                graph,
                solver.UserTime(),
                self.__class__.__name__,
                self.solution_type,
                is_optimal=(status == cp_model.OPTIMAL),
                order=order,
                )
        else:
            sol = AngularGraphSolution(
                graph,
                solver.UserTime(),
                self.__class__.__name__,
                self.solution_type,
                is_optimal=(status == cp_model.OPTIMAL),
                error_message="No feasable solution found",
                )

        return sol
Пример #2
0
 def solve(self, graph: Graph, **kwargs):
     start_time = time.time()
     times = None
     error_message = None
     try:
         # Split edges into log n subgraphs along the x-axis
         n = graph.vert_amount
         split_array = np.zeros((math.ceil(math.log2(n)), n))
         self._calculate_split(split_array, 0, 0, n)
         # Calculate subgraphs
         used_edges = set()
         argsorted = np.argsort(graph.vertices[:, 0])
         solutions = []
         self._solve_subgraphs(split_array, argsorted, graph, used_edges, solutions)
         times = self._calculate_order(solutions, graph)
         if len(times) != graph.edge_amount:
             times = None
             raise Exception("Edge order does not contain all edges!")
     except Exception as e:
         error_message = str(e)
         raise e
     return AngularGraphSolution(graph,
                                 time.time() - start_time,
                                 self.__class__.__name__,
                                 self.sub_solver.solution_type,
                                 times=times,
                                 error_message=error_message)
 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(pd.DataFrame(data),
                                            ignore_index=True)
     update_callback(gen_algo)
Пример #4
0
 def _get_random_sol(self, graph: Graph) -> AngularGraphSolution:
     order = np.random.permutation(graph.edges).tolist()
     sol = AngularGraphSolution(graph,
                                0,
                                self.__class__.__name__,
                                self.solution_type,
                                is_optimal=False,
                                order=order)
     return sol
    def build_ip_and_optimize(self,
                              graph: Graph,
                              start_solution: Optional[dict] = None,
                              callbacks: Optional[Union[Multidict,
                                                        dict]] = None,
                              time_limit=None):
        error_message = None
        runtime = 0
        is_optimal = False
        times = None
        try:
            self.graph = graph
            self.model = gurobipy.Model()
            self.model.setParam("LazyConstraints", 1)
            for param in self.params:
                self.model.setParam(param, self.params[param])
            # Override general time limit, if one is provided
            if time_limit:
                self.model.setParam("TimeLimit", time_limit)

            times_first, times_reverse = self._add_times_variables()

            self.edges, self.angles = self._add_hamilton_paths()

            self._add_times_equals_constraints(times_first, times_reverse)

            self.times = gurobipy.tupledict()
            self.times.update(times_first)
            self.times.update(times_reverse)

            self._add_taken_edges_constraints()

            self._set_objective()

            self._add_callbacks(callbacks)
            self._add_pre_solution(graph, start_solution)
            self.model.update()
            self.model.optimize(callback_rerouter)
            runtime = self.model.Runtime
            is_optimal = self.model.Status == gurobipy.GRB.OPTIMAL
            times = {t: self.times[t].x for t in self.times}
        except Exception as e:
            if self.model.Status != gurobipy.GRB.TIME_LIMIT:
                error_message = str(e)
                if is_debug_env():
                    raise e

        sol = AngularGraphSolution(self.graph,
                                   runtime,
                                   times=times,
                                   solution_type=self.solution_type,
                                   is_optimal=is_optimal,
                                   solver=self.__class__.__name__,
                                   error_message=error_message)
        return sol
Пример #6
0
    def solve(self, graph: Graph, **kwargs):
        # count how many vertices have largest angle north or south
        # Maybe choose which set get which starting position accordingly
        order = None
        start_time = time.time()
        error_message = None
        try:
            colors = kwargs.pop("colors", None)
            if colors is None:
                colors = self._calc_subsets(graph)
            # Make sure V_1 and V_2 are bipartite partitions
            assert len(colors) == graph.vert_amount
            assert np.alltrue([colors[i] != colors[j] for i, j in graph.edges])
            sectors_V = {
                i: get_vertex_sectors(graph.vertices[i],
                                      graph.vertices[np.nonzero(
                                          graph.ad_matrix[i])],
                                      start_north=bool(colors[i]))
                for i in range(graph.vert_amount)
            }

            tripel_edges, abs_graph = convert_graph_to_angular_abstract_graph(
                graph, simple_graph=False, return_tripel_edges=True)
            edge_vert = {i: {} for i in range(graph.vert_amount)}
            for edge in tripel_edges:
                edge_vert[edge[0]][edge[1:]] = tripel_edges[edge]

            used_edges = []
            for vertex_key in sectors_V:
                sectors_info = sectors_V[vertex_key]
                if len(sectors_info) == 1:
                    continue
                non_zeros = np.nonzero(graph.ad_matrix[vertex_key])[0]
                for from_vert, to_vert, angle in sectors_info[:-1]:
                    used_edges.append(
                        edge_vert[vertex_key][non_zeros[from_vert],
                                              non_zeros[to_vert]])

            dep_graph = get_dep_graph(used_edges, abs_graph)
            order = [
                tuple(abs_graph.vertices[i])
                for i in calculate_order(dep_graph, calculate_circle_dep=True)
            ]
        except NotImplementedError as e:
            error_message = str(e)
            raise e
        sol = AngularGraphSolution(graph,
                                   time.time() - start_time,
                                   self.__class__.__name__,
                                   self.solution_type,
                                   is_optimal=False,
                                   error_message=error_message,
                                   order=order)
        return sol
    def solve(self, graph: Graph, **kwargs):
        start_time = time.time()
        times = None
        error_message = None
        try:
            coloring = self.coloring_solver(graph)
            max_color = max(coloring)
            index_colorings = []

            log_max_color = math.ceil(math.log2(max_color))
            color_bit_vector = np.array([[(color >>
                                           (log_max_color - 1 - i)) & 1
                                          for i in range(log_max_color)]
                                         for color in range(max_color)])

            for vec in color_bit_vector.T:
                # Get indices of the vertices where in one of the sets
                to_color = np.arange(len(vec))[vec == 1]
                isin = np.isin(coloring, to_color)
                both_sets_indices = (*np.where(isin == 0),
                                     *np.where(isin == 1))
                index_colorings.append(both_sets_indices)

            solutions = []
            used_edges = set()
            for set_one, set_two in index_colorings:
                subgraph = graph.get_bipartite_subgraph(
                    set_one, set_two, forbidden_edges=used_edges)
                if subgraph.edge_amount > 0:
                    sol = self.sub_solver.solve(
                        subgraph,
                        colors=[
                            int(i in set_one) for i in range(graph.vert_amount)
                        ])
                    solutions.append(sol)
                    # If wanted collect the already used edges to maybe get a better solution
                    if self.no_used_edges:
                        used_edges.update({(u)
                                           for u in product(set_one, set_two)})

            times = self._calculate_order(solutions, graph)
            if len(times) != graph.edge_amount:
                times = None
                raise Exception("Edge order does not contain all edges!")
        except Exception as e:
            error_message = str(e)
            raise e
        return AngularGraphSolution(graph,
                                    time.time() - start_time,
                                    self.__class__.__name__,
                                    self.sub_solver.solution_type,
                                    times=times,
                                    error_message=error_message)
Пример #8
0
    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
Пример #9
0
    def solve(self, graph: Graph, **kwargs):
        self._initiate_variables(graph, kwargs.pop("upper_bound", None))

        best_order = self._start_solves(graph)
        print("Searched nodes:", self.searched_nodes, "of possible",
              self.possible_nodes_amount, "(",
              self.searched_nodes / self.possible_nodes_amount, "%)")
        sol = AngularGraphSolution(
            graph,
            time.time() - self.start_time,
            self.__class__.__name__,
            self.solution_type,
            is_optimal=self.start_time + self.max_time > time.time(),
            order=best_order)
        return sol
Пример #10
0
    def solve(self, graph: Graph, **kwargs):
        self.model = cp_model.CpModel()
        self.graph = graph

        time = 0
        is_optimal = False
        times_dict = None
        error_message = None
        try:

            arcs, self.degrees = self._calculate_degrees()
            time, diffs, absolutes, self.max_time = self._add_variables(arcs)
            self._add_constraints(arcs, self.degrees, time, diffs, absolutes,
                                  self.max_time)

            #self._add_initial_heading(time, initial_heading)

            #self._add_pre_solution(time, start_solution)
            self._setObj()

            solver = cp_model.CpSolver()

            for param in self.params:
                val = self.params[param]
                setattr(solver.parameters, param, val)
            if "time_limit" in kwargs:
                solver.parameters.max_time_in_seconds = kwargs["time_limit"]

            status = solver.Solve(self.model)
            if status in [cp_model.FEASIBLE, cp_model.OPTIMAL]:
                values = np.array([solver.Value(time[key]) for key in time])
                times = np.degrees((values / self.multiplier) * np.pi)
                times_dict = {
                    key: value
                    for key, value in zip(time.keys(), times)
                }
            is_optimal = (status == cp_model.OPTIMAL)
            time = solver.UserTime()
        except Exception as e:
            error_message = str(e)
        sol = AngularGraphSolution(graph,
                                   time,
                                   self.__class__.__name__,
                                   self.solution_type,
                                   is_optimal=is_optimal,
                                   times=times_dict,
                                   error_message=error_message)
        return sol
Пример #11
0
    def solve(self, graph: Graph, no_sol_return=None, **kwargs):
        if no_sol_return is None:
            no_sol_return = self.no_sol_return if self.no_sol_return is not None else False

        start_time = time.time()
        # Process kwargs
        upper_bound = kwargs.pop("ub", None)
        order = kwargs.pop("presolved", [])
        order = order.copy()
        headings = kwargs.pop("headings", [[] for head in graph.vertices])
        assert isinstance(headings, list)
        headings = headings.copy()
        for i, heading in enumerate(headings):
            headings[i] = heading.copy()
        remaining_edges = kwargs.pop("remaining", graph.edges)
        if isinstance(remaining_edges, np.ndarray):
            remaining_edges = remaining_edges.tolist()
        remaining_edges = remaining_edges.copy()
        # If one is empty, the other also needs to be emtpy
        assert order or len(remaining_edges) == graph.edge_amount
        assert len(remaining_edges) != graph.edge_amount or not order
        angles = graph.costs
        if angles is None:
            angles = get_graph_angles(graph)
        overall_cost = self._calc_pre_cost(headings, angles)
        while remaining_edges and (upper_bound is None
                                   or upper_bound > overall_cost):
            candidate_edge, candidate_cost = self._get_candidate(
                order, remaining_edges, headings, angles)

            self._set_new_headings(candidate_edge, headings)

            to_remove = self._get_edge(remaining_edges, candidate_edge)
            remaining_edges.remove(to_remove)
            order.append(to_remove)
            overall_cost += candidate_cost

        if no_sol_return:
            return order, overall_cost
        sol = AngularGraphSolution(graph,
                                   time.time() - start_time,
                                   self.__class__.__name__,
                                   self.solution_type,
                                   is_optimal=False,
                                   order=order)
        return sol
Пример #12
0
    def solve(self, graph: Graph, **kwargs):
        # Sort'em
        hull = ConvexHull(graph.vertices)
        # Indices are in counter clockwise order, therefore reverse them
        indices = [vertex for vertex in reversed(hull.vertices)]
        length = len(indices)
        assert length == graph.vert_amount
        k = graph.ad_matrix[0].sum() / 2
        assert k.is_integer()
        k = int(k)
        neighbors = {
            indices[i]: tuple(indices[int(j % length)]
                              for j in range(i - k, i + k + 1) if i != j)
            for i in range(length)
        }
        # Just check if every node has 2k neighbors
        for index in indices:
            #neighbors = tuple(indices[int(j % length)] for j in range(i-k, i+k+1) if i != j)
            assert graph.ad_matrix[index, neighbors[index]].sum() == 2 * k
        tripel_edges, abs_graph = convert_graph_to_angular_abstract_graph(
            graph, simple_graph=False, return_tripel_edges=True)
        edge_vert = {i: {} for i in range(length)}
        for edge in tripel_edges:
            edge_vert[edge[0]][edge[1:]] = tripel_edges[edge]
            #edge_vert[edge[0]][tuple(reversed(edge[1:]))] = tripel_edges[edge]
        taken_edges = []

        # Phase one
        self._phase_one(indices, k, neighbors, taken_edges, edge_vert)
        # Phase two
        split_vertex_index = round(length / 2)
        self._phase_two(split_vertex_index, k, indices, neighbors, taken_edges,
                        edge_vert, length)
        # Clockwise part
        self._phase_three(k, indices, split_vertex_index, neighbors,
                          taken_edges, edge_vert)
        dep_graph = get_dep_graph(taken_edges, abs_graph)
        order = calculate_order(dep_graph, calculate_circle_dep=True)
        returned_order = [tuple(abs_graph.vertices[i]) for i in order]

        return AngularGraphSolution(graph,
                                    0,
                                    self.__class__.__name__,
                                    'MinSum',
                                    False,
                                    order=reversed(returned_order))
Пример #13
0
    def solve(self, graph: Graph, **kwargs):
        # count how many vertices have largest angle north or south
        # Maybe choose which set get which starting position accordingly
        order = None
        start_time = time.time()
        error_message = None
        try:
            colors = kwargs.pop("colors", None)
            if colors is None:
                colors = self._calc_subsets(graph)
            colors = self._check_bipartite(colors, graph)
            sectors_v = {
                i: get_vertex_sectors(graph.vertices[i],
                                      graph.vertices[np.nonzero(
                                          graph.ad_matrix[i])],
                                      start_north=bool(colors[i]))
                for i in range(graph.vert_amount)
            }

            edge_vert, abs_graph = self._create_abs_graph_and_edge_translation(
                graph)

            used_edges = self._calculated_used_edges(sectors_v, graph,
                                                     edge_vert)

            dep_graph = get_dep_graph(used_edges, abs_graph)
            order = [
                tuple(abs_graph.vertices[i])
                for i in calculate_order(dep_graph, calculate_circle_dep=True)
            ]
        except NotImplementedError as e:
            error_message = str(e)
            raise e
        # For small instances it could happen that two vertices have connections only to each other.
        # These edges will not be scheduled. Since they do not depend on any other edge, we just add them at the end.
        order = self._add_single_edges(order, graph)
        sol = AngularGraphSolution(graph,
                                   time.time() - start_time,
                                   self.__class__.__name__,
                                   self.solution_type,
                                   is_optimal=False,
                                   error_message=error_message,
                                   order=order)
        return sol
Пример #14
0
    def solve(self, graph: Graph, **kwargs):
        self.time_limit = kwargs.pop("time_limit", self.max_time)
        self.upper_bound = kwargs.pop("upper_bound", None)
        self.relax_solver.build_model(graph)
        self.relax_solver.set_output(False)
        self.abs_graph = self.relax_solver.abstract_graph
        self.edge_vars = self.relax_solver.edges
        self.max_edges = 0
        for v_i in range(len(graph.vertices)):
            # Constraint over all vertices: least 2k-1 connections between incident edges
            incident_vertices = [
                i for i in range(self.abs_graph.vert_amount)
                if np.intersect1d(self.abs_graph.vertices[i], v_i).size > 0
            ]
            self.max_edges += (len(incident_vertices) - 1)

        self.solve_time_start = time.time()
        self.lock = asyncio.Lock()
        asyncio.get_event_loop().run_until_complete(
            self._inner_solve(self.abs_graph, {}, 0, 0, {}))

        status = 'OPTIMAL'
        if self.time_limit and time.time(
        ) - self.solve_time_start > self.time_limit:
            status = 'TIME_LIMIT'
        returned_order = None
        self.upper_bound = None
        if self.upper_bound_sol:
            dep_graph = self._get_dep_graph(self.upper_bound_sol)
            order = calculate_order(dep_graph, calculate_circle_dep=True)
            returned_order = [tuple(self.abs_graph.vertices[i]) for i in order]
        sol = AngularGraphSolution(graph,
                                   time.time() - self.solve_time_start,
                                   solution_type=self.solution_type,
                                   solver=self.__class__.__name__,
                                   is_optimal=status == "OPTIMAL",
                                   order=returned_order)

        self.upper_bound_sol = None
        return sol
Пример #15
0
    def solve(self, graph: Graph, start_solution=None, **kwargs):
        self.time_limit = float(kwargs.pop("time_limit", self.max_time))
        start_time = time.time()

        #    graph.costs = get_graph_angles(graph)
        solution = self.sub_solver(
            graph) if start_solution is None else start_solution
        angles = None
        if not isinstance(solution, AngularGraphSolution):
            angles = get_graph_angles(graph)
        best_order, best_cost = self._get_cost(solution, angles)
        with concurrent.futures.ThreadPoolExecutor(
                max_workers=cpu_count()) as executor:
            try:
                error_message = None
                futures = [
                    executor.submit(self._inner_solve, graph, best_order)
                    for swap in range(cpu_count())
                ]
                timeout = self.time_limit - (time.time() - start_time) + 10
                concurrent.futures.wait(futures, timeout=timeout)
            except TimeoutError as time_error:
                error_message = str(time_error)
            for future in futures:
                if future.done():
                    order, cost = future.result()
                    if cost < best_cost:
                        best_cost = cost
                        best_order = order
            if isinstance(best_order, np.ndarray):
                best_order = best_order.tolist()
            sol = AngularGraphSolution(graph,
                                       time.time() - start_time,
                                       self.__class__.__name__,
                                       self.solution_type,
                                       is_optimal=False,
                                       order=best_order,
                                       error_message=error_message)
            return sol
Пример #16
0
    def solve(self, graph: Graph, **kwargs):
        error_message = None
        returned_order = None
        is_optimal = False
        runtime = 0
        try:
            self.build_model(graph)
            if "time_limit" in kwargs:            
                self.model.setParam("TimeLimit", kwargs.pop("time_limit"))
            self.add_start_solution(graph, kwargs.pop("start_solution", None))
            self._add_callbacks(kwargs.pop("callbacks", None))
            if kwargs.pop("relax", False):
                old_edges = self.edges
                used_edges = None
                rel_model = self.model.relax()
                keys, self.edges = grb.multidict({key: rel_model.getVarByName(self.edges[key].VarName) for key in self.edges})
                rel_model.optimize(callback_rerouter)
                runtime = self.model.Runtime
                
            else:
                circle_found = True
                max_runtime = self.params["TimeLimit"]
                while(circle_found and max_runtime > 0):
                    self.model.optimize(callback_rerouter)
                    max_runtime -= self.model.Runtime
                    runtime = abs(self.params["TimeLimit"] - max_runtime)
                    try:
                        used_edges = grb.tupledict({key: self.edges[key] for key in self.edges if not math.isclose(0, self.edges[key].x, abs_tol=10**-6)})
                        circle_found = self._check_for_cycle(used_edges, self.model, lazy=False)
                        if circle_found and max_runtime > 0:
                            self.model.setParam("TimeLimit", max_runtime)
                    except AttributeError as e:
                        # Can happen if no solution was found in the time limit
                        # If not, raise error
                        if runtime < self.params["TimeLimit"]:
                            raise e
                    

            is_optimal = self.model.Status == grb.GRB.OPTIMAL
            if is_debug_env():
                local_subtours = 0
                for circle in self.found_circles:
                    verts = [key[1] for key in circle]
                    for v_i in self.v_incident_edges:
                        if self.v_incident_edges[v_i].issuperset(verts):
                            local_subtours += 1
                            break
                print("Overall subtours:", len(self.found_circles), "local subtours:", local_subtours,\
                    "in percent:", local_subtours*100/len(self.found_circles))
            
            try:
                used_edges = {key: self.edges[key] for key in self.edges if not math.isclose(0, self.edges[key].x, abs_tol=10**-6)}
                dep_graph = self._get_dep_graph(used_edges)
                order = calculate_order(dep_graph, calculate_circle_dep=True)
                returned_order = [tuple(self.abstract_graph.vertices[i]) for i in order]
            except (CircularDependencyException, AttributeError) as e:
                # If we have a circular dependency after the time limit we just didnt managed to get a feasable solution in time
                # Else something went wrong and the error should be raised
                if runtime < self.params["TimeLimit"]:
                    raise e
        except Exception as e:
            error_message = str(e)
            if is_debug_env():
                raise e
        #times = calculate_times(returned_order, self.graph)
        sol = AngularGraphSolution(self.graph,
                                    runtime,
                                    solution_type=self.solution_type,
                                    solver=self.__class__.__name__,
                                    is_optimal=is_optimal,
                                    order=returned_order,
                                    error_message=error_message)
        return sol
Пример #17
0
    def solve(self, graph: Graph, **kwargs):
        # count how many vertices have largest angle north or south
        # Maybe choose which set get which starting position accordingly
        order = None
        start_time = time.time()
        error_message = None
        try:
            colors = kwargs.pop("colors", None)
            if colors is None:
                colors = self._calc_subsets(graph)
            colors = self._check_bipartite(colors, graph)

            force_strategy = kwargs.pop("strategy", None)
            debug = kwargs.pop("debug", False)

            # MLSSC (LocalMinSum) lower bound is exactly the value for the cone described in the paper.
            mlssc_lb = max(get_lower_bounds(graph))
            if mlssc_lb >= 90 or force_strategy == 1:  # If we have a LB >= 90, we can use the same algorithm as before
                return super().solve(graph, colors=colors)
            else:  # LB < 90 needs another strategy with the sector splits. See paper for more details
                if mlssc_lb > 0:
                    s = math.floor(
                        180 /
                        mlssc_lb)  # The minium amount of lines where cone > lb
                    cone = np.radians(360 / (2 * s))
                    ad_angles_v = {
                        i: np.array([
                            i if i > 0 else 2 * np.pi + i
                            for i in np.arctan2(*(graph.vertices[np.nonzero(
                                graph.ad_matrix[i])] - graph.vertices[i]).T)
                        ])
                        for i in range(graph.vert_amount)
                    }
                    sectors_v = {i: {} for i in range(graph.vert_amount)}
                    for key in ad_angles_v:
                        angles = ad_angles_v[key] % (2 * np.pi)
                        non_zeros = np.nonzero(graph.ad_matrix[key])[0]
                        argsorted = np.argsort(angles)
                        for i in argsorted:
                            angle = angles[i]
                            current_sector = math.floor(angle / cone) % (
                                2 * s
                            )  # if colors[i] else (math.ceil(angle/cone)-1) % (2*s)
                            if current_sector not in sectors_v[key]:
                                sectors_v[key][current_sector] = [non_zeros[i]]
                            else:
                                sectors_v[key][current_sector].append(
                                    non_zeros[i])
                    # Check if every vertex has at most two sectors
                    for key in sectors_v:
                        assert len(
                            sectors_v[key]
                        ) <= 2, f"Sector build is wrong! Vertex index {key} has {len(sectors_v[key])} sectors"
                    # Give sectors directions
                    sector_directions_v = {
                        i: {
                            j: 1 - j % 2 if (s % 2 and colors[i]) else j % 2
                            for j in sectors_v[i]
                        }
                        for i in range(graph.vert_amount)
                    }
                    edge_vert, abs_graph = self._create_abs_graph_and_edge_translation(
                        graph)
                    used_edges = []
                    sector_orders = {}
                    for key in sectors_v:
                        sector_order = [-1, -1]
                        for j in sector_directions_v[key]:
                            #if s%2 == 0:
                            #    sector_order[j%2] = j
                            #else:
                            inner_key = 1 - j % 2 if (
                                s % 2 and colors[key]) else j % 2
                            sector_order[inner_key] = j
                        sector_orders[key] = sector_order

                    for key in sector_orders:
                        sector_order = sector_orders[key]
                        from_vert = None
                        for o in sector_order:
                            if o == -1:
                                continue
                            sectors_info = sectors_v[key][o]

                            non_zeros = np.nonzero(graph.ad_matrix[key])[0]

                            it = iter(sectors_info) if sector_directions_v[
                                key][o] == 0 else reversed(sectors_info)
                            for to_vert in it:
                                if from_vert is not None:
                                    used_edges.append(edge_vert[key][from_vert,
                                                                     to_vert])
                                    if debug:
                                        print("Used edge:", key, from_vert,
                                              to_vert)
                                from_vert = to_vert
                    dep_graph = get_dep_graph(used_edges, abs_graph)

                    try:
                        order = [
                            tuple(abs_graph.vertices[i])
                            for i in calculate_order(dep_graph,
                                                     calculate_circle_dep=True)
                        ]
                    except CircularDependencyException as c_e:
                        if debug:
                            translated_cycle = [
                                abs_graph.vertices[i.value].tolist()
                                for i in c_e.circle_nodes
                            ]
                            print("Cycle:", translated_cycle)
                        raise c_e
        except NotImplementedError as e:
            error_message = str(e)
            raise e
        order = self._add_single_edges(order, graph)
        sol = AngularGraphSolution(graph,
                                   time.time() - start_time,
                                   self.__class__.__name__,
                                   self.solution_type,
                                   is_optimal=False,
                                   error_message=error_message,
                                   order=order)
        assert sol.makespan <= mlssc_lb * 4.5
        return sol
Пример #18
0
 def _decode_sol(self, sol):
     return AngularGraphSolution(sol["graph"],
                                 times=sol["order"],
                                 runtime=sol["runtime"],
                                 name=sol["name"])
Пример #19
0
    def solve(self, graph: Graph, start_solution=None, **kwargs):
        time_limit = float(kwargs.pop("time_limit", self.time_limit))
        start_time = time.time()

        if graph.costs is None:
            angles = get_graph_angles(graph)
            graph.costs = angles
        else:
            angles = [i.copy() for i in graph.costs]

        solution = self.sub_solver(
            graph) if start_solution is None else start_solution
        improvement = True
        # solution can be AngularGraphSolution or simple edge order
        best_order = np.array(solution.order) if isinstance(
            solution, AngularGraphSolution) else np.array(solution)
        best_cost = self._get_cost(solution, angles)
        with concurrent.futures.ThreadPoolExecutor(
                max_workers=cpu_count()) as executor:
            try:
                error_message = None
                with tqdm.tqdm(
                        total=self.max_iterations,
                        desc=
                        f"Iterating local neighborhood. Best Sol: {best_cost}"
                ) as progressbar:
                    iteration = 0
                    while (self.max_iterations is None or iteration < self.max_iterations) and\
                          (time_limit or time.time() - start_time < time_limit) and\
                          (improvement):
                        improvement = False
                        candidate_order = None
                        candidate_cost = None
                        futures = [
                            executor.submit(self._inner_solve,
                                            [i.copy()
                                             for i in angles], i, best_order,
                                            best_cost, time_limit, start_time)
                            for i in range(graph.edge_amount)
                        ]
                        timeout = time_limit - (time.time() - start_time) + 10
                        concurrent.futures.wait(futures, timeout=timeout)
                        for future in futures:
                            if future.done():
                                order, cost = future.result()
                                if candidate_cost is None or cost < candidate_cost:
                                    candidate_cost = cost
                                    candidate_order = order

                        if candidate_cost is not None and candidate_cost < best_cost:
                            improvement = True
                            best_cost = candidate_cost
                            best_order = candidate_order
                            progressbar.set_description(
                                f"Iterating local neighborhood. Best Sol: {best_cost}"
                            )
                        if not improvement:
                            break
                        progressbar.update()
                        iteration += 1
            except concurrent.futures.TimeoutError as time_error:
                error_message = str(time_error) + " in iteration " + str(
                    iteration)
        sol = AngularGraphSolution(graph,
                                   time.time() - start_time,
                                   self.__class__.__name__,
                                   self.solution_type,
                                   is_optimal=False,
                                   order=best_order.tolist(),
                                   error_message=error_message)
        return sol
Пример #20
0
    def solve(self, graph: Graph, **kwargs):
        if graph.costs is None:
            graph.costs = get_graph_angles(graph)
        error_message = None
        self.time_limit = kwargs.pop("time_limit", self.max_time)
        self.graph = graph
        try:
            self.start_time = time.time()
            genomes = np.zeros(self.pop_size, dtype=object)
            genomes[:] = [
                EdgeOrderGraphGenome(graph, skip_graph_calc=True)
                for i in range(self.pop_size)
            ]
            with concurrent.futures.ThreadPoolExecutor(
                    max_workers=cpu_count()) as executor:
                self.executor = executor
                if self.greedy_start:
                    slicings = self._get_slicing(genomes)
                    futures = [
                        executor.submit(
                            _greedy_order, [
                                genome.order_numbers
                                for genome in genomes[slicing]
                            ], self.graph, self.sub_solvers[np.random.randint(
                                0, len(self.sub_solvers))]
                            #self._greedy_order, genomes[slicing],\
                            #self.sub_solvers[np.random.randint(0, len(self.sub_solvers))]
                        ) for slicing in slicings
                    ]
                    timeout_time = self.time_limit - (time.time() -
                                                      self.start_time)
                    concurrent.futures.wait(futures, timeout=timeout_time)
                    for future in futures:
                        future.exception()

                # Start solver
                genetic_algorithm = GeneticAlgorithm(
                    genomes=genomes,
                    selection=self.selection,
                    mutation=self._mutation,
                    fitness=self._fitness,
                    crossover=self.crossover,
                    callback=self.callback,
                    termCon=self.termination_condition,
                    elitism=self.elitism,
                    mutationChance=self.mutation_chance_genome,
                    mutationChanceGene=self.mutation_chance_gene)
                last_gen = genetic_algorithm.evolve()

        except concurrent.futures.TimeoutError as time_error:
            error_message = str(time_error)
            last_gen = genetic_algorithm.genomes
        finally:
            self.executor = None
            self.graph = None

        max_index = np.argmax([gen.solution for gen in last_gen])
        arg_sorted = np.argsort(last_gen[max_index].order_numbers)
        order = graph.edges[arg_sorted].tolist()
        sol = AngularGraphSolution(graph,
                                   time.time() - self.start_time,
                                   self.__class__.__name__,
                                   self.solution_type,
                                   is_optimal=False,
                                   order=order,
                                   error_message=error_message)
        return sol
    def build_ip_and_optimize(
            self,
            graph: Graph,
            initial_heading: Optional[Union[list, np.array]] = None,
            start_solution: Optional[dict] = None,
            callbacks: Optional[Union[Multidict, dict]] = None,
            **kwargs):
        try:
            error_message = None
            runtime = 0
            is_optimal = False
            times = None
            try:
                self.graph = graph
                self.model = grb.Model()
                for param in self.params:
                    self.model.setParam(param, self.params[param])
                if "time_limit" in kwargs:
                    self.model.setParam("TimeLimit", kwargs["time_limit"])

                self._add_callbacks(callbacks)

                arcs, degrees = self._calculate_degrees()
                time, diffs, absolutes, max_time = self._add_variables(arcs)
                self._add_constraints(arcs, degrees, time, diffs, absolutes,
                                      max_time)

                self.model.setObjective(max_time, grb.GRB.MINIMIZE)

                self._add_initial_heading(time, initial_heading)

                self._add_pre_solution(time, graph, start_solution)

                self.model.update()
                self.model.optimize(callback_rerouter)
                #for v in time:
                #if v.x != 0 or "time" in v.varName:
                #print('%s %g' % (time[v].varName, time[v].x))
                #for v in absolutes:
                #    if absolutes[v].x >= 180:
                #        print('%s %g' % (absolutes[v].varName, absolutes[v].x))
                #print('%s %g' % (max_time.varName, max_time.x))
                runtime = self.model.Runtime
                times = {t: time[t].x for t in time}

                is_optimal = self.model.Status == grb.GRB.OPTIMAL

            except Exception as e:
                error_message = str(e)
                if is_debug_env():
                    raise e
            sol = AngularGraphSolution(self.graph,
                                       runtime=runtime,
                                       solver=self.__class__.__name__,
                                       solution_type="makespan",
                                       is_optimal=is_optimal,
                                       times=times,
                                       error_message=error_message)
            return sol

        except Exception as exception:
            raise exception
        finally:
            self._cleanup()
        return None