PyPyNum 1.7.0__py3-none-any.whl → 1.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyPyNum
3
- Version: 1.7.0
3
+ Version: 1.8.0
4
4
  Summary: A multifunctional mathematical calculation package written in pure Python programming language [Python>=3.5]
5
5
  Home-page: https://www.gitee.com/PythonSJL/PyPyNum
6
6
  Author: Shen Jiayi
@@ -668,6 +668,7 @@ License:
668
668
  For more information on this, and how to apply and follow the GNU AGPL, see
669
669
  <http://www.gnu.org/licenses/>.
670
670
 
671
+ Keywords: math,数学,mathematics,数学计算,numerical,数值,computation,计算,scientific,科学,algebra,代数,calculus,微积分,statistics,统计,linear-algebra,线性代数,optimization,优化,numerical-analysis,数值分析,matrix,矩阵,vector,向量,tensor,张量,numerics,数值计算,library,库,tools,工具,utils,实用程序,algorithms,算法,software,软件,package,包,methods,方法,data-science,数据科学,machine-learning,机器学习,computational,计算的,operations,操作,functions,函数,processing,处理,programming,编程,simulation,仿真,visualization,可视化,physics,物理
671
672
  Requires-Python: >=3.5
672
673
  Description-Content-Type: text/markdown
673
674
 
@@ -691,7 +692,7 @@ Description-Content-Type: text/markdown
691
692
  [![Downloads](https://static.pepy.tech/badge/pypynum/month)](https://pepy.tech/project/pypynum)
692
693
  [![Downloads](https://static.pepy.tech/badge/pypynum/week)](https://pepy.tech/project/pypynum)
693
694
 
694
- ## Version -> 1.7.0 | PyPI -> https://pypi.org/project/PyPyNum/ | Gitee -> https://www.gitee.com/PythonSJL/PyPyNum
695
+ ## Version -> 1.8.0 | PyPI -> https://pypi.org/project/PyPyNum/ | Gitee -> https://www.gitee.com/PythonSJL/PyPyNum
695
696
 
696
697
  ![LOGO](PyPyNum.png)
697
698
 
@@ -740,54 +741,65 @@ Python interpreter and run it!)
740
741
  ```
741
742
  !=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
742
743
 
743
- 新增代码行数:
744
- 约八百行
744
+ 新增代码行数为603行
745
745
 
746
- New code lines:
747
- approximately 800 lines
746
+ Add 603 new lines of code
748
747
 
749
748
  !=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
750
749
 
751
- 部分函数再次优化,性能提高一倍。
750
+ 新增函数“magic_square”的功能简介:可
751
+ 以生成任意大于等于三的整数阶幻方。
752
752
 
753
- Partial functions were optimized
754
- again, resulting in a doubling
755
- of performance.
753
+ Introduction to the newly added
754
+ function "magic square": It can
755
+ generate any integer order magic
756
+ square greater than or equal to
757
+ three.
756
758
 
757
759
  !=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
758
760
 
759
- 新增的好玩功能举例。
760
-
761
- Examples of newly added fun
762
- features.
763
-
764
- 新增的有序集合包含绝大多数内置集合的运算
765
- ,并且另有几个新函数。请注意它不是从内置
766
- 集合继承的。
767
-
768
- The newly added ordered set
769
- contains the majority of
770
- built-in set operations, and
771
- there are also several new
772
- functions. Please note that it
773
- does not inherit from the
774
- built-in set.
775
-
776
- 新增的无穷迭代器支持迭代多种数列,默认的
777
- 空字符串即为自增数列。目前支持的数列有等
778
- 差数列、等比数列、斐波那契数列与卡特兰数
779
- 列。
780
-
781
- The newly added infinite
782
- iterator supports iterating
783
- multiple sequences, and the
784
- default empty string is the self
785
- increasing sequence. The
786
- currently supported sequences
787
- include arithmetic sequences,
788
- proportional sequences,
789
- Fibonacci sequences, and Catalan
790
- sequences.
761
+ 新增模块“Graph”的功能简介:具有有向图
762
+ 、无向图、带权有向图、带权无向图这四个对
763
+ 象,支持添加或删除顶点和边,以及深度优先
764
+ 搜索与广度优先搜索这两种图的遍历方式,还
765
+ 有计算最短路径等功能。
766
+
767
+ Introduction to the functions of
768
+ the newly added module "Graph":
769
+ it has four objects: directed
770
+ graph, undirected graph,
771
+ weighted directed graph, and
772
+ weighted undirected graph. It
773
+ supports adding or removing
774
+ vertices and edges, as well as
775
+ depth first search and breadth
776
+ first search for graph
777
+ traversal. It also has functions
778
+ such as calculating the shortest
779
+ path.
780
+
781
+ !=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
782
+
783
+ 新增模块“polynomial”的功能简介:有一
784
+ 个多项式对象,可以通过传入包含“(次数,
785
+ 系数)”的二元组组成的序列创建多项式对象
786
+ ,可以随时设置某一项的数值,并且支持多
787
+ 项式形式的四则运算,还有取商式、取余式
788
+ 、求幂、求模幂的功能。
789
+
790
+ Introduction to the newly added
791
+ module "polynomial": There is a
792
+ polynomial object that can be
793
+ created by passing in a sequence
794
+ of binary tuples containing
795
+ "degree, coefficient". The value
796
+ of a certain term can be set at
797
+ any time, and it supports
798
+ polynomial form arithmetic
799
+ operations. It also has
800
+ functions such as quotient,
801
+ remainder, exponentiation, and
802
+ modular exponentiation.
791
803
 
792
804
  !=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
793
805
 
@@ -796,34 +808,23 @@ sequences.
796
808
  <<<The ellipsis in the following structure represents the original part>>>
797
809
 
798
810
  PyPyNum
799
- Tree [Various trees]
811
+ Graph [Graph theory]
800
812
  CLASSES
801
- MultiTree
802
- MultiTreeNode
803
- ★ maths [Mathematical functions]
804
- FUNCTIONS
805
- ...
806
- totient(n: int) -> int
807
- mod_order(a: int, n: int, b: int) -> int
808
- primitive_root(a: int, single: bool = False) -> Union[int, list]
809
- normalize(data: arr, target: num = 1) -> arr
810
- average(data, weights, expected=False)
811
- exgcd(a: int, b: int) -> tuple
812
- crt(n: arr, a: arr) -> int
813
- ★ sequence [Various sequences]
813
+ BaseGraph
814
+ BaseWeGraph
815
+ WeDiGraph
816
+ WeUnGraph
817
+ DiGraph
818
+ UnGraph
819
+ polynomial [Polynomial object]
820
+ CLASSES
821
+ Polynomial
814
822
  FUNCTIONS
815
- farey(n: int) -> list
816
- ...
823
+ poly(terms=None)
817
824
  ★ tools [Other useful tools]
818
825
  FUNCTIONS
819
826
  ...
820
- primality(n: int, iter_num: int = 10) -> bool
821
- generate_primes(limit: int) -> list
822
- prime_factors(integer: int, dictionary: bool = False, pollard_rho: bool = True) -> Union[list, dict]
823
- ★ utils [Other useful tools]
824
- CLASSES
825
- InfIterator
826
- OrderedSet
827
+ magic_square(n)
827
828
  ```
828
829
 
829
830
  ### 运行用时测试
@@ -893,6 +894,14 @@ PyPyNum
893
894
  Triangle
894
895
  FUNCTIONS
895
896
  distance(g1, g2, error: int | float = 0) -> float
897
+ ★ Graph [Graph theory]
898
+ CLASSES
899
+ BaseGraph
900
+ BaseWeGraph
901
+ WeDiGraph
902
+ WeUnGraph
903
+ DiGraph
904
+ UnGraph
896
905
  ★ Group [Group theory]
897
906
  CLASSES
898
907
  Group
@@ -1138,6 +1147,11 @@ PyPyNum
1138
1147
  unary(function, right: real = 5, left: real = -5, top: real = 5, bottom: real = -5, complexity: real = 5...
1139
1148
  binary(function, right: real = 5, left: real = -5, top: real = 5, bottom: real = -5, complexity: real = 5...
1140
1149
  c_unary(function, start: real, end: real, interval: real = 5, projection: str = "ri", right: real = 5...
1150
+ ★ polynomial [Polynomial object]
1151
+ CLASSES
1152
+ Polynomial
1153
+ FUNCTIONS
1154
+ poly(terms=None)
1141
1155
  ★ probability [Probability function]
1142
1156
  FUNCTIONS
1143
1157
  binomial(sample_size: int, successes: int, success_probability: Union[int, float]) -> float
@@ -1176,6 +1190,7 @@ PyPyNum
1176
1190
  primality(n: int, iter_num: int = 10) -> bool
1177
1191
  generate_primes(limit: int) -> list
1178
1192
  prime_factors(integer: int, dictionary: bool = False, pollard_rho: bool = True) -> Union[list, dict]
1193
+ magic_square(n)
1179
1194
  ★ utils [Other useful tools]
1180
1195
  CLASSES
1181
1196
  InfIterator
@@ -1,16 +1,19 @@
1
1
  pypynum/Array.py,sha256=MLGvkYC9V7fGAR3g1Xykt_-hJYDC8mE47ji8dBcqFhk,6632
2
2
  pypynum/FourierT.py,sha256=AtG0tESykzEs4gDsXhcizW7qhQnmw0gjcWcXefBqzhs,1401
3
3
  pypynum/Geometry.py,sha256=bJCuif-wHO-t7oHFEE7ntzIdQwzUEbT3mcKgmBV6Wps,13982
4
+ pypynum/Graph.py,sha256=m9iTCNYRCZmAexDzwJ8Y6J7v1aweT-6TZkqh4fOtZDE,10131
4
5
  pypynum/Group.py,sha256=m39OZNRoG9b3p_7sS1u50A0rJl0aYqYPVvnttkYQ_gw,2944
5
6
  pypynum/Logic.py,sha256=IJAv59ECHU0HmG9lYCAQ_puqeL6Zor3-IDIVH48KBWE,11000
6
7
  pypynum/Matrix.py,sha256=Z2k0bl_VpnaWB3QZjokR9CR7-kDaYIKUjKITWTYGa98,11024
7
8
  pypynum/NeuralN.py,sha256=iSOvC9JW1h4AFGokGGOTkKie5hAYN_YT9H4f3apI9b8,3275
9
+ pypynum/PyPyNum.png,sha256=t96tJPWfHxT8kcXm_qZI2z5W36TgOqjCU9qdgbmlFws,11623
8
10
  pypynum/Quaternion.py,sha256=E7ajc4sDJyOuQQIwKPhUEHgiaeeR5BEzFZHhJMxvbok,8007
11
+ pypynum/README.md,sha256=fiCTdsbI9rza9ZogDQ2jwxHhTFXD7dR6vfAbBTkYUP4,43971
9
12
  pypynum/Symbolics.py,sha256=Nfo0DEch7LII53ye1wZAdIfd3IAOKbECnZQMSk_cmCs,2898
10
13
  pypynum/Tensor.py,sha256=SJzGRNwHZzOgEabt47scccb-plA25-6s01SFyHd6lJo,3801
11
- pypynum/Tree.py,sha256=7zqhVRdDu9u5lBQLM99AmfwIe0mgkfofj-VcHGguQGc,2816
14
+ pypynum/Tree.py,sha256=MUT9LErZ3ER_cbiga-nOaZC7Hln8jEV8tRca2dRPWmY,2827
12
15
  pypynum/Vector.py,sha256=eiFCY6H35pMvvDX7NpLux_bSfLI8rK8JHkaRxv7pOW8,3552
13
- pypynum/__init__.py,sha256=X6ENdfAc5xxaFMNRMbT2JAx4VCPEa6W4nLkDdNASUsM,1782
16
+ pypynum/__init__.py,sha256=akxx-NuZTFE9fnNW9u6KUo3KyA-vU8iU_m70FQmfzb0,1831
14
17
  pypynum/__temporary.py,sha256=OAs7it7xjDovgAmKLcj-9Pqp0228SSon3OZx0ih_h4I,5860
15
18
  pypynum/chars.py,sha256=VcK9w0i73FMCzc-9aIibjdHqyMsofJXdoBq0d8L7Vr0,1001
16
19
  pypynum/cipher.py,sha256=J5PZl8Xt71LuX29eSBu4cybNK6Z3rhA9og_YzD0YJfU,1002
@@ -18,19 +21,20 @@ pypynum/constants.py,sha256=s2P1K8HH2nqoA6_YOVf6TKRl1Ozjf79GmCmLN9YbWxI,843
18
21
  pypynum/equations.py,sha256=_4xIXr7A56qBXKzJXyb91L4h09H7TDVNrcufy-XxkaI,744
19
22
  pypynum/errors.py,sha256=11-Au4aV8H5ExaDuMtu5iuGvpRaJP8gW7XbGNRmefSI,173
20
23
  pypynum/file.py,sha256=rqrPdcX0NOEPM8s40-ymgPKsTn0HKABW-VEh1OtPnsk,3188
21
- pypynum/maths.py,sha256=GgEbFMGKim6ZwPwrFpwIIfhD5rDHsprIbR7mijoTWvc,24753
24
+ pypynum/maths.py,sha256=53TDBkZkHh1FZIQFfhi-_YwXvTSf630G-ooDS1Z7PFc,26518
22
25
  pypynum/numbers.py,sha256=WOxwwAN3yHakN4eHcVNn35qsfDcgw3UPSblv4woWyDE,6028
23
26
  pypynum/plotting.py,sha256=YQg9sO_nuLSaAKQuSpebWVvbu-ns2A7JOrHch6r0FQ0,8326
27
+ pypynum/polynomial.py,sha256=psFukA31Ed4U7hZHcCGWCpYMi8tanTsZl-pUdklikfg,5998
24
28
  pypynum/probability.py,sha256=kZLCfZb2q_y1CVbozSZj9xQ8Dw3il5WcAojX0jsNyXw,2130
25
29
  pypynum/random.py,sha256=vfTtyH5yOSKJoSI_-NT_Tg8wC-ZXT0wt34f87oaSpJY,4610
26
30
  pypynum/regression.py,sha256=D9J9lM23HiyY4eE8vHKaHoiwuvD1RYhkVNO0jQ4yml4,2118
27
31
  pypynum/sequence.py,sha256=7NSZm_p_B00KFj5XZrtSm2FXhsowxs0qg_Q_P4pAA8o,7194
28
32
  pypynum/test.py,sha256=Bksa7HZaywKBbLaCw2R5kGRFj6eKzkkJ7BdJBgIB3uM,8428
29
33
  pypynum/this.py,sha256=8Swp75xE5g6436NCVDfYUVwUzUcQFPLcCNFWQWY5eGQ,2129
30
- pypynum/tools.py,sha256=Ki33faUpijydG1AKqh3R6qmU4EFky_35p-ZsdUZPxJM,9823
34
+ pypynum/tools.py,sha256=jqmzsRi2INRlnI4hb4IbpMKHlvEww3ZKO9y6DxrJUbA,12697
31
35
  pypynum/types.py,sha256=CVWPZo_ACr_QGH5gAOhoG3jK35peiqipu3PH8ScEYHE,181
32
36
  pypynum/utils.py,sha256=V1k-JFHLr_VGUVqwOeAVH9Ju7AHQVEoVgYA7M-dPsLw,9881
33
- PyPyNum-1.7.0.dist-info/METADATA,sha256=ji2R_OijTBE2tNPK1GN5EVoTo4H6VNrbewnoVwtUCik,84411
34
- PyPyNum-1.7.0.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
35
- PyPyNum-1.7.0.dist-info/top_level.txt,sha256=4wW_Xb4bRglmiMsdPAe9f75MkXhNpuN88H17g_Cr5u8,8
36
- PyPyNum-1.7.0.dist-info/RECORD,,
37
+ PyPyNum-1.8.0.dist-info/METADATA,sha256=sKDkUYxVw125A9ZsbFD_AigRGifQOSUMR0jrIgKkIh8,85418
38
+ PyPyNum-1.8.0.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
39
+ PyPyNum-1.8.0.dist-info/top_level.txt,sha256=4wW_Xb4bRglmiMsdPAe9f75MkXhNpuN88H17g_Cr5u8,8
40
+ PyPyNum-1.8.0.dist-info/RECORD,,
pypynum/Graph.py ADDED
@@ -0,0 +1,270 @@
1
+ class BaseGraph:
2
+ def __init__(self):
3
+ self.graph = {}
4
+
5
+ def __repr__(self):
6
+ return "{}({})".format(self.__class__.__name__, sorted(self.graph.items()))
7
+
8
+ def add_vertex(self, vertex):
9
+ if vertex not in self.graph:
10
+ self.graph[vertex] = []
11
+
12
+ def remove_vertex(self, vertex):
13
+ if vertex in self.graph:
14
+ neighbors = self.graph[vertex]
15
+ del self.graph[vertex]
16
+ for neighbor in neighbors:
17
+ self.graph[neighbor].remove(vertex)
18
+
19
+ def has_vertex(self, vertex):
20
+ return vertex in self.graph
21
+
22
+ def has_edge(self, vertex1, vertex2):
23
+ return vertex1 in self.graph and vertex2 in self.graph[vertex1]
24
+
25
+ def get_edges(self, vertex):
26
+ return self.graph.get(vertex, {})
27
+
28
+ def all_vertices(self):
29
+ return sorted(set(list(self.graph) + sum([list(self.graph[vertex]) for vertex in self.graph], [])))
30
+
31
+ def all_edges(self):
32
+ edges = []
33
+ for vertex, neighbours in self.graph.items():
34
+ for neighbour in neighbours:
35
+ edges.append((vertex, neighbour))
36
+ return sorted(edges)
37
+
38
+ def to_adjacency_matrix(self):
39
+ vertices = self.all_vertices()
40
+ num_vertices = len(vertices)
41
+ matrix = [[0] * num_vertices for _ in range(num_vertices)]
42
+ if isinstance(self, BaseWeGraph):
43
+ for u in self.graph:
44
+ for v in self.graph[u].items():
45
+ try:
46
+ v, w = v
47
+ matrix_index_u = vertices.index(u)
48
+ matrix_index_v = vertices.index(v)
49
+ matrix[matrix_index_u][matrix_index_v] = w
50
+ except ValueError:
51
+ continue
52
+ else:
53
+ for u in self.graph:
54
+ for v in self.graph[u]:
55
+ try:
56
+ matrix_index_u = vertices.index(u)
57
+ matrix_index_v = vertices.index(v)
58
+ matrix[matrix_index_u][matrix_index_v] = 1
59
+ except ValueError:
60
+ continue
61
+ return [[self.__class__.__name__] + vertices] + [[vertex] + row for vertex, row in zip(vertices, matrix)]
62
+
63
+ def dfs(self, start_vertex, visited=None):
64
+ if visited is None:
65
+ visited = set()
66
+ visited.add(start_vertex)
67
+ search_list = [start_vertex]
68
+ if start_vertex not in self.graph:
69
+ return [start_vertex]
70
+ for neighbour in self.graph[start_vertex]:
71
+ if neighbour not in visited:
72
+ search_list.extend(self.dfs(neighbour, visited))
73
+ return search_list
74
+
75
+ def bfs(self, start_vertex):
76
+ visited = {start_vertex}
77
+ queue = [start_vertex]
78
+ search_list = [start_vertex]
79
+ while queue:
80
+ vertex = queue.pop(0)
81
+ if vertex in self.graph:
82
+ for neighbour in self.graph[vertex]:
83
+ if neighbour not in visited:
84
+ visited.add(neighbour)
85
+ queue.append(neighbour)
86
+ search_list.append(neighbour)
87
+ return search_list
88
+
89
+ def is_connected(self):
90
+ visited = set()
91
+ queue = []
92
+ for node in self.graph:
93
+ if node not in visited:
94
+ visited.add(node)
95
+ queue.append(node)
96
+ break
97
+ while queue:
98
+ node = queue.pop(0)
99
+ for neighbor in self.graph[node]:
100
+ if neighbor not in visited:
101
+ visited.add(neighbor)
102
+ queue.append(neighbor)
103
+ return len(visited) == len(self.graph)
104
+
105
+ def is_complete(self):
106
+ num_nodes = len(self.graph)
107
+ return all([len(self.graph[node]) == num_nodes - 1 for node in self.graph])
108
+
109
+
110
+ class DiGraph(BaseGraph):
111
+ def add_edge(self, vertex1, vertex2):
112
+ if vertex1 in self.graph:
113
+ self.graph[vertex1].append(vertex2)
114
+ else:
115
+ self.graph[vertex1] = [vertex2]
116
+
117
+ def remove_edge(self, vertex1, vertex2):
118
+ if vertex1 in self.graph and vertex2 in self.graph[vertex1]:
119
+ self.graph[vertex1].remove(vertex2)
120
+ if not self.graph[vertex1]:
121
+ del self.graph[vertex1]
122
+
123
+ def __str__(self):
124
+ edges = []
125
+ for vertex, neighbours in self.graph.items():
126
+ for neighbour in neighbours:
127
+ edges.append("{} -> {}".format(vertex, neighbour))
128
+ return "\n".join(sorted(edges))
129
+
130
+
131
+ class UnGraph(BaseGraph):
132
+ def add_edge(self, vertex1, vertex2):
133
+ if vertex1 in self.graph:
134
+ self.graph[vertex1].append(vertex2)
135
+ else:
136
+ self.graph[vertex1] = [vertex2]
137
+ if vertex2 in self.graph:
138
+ self.graph[vertex2].append(vertex1)
139
+ else:
140
+ self.graph[vertex2] = [vertex1]
141
+
142
+ def remove_edge(self, vertex1, vertex2):
143
+ if vertex1 in self.graph and vertex2 in self.graph:
144
+ if vertex2 in self.graph[vertex1]:
145
+ self.graph[vertex1].remove(vertex2)
146
+ if vertex1 in self.graph[vertex2]:
147
+ self.graph[vertex2].remove(vertex1)
148
+ if not self.graph[vertex1]:
149
+ del self.graph[vertex1]
150
+ if not self.graph[vertex2]:
151
+ del self.graph[vertex2]
152
+
153
+ def __str__(self):
154
+ edges = []
155
+ for vertex, neighbours in self.graph.items():
156
+ for neighbour in neighbours:
157
+ edges.append("{} -- {}".format(vertex, neighbour))
158
+ return "\n".join(sorted(edges))
159
+
160
+
161
+ class BaseWeGraph(BaseGraph):
162
+ def add_edge(self, vertex1, vertex2, weight=0):
163
+ raise NotImplementedError
164
+
165
+ def remove_edge(self, vertex1, vertex2):
166
+ raise NotImplementedError
167
+
168
+ def add_vertex(self, vertex):
169
+ if vertex not in self.graph:
170
+ self.graph[vertex] = {}
171
+
172
+ def remove_vertex(self, vertex):
173
+ if vertex in self.graph:
174
+ neighbors = self.graph[vertex]
175
+ del self.graph[vertex]
176
+ for neighbor in neighbors:
177
+ self.remove_edge(neighbor, vertex)
178
+
179
+ def get_edge_weight(self, vertex1, vertex2):
180
+ if self.has_edge(vertex1, vertex2):
181
+ return self.graph[vertex1][vertex2]
182
+
183
+ def get_in_degree_weight_sum(self, vertex):
184
+ return sum([self.get_edge_weight(neighbor, vertex)
185
+ for neighbor in self.graph if vertex in self.graph[neighbor]])
186
+
187
+ def get_out_degree_weight_sum(self, vertex):
188
+ return sum([self.get_edge_weight(vertex, neighbor) for neighbor in self.graph.get(vertex, {})])
189
+
190
+ def dijkstra(self, start):
191
+ distances = {vertex: float("inf") for vertex in self.graph}
192
+ distances[start] = 0
193
+ queue = [(0, start)]
194
+ visited = set()
195
+ while queue:
196
+ current_distance, current_vertex = min(queue, key=lambda x: x[0])
197
+ if current_vertex in visited:
198
+ queue.remove((current_distance, current_vertex))
199
+ continue
200
+ visited.add(current_vertex)
201
+ queue.remove((current_distance, current_vertex))
202
+ if current_distance > distances[current_vertex] or current_vertex not in self.graph:
203
+ continue
204
+ for neighbor, weight in self.graph[current_vertex].items():
205
+ distance = current_distance + weight
206
+ if neighbor in distances:
207
+ if distance < distances[neighbor]:
208
+ distances[neighbor] = distance
209
+ queue.append((distance, neighbor))
210
+ else:
211
+ distances[neighbor] = distance
212
+ queue.append((distance, neighbor))
213
+ return distances
214
+
215
+ def reconstruct_path(self, start, end, distances):
216
+ current = end
217
+ path = [current]
218
+ while current != start:
219
+ for neighbor, weight in self.get_edges(current).items():
220
+ if distances[current] == distances[neighbor] + weight:
221
+ current = neighbor
222
+ path.append(current)
223
+ break
224
+ return path[::-1]
225
+
226
+
227
+ class WeDiGraph(BaseWeGraph):
228
+ def add_edge(self, vertex1, vertex2, weight=0):
229
+ if vertex1 not in self.graph:
230
+ self.graph[vertex1] = {}
231
+ self.graph[vertex1][vertex2] = weight
232
+
233
+ def remove_edge(self, vertex1, vertex2):
234
+ if vertex1 in self.graph and vertex2 in self.graph[vertex1]:
235
+ del self.graph[vertex1][vertex2]
236
+ if not self.graph[vertex1]:
237
+ del self.graph[vertex1]
238
+
239
+ def __str__(self):
240
+ edges = []
241
+ for vertex, neighbours in self.graph.items():
242
+ for neighbour, weight in neighbours.items():
243
+ edges.append("{} -[{}]> {}".format(vertex, weight, neighbour))
244
+ return "\n".join(sorted(edges))
245
+
246
+
247
+ class WeUnGraph(BaseWeGraph):
248
+ def add_edge(self, vertex1, vertex2, weight=0):
249
+ if vertex1 not in self.graph:
250
+ self.graph[vertex1] = {}
251
+ if vertex2 not in self.graph:
252
+ self.graph[vertex2] = {}
253
+ self.graph[vertex1][vertex2] = weight
254
+ self.graph[vertex2][vertex1] = weight
255
+
256
+ def remove_edge(self, vertex1, vertex2):
257
+ if vertex1 in self.graph and vertex2 in self.graph[vertex1]:
258
+ del self.graph[vertex1][vertex2]
259
+ del self.graph[vertex2][vertex1]
260
+ if not self.graph[vertex1]:
261
+ del self.graph[vertex1]
262
+ if vertex1 != vertex2 and not self.graph[vertex2]:
263
+ del self.graph[vertex2]
264
+
265
+ def __str__(self):
266
+ edges = []
267
+ for vertex, neighbours in self.graph.items():
268
+ for neighbour, weight in neighbours.items():
269
+ edges.append("{} -[{}]- {}".format(vertex, weight, neighbour))
270
+ return "\n".join(sorted(edges))
pypynum/PyPyNum.png ADDED
Binary file