Esempio n. 1
0
class CrowdSolution(object):
    def __init__(self, graph):
        self.graph = graph
        self.edge_dictionary = {}
        self.route = Route(graph)
        self.max_edge_count = 0

    def log(self, log_path):
        log = open(log_path, "w+")
        log.write("edge_key" + ", " + "edge_count" + "\n")

        for edge_key, edge_entry in self.edge_dictionary.items():
            log.write(str(edge_entry.edge_key) + ", " + str(edge_entry.edge_count) + "\n")

        log.close()

    def add_edge_entry(self, new_edge_entry):
        ## EDGE CANNOT BE REMOVED HERE. NEEDS TO BE CONSERVATIVE
        ## ISSUE
        spot_taken = False
        keys_to_be_deleted = list([])

        self.display()
        for edge_key, edge_entry in self.edge_dictionary.items():
            if edge_entry.edge.vertices[0].vertex_id == new_edge_entry.edge.vertices[0].vertex_id or edge_entry.edge.vertices[0].vertex_id == new_edge_entry.edge.vertices[0].vertex_id:
                if new_edge_entry.edge_count >= edge_entry.edge.distance:
                    # Entries have same starting vertex
                    if new_edge_entry.edge.distance <= edge_entry.edge.distance:
                        keys_to_be_deleted.append(edge_entry.edge_key)
                        break
                    else:
                        spot_taken = True
                else:
                    spot_taken = True

        for key in keys_to_be_deleted:
            del self.edge_dictionary[key]

        if not spot_taken:
            self.edge_dictionary[new_edge_entry.edge_key] = new_edge_entry


    def load(self, log_path):
        with open(log_path, "r") as log:
            data_line = log.readline()

            while True:
                data_line = log.readline()
                if len(data_line) == 0:
                    break

                edge_key, edge_count = data_line.split(", ")
                edge_count = int(edge_count)
                if edge_count > self.max_edge_count:
                    self.max_edge_count = edge_count
                vertices = re.findall(r'\d+', edge_key)
                vertex_start = self.graph.get_vertex_by_id(int(vertices[0]))
                vertex_end = self.graph.get_vertex_by_id(int(vertices[1]))
                edge_entry = CrowdSolution.EdgeEntry(edge_key=edge_key, edge_count=edge_count, edge=Edge(vertex_start, vertex_end))
                self.edge_dictionary[edge_entry.edge_key] = edge_entry

#        self.display()

    def display(self):
        for edge_key, edge_entry in self.edge_dictionary.items():
            print(str(edge_entry.edge_key) + ", " + str(edge_entry.edge_count))

    def generate_heat_map(self, superiority_tolerance=0.8):
        graph = self.graph
        x = list([])
        y = list([])
        plots = list([])
        arrow_plots = list([])
        arrow_labels = list([])

        # Iterate over vertices, retrieving x and y coordinates
        for vertex in graph.vertices:
            x.append(vertex.x)
            y.append(vertex.y)

        # Plot the vertices
        vertex_plot = plt.scatter(x, y, label="Vertices")
        plots.append(vertex_plot)

        for edge_key, edge_entry in self.edge_dictionary.items():
            if edge_entry.edge_count >= (self.max_edge_count * superiority_tolerance):
                vertices = re.findall(r'\d+', edge_entry.edge_key)
                vertex_start = graph.get_vertex_by_id(int(vertices[0]))
                vertex_end = graph.get_vertex_by_id(int(vertices[1]))
                arrow_label = "Edge {}->{}".format(vertices[0], vertices[1])
                arrow_plot = plt.arrow(vertex_start.x, vertex_start.y, vertex_end.x-vertex_start.x, vertex_end.y-vertex_start.y,
                                       head_width=1, head_length=1,
                                       color='#{}{}{}'.format(Math.normalize_rgb(self.max_edge_count - edge_entry.edge_count, 0, self.max_edge_count),
                                                              "00",
                                                              Math.normalize_rgb(edge_entry.edge_count, 0, self.max_edge_count)),
                                       label=arrow_label)
                plots.append(arrow_plot)
                arrow_plots.append(arrow_plot)
                arrow_labels.append(arrow_label)

        # Show the graph with a legend
        plt.legend(arrow_plots, arrow_labels, loc=2, fontsize='small')
        plt.show()

    def get_unvisited_vertices_and_ending_vertices(self):
        last_visited_vertex = None
        unvisited_vertices = list([])
        ending_vertices = list([])
        for vertex in self.route.vertices:
            if not vertex.visited:
                unvisited_vertices.append(vertex)
                if last_visited_vertex is not None:
                    ending_vertices.append(last_visited_vertex)
            last_visited_vertex = vertex
        ending_vertices.append(self.route.vertices[-1])

        return unvisited_vertices, ending_vertices

    def edge_create_circular_path(self, edge):
        starting_vertex = edge.vertices[0]
        ending_vertex = edge.vertices[1]
        initial_ending_vertex = ending_vertex

        while True:
#            print(starting_vertex)
            edge_matching_starting_vertex = self.route.get_edge_by_vertex_id(starting_vertex.vertex_id, 1)

            if edge_matching_starting_vertex is None:
                break
            else:
                if edge_matching_starting_vertex.vertices[0].vertex_id == initial_ending_vertex.vertex_id:
                    return True

                starting_vertex = edge_matching_starting_vertex.vertices[0]
                ending_vertex = edge_matching_starting_vertex.vertices[1]

        return False

    def complete_graph_greedy_heuristic(self, superiority_tolerance=0.8):
        self.route.reset_route()
        starting_vertex = None

        # Update route to match current representation given superiority_tolerance
        superiority_edges = [(edge_key, edge_entry) for (edge_key, edge_entry) in self.edge_dictionary.items() if edge_entry.edge_count >= (self.max_edge_count * superiority_tolerance)]

        for edge_key, edge_entry in superiority_edges:
            better_edge = False
            for edge_key_1, edge_entry_1 in superiority_edges:
                if edge_entry.edge.vertices[0].vertex_id == edge_entry_1.edge.vertices[0].vertex_id or edge_entry.edge.vertices[1].vertex_id == edge_entry_1.edge.vertices[1].vertex_id:
                    if edge_entry.edge_count == edge_entry_1.edge_count:
                        if edge_entry.edge.distance > edge_entry_1.edge.distance:
                            better_edge = True
                    elif edge_entry.edge_count < edge_entry_1.edge_count:
                        better_edge = True

            if not better_edge:
                if self.route.edges is None:
                    self.route.add_edge(edge_entry.edge)
                else:
                    if not self.edge_create_circular_path(edge_entry.edge):
                        self.route.add_edge(edge_entry.edge)
        self.route.distance_traveled = self.route.recount_distance()

        def choose_next_vertex():
            closest_item_next_to_closest_vertex = None
            r_type_of_closest_item = None
            closest_vertex = None
            closest_distance = None
            starting_vertex = self.route.vertices[0]

            for vertex in self.route.get_vertices_not_in_route():
                closest_item_next_to_vertex, item_distance = self.route.get_shortest_distance_to_route(vertex)

                if closest_vertex is None:
                    closest_vertex = vertex
                    closest_distance = item_distance
                    closest_item_next_to_closest_vertex = closest_item_next_to_vertex
                else:
                    if item_distance < closest_distance:
                        closest_distance = item_distance
                        closest_vertex = vertex
                        closest_item_next_to_closest_vertex = closest_item_next_to_vertex

            if len(self.route.get_unvisited_vertices()) == 0:
                return self.route.vertices[0], self.route.vertices[1]
            else:
                return closest_vertex, closest_item_next_to_closest_vertex

        while len(self.route.vertices) < len(self.route.graph.vertices):
            next_vertex, closest_item_next_to_vertex = choose_next_vertex()
            self.route.lasso(next_vertex, closest_item_next_to_vertex)

        self.route.greedy_recombine()

        return self.route

    class EdgeEntry(object):
        def __init__(self, edge_key, edge_count, edge):
            self.edge_key = edge_key
            self.edge_count = edge_count
            self.edge = edge

        def __eq__(self, other):
            return self.edge_key == other.edge_key

        def __lt__(self, other):
            return self.edge_count < other.edge_count

        def __le__(self, other):
            return self.edge_count <= other.edge_count

        def __gt__(self, other):
            return self.edge_count > other.edge_count

        def __ge__(self, other):
            return self.edge_count >= other.edge_count

        def __str__(self):
            return "[edge_key: " + str(self.edge_key) + ", edge_count: " + str(self.edge_count) + ", edge: " + str(self.edge) + "]"

        def increment(self):
            self.edge_count += 1
Esempio n. 2
0
    class GreedyAlgorithm(object):
        def __init__(self, graph, starting_vertex_id=1, reset_heuristic=False):
            self.route = Route(graph)
            self.starting_vertex_id = starting_vertex_id
            self.route.goto(
                self.route.graph.get_vertex_by_id(starting_vertex_id))
            self.done = False
            self.attempted_starting_vertex_ids = list([starting_vertex_id])
            self.remaining_starting_vertex_ids = self.get_remaining_starting_vertex_ids(
            )
            self.reset_heuristic = reset_heuristic
            self.crosses = 0

        def __eq__(self, other):
            return self.route.distance_traveled == other.route.distance_traveled

        def __lt__(self, other):
            return self.route.distance_traveled < other.route.distance_traveled

        def __le__(self, other):
            return self.route.distance_traveled <= other.route.distance_traveled

        def __gt__(self, other):
            return self.route.distance_traveled > other.route.distance_traveled

        def __ge__(self, other):
            return self.route.distance_traveled >= other.route.distance_traveled

        def __str__(self):
            string = "Starting vertex id: " + str(
                self.starting_vertex_id) + "\n"

            string += "Route: " + str(self.route) + "\n"

            string += "reset_heuristic: " + str(self.reset_heuristic) + "\n"

            string += "Crosses: " + str(self.crosses)

            return string

        def complete(self):
            while not self.done:
                self.step_forward()

            return self.route

        def step_forward(self):
            next_vertex, closest_item_next_to_vertex = self.choose_next_vertex(
            )
            self.route.lasso(next_vertex, closest_item_next_to_vertex)

            if len(self.route.vertices) > len(self.route.graph.vertices):
                self.done = True

        def step_backward(self):
            if len(self.route.vertices) > 0:
                self.route.walk_back()
                self.attempted_starting_vertex_ids.pop()
                self.remaining_starting_vertex_ids = self.get_remaining_starting_vertex_ids(
                )

                if self.done:
                    self.done = False

        def choose_next_vertex(self):
            closest_item_next_to_closest_vertex = None
            r_type_of_closest_item = None
            closest_vertex = None
            closest_distance = None

            for vertex in self.route.get_unvisited_vertices():
                closest_item_next_to_vertex, item_distance = self.route.get_shortest_distance_to_route(
                    vertex)

                if closest_vertex is None:
                    closest_vertex = vertex
                    closest_distance = item_distance
                    closest_item_next_to_closest_vertex = closest_item_next_to_vertex
                else:
                    if item_distance < closest_distance:
                        closest_distance = item_distance
                        closest_vertex = vertex
                        closest_item_next_to_closest_vertex = closest_item_next_to_vertex

            if len(self.route.get_unvisited_vertices()) == 0:
                return self.route.vertices[0], self.route.vertices[1]
            else:
                return closest_vertex, closest_item_next_to_closest_vertex

        def get_remaining_starting_vertex_ids(self):
            return [
                vertex_id for vertex_id in list(
                    range(1,
                          len(self.route.graph.vertices) + 1))
                if vertex_id not in self.attempted_starting_vertex_ids
            ]