PyPyNum 1.7.0__py3-none-any.whl → 1.8.1__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.1
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.1 | 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,11 @@ Python interpreter and run it!)
740
741
  ```
741
742
  !=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
742
743
 
743
- 新增代码行数:
744
- 约八百行
744
+ eig函数修复了计算错误并改名为eigen
745
745
 
746
- New code lines:
747
- approximately 800 lines
748
-
749
- !=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
750
-
751
- 部分函数再次优化,性能提高一倍。
752
-
753
- Partial functions were optimized
754
- again, resulting in a doubling
755
- of performance.
756
-
757
- !=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
758
-
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.
746
+ The eig function fixed
747
+ calculation errors and changed
748
+ its name to eigen
791
749
 
792
750
  !=!=!=!=!=!=!=!=!=!=!=!=!=!=!=!=
793
751
 
@@ -796,34 +754,13 @@ sequences.
796
754
  <<<The ellipsis in the following structure represents the original part>>>
797
755
 
798
756
  PyPyNum
799
- Tree [Various trees]
800
- 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]
757
+ Matrix [Matrix calculation]
814
758
  FUNCTIONS
815
- farey(n: int) -> list
816
759
  ...
817
- tools [Other useful tools]
818
- FUNCTIONS
760
+ rotate90(matrix: pypynum.Matrix.Matrix, times: int) -> pypynum.Matrix.Matrix
761
+ hessenberg(matrix: pypynum.Matrix.Matrix) -> tuple
762
+ eigen(matrix: pypynum.Matrix.Matrix) -> tuple
819
763
  ...
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
764
  ```
828
765
 
829
766
  ### 运行用时测试
@@ -893,6 +830,14 @@ PyPyNum
893
830
  Triangle
894
831
  FUNCTIONS
895
832
  distance(g1, g2, error: int | float = 0) -> float
833
+ ★ Graph [Graph theory]
834
+ CLASSES
835
+ BaseGraph
836
+ BaseWeGraph
837
+ WeDiGraph
838
+ WeUnGraph
839
+ DiGraph
840
+ UnGraph
896
841
  ★ Group [Group theory]
897
842
  CLASSES
898
843
  Group
@@ -930,14 +875,16 @@ PyPyNum
930
875
  CLASSES
931
876
  Matrix
932
877
  FUNCTIONS
933
- eig(matrix)
934
- identity(n)
935
- lu(matrix)
878
+ eigen(matrix: pypynum.Matrix.Matrix) -> tuple
879
+ hessenberg(matrix: pypynum.Matrix.Matrix) -> tuple
880
+ identity(n: int) -> pypynum.Matrix.Matrix
881
+ lu(matrix: pypynum.Matrix.Matrix) -> tuple
936
882
  mat(data)
937
- qr(matrix)
883
+ qr(matrix: pypynum.Matrix.Matrix) -> tuple
884
+ rotate90(matrix: pypynum.Matrix.Matrix, times: int) -> pypynum.Matrix.Matrix
938
885
  same(rows, cols, value=0)
939
- svd(matrix)
940
- tril_indices(n, k=0, m=None)
886
+ svd(matrix: pypynum.Matrix.Matrix) -> tuple
887
+ tril_indices(n: int, k: int = 0, m: int = None) -> tuple
941
888
  zeros(_dimensions)
942
889
  zeros_like(_nested_list)
943
890
  ★ NeuralN [A simple neural network model]
@@ -1121,6 +1068,9 @@ PyPyNum
1121
1068
  average(data, weights, expected=False)
1122
1069
  exgcd(a: int, b: int) -> tuple
1123
1070
  crt(n: arr, a: arr) -> int
1071
+ isqrt(x: int) -> int
1072
+ is_possibly_square(n: int) -> bool
1073
+ is_square(n: int) -> bool
1124
1074
  ★ numbers [Conversion of various numbers]
1125
1075
  FUNCTIONS
1126
1076
  float2fraction(number: float, mixed: bool = False, error: float = 1e-15) -> tuple
@@ -1138,6 +1088,11 @@ PyPyNum
1138
1088
  unary(function, right: real = 5, left: real = -5, top: real = 5, bottom: real = -5, complexity: real = 5...
1139
1089
  binary(function, right: real = 5, left: real = -5, top: real = 5, bottom: real = -5, complexity: real = 5...
1140
1090
  c_unary(function, start: real, end: real, interval: real = 5, projection: str = "ri", right: real = 5...
1091
+ ★ polynomial [Polynomial object]
1092
+ CLASSES
1093
+ Polynomial
1094
+ FUNCTIONS
1095
+ poly(terms=None)
1141
1096
  ★ probability [Probability function]
1142
1097
  FUNCTIONS
1143
1098
  binomial(sample_size: int, successes: int, success_probability: Union[int, float]) -> float
@@ -1176,6 +1131,7 @@ PyPyNum
1176
1131
  primality(n: int, iter_num: int = 10) -> bool
1177
1132
  generate_primes(limit: int) -> list
1178
1133
  prime_factors(integer: int, dictionary: bool = False, pollard_rho: bool = True) -> Union[list, dict]
1134
+ magic_square(n)
1179
1135
  ★ utils [Other useful tools]
1180
1136
  CLASSES
1181
1137
  InfIterator
@@ -1344,7 +1300,7 @@ print(v1.angles())
1344
1300
  6.62607015e-34
1345
1301
  1.618033988749895
1346
1302
  3.141592653589793
1347
- 1000000000000.0
1303
+ 1000000000000
1348
1304
 
1349
1305
  >>> p = [1, -2, -3, 4]
1350
1306
  >>> m = [
@@ -1358,7 +1314,9 @@ print(v1.angles())
1358
1314
  >>> print(equations.polynomial_equation(p))
1359
1315
  >>> print(equations.linear_equation(*m))
1360
1316
 
1361
- [(-1.5615528128088307-6.5209667308287455e-24j) (2.5615528128088294+4.456233626665941e-24j) (1.0000000000000007+3.241554513744382e-25j)]
1317
+ [[(-1.5615528128088307-6.5209667308287455e-24j) 0 0]
1318
+ [ 0 (2.5615528128088294+4.456233626665941e-24j) 0]
1319
+ [ 0 0 (1.0000000000000007+3.241554513744382e-25j)]]
1362
1320
  [ 1.6666666666666667 -0.6666666666666666 -0.4444444444444444]
1363
1321
 
1364
1322
  >>> print(maths.cot(constants.pi / 3))
@@ -1453,10 +1411,10 @@ print(v1.angles())
1453
1411
  >>> print(random.randint(0, 9, [2, 3, 4]))
1454
1412
  >>> print(random.uniform(0, 9, [2, 3, 4]))
1455
1413
 
1456
- [[[0.4334341920363395, 0.055711784711422116, -1.0235500373980284, 0.30031229336738374], [-0.2650367914670356, 0.5513398538865067, -0.9735921328831166, 0.41345578602104827], [-0.11598957920080871, -0.9044539791933183, 1.6448227575237069, -0.26304156924843813]], [[0.27363898507271256, -0.5897181011789576, 1.5120937498473583, 2.1302709742844694], [1.9743293887616236, 0.4117207260898469, 0.5809554193110543, -1.8456249006764007], [1.274481044612177, -0.30645083457981553, -1.3285606156236818, 0.33473439037886943]]]
1457
- [[[0.5269441534226782, 0.36498666932667356, 0.7363066388832684, 0.5878544826035406], [0.5684721009896431, 0.9009577979323332, 0.036288112799501615, 0.18351641818419884], [0.24258369409385339, 0.09354340906140202, 0.4856203412285762, 0.783031677244552]], [[0.8777465681935882, 0.6406910705155251, 0.10275292827025073, 0.01295823682977526], [0.3898500974345528, 0.6216248983423127, 0.3179425906177036, 0.012870877167621808], [0.2660481991211192, 0.09872041627158801, 0.3681944568198672, 0.494087114885137]]]
1458
- [[[5, 9, 5, 6], [6, 7, 6, 1], [1, 3, 2, 4]], [[5, 8, 8, 3], [3, 2, 3, 9], [3, 0, 7, 1]]]
1459
- [[[8.610851610963957, 1.3747433091161905, 1.3831050577679438, 4.715182178697273], [0.8765517657148284, 4.809554825684029, 2.7557819856736137, 5.938765584746821], [6.088739464744903, 4.627722536295625, 0.6116370455995369, 5.875683438664389]], [[7.7228845997304845, 5.428461366109726, 8.02712172516869, 5.9319006090345425], [5.726626482636939, 7.978329508380601, 1.114307478513796, 6.236721706167868], [1.4123245528031072, 5.327811122183013, 7.324213082306745, 1.5016363011868927]]]
1414
+ [[[1.524086835643172, -0.20868457467847845, 0.5240261503975477, -0.6439838767682032], [-1.091904210196648, -0.20567633973733265, 1.374424576574523, 0.6563097903476932], [0.2171635934136032, 1.0821030876490199, -0.8410496800310051, -0.8321549344577578]], [[0.5306996954571072, -0.4441704154154241, 1.0481960055260355, 0.39805451821848287], [-0.4006858882593715, -0.06238294764009237, -1.1536673264483728, -0.8063185246185602], [0.3029117113345387, -0.32570360518676644, 0.6608320231980702, 1.7415150171137153]]]
1415
+ [[[0.3736243541521843, 0.8599079983285199, 0.4260061864869946, 0.8441437619796597], [0.8955986631978392, 0.7570336992646656, 0.6706841989644684, 0.328634366074538], [0.4371430562585502, 0.9576395263025738, 0.2380278778546957, 0.806813631306664]], [[0.18549375381453237, 0.5749941389233029, 0.7009767023241946, 0.30017399397762223], [0.6661914823434657, 0.7802291606608635, 0.6847755352217044, 0.2661053533652564], [0.07937643994416943, 0.5452043474222034, 0.8026792060861194, 0.07776400257578953]]]
1416
+ [[[9, 0, 9, 0], [2, 6, 3, 4], [5, 8, 4, 7]], [[7, 7, 6, 3], [5, 5, 5, 8], [3, 4, 6, 6]]]
1417
+ [[[5.049093842782947, 1.3880585421884204, 8.533634113864629, 3.550264239771317], [3.3311351975225176, 5.131771033264564, 0.9570872044431911, 5.165536082759862], [1.2035779060925538, 8.292998518472567, 8.014641974770818, 6.251632912237915]], [[6.411677800595937, 5.365937405245105, 8.70943859614565, 4.348757668525482], [7.827612569569748, 1.3718742546020972, 0.5252489627763138, 2.065015517785291], [4.620664668451086, 2.604569735623819, 5.548107842615733, 7.60342292447815]]]
1460
1418
 
1461
1419
  >>> print(regression.linear_regression(list(range(5)), [2, 4, 6, 7, 8]))
1462
1420
  >>> print(regression.parabolic_regression(list(range(5)), [2, 4, 6, 7, 8]))
@@ -1,36 +1,39 @@
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
- pypynum/Matrix.py,sha256=Z2k0bl_VpnaWB3QZjokR9CR7-kDaYIKUjKITWTYGa98,11024
7
+ pypynum/Matrix.py,sha256=vjkz-m90aWDIv2vzXBriyb4vwaZv8tsPYZzPUeUh-Vk,18050
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=eouG6yg8No8iooz_5cLZqS-pR0eMzgtbLBassoqspVE,42891
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
14
- pypynum/__temporary.py,sha256=OAs7it7xjDovgAmKLcj-9Pqp0228SSon3OZx0ih_h4I,5860
16
+ pypynum/__init__.py,sha256=wjl8Vtz9hWI7UP-Hh2JggiLf1FR0VMusXUyG2CGfzAg,1843
15
17
  pypynum/chars.py,sha256=VcK9w0i73FMCzc-9aIibjdHqyMsofJXdoBq0d8L7Vr0,1001
16
18
  pypynum/cipher.py,sha256=J5PZl8Xt71LuX29eSBu4cybNK6Z3rhA9og_YzD0YJfU,1002
17
19
  pypynum/constants.py,sha256=s2P1K8HH2nqoA6_YOVf6TKRl1Ozjf79GmCmLN9YbWxI,843
18
- pypynum/equations.py,sha256=_4xIXr7A56qBXKzJXyb91L4h09H7TDVNrcufy-XxkaI,744
20
+ pypynum/equations.py,sha256=Bn1_VjwMnnvzT0mHYI0eAARRqIHuc3IpOfYvzojTPx0,713
19
21
  pypynum/errors.py,sha256=11-Au4aV8H5ExaDuMtu5iuGvpRaJP8gW7XbGNRmefSI,173
20
22
  pypynum/file.py,sha256=rqrPdcX0NOEPM8s40-ymgPKsTn0HKABW-VEh1OtPnsk,3188
21
- pypynum/maths.py,sha256=GgEbFMGKim6ZwPwrFpwIIfhD5rDHsprIbR7mijoTWvc,24753
23
+ pypynum/maths.py,sha256=Nf_1k1VpKDFWUJQlwB40ljML6xHcW9INlAtstJi3Uc0,26637
22
24
  pypynum/numbers.py,sha256=WOxwwAN3yHakN4eHcVNn35qsfDcgw3UPSblv4woWyDE,6028
23
- pypynum/plotting.py,sha256=YQg9sO_nuLSaAKQuSpebWVvbu-ns2A7JOrHch6r0FQ0,8326
25
+ pypynum/plotting.py,sha256=xoaG6KVoKTu2Zax2FXk3_bHkiu5LguGi_siNi1FLE98,8463
26
+ pypynum/polynomial.py,sha256=psFukA31Ed4U7hZHcCGWCpYMi8tanTsZl-pUdklikfg,5998
24
27
  pypynum/probability.py,sha256=kZLCfZb2q_y1CVbozSZj9xQ8Dw3il5WcAojX0jsNyXw,2130
25
28
  pypynum/random.py,sha256=vfTtyH5yOSKJoSI_-NT_Tg8wC-ZXT0wt34f87oaSpJY,4610
26
29
  pypynum/regression.py,sha256=D9J9lM23HiyY4eE8vHKaHoiwuvD1RYhkVNO0jQ4yml4,2118
27
30
  pypynum/sequence.py,sha256=7NSZm_p_B00KFj5XZrtSm2FXhsowxs0qg_Q_P4pAA8o,7194
28
31
  pypynum/test.py,sha256=Bksa7HZaywKBbLaCw2R5kGRFj6eKzkkJ7BdJBgIB3uM,8428
29
32
  pypynum/this.py,sha256=8Swp75xE5g6436NCVDfYUVwUzUcQFPLcCNFWQWY5eGQ,2129
30
- pypynum/tools.py,sha256=Ki33faUpijydG1AKqh3R6qmU4EFky_35p-ZsdUZPxJM,9823
33
+ pypynum/tools.py,sha256=jqmzsRi2INRlnI4hb4IbpMKHlvEww3ZKO9y6DxrJUbA,12697
31
34
  pypynum/types.py,sha256=CVWPZo_ACr_QGH5gAOhoG3jK35peiqipu3PH8ScEYHE,181
32
35
  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,,
36
+ PyPyNum-1.8.1.dist-info/METADATA,sha256=y9fXQuOCwcMcXjemYXpTwz5vPiQKTACt3l_9w-nhjxA,84338
37
+ PyPyNum-1.8.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
38
+ PyPyNum-1.8.1.dist-info/top_level.txt,sha256=4wW_Xb4bRglmiMsdPAe9f75MkXhNpuN88H17g_Cr5u8,8
39
+ PyPyNum-1.8.1.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))