topologicpy 0.7.98__py3-none-any.whl → 0.7.99__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.
topologicpy/Graph.py CHANGED
@@ -1421,6 +1421,75 @@ class Graph:
1421
1421
  graph_edges[i] = Topology.SetDictionary(graph_edges[i], d)
1422
1422
  return edge_betweenness_scores
1423
1423
 
1424
+ @staticmethod
1425
+ def BetweennessPartition(graph, n=2, m=10, key="partition", tolerance=0.0001, silent=False):
1426
+ """
1427
+ Computes a partition of the input graph based on the edge betweenness method. See https://en.wikipedia.org/wiki/Graph_partition.
1428
+
1429
+ Parameters
1430
+ ----------
1431
+ graph : topologicp.Graph
1432
+ The input topologic graph.
1433
+ n : int , optional
1434
+ The desired number of partitions when selecting the "Betweenness" method. This parameter is ignored for other methods. The default is 2.
1435
+ m : int , optional
1436
+ The desired maximum number of tries to partition the graph when selecting the "Betweenness" method. This parameter is ignored for other methods. The default is 10.
1437
+ key : str , optional
1438
+ The vertex and edge dictionary key under which to store the parition number. The default is "partition".
1439
+ Valid partition numbers start from 1. Cut edges receive a partition number of 0.
1440
+ tolerance : float , optional
1441
+ The desired tolerance. The default is 0.0001.
1442
+ silent : bool , optional
1443
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
1444
+
1445
+ Returns
1446
+ -------
1447
+ topologicpy.Graph
1448
+ The partitioned topologic graph.
1449
+
1450
+ """
1451
+ from topologicpy.Topology import Topology
1452
+ from topologicpy.Helper import Helper
1453
+ from topologicpy.Dictionary import Dictionary
1454
+
1455
+ edge_scores = Graph.BetweennessCentrality(graph, method="edge")
1456
+ graph_edges = Graph.Edges(graph)
1457
+
1458
+ graph_edges = Helper.Sort(graph_edges, edge_scores)
1459
+ graph_edges.reverse()
1460
+ cut_edges = []
1461
+ components = 1
1462
+ tries = 0
1463
+ while components < n and tries < m:
1464
+ components = len(Graph.ConnectedComponents(graph, key=key, tolerance=tolerance, silent=silent))
1465
+ if components == n:
1466
+ if not silent:
1467
+ print("Graph.BetweennessPartition - Warning: The input graph is already partitioned into partitions that are equal in number to the desired number of partitions.")
1468
+ return graph
1469
+ elif components > n:
1470
+ if not silent:
1471
+ print("Graph.BetweennessPartition - Warning: The input graph is already partitioned into partitions that are greater in number than the desired number of partitions.")
1472
+ return graph
1473
+ elif len(graph_edges) < 1:
1474
+ components = n
1475
+ else:
1476
+ edge = graph_edges[0]
1477
+ d = Topology.Dictionary(edge)
1478
+ d = Dictionary.SetValueAtKey(d, key, 0) # 0 indicates a cut edge
1479
+ edge = Topology.SetDictionary(edge, d)
1480
+ cut_edges.append(edge)
1481
+ graph = Graph.RemoveEdge(graph, edge, tolerance=tolerance)
1482
+ graph_edges = graph_edges[1:]
1483
+ components = len(Graph.ConnectedComponents(graph, key=key, tolerance=tolerance, silent=silent))
1484
+ tries += 1
1485
+ if tries == m:
1486
+ if not silent:
1487
+ print("Graph.Partition - Warning: Reached the maximum number of tries.")
1488
+ return_vertices = Graph.Vertices(graph)
1489
+ return_edges = Graph.Edges(graph) + cut_edges
1490
+ return_graph = Graph.ByVerticesEdges(return_vertices, return_edges)
1491
+ return return_graph
1492
+
1424
1493
  @staticmethod
1425
1494
  def Bridges(graph, key: str = "bridge", silent: bool = False):
1426
1495
  """
@@ -4394,7 +4463,7 @@ class Graph:
4394
4463
  return Graph.ByVerticesEdges(vertices, edges)
4395
4464
 
4396
4465
  @staticmethod
4397
- def ConnectedComponents(graph, tolerance: float = 0.0001, silent: bool = False):
4466
+ def ConnectedComponents(graph, key: str = "component", tolerance: float = 0.0001, silent: bool = False):
4398
4467
  """
4399
4468
  Returns the connected components (islands) of the input graph.
4400
4469
 
@@ -4402,6 +4471,8 @@ class Graph:
4402
4471
  ----------
4403
4472
  graph : topologic_core.Graph
4404
4473
  The input graph.
4474
+ key : str , optional
4475
+ The vertex and edge dictionary key under which to store the component number. The default is "component".
4405
4476
  tolerance : float , optional
4406
4477
  The desired tolerance. The default is 0.0001.
4407
4478
  silent : bool , optional
@@ -4447,23 +4518,36 @@ class Graph:
4447
4518
  labelKey = "__label__"
4448
4519
  lengths = [] #List of lengths to sort the list of components by number of their vertices
4449
4520
  vertices = Graph.Vertices(graph)
4521
+ vertex_map = {}
4522
+ for i, v in enumerate(vertices):
4523
+ d = Topology.Dictionary(v)
4524
+ d = Dictionary.SetValueAtKey(d, labelKey, i)
4525
+ v = Topology.SetDictionary(v, d)
4526
+ vertex_map[i] = v
4450
4527
  g_dict = Graph.AdjacencyDictionary(graph, vertexLabelKey=labelKey)
4451
4528
  components = find_connected_components(g_dict)
4452
4529
  return_components = []
4453
- for component in components:
4530
+ for i, component in enumerate(components):
4454
4531
  i_verts = []
4455
- for v in component:
4456
- vert = Topology.Filter(vertices, searchType="equal to", key=labelKey, value=v)['filtered'][0]
4532
+ for v in component:
4533
+ vert = vertex_map[v]
4457
4534
  d = Topology.Dictionary(vert)
4458
4535
  d = Dictionary.RemoveKey(d, labelKey)
4536
+ d = Dictionary.SetValueAtKey(d, key, i+1)
4459
4537
  vert = Topology.SetDictionary(vert, d)
4460
4538
  i_verts.append(vert)
4461
- i_edges = Graph.Edges(graph, i_verts)
4462
- lengths.append(len(i_verts))
4463
- g_component = Graph.ByVerticesEdges(i_verts, i_edges)
4464
- return_components.append(g_component)
4465
- return_components = Helper.Sort(return_components, lengths)
4466
- return_components.reverse()
4539
+ if len(i_verts) > 0:
4540
+ i_edges = Graph.Edges(graph, i_verts)
4541
+ for i_edge in i_edges:
4542
+ d = Topology.Dictionary(i_edge)
4543
+ d = Dictionary.SetValueAtKey(d, key, i+1)
4544
+ i_edge = Topology.SetDictionary(i_edge, d)
4545
+ lengths.append(len(i_verts))
4546
+ g_component = Graph.ByVerticesEdges(i_verts, i_edges)
4547
+ return_components.append(g_component)
4548
+ if len(return_components) > 0:
4549
+ return_components = Helper.Sort(return_components, lengths)
4550
+ return_components.reverse()
4467
4551
  return return_components
4468
4552
 
4469
4553
  @staticmethod
@@ -4658,17 +4742,16 @@ class Graph:
4658
4742
  return centralities
4659
4743
 
4660
4744
  @staticmethod
4661
- def Community(graph, key: str = "community", mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
4745
+ def Community(graph, key: str = "partition", mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
4662
4746
  """
4663
4747
  Computes the best community partition of the input graph based on the Louvain method. See https://en.wikipedia.org/wiki/Louvain_method.
4664
- This method depends on NetworkX and the python-louvain libraries
4665
4748
 
4666
4749
  Parameters
4667
4750
  ----------
4668
4751
  graph : topologicp.Graph
4669
4752
  The input topologic graph.
4670
4753
  key : str , optional
4671
- The dictionary key under which to store the closeness centrality score. The default is "community".
4754
+ The dictionary key under which to store the partition number. The default is "partition".
4672
4755
  mantissa : int , optional
4673
4756
  The desired length of the mantissa. The default is 6.
4674
4757
  tolerance : float , optional
@@ -4678,9 +4761,38 @@ class Graph:
4678
4761
  Returns
4679
4762
  -------
4680
4763
  topologicpy.Graph
4681
- The created topologic graph.
4764
+ The partitioned topologic graph.
4765
+
4766
+ """
4767
+ if not silent:
4768
+ print("Graph.Community - Warning: This method is deprectated. Please use Graph.CommunityPartition instead.")
4769
+ return Graph.CommunityPartition(graph=graph, key=key, mantissa=mantissa, tolerance=tolerance, silent=silent)
4770
+
4771
+ @staticmethod
4772
+ def CommunityPartition(graph, key: str = "partition", mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
4773
+ """
4774
+ Computes the best community partition of the input graph based on the Louvain method. See https://en.wikipedia.org/wiki/Louvain_method.
4775
+
4776
+ Parameters
4777
+ ----------
4778
+ graph : topologicp.Graph
4779
+ The input topologic graph.
4780
+ key : str , optional
4781
+ The dictionary key under which to store the partition number. The default is "partition".
4782
+ mantissa : int , optional
4783
+ The desired length of the mantissa. The default is 6.
4784
+ tolerance : float , optional
4785
+ The desired tolerance. The default is 0.0001.
4786
+ silent : bool , optional
4787
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
4788
+ Returns
4789
+ -------
4790
+ topologicpy.Graph
4791
+ The partitioned topologic graph.
4682
4792
 
4683
4793
  """
4794
+ from topologicpy.Vertex import Vertex
4795
+ from topologicpy.Edge import Edge
4684
4796
  from topologicpy.Topology import Topology
4685
4797
  from topologicpy.Dictionary import Dictionary
4686
4798
  import os
@@ -4713,13 +4825,39 @@ class Graph:
4713
4825
  communities = ig_graph.community_multilevel()
4714
4826
 
4715
4827
  # Get the list of communities sorted same as vertices
4716
- community_list = communities.membership
4828
+ partition_list = communities.membership
4717
4829
  vertices = Graph.Vertices(graph)
4718
4830
  for i, v in enumerate(vertices):
4719
4831
  d = Topology.Dictionary(v)
4720
- d = Dictionary.SetValueAtKey(d, key, community_list[i])
4832
+ d = Dictionary.SetValueAtKey(d, key, partition_list[i]+1)
4721
4833
  v = Topology.SetDictionary(v, d)
4722
- return community_list
4834
+ edges = Graph.Edges(graph)
4835
+ if not edges == None:
4836
+ for edge in edges:
4837
+ sv = Edge.StartVertex(edge)
4838
+ ev = Edge.EndVertex(edge)
4839
+ status_1 = False
4840
+ status_2 = False
4841
+ partition_1 = 0
4842
+ partition_2 = 0
4843
+ for i, v in enumerate(vertices):
4844
+ if Vertex.IsCoincident(sv, v, tolerance=tolerance):
4845
+ status_1 = True
4846
+ partition_1 = Dictionary.ValueAtKey(Topology.Dictionary(v), key)
4847
+ break
4848
+ for i, v in enumerate(vertices):
4849
+ if Vertex.IsCoincident(ev, v, tolerance=tolerance):
4850
+ status_2 = True
4851
+ partition_2 = Dictionary.ValueAtKey(Topology.Dictionary(v), key)
4852
+ break
4853
+ partition = 0
4854
+ if status_1 and status_2:
4855
+ if partition_1 == partition_2:
4856
+ partition = partition_1
4857
+ d = Topology.Dictionary(edge)
4858
+ d = Dictionary.SetValueAtKey(d, key, partition)
4859
+ edge = Topology.SetDictionary(edge, d)
4860
+ return graph
4723
4861
 
4724
4862
  @staticmethod
4725
4863
  def Connect(graph, verticesA, verticesB, tolerance=0.0001):
@@ -6412,6 +6550,80 @@ class Graph:
6412
6550
  eigenvalues, eigenvectors = Matrix.EigenvaluesAndVectors(laplacian, mantissa=mantissa)
6413
6551
  return eigenvectors[1]
6414
6552
 
6553
+ @staticmethod
6554
+ def FiedlerVectorPartition(graph, key="partition", mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
6555
+ """
6556
+ Partitions the input graph based on FiedlerVector method. See https://en.wikipedia.org/wiki/Graph_partition.
6557
+
6558
+ Parameters
6559
+ ----------
6560
+ graph : topologicp.Graph
6561
+ The input topologic graph.
6562
+ key : str , optional
6563
+ The vertex and edge dictionary key under which to store the parition number. The default is "partition".
6564
+ Valid partition numbers start from 1. Cut edges receive a partition number of 0.
6565
+ mantissa : int , optional
6566
+ The desired length of the mantissa. The default is 6.
6567
+ tolerance : float , optional
6568
+ The desired tolerance. The default is 0.0001.
6569
+ silent : bool , optional
6570
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
6571
+
6572
+ Returns
6573
+ -------
6574
+ topologicpy.Graph
6575
+ The partitioned topologic graph.
6576
+
6577
+ """
6578
+ from topologicpy.Vertex import Vertex
6579
+ from topologicpy.Edge import Edge
6580
+ from topologicpy.Topology import Topology
6581
+ from topologicpy.Dictionary import Dictionary
6582
+
6583
+ if not Topology.IsInstance(graph, "graph"):
6584
+ if not silent:
6585
+ print("Graph.FiedlerVectorPartition - Error: The input graph parameter is not a valid topologic graph. Returning None.")
6586
+ return None
6587
+
6588
+ fiedler_vector = Graph.FiedlerVector(graph, mantissa=mantissa, silent=silent)
6589
+
6590
+ vertices = Graph.Vertices(graph)
6591
+ for i, f_v in enumerate(fiedler_vector):
6592
+ if f_v >=0:
6593
+ partition = 1
6594
+ else:
6595
+ partition = 2
6596
+ d = Topology.Dictionary(vertices[i])
6597
+ d = Dictionary.SetValueAtKey(d, key, partition)
6598
+ vertices[i] = Topology.SetDictionary(vertices[i], d)
6599
+ edges = Graph.Edges(graph)
6600
+ if not edges == None:
6601
+ for edge in edges:
6602
+ sv = Edge.StartVertex(edge)
6603
+ ev = Edge.EndVertex(edge)
6604
+ status_1 = False
6605
+ status_2 = False
6606
+ partition_1 = 0
6607
+ partition_2 = 0
6608
+ for i, v in enumerate(vertices):
6609
+ if Vertex.IsCoincident(sv, v, tolerance=tolerance):
6610
+ status_1 = True
6611
+ partition_1 = Dictionary.ValueAtKey(Topology.Dictionary(v), key)
6612
+ break
6613
+ for i, v in enumerate(vertices):
6614
+ if Vertex.IsCoincident(ev, v, tolerance=tolerance):
6615
+ status_2 = True
6616
+ partition_2 = Dictionary.ValueAtKey(Topology.Dictionary(v), key)
6617
+ break
6618
+ partition = 0
6619
+ if status_1 and status_2:
6620
+ if partition_1 == partition_2:
6621
+ partition = partition_1
6622
+ d = Topology.Dictionary(edge)
6623
+ d = Dictionary.SetValueAtKey(d, key, partition)
6624
+ edge = Topology.SetDictionary(edge, d)
6625
+ return graph
6626
+
6415
6627
  @staticmethod
6416
6628
  def IsIsomorphic(graphA, graphB, maxIterations=10, silent=False):
6417
6629
  """
@@ -9163,7 +9375,63 @@ class Graph:
9163
9375
  d = Dictionary.SetValueAtKey(d, key, scores[i])
9164
9376
  v = Topology.SetDictionary(v, d)
9165
9377
  return scores
9166
-
9378
+
9379
+ @staticmethod
9380
+ def Partition(graph, method: str = "Betweenness", n: int = 2, m: int = 10, key: str ="partition",
9381
+ mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
9382
+ """
9383
+ Partitions the input graph based on the desired partition method. See https://en.wikipedia.org/wiki/Graph_partition.
9384
+
9385
+ Parameters
9386
+ ----------
9387
+ graph : topologicp.Graph
9388
+ The input topologic graph.
9389
+ method : str , optional
9390
+ The desired partitioning method. The options are:
9391
+ - "Betweenness"
9392
+ - "Community" or "Louvain"
9393
+ - "Fiedler" or "Eigen"
9394
+ It is case insensitive. The default is "Betweenness"
9395
+ n : int , optional
9396
+ The desired number of partitions when selecting the "Betweenness" method. This parameter is ignored for other methods. The default is 2.
9397
+ m : int , optional
9398
+ The desired maximum number of tries to partition the graph when selecting the "Betweenness" method. This parameter is ignored for other methods. The default is 10.
9399
+ key : str , optional
9400
+ The vertex and edge dictionary key under which to store the parition number. The default is "partition".
9401
+ Valid partition numbers start from 1. Cut edges receive a partition number of 0.
9402
+ mantissa : int , optional
9403
+ The desired length of the mantissa. The default is 6.
9404
+ tolerance : float , optional
9405
+ The desired tolerance. The default is 0.0001.
9406
+ silent : bool , optional
9407
+ If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
9408
+
9409
+ Returns
9410
+ -------
9411
+ topologicpy.Graph
9412
+ The partitioned topologic graph.
9413
+
9414
+ """
9415
+
9416
+ m_d = Graph.MeshData(graph)
9417
+ new_graph = Graph.ByMeshData(vertices = m_d['vertices'],
9418
+ edges = m_d['edges'],
9419
+ vertexDictionaries = m_d['vertexDictionaries'],
9420
+ edgeDictionaries = m_d['edgeDictionaries'])
9421
+ if "between" in method.lower():
9422
+ _ = Graph.BetweennessPartition(new_graph, n=n, m=m, key=key, tolerance=tolerance, silent=silent)
9423
+ return new_graph
9424
+ elif "community" in method.lower() or "louvain" in method.lower():
9425
+ _ = Graph.CommunityPartition(new_graph, key=key, mantissa=mantissa, tolerance=tolerance, silent=silent)
9426
+ return new_graph
9427
+ elif "fied" in method.lower() or "eig" in method.lower():
9428
+ _ = Graph.FiedlerVectorPartition(new_graph, key=key, mantissa=mantissa, tolerance=tolerance, silent=silent)
9429
+ return new_graph
9430
+ else:
9431
+ if not silent:
9432
+ print("Graph.Partition - Error: The chosen method is not supported. Returning None.")
9433
+ return None
9434
+
9167
9435
  @staticmethod
9168
9436
  def Path(graph, vertexA, vertexB, tolerance=0.0001):
9169
9437
  """
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.7.98'
1
+ __version__ = '0.7.99'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: topologicpy
3
- Version: 0.7.98
3
+ Version: 0.7.99
4
4
  Summary: An AI-Powered Spatial Modelling and Analysis Software Library for Architecture, Engineering, and Construction.
5
5
  Author-email: Wassim Jabi <wassim.jabi@gmail.com>
6
6
  License: AGPL v3 License
@@ -11,7 +11,7 @@ topologicpy/Dictionary.py,sha256=t0O7Du-iPq46FyKqZfcjHfsUK1E8GS_e67R2V5cpkbw,331
11
11
  topologicpy/Edge.py,sha256=gaLqyjFOqFHpw69Ftr4rc-kvakYpauQwhOK4ZO-V35g,67287
12
12
  topologicpy/EnergyModel.py,sha256=UoQ9Jm-hYsN383CbcLKw-y6BKitRHj0uyh84yQ-8ACg,53856
13
13
  topologicpy/Face.py,sha256=wczXpMcfub8Eb10lA4rrXksvi5YYCbRjBdp3lOTUwK0,172618
14
- topologicpy/Graph.py,sha256=IL7htimFIpRIFSGlNgXqdIkq6KgHFUe9T144yGIk2Qc,479404
14
+ topologicpy/Graph.py,sha256=-vB47i0s7fbh6pTQGuiJujm1tM-ubTuUeyjJeQ8iAEo,492172
15
15
  topologicpy/Grid.py,sha256=2s9cSlWldivn1i9EUz4OOokJyANveqmRe_vR93CAndI,18245
16
16
  topologicpy/Helper.py,sha256=F3h4_qcOD_PHAoVe0tEbEE7_jYyVcaHjtwVs4QHOZuI,23978
17
17
  topologicpy/Honeybee.py,sha256=Y_El6M8x3ixvvIe_VcRiwj_4C89ZZg5_WlT7adbCkpw,21849
@@ -28,9 +28,9 @@ topologicpy/Vector.py,sha256=Cl7besf20cAGmyNPh-9gbFAHnRU5ZWSMChJ3VyFIDs4,35416
28
28
  topologicpy/Vertex.py,sha256=tv6C-rbuNgXHDGgVLT5fbalynLdXqlUuiCDKtkeQ0vk,77814
29
29
  topologicpy/Wire.py,sha256=bX8wO96gFa7HZPY0CFlmYQBOUP_1e0jCb02BPxaY-ao,222981
30
30
  topologicpy/__init__.py,sha256=vlPCanUbxe5NifC4pHcnhSzkmmYcs_UrZrTlVMsxcFs,928
31
- topologicpy/version.py,sha256=edt03iPp-fWm-GyKIDUNJimGnmtCRb6Pjv3dsEvhru4,23
32
- topologicpy-0.7.98.dist-info/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
33
- topologicpy-0.7.98.dist-info/METADATA,sha256=U6xzVbESx3zzAX4CakRjfE90LNZLqEdPZMN3SKbRBdQ,10513
34
- topologicpy-0.7.98.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
35
- topologicpy-0.7.98.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
36
- topologicpy-0.7.98.dist-info/RECORD,,
31
+ topologicpy/version.py,sha256=gGhfskMFYv1QhkPM9mcpO5BWm5CMyWE6f2zQSx3Zec4,23
32
+ topologicpy-0.7.99.dist-info/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
33
+ topologicpy-0.7.99.dist-info/METADATA,sha256=Mzw982237903EfiTROFP2zAKuxkY8RIBQ1GjJdJQ-9s,10513
34
+ topologicpy-0.7.99.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
35
+ topologicpy-0.7.99.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
36
+ topologicpy-0.7.99.dist-info/RECORD,,