hbui
2024-07-23 97dc9f0c94dc9bf0f244be8aedcf137574cc497e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
class Graph:
    def __init__(self):
        self._adjacent: dict[int, set] = {}
        self._vertex_attribute: dict[int, dict] = {}
 
    def add_vertex(self, vertex):
        if vertex not in self._adjacent:
            if not isinstance(vertex, int):
                raise TypeError(f"Argument {vertex} is not a valid vertex")
            self._adjacent[vertex] = set()
            self._vertex_attribute[vertex] = {}
        pass
 
    def add_edge(self, u, v):
        self.add_vertex(u)
        self.add_vertex(v)
        v_neighbor = self._adjacent[v]
        if u not in v_neighbor:
            v_neighbor.add(u)
        u_neighbor = self._adjacent[u]
        if v not in u_neighbor:
            u_neighbor.add(v)
        pass
 
    def merge_attribute(self, vertex: int, properties: dict):
        """
        merge a dict of attribute to a vertex. Usage example:
        ```
        g = Graph();
        g.add_vertex(1);
        g.mergeAttribute(1, {'color': 0});
        ```
        :param vertex:
        :param properties:
        :return: self
        """
        if vertex not in self._adjacent:
            raise ValueError(f"Graph does not include vertex {vertex}")
        old_attributes = self._vertex_attribute.get[vertex]
        self._vertex_attribute[vertex] = old_attributes | properties
        return self
        pass
 
    def get_attribute(self, vertex):
        if vertex in self._adjacent:
            return self._vertex_attribute[vertex]
        else:
            raise ValueError(f"Graph does not include vertex {vertex}")
        pass
 
    def vertices(self):
        return self._adjacent.keys()
 
    def for_each_vertices(self, action):
        for v in self.vertices():
            action(v)
 
    def adjacent_of(self, vertex):
        if vertex not in self._adjacent:
            raise ValueError(f"Graph does not include vertex {vertex}")
        return self._adjacent.get(vertex)
 
    def for_each_edges(self, action):
        visited_edges: dict[int, set] = {}
        for start in self.vertices():
            for end in self.adjacent_of(start):
                (first, second) = (start, end) if (start >= end) else (end, start)
            if first in visited_edges:
                visited_adjacent = visited_edges.get(first)
                if second not in visited_adjacent:
                    visited_adjacent.add(second)
                    action(start, end)
            else:
                adjacent = set()
                visited_edges[first] = adjacent
                adjacent.add(second)
                action(start, end)
 
    def get_lecture_name(self, vertex):
        pass
 
    def set_lecture_name(self, vertex, name):
        pass
 
    def __repr__(self):
        text = ""
        sorted_key = sorted(self._adjacent.keys())
        last_key = sorted_key.pop()
        def adjacent_fn(vertex): return "[" + ", ".join([str(v) for v in self._adjacent[vertex]]) + "]"
        for key in sorted_key:
            text += f"{key} → {adjacent_fn(key)}\n"
        text += f"{last_key} → {adjacent_fn(last_key)}"
        return text
 
    def to_dot(self) -> str:
        pass