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.
- {PyPyNum-1.7.0.dist-info → PyPyNum-1.8.0.dist-info}/METADATA +80 -65
- {PyPyNum-1.7.0.dist-info → PyPyNum-1.8.0.dist-info}/RECORD +12 -8
- pypynum/Graph.py +270 -0
- pypynum/PyPyNum.png +0 -0
- pypynum/README.md +835 -0
- pypynum/Tree.py +1 -1
- pypynum/__init__.py +3 -1
- pypynum/maths.py +75 -0
- pypynum/polynomial.py +158 -0
- pypynum/tools.py +97 -1
- {PyPyNum-1.7.0.dist-info → PyPyNum-1.8.0.dist-info}/WHEEL +0 -0
- {PyPyNum-1.7.0.dist-info → PyPyNum-1.8.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyPyNum
|
|
3
|
-
Version: 1.
|
|
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
|
[](https://pepy.tech/project/pypynum)
|
|
692
693
|
[](https://pepy.tech/project/pypynum)
|
|
693
694
|
|
|
694
|
-
## Version -> 1.
|
|
695
|
+
## Version -> 1.8.0 | PyPI -> https://pypi.org/project/PyPyNum/ | Gitee -> https://www.gitee.com/PythonSJL/PyPyNum
|
|
695
696
|
|
|
696
697
|

|
|
697
698
|
|
|
@@ -740,54 +741,65 @@ Python interpreter and run it!)
|
|
|
740
741
|
```
|
|
741
742
|
!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
|
|
742
743
|
|
|
743
|
-
|
|
744
|
-
约八百行
|
|
744
|
+
新增代码行数为603行
|
|
745
745
|
|
|
746
|
-
|
|
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
|
-
|
|
754
|
-
|
|
755
|
-
|
|
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
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
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
|
-
★
|
|
811
|
+
★ Graph [Graph theory]
|
|
800
812
|
CLASSES
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
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
|
-
|
|
816
|
-
...
|
|
823
|
+
poly(terms=None)
|
|
817
824
|
★ tools [Other useful tools]
|
|
818
825
|
FUNCTIONS
|
|
819
826
|
...
|
|
820
|
-
|
|
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=
|
|
14
|
+
pypynum/Tree.py,sha256=MUT9LErZ3ER_cbiga-nOaZC7Hln8jEV8tRca2dRPWmY,2827
|
|
12
15
|
pypynum/Vector.py,sha256=eiFCY6H35pMvvDX7NpLux_bSfLI8rK8JHkaRxv7pOW8,3552
|
|
13
|
-
pypynum/__init__.py,sha256=
|
|
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=
|
|
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=
|
|
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.
|
|
34
|
-
PyPyNum-1.
|
|
35
|
-
PyPyNum-1.
|
|
36
|
-
PyPyNum-1.
|
|
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
|