Пример #1
0
    def test_arrival_departure_dfs(self):
        disjoint_graph = {
            "graph": {
                "a": ["b", "c"],
                "b": [],
                "c": ["d", "e"],
                "d": ["b", "f"],
                "e": ["f"],
                "f": [],
                "g": ["h"],
                "h": []
            },
            "directed": True
        }

        graph = Graph(input_graph=json.dumps(disjoint_graph))

        # list to store the arrival time of vertex
        arrival = {v: 0 for v in graph.vertices()}
        # list to store the departure time of vertex
        departure = {v: 0 for v in graph.vertices()}
        # mark all the vertices as not discovered
        discovered = {v: False for v in graph.vertices()}
        time = -1

        for v in graph.vertices():
            if not discovered[v]:
                time = arrival_departure_dfs(graph, v, discovered, arrival,
                                             departure, time)

        # pair up the arrival and departure times and ensure correct ordering
        result = list(zip(arrival.values(), departure.values()))
        expected_times = [(0, 11), (1, 2), (3, 10), (4, 7), (8, 9), (5, 6),
                          (12, 15), (13, 14)]
        self.assertListEqual(expected_times, result)
Пример #2
0
 def test_add_edge(self):
     graph = Graph("my graph")
     graph.add_vertex("A")
     graph.add_vertex("B")
     graph.add_edge("A", "B")
     self.assertEqual(1, len(graph.edges()))
     graph.add_edge("X", "Y")
     self.assertEqual(2, len(graph.edges()))
     self.assertEqual(4, len(graph.vertices()))
Пример #3
0
def density(graph: Graph) -> float:
    """
    The graph density is defined as the ratio of the number of edges of a given
    graph, and the total number of edges, the graph could have.
    A dense graph is a graph G = (V, E) in which |E| = Θ(|V|^2)
    :param graph:
    :return:
    """
    V = len(graph.vertices())
    E = len(graph.edges())
    return 2.0 * (E / (V**2 - V))
Пример #4
0
def check_for_cycles(graph: Graph, v: str, visited: Dict[str, bool],
                     rec_stack: List[bool]) -> bool:
    """

    :param graph:
    :param v: vertex to start from
    :param visited: list of visited vertices
    :param rec_stack:
    :return: whether or not the graph contains a cycle
    """
    visited[v] = True
    rec_stack[graph.vertices().index(v)] = True

    for neighbour in graph[v]:
        if not visited.get(neighbour, False):
            if check_for_cycles(graph, neighbour, visited, rec_stack):
                return True
        elif rec_stack[graph.vertices().index(neighbour)]:
            return True

    rec_stack[graph.vertices().index(v)] = False
    return False
Пример #5
0
def topological(graph: Graph) -> List[str]:
    """
    O(V+E)
    :param graph:
    :return: List of vertices sorted topologically
    """
    def mark_visited(g: Graph, v: str, v_map: Dict[str, bool],
                     t_sort_results: List[str]):
        v_map[v] = True
        for n in g.get_neighbors(v):
            if not v_map[n]:
                mark_visited(g, n, v_map, t_sort_results)
        t_sort_results.append(v)

    visited = {v: False for v in graph.vertices()}
    result: List[str] = []

    for v in graph.vertices():
        if not visited[v]:
            mark_visited(graph, v, visited, result)

    # Contains topo sort results in reverse order
    return result[::-1]
Пример #6
0
def diameter(graph: Graph) -> int:
    """
    :param graph:
    :return: length of longest path in graph
    """
    vee = graph.vertices()
    pairs = [(vee[i], vee[j]) for i in range(len(vee) - 1)
             for j in range(i + 1, len(vee))]
    smallest_paths = []
    for (start, end) in pairs:
        paths = find_all_paths(graph, start, end)
        smallest = sorted(paths, key=len)[0]
        smallest_paths.append(smallest)

    smallest_paths.sort(key=len)
    # longest path is at the end of list,
    # i.e. diameter corresponds to the length of this path
    dia = len(smallest_paths[-1]) - 1
    return dia
Пример #7
0
def is_complete(graph: Graph) -> bool:
    """
    Checks that each vertex has V(V-1) / 2 edges and that each vertex is
    connected to V - 1 others.

    runtime: O(n^2)
    :param graph:
    :return: true or false
    """
    V = len(graph.vertices())
    max_edges = (V**2 - V)
    if not graph.is_directed():
        max_edges //= 2

    E = len(graph.edges())
    if E != max_edges:
        return False

    for vertex in graph:
        if len(graph[vertex]) != V - 1:
            return False
    return True
Пример #8
0
def breadth_first_search(graph: Graph, start: str) -> List[str]:
    """

    :param graph:
    :param start: the vertex to start the traversal from
    :return:
    """
    # Mark all the vertices as not visited
    visited = {k: False for k in graph.vertices()}
    # Mark the start vertices as visited and enqueue it
    visited[start] = True

    queue = [start]
    walk = []
    while queue:
        cur = queue.pop(0)
        walk.append(cur)

        for i in graph[cur]:
            if not visited[i]:
                queue.append(i)
                visited[i] = True
    return walk
Пример #9
0
def is_connected(graph: Graph,
                 start_vertex: str = None,
                 vertices_encountered: Set[str] = None) -> bool:
    """
    :param graph:
    :param start_vertex:
    :param vertices_encountered:
    :return: whether or not the graph is connected
    """
    if vertices_encountered is None:
        vertices_encountered = set()
    vertices = graph.vertices()
    if not start_vertex:
        # choose a vertex from graph as a starting point
        start_vertex = vertices[0]
    vertices_encountered.add(start_vertex)
    if len(vertices_encountered) != len(vertices):
        for vertex in graph[start_vertex]:
            if vertex not in vertices_encountered:
                if is_connected(graph, vertex, vertices_encountered):
                    return True
    else:
        return True
    return False
Пример #10
0
 def test_set_from_adjacency_matrix(self):
     array_graph = np.array([[0, 1], [1, 0]], dtype=object)
     graph = Graph(input_array=array_graph)
     self.assertEqual(2, len(graph.vertices()))
     self.assertEqual(1, len(graph.edges()))
Пример #11
0
 def test_add_vertex(self):
     graph = Graph("my graph")
     graph.add_vertex("A")
     self.assertEqual(['A'], graph.vertices())