Parcourir la source

initial commit

jezvgg il y a 6 mois
commit
64c3b89360
4 fichiers modifiés avec 204 ajouts et 0 suppressions
  1. BIN
      __pycache__/verticle.cpython-310.pyc
  2. BIN
      __pycache__/verticle.cpython-312.pyc
  3. 189 0
      graph.py
  4. 15 0
      verticle.py

BIN
__pycache__/verticle.cpython-310.pyc


BIN
__pycache__/verticle.cpython-312.pyc


+ 189 - 0
graph.py

@@ -0,0 +1,189 @@
+import numpy as np
+from verticle import verticle
+import matplotlib.pyplot as plt
+from matplotlib.patches import FancyArrowPatch
+from functools import singledispatch
+
+
+class Graph:
+    '''
+    Graph by matrix
+    '''
+
+    __verticles = []
+    __edges = []
+    matrix = []
+
+
+    def __init__(self, verticles, matrix):
+        self.verticles = verticles
+        self.matrix = matrix
+
+
+    @singledispatch
+    def build(structs) -> "Graph":
+        raise Exception("Конструктор не работает")
+    
+
+    @build.register
+    @staticmethod
+    def build_verticles(verticles: dict):
+        matrix = []
+        for vert in verticles:
+            to = verticles[vert]
+            matrix.append( [1 if x in to else 0 for x in verticles] )
+        matrix = np.array(matrix)
+        return Graph(verticles, matrix)
+
+
+    @build.register
+    @staticmethod
+    def build_matrix(matrix: np.ndarray):
+        return Graph([str(i) for i in range(matrix.shape[0])], matrix)
+
+
+    @build.register
+    @staticmethod
+    def build_matrix(matrix: list):
+        return Graph([str(i) for i in range(len(matrix))], np.array(matrix))
+
+
+    def __eq__(self, __o: object) -> bool:
+        return np.array_equal(self.matrix, __o.matrix)
+
+
+    def __and__(self, __o: "Graph"):
+        result = self.copy()
+        result.matrix = (self.matrix+__o.matrix==2).astype(int)
+        return result
+
+
+    def __or__(self, __o: "Graph"):
+        result = self.copy()
+        result.matrix = (self.matrix+__o.matrix>0).astype(int)
+        return result
+
+
+    def __sub__(self, __o: "Graph"):
+        result = self.copy()
+        result.matrix = (self.matrix-__o.matrix>0).astype(int)
+        return result
+
+
+    def __xor__(self, __o: "Graph"):
+        result = self.copy()
+        result.matrix = (self.matrix!=__o.matrix).astype(int)
+        return result
+
+
+    def __str__(self):
+        result = "  "+"".join([str(node) for node in self.verticles])+"\n"
+        for i,row in enumerate(self.matrix):
+            result += str(self.verticles[i]) + " " + "".join(map(str,row))+"\n"
+        return result
+
+
+    def __invert__(self):
+        result = self.copy()
+        result.matrix = (self.matrix==0).astype(int)
+        return result
+
+
+    def set(self, indexes: list[int]):
+        '''
+        Меняет вершины по заданым индексам.
+        '''
+        if len(indexes) != len(self.verticles):
+            raise IndexError(f"indexes must be len of {len(self.verticles)}")
+
+        new_matrix = self.matrix[indexes]
+        self.matrix = new_matrix[:, indexes]
+        self.__verticles = [self.verticles[x] for x in indexes]
+
+
+    def replace(self, fro:str|verticle, to:str|verticle):
+        '''
+        Меняет 2 переданные вершины графа местами.
+        '''
+        index_fro = self.verticles.index(str(fro))
+        index_to = self.verticles.index(str(to))
+        indexes = [index_to if i==index_fro else index_fro if i==index_to else i for i in range(len(self.verticles))]
+        self.set(indexes)
+
+
+    def copy(self):
+        return Graph(self.dict)
+
+
+    def plot(self, x=0, y=0):
+        '''
+        x,y - смещение построения графа, если координаты вершин не заданы
+        '''
+        if not isinstance(self.verticles[0], verticle):
+            print("Перепись " + "="*32)
+            space = np.linspace(0, 2*np.pi, len(self.verticles)+1)[:-1]
+            self.__verticles = [verticle(name, np.cos(sp)+x, np.sin(sp)+y) for name, sp in zip(self.verticles, space)]
+
+        print([vert.name for vert in self.verticles])
+        print([vert.x for vert in self.verticles])
+        print([vert.y for vert in self.verticles])
+
+        for i,row in enumerate(self.matrix):
+            for j,elem in enumerate(row):
+                if elem == 0: continue
+                print(i, j ,elem)
+                print(self.verticles[i].x, self.verticles[i].y, self.verticles[j].x, self.verticles[j].y)
+                plt.arrow(self.verticles[i].x, self.verticles[i].y, 
+                          (self.verticles[j].x-self.verticles[i].x)*0.93, (self.verticles[j].y-self.verticles[i].y)*0.93, 
+                          head_width=0.035, head_length=0.035, arrowstyle='->')
+
+        print(self.verticles)
+        x = [v.x for v in self.verticles]
+        y = [v.y for v in self.verticles]
+        plt.scatter(x,y, c='red', zorder=1)
+
+
+
+    @property
+    def dict(self):
+        review = {}
+        if isinstance(self.__verticles[0],verticle): n_vert = [verticle(vert.name, vert.x, vert.y) for vert in self.verticles]
+        else: n_vert = self.__verticles
+        for vert, row in zip(n_vert, self.matrix):
+            if isinstance(vert,verticle):
+                review[vert] = [n_vert[i] for i,sym in enumerate(row) if sym]
+            else:
+                review[vert] = ''.join([self.__verticles[i] for i,sym in enumerate(row) if sym])
+        return review
+
+
+    @property
+    def verticles(self):
+        return self.__verticles
+
+
+    @verticles.setter
+    def verticles(self, verts):
+        self.__verticles = verts
+
+
+if __name__ == "__main__":
+    # g = Graph({'a':'ad','b':'ad','c':'bc','d':'bc', 'e':'ac', 'f':'bd'})
+    # h = Graph({'a':'bd','b':'bc','c':'bc','d':'ac'})
+    # print("graph G1:",g,sep="\n")
+    # print("graph H1:",h,sep="\n")
+    # print("graph G1 and H1:",g&h,sep="\n")
+    # print("graph G1 or H1:",g|h,sep="\n")
+    # print("graph G1 / H1:",g-h,sep="\n")
+    # print("graph G1 xor H1:",g^h,sep="\n")
+    # print("Invert G1:",~g)
+    # g.plot(1, 1)
+    # h.plot(3.2, 1)
+    g = Graph.build([[0, 1, 1, 1, 1],
+               [1, 0, 1, 1, 1],
+               [1, 1, 0, 1, 1],
+               [1, 1, 1, 0, 1],
+               [1, 1, 1, 1, 0]])
+    g.plot()
+    print(g)
+    plt.show()

+ 15 - 0
verticle.py

@@ -0,0 +1,15 @@
+class verticle:
+    def __init__(self, name, x, y):
+        self.name = name
+        self.x = x
+        self.y = y
+
+    def __str__(self):
+        return f"{self.name}"
+
+    def __repr__(self):
+        return f"{self.name} ({self.x}, {self.y})"
+
+if __name__ == "__main__":
+    p1 = verticle("A", 3, 4)
+    print(p1)