topologicpy 0.7.94__py3-none-any.whl → 0.7.97__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/Cell.py +30 -29
- topologicpy/CellComplex.py +9 -8
- topologicpy/DGL.py +3 -2
- topologicpy/Edge.py +14 -14
- topologicpy/EnergyModel.py +7 -7
- topologicpy/Graph.py +262 -130
- topologicpy/Honeybee.py +1 -1
- topologicpy/Neo4j.py +3 -2
- topologicpy/Shell.py +9 -9
- topologicpy/Topology.py +6 -5
- topologicpy/Vertex.py +21 -15
- topologicpy/Wire.py +133 -52
- topologicpy/version.py +1 -1
- {topologicpy-0.7.94.dist-info → topologicpy-0.7.97.dist-info}/METADATA +1 -1
- {topologicpy-0.7.94.dist-info → topologicpy-0.7.97.dist-info}/RECORD +18 -18
- {topologicpy-0.7.94.dist-info → topologicpy-0.7.97.dist-info}/LICENSE +0 -0
- {topologicpy-0.7.94.dist-info → topologicpy-0.7.97.dist-info}/WHEEL +0 -0
- {topologicpy-0.7.94.dist-info → topologicpy-0.7.97.dist-info}/top_level.txt +0 -0
topologicpy/Graph.py
CHANGED
@@ -750,102 +750,6 @@ class Graph:
|
|
750
750
|
_ = graph.AllPaths(vertexA, vertexB, True, timeLimit, paths) # Hook to Core
|
751
751
|
return paths
|
752
752
|
|
753
|
-
@staticmethod
|
754
|
-
def AreIsomorphic(graphA, graphB, maxIterations=10, silent=False):
|
755
|
-
"""
|
756
|
-
Tests if the two input graphs are isomorphic according to the Weisfeiler Lehman graph isomorphism test. See https://en.wikipedia.org/wiki/Weisfeiler_Leman_graph_isomorphism_test
|
757
|
-
|
758
|
-
Parameters
|
759
|
-
----------
|
760
|
-
graphA : topologic_core.Graph
|
761
|
-
The first input graph.
|
762
|
-
graphB : topologic_core.Graph
|
763
|
-
The second input graph.
|
764
|
-
maxIterations : int , optional
|
765
|
-
This number limits the number of iterations to prevent the function from running indefinitely, particularly for very large or complex graphs.
|
766
|
-
silent : bool , optional
|
767
|
-
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
768
|
-
|
769
|
-
Returns
|
770
|
-
-------
|
771
|
-
bool
|
772
|
-
True if the two input graphs are isomorphic. False otherwise
|
773
|
-
|
774
|
-
"""
|
775
|
-
|
776
|
-
from topologicpy.Topology import Topology
|
777
|
-
|
778
|
-
def weisfeiler_lehman_test(graph1, graph2, max_iterations=10):
|
779
|
-
"""
|
780
|
-
Test if two graphs are isomorphic using the Weisfeiler-Leman (WL) algorithm with early stopping.
|
781
|
-
|
782
|
-
Parameters:
|
783
|
-
graph1 (dict): Adjacency list representation of the first graph.
|
784
|
-
graph2 (dict): Adjacency list representation of the second graph.
|
785
|
-
max_iterations (int): Maximum WL iterations allowed (default is 10).
|
786
|
-
|
787
|
-
Returns:
|
788
|
-
bool: True if the graphs are WL-isomorphic, False otherwise.
|
789
|
-
"""
|
790
|
-
|
791
|
-
def wl_iteration(labels, graph):
|
792
|
-
"""Perform one WL iteration and return updated labels."""
|
793
|
-
new_labels = {}
|
794
|
-
for node in graph:
|
795
|
-
neighborhood_labels = sorted([labels[neighbor] for neighbor in graph[node]])
|
796
|
-
new_labels[node] = (labels[node], tuple(neighborhood_labels))
|
797
|
-
unique_labels = {}
|
798
|
-
count = 0
|
799
|
-
for node in sorted(new_labels):
|
800
|
-
if new_labels[node] not in unique_labels:
|
801
|
-
unique_labels[new_labels[node]] = count
|
802
|
-
count += 1
|
803
|
-
new_labels[node] = unique_labels[new_labels[node]]
|
804
|
-
return new_labels
|
805
|
-
|
806
|
-
# Initialize labels
|
807
|
-
labels1 = {node: 1 for node in graph1}
|
808
|
-
labels2 = {node: 1 for node in graph2}
|
809
|
-
|
810
|
-
for i in range(max_iterations):
|
811
|
-
# Perform WL iteration for both graphs
|
812
|
-
new_labels1 = wl_iteration(labels1, graph1)
|
813
|
-
new_labels2 = wl_iteration(labels2, graph2)
|
814
|
-
|
815
|
-
# Check if the label distributions match
|
816
|
-
if sorted(new_labels1.values()) != sorted(new_labels2.values()):
|
817
|
-
return False
|
818
|
-
|
819
|
-
# Check for stability (early stopping)
|
820
|
-
if new_labels1 == labels1 and new_labels2 == labels2:
|
821
|
-
break
|
822
|
-
|
823
|
-
# Update labels for next iteration
|
824
|
-
labels1, labels2 = new_labels1, new_labels2
|
825
|
-
|
826
|
-
return True
|
827
|
-
|
828
|
-
if not Topology.IsInstance(graphA, "Graph") and not Topology.IsInstance(graphB, "Graph"):
|
829
|
-
if not silent:
|
830
|
-
print("Graph.AreIsomorphic - Error: The input graph parameters are not valid graphs. Returning None.")
|
831
|
-
return None
|
832
|
-
if not Topology.IsInstance(graphA, "Graph"):
|
833
|
-
if not silent:
|
834
|
-
print("Graph.AreIsomorphic - Error: The input graphA parameter is not a valid graph. Returning None.")
|
835
|
-
return None
|
836
|
-
if not Topology.IsInstance(graphB, "Graph"):
|
837
|
-
if not silent:
|
838
|
-
print("Graph.AreIsomorphic - Error: The input graphB parameter is not a valid graph. Returning None.")
|
839
|
-
return None
|
840
|
-
if maxIterations <= 0:
|
841
|
-
if not silent:
|
842
|
-
print("Graph.AreIsomorphic - Error: The input maxIterations parameter is not within a valid range. Returning None.")
|
843
|
-
return None
|
844
|
-
|
845
|
-
g1 = Graph.AdjacencyDictionary(graphA)
|
846
|
-
g2 = Graph.AdjacencyDictionary(graphB)
|
847
|
-
return weisfeiler_lehman_test(g1, g2, max_iterations=maxIterations)
|
848
|
-
|
849
753
|
@staticmethod
|
850
754
|
def AverageClusteringCoefficient(graph, mantissa: int = 6, silent: bool = False):
|
851
755
|
"""
|
@@ -1345,7 +1249,7 @@ class Graph:
|
|
1345
1249
|
graph : topologic_core.Graph
|
1346
1250
|
The input graph.
|
1347
1251
|
key : str , optional
|
1348
|
-
The dictionary key under which to
|
1252
|
+
The dictionary key under which to store the betweeness centrality score. The default is "betweenness_centrality".
|
1349
1253
|
mantissa : int , optional
|
1350
1254
|
The desired length of the mantissa. The default is 6.
|
1351
1255
|
tolerance : float , optional
|
@@ -1427,7 +1331,75 @@ class Graph:
|
|
1427
1331
|
return_betweenness[int(i)] = v
|
1428
1332
|
|
1429
1333
|
return return_betweenness
|
1430
|
-
|
1334
|
+
|
1335
|
+
@staticmethod
|
1336
|
+
def Bridges(graph, key: str = "bridge", silent: bool = False):
|
1337
|
+
"""
|
1338
|
+
Returns the list of bridge edges in the input graph. See: https://en.wikipedia.org/wiki/Bridge_(graph_theory)
|
1339
|
+
|
1340
|
+
Parameters
|
1341
|
+
----------
|
1342
|
+
graph : topologic_core.Graph
|
1343
|
+
The input graph.
|
1344
|
+
key : str , optional
|
1345
|
+
The edge dictionary key under which to store the bridge status. 0 means the edge is NOT a bridge. 1 means that the edge IS a bridge. The default is "bridge".
|
1346
|
+
silent : bool , optional
|
1347
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
1348
|
+
|
1349
|
+
Returns
|
1350
|
+
-------
|
1351
|
+
list
|
1352
|
+
The list of bridge edges in the input graph.
|
1353
|
+
|
1354
|
+
"""
|
1355
|
+
import os
|
1356
|
+
import warnings
|
1357
|
+
from topologicpy.Topology import Topology
|
1358
|
+
from topologicpy.Dictionary import Dictionary
|
1359
|
+
|
1360
|
+
try:
|
1361
|
+
import igraph as ig
|
1362
|
+
except:
|
1363
|
+
print("Graph.Bridges - Installing required pyhon-igraph library.")
|
1364
|
+
try:
|
1365
|
+
os.system("pip install python-igraph")
|
1366
|
+
except:
|
1367
|
+
os.system("pip install python-igraph --user")
|
1368
|
+
try:
|
1369
|
+
import igraph as ig
|
1370
|
+
print("Graph.Bridges - python-igraph library installed correctly.")
|
1371
|
+
except:
|
1372
|
+
warnings.warn("Graph.Bridges - Error: Could not import python-igraph. Please install manually.")
|
1373
|
+
|
1374
|
+
if not Topology.IsInstance(graph, "graph"):
|
1375
|
+
if not silent:
|
1376
|
+
print("Graph.Bridges - Error: The input graph parameter is not a valid topologic graph. Returning None")
|
1377
|
+
return None
|
1378
|
+
|
1379
|
+
edges = Graph.Edges(graph)
|
1380
|
+
if len(edges) < 1:
|
1381
|
+
return []
|
1382
|
+
if len(edges) == 1:
|
1383
|
+
d = Topology.Dictionary(edge)
|
1384
|
+
d = Dictionary.SetValueAtKey(d, key, 1)
|
1385
|
+
edge = Topology.SetDictionary(edge, d)
|
1386
|
+
return [edge]
|
1387
|
+
mesh_data = Graph.MeshData(graph)
|
1388
|
+
graph_edges = mesh_data['edges']
|
1389
|
+
ig_graph = ig.Graph(edges=graph_edges)
|
1390
|
+
|
1391
|
+
bridges = ig_graph.bridges()
|
1392
|
+
bridge_edges = []
|
1393
|
+
for i, edge in enumerate(edges):
|
1394
|
+
d = Topology.Dictionary(edge)
|
1395
|
+
if i in bridges:
|
1396
|
+
d = Dictionary.SetValueAtKey(d, key, 1)
|
1397
|
+
bridge_edges.append(edge)
|
1398
|
+
else:
|
1399
|
+
d = Dictionary.SetValueAtKey(d, key, 0)
|
1400
|
+
edge = Topology.SetDictionary(edge, d)
|
1401
|
+
return bridge_edges
|
1402
|
+
|
1431
1403
|
@staticmethod
|
1432
1404
|
def ByAdjacencyMatrixCSVPath(path: str, dictionaries: list = None, silent: bool = False):
|
1433
1405
|
"""
|
@@ -4410,7 +4382,7 @@ class Graph:
|
|
4410
4382
|
vertices : list , optional
|
4411
4383
|
The input list of vertices. The default is None.
|
4412
4384
|
key : str , optional
|
4413
|
-
The dictionary key under which to
|
4385
|
+
The dictionary key under which to store the closeness centrality score. The default is "closeness_centrality".
|
4414
4386
|
mantissa : int , optional
|
4415
4387
|
The desired length of the mantissa. The default is 6.
|
4416
4388
|
tolerance : float , optional
|
@@ -4498,7 +4470,7 @@ class Graph:
|
|
4498
4470
|
graph : topologicp.Graph
|
4499
4471
|
The input topologic graph.
|
4500
4472
|
key : str , optional
|
4501
|
-
The dictionary key under which to
|
4473
|
+
The dictionary key under which to store the closeness centrality score. The default is "community".
|
4502
4474
|
mantissa : int , optional
|
4503
4475
|
The desired length of the mantissa. The default is 6.
|
4504
4476
|
tolerance : float , optional
|
@@ -4517,37 +4489,39 @@ class Graph:
|
|
4517
4489
|
import warnings
|
4518
4490
|
|
4519
4491
|
try:
|
4520
|
-
import
|
4492
|
+
import igraph as ig
|
4521
4493
|
except:
|
4522
|
-
print("Graph.Community - Installing required pyhon-
|
4494
|
+
print("Graph.Community - Installing required pyhon-igraph library.")
|
4523
4495
|
try:
|
4524
|
-
os.system("pip install python-
|
4496
|
+
os.system("pip install python-igraph")
|
4525
4497
|
except:
|
4526
|
-
os.system("pip install python-
|
4498
|
+
os.system("pip install python-igraph --user")
|
4527
4499
|
try:
|
4528
|
-
import
|
4529
|
-
print("Graph.Community - python-
|
4500
|
+
import igraph as ig
|
4501
|
+
print("Graph.Community - python-igraph library installed correctly.")
|
4530
4502
|
except:
|
4531
|
-
warnings.warn("Graph.Community - Error: Could not import python-
|
4503
|
+
warnings.warn("Graph.Community - Error: Could not import python-igraph. Please install manually.")
|
4532
4504
|
|
4533
4505
|
if not Topology.IsInstance(graph, "graph"):
|
4534
4506
|
if not silent:
|
4535
4507
|
print("Graph.Community - Error: The input graph parameter is not a valid topologic graph. Returning None")
|
4536
4508
|
return None
|
4537
4509
|
|
4510
|
+
mesh_data = Graph.MeshData(graph)
|
4511
|
+
# Create an igraph graph from the edge list
|
4512
|
+
ig_graph = ig.Graph(edges=mesh_data['edges'])
|
4513
|
+
|
4514
|
+
# Detect communities using Louvain method
|
4515
|
+
communities = ig_graph.community_multilevel()
|
4516
|
+
|
4517
|
+
# Get the list of communities sorted same as vertices
|
4518
|
+
community_list = communities.membership
|
4538
4519
|
vertices = Graph.Vertices(graph)
|
4539
|
-
|
4540
|
-
|
4541
|
-
|
4542
|
-
|
4543
|
-
|
4544
|
-
for node, community_id in partition.items():
|
4545
|
-
nx_graph.nodes[node][key] = community_id
|
4546
|
-
d = Topology.Dictionary(vertices[node])
|
4547
|
-
d = Dictionary.SetValueAtKey(d, key, community_id)
|
4548
|
-
vertices[node] = Topology.SetDictionary(vertices[node], d)
|
4549
|
-
communities.append(community_id)
|
4550
|
-
return communities
|
4520
|
+
for i, v in enumerate(vertices):
|
4521
|
+
d = Topology.Dictionary(v)
|
4522
|
+
d = Dictionary.SetValueAtKey(d, key, community_list[i])
|
4523
|
+
v = Topology.SetDictionary(v, d)
|
4524
|
+
return community_list
|
4551
4525
|
|
4552
4526
|
@staticmethod
|
4553
4527
|
def Connect(graph, verticesA, verticesB, tolerance=0.0001):
|
@@ -4608,7 +4582,7 @@ class Graph:
|
|
4608
4582
|
vertices : list , optional
|
4609
4583
|
The input list of vertices. The default is None.
|
4610
4584
|
key : str , optional
|
4611
|
-
The dictionary key under which to
|
4585
|
+
The dictionary key under which to store the connectivity score. The default is "connectivity".
|
4612
4586
|
edgeKey : str , optional
|
4613
4587
|
If specified, the value in the connected edges' dictionary specified by the edgeKey string will be aggregated to calculate
|
4614
4588
|
the vertex degree. If a numeric value cannot be retrieved from an edge, a value of 1 is used instead. This is used in weighted graphs.
|
@@ -4703,6 +4677,67 @@ class Graph:
|
|
4703
4677
|
return None
|
4704
4678
|
return graph.ContainsVertex(vertex, tolerance) # Hook to Core
|
4705
4679
|
|
4680
|
+
@staticmethod
|
4681
|
+
def CutVertices(graph, key: str = "cut", silent: bool = False):
|
4682
|
+
"""
|
4683
|
+
Returns the list of cut vertices in the input graph. See: https://en.wikipedia.org/wiki/Bridge_(graph_theory)
|
4684
|
+
|
4685
|
+
Parameters
|
4686
|
+
----------
|
4687
|
+
graph : topologic_core.Graph
|
4688
|
+
The input graph.
|
4689
|
+
key : str , optional
|
4690
|
+
The vertex dictionary key under which to store the cut status. 0 means the vertex is NOT a cut vertex. 1 means that the vertex IS a cut vertex. The default is "cut".
|
4691
|
+
silent : bool , optional
|
4692
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
4693
|
+
|
4694
|
+
Returns
|
4695
|
+
-------
|
4696
|
+
list
|
4697
|
+
The list of bridge edges in the input graph.
|
4698
|
+
|
4699
|
+
"""
|
4700
|
+
import os
|
4701
|
+
import warnings
|
4702
|
+
from topologicpy.Topology import Topology
|
4703
|
+
from topologicpy.Dictionary import Dictionary
|
4704
|
+
|
4705
|
+
try:
|
4706
|
+
import igraph as ig
|
4707
|
+
except:
|
4708
|
+
print("Graph.CutVertices - Installing required pyhon-igraph library.")
|
4709
|
+
try:
|
4710
|
+
os.system("pip install python-igraph")
|
4711
|
+
except:
|
4712
|
+
os.system("pip install python-igraph --user")
|
4713
|
+
try:
|
4714
|
+
import igraph as ig
|
4715
|
+
print("Graph.CutVertices - python-igraph library installed correctly.")
|
4716
|
+
except:
|
4717
|
+
warnings.warn("Graph.CutVertices - Error: Could not import python-igraph. Please install manually.")
|
4718
|
+
|
4719
|
+
if not Topology.IsInstance(graph, "graph"):
|
4720
|
+
if not silent:
|
4721
|
+
print("Graph.CutVertices - Error: The input graph parameter is not a valid topologic graph. Returning None")
|
4722
|
+
return None
|
4723
|
+
|
4724
|
+
vertices = Graph.Vertices(graph)
|
4725
|
+
mesh_data = Graph.MeshData(graph)
|
4726
|
+
graph_edges = mesh_data['edges']
|
4727
|
+
ig_graph = ig.Graph(edges=graph_edges)
|
4728
|
+
articulation_points = ig_graph.vs[ig_graph.articulation_points()]
|
4729
|
+
articulation_points_list = [v.index for v in articulation_points]
|
4730
|
+
cut_vertices = []
|
4731
|
+
for i, vertex in enumerate(vertices):
|
4732
|
+
d = Topology.Dictionary(vertex)
|
4733
|
+
if i in articulation_points_list:
|
4734
|
+
d = Dictionary.SetValueAtKey(d, key, 1)
|
4735
|
+
cut_vertices.append(vertex)
|
4736
|
+
else:
|
4737
|
+
d = Dictionary.SetValueAtKey(d, key, 0)
|
4738
|
+
vertex = Topology.SetDictionary(vertex, d)
|
4739
|
+
|
4740
|
+
return cut_vertices
|
4706
4741
|
|
4707
4742
|
@staticmethod
|
4708
4743
|
def Degree(graph, vertices=None, key: str = "degree", edgeKey: str = None, mantissa: int = 6, tolerance = 0.0001):
|
@@ -4716,7 +4751,7 @@ class Graph:
|
|
4716
4751
|
vertices : list , optional
|
4717
4752
|
The input list of vertices. The default is None.
|
4718
4753
|
key : str , optional
|
4719
|
-
The dictionary key under which to
|
4754
|
+
The dictionary key under which to store the closeness centrality score. The default is "degree".
|
4720
4755
|
edgeKey : str , optional
|
4721
4756
|
If specified, the value in the connected edges' dictionary specified by the edgeKey string will be aggregated to calculate
|
4722
4757
|
the vertex degree. If a numeric value cannot be retrieved from an edge, a value of 1 is used instead. This is used in weighted graphs.
|
@@ -4872,7 +4907,7 @@ class Graph:
|
|
4872
4907
|
vertices : list , optional
|
4873
4908
|
The input list of vertices. The default is None.
|
4874
4909
|
key : str , optional
|
4875
|
-
The dictionary key under which to
|
4910
|
+
The dictionary key under which to store the depth score. The default is "depth".
|
4876
4911
|
type : str , optional
|
4877
4912
|
The type of depth distance to calculate. The options are "topological" or "metric". The default is "topological". See https://www.spacesyntax.online/overview-2/analysis-of-spatial-relations/.
|
4878
4913
|
mantissa : int , optional
|
@@ -6125,7 +6160,103 @@ class Graph:
|
|
6125
6160
|
f.close()
|
6126
6161
|
return False
|
6127
6162
|
return False
|
6128
|
-
|
6163
|
+
|
6164
|
+
@staticmethod
|
6165
|
+
def IsIsomorphic(graphA, graphB, maxIterations=10, silent=False):
|
6166
|
+
"""
|
6167
|
+
Tests if the two input graphs are isomorphic according to the Weisfeiler Lehman graph isomorphism test. See https://en.wikipedia.org/wiki/Weisfeiler_Leman_graph_isomorphism_test
|
6168
|
+
|
6169
|
+
Parameters
|
6170
|
+
----------
|
6171
|
+
graphA : topologic_core.Graph
|
6172
|
+
The first input graph.
|
6173
|
+
graphB : topologic_core.Graph
|
6174
|
+
The second input graph.
|
6175
|
+
maxIterations : int , optional
|
6176
|
+
This number limits the number of iterations to prevent the function from running indefinitely, particularly for very large or complex graphs.
|
6177
|
+
silent : bool , optional
|
6178
|
+
If set to True, no error and warning messages are printed. Otherwise, they are. The default is False.
|
6179
|
+
|
6180
|
+
Returns
|
6181
|
+
-------
|
6182
|
+
bool
|
6183
|
+
True if the two input graphs are isomorphic. False otherwise
|
6184
|
+
|
6185
|
+
"""
|
6186
|
+
|
6187
|
+
from topologicpy.Topology import Topology
|
6188
|
+
|
6189
|
+
def weisfeiler_lehman_test(graph1, graph2, max_iterations=10):
|
6190
|
+
"""
|
6191
|
+
Test if two graphs are isomorphic using the Weisfeiler-Leman (WL) algorithm with early stopping.
|
6192
|
+
|
6193
|
+
Parameters:
|
6194
|
+
graph1 (dict): Adjacency list representation of the first graph.
|
6195
|
+
graph2 (dict): Adjacency list representation of the second graph.
|
6196
|
+
max_iterations (int): Maximum WL iterations allowed (default is 10).
|
6197
|
+
|
6198
|
+
Returns:
|
6199
|
+
bool: True if the graphs are WL-isomorphic, False otherwise.
|
6200
|
+
"""
|
6201
|
+
|
6202
|
+
def wl_iteration(labels, graph):
|
6203
|
+
"""Perform one WL iteration and return updated labels."""
|
6204
|
+
new_labels = {}
|
6205
|
+
for node in graph:
|
6206
|
+
neighborhood_labels = sorted([labels[neighbor] for neighbor in graph[node]])
|
6207
|
+
new_labels[node] = (labels[node], tuple(neighborhood_labels))
|
6208
|
+
unique_labels = {}
|
6209
|
+
count = 0
|
6210
|
+
for node in sorted(new_labels):
|
6211
|
+
if new_labels[node] not in unique_labels:
|
6212
|
+
unique_labels[new_labels[node]] = count
|
6213
|
+
count += 1
|
6214
|
+
new_labels[node] = unique_labels[new_labels[node]]
|
6215
|
+
return new_labels
|
6216
|
+
|
6217
|
+
# Initialize labels
|
6218
|
+
labels1 = {node: 1 for node in graph1}
|
6219
|
+
labels2 = {node: 1 for node in graph2}
|
6220
|
+
|
6221
|
+
for i in range(max_iterations):
|
6222
|
+
# Perform WL iteration for both graphs
|
6223
|
+
new_labels1 = wl_iteration(labels1, graph1)
|
6224
|
+
new_labels2 = wl_iteration(labels2, graph2)
|
6225
|
+
|
6226
|
+
# Check if the label distributions match
|
6227
|
+
if sorted(new_labels1.values()) != sorted(new_labels2.values()):
|
6228
|
+
return False
|
6229
|
+
|
6230
|
+
# Check for stability (early stopping)
|
6231
|
+
if new_labels1 == labels1 and new_labels2 == labels2:
|
6232
|
+
break
|
6233
|
+
|
6234
|
+
# Update labels for next iteration
|
6235
|
+
labels1, labels2 = new_labels1, new_labels2
|
6236
|
+
|
6237
|
+
return True
|
6238
|
+
|
6239
|
+
if not Topology.IsInstance(graphA, "Graph") and not Topology.IsInstance(graphB, "Graph"):
|
6240
|
+
if not silent:
|
6241
|
+
print("Graph.IsIsomorphic - Error: The input graph parameters are not valid graphs. Returning None.")
|
6242
|
+
return None
|
6243
|
+
if not Topology.IsInstance(graphA, "Graph"):
|
6244
|
+
if not silent:
|
6245
|
+
print("Graph.IsIsomorphic - Error: The input graphA parameter is not a valid graph. Returning None.")
|
6246
|
+
return None
|
6247
|
+
if not Topology.IsInstance(graphB, "Graph"):
|
6248
|
+
if not silent:
|
6249
|
+
print("Graph.IsIsomorphic - Error: The input graphB parameter is not a valid graph. Returning None.")
|
6250
|
+
return None
|
6251
|
+
if maxIterations <= 0:
|
6252
|
+
if not silent:
|
6253
|
+
print("Graph.IsIsomorphic - Error: The input maxIterations parameter is not within a valid range. Returning None.")
|
6254
|
+
return None
|
6255
|
+
|
6256
|
+
g1 = Graph.AdjacencyDictionary(graphA)
|
6257
|
+
g2 = Graph.AdjacencyDictionary(graphB)
|
6258
|
+
return weisfeiler_lehman_test(g1, g2, max_iterations=maxIterations)
|
6259
|
+
|
6129
6260
|
@staticmethod
|
6130
6261
|
def Reshape(graph,
|
6131
6262
|
shape="spring 2D",
|
@@ -7765,7 +7896,7 @@ class Graph:
|
|
7765
7896
|
vertices : list , optional
|
7766
7897
|
The input list of vertices. If set to None, the local clustering coefficient of all vertices will be computed. The default is None.
|
7767
7898
|
key : str , optional
|
7768
|
-
The dictionary key under which to
|
7899
|
+
The dictionary key under which to store the local clustering coefficient score. The default is "lcc".
|
7769
7900
|
mantissa : int , optional
|
7770
7901
|
The desired length of the mantissa. The default is 6.
|
7771
7902
|
tolerance : float , optional
|
@@ -8102,6 +8233,7 @@ class Graph:
|
|
8102
8233
|
|
8103
8234
|
"""
|
8104
8235
|
from topologicpy.Vertex import Vertex
|
8236
|
+
from topologicpy.Edge import Edge
|
8105
8237
|
from topologicpy.Dictionary import Dictionary
|
8106
8238
|
from topologicpy.Topology import Topology
|
8107
8239
|
|
@@ -8116,8 +8248,8 @@ class Graph:
|
|
8116
8248
|
m_edges = []
|
8117
8249
|
e_dicts = []
|
8118
8250
|
for g_edge in g_edges:
|
8119
|
-
sv =
|
8120
|
-
ev =
|
8251
|
+
sv = Edge.StartVertex(g_edge)
|
8252
|
+
ev = Edge.EndVertex(g_edge)
|
8121
8253
|
si = Vertex.Index(sv, g_vertices, tolerance=tolerance)
|
8122
8254
|
ei = Vertex.Index(ev, g_vertices, tolerance=tolerance)
|
8123
8255
|
if (not si == None) and (not ei == None):
|
@@ -8421,11 +8553,11 @@ class Graph:
|
|
8421
8553
|
graph : topologic_core.Graph
|
8422
8554
|
The input graph.
|
8423
8555
|
xKey : str , optional
|
8424
|
-
The dictionary key under which to
|
8556
|
+
The dictionary key under which to store the X-Coordinate of the vertex. The default is 'x'.
|
8425
8557
|
yKey : str , optional
|
8426
|
-
The dictionary key under which to
|
8558
|
+
The dictionary key under which to store the Y-Coordinate of the vertex. The default is 'y'.
|
8427
8559
|
zKey : str , optional
|
8428
|
-
The dictionary key under which to
|
8560
|
+
The dictionary key under which to store the Z-Coordinate of the vertex. The default is 'z'.
|
8429
8561
|
mantissa : int , optional
|
8430
8562
|
The desired length of the mantissa. The default is 6.
|
8431
8563
|
tolerance : float , optional
|
@@ -8624,7 +8756,7 @@ class Graph:
|
|
8624
8756
|
directed : bool , optional
|
8625
8757
|
If set to True, the graph is considered as a directed graph. Otherwise, it will be considered as an undirected graph. The default is False.
|
8626
8758
|
key : str , optional
|
8627
|
-
The dictionary key under which to
|
8759
|
+
The dictionary key under which to store the page_rank score. The default is "page_rank"
|
8628
8760
|
mantissa : int , optional
|
8629
8761
|
The desired length of the mantissa.
|
8630
8762
|
tolerance : float , optional
|
topologicpy/Honeybee.py
CHANGED
@@ -255,7 +255,7 @@ class Honeybee:
|
|
255
255
|
|
256
256
|
def cellFloor(cell):
|
257
257
|
faces = Topology.Faces(cell)
|
258
|
-
c = [
|
258
|
+
c = [Vertex.Z(Topology.CenterOfMass(x)) for x in faces]
|
259
259
|
return round(min(c),2)
|
260
260
|
|
261
261
|
def floorLevels(cells, min_difference):
|
topologicpy/Neo4j.py
CHANGED
@@ -413,6 +413,7 @@ class Neo4j:
|
|
413
413
|
|
414
414
|
"""
|
415
415
|
from topologicpy.Vertex import Vertex
|
416
|
+
from topologicpy.Edge import Edge
|
416
417
|
from topologicpy.Graph import Graph
|
417
418
|
from topologicpy.Topology import Topology
|
418
419
|
from topologicpy.Dictionary import Dictionary
|
@@ -458,8 +459,8 @@ class Neo4j:
|
|
458
459
|
nodes.append(n)
|
459
460
|
for i in range(len(edges)):
|
460
461
|
e = edges[i]
|
461
|
-
sv =
|
462
|
-
ev =
|
462
|
+
sv = Edge.StartVertex(e)
|
463
|
+
ev = Edge.EndVertex(e)
|
463
464
|
sn = nodes[Vertex.Index(vertex=sv, vertices=vertices, strict=False, tolerance=tolerance)]
|
464
465
|
en = nodes[Vertex.Index(vertex=ev, vertices=vertices, strict=False, tolerance=tolerance)]
|
465
466
|
ed = Topology.Dictionary(e)
|
topologicpy/Shell.py
CHANGED
@@ -432,17 +432,17 @@ class Shell():
|
|
432
432
|
e3 = None
|
433
433
|
e4 = None
|
434
434
|
try:
|
435
|
-
e3 = Edge.ByVertices([
|
435
|
+
e3 = Edge.ByVertices([Edge.StartVertex(e1), Edge.StartVertex(e2)], tolerance=tolerance, silent=silent)
|
436
436
|
except:
|
437
|
-
e4 = Edge.ByVertices([
|
437
|
+
e4 = Edge.ByVertices([Edge.EndVertex(e1), Edge.EndVertex(e2)], tolerance=tolerance, silent=silent)
|
438
438
|
faces.append(Face.ByWire(Wire.ByEdges([e1, e2, e4], tolerance=tolerance), tolerance=tolerance))
|
439
439
|
try:
|
440
|
-
e4 = Edge.ByVertices([
|
440
|
+
e4 = Edge.ByVertices([Edge.EndVertex(e1), Edge.EndVertex(e2)], tolerance=tolerance, silent=silent)
|
441
441
|
except:
|
442
|
-
e3 = Edge.ByVertices([
|
442
|
+
e3 = Edge.ByVertices([Edge.StartVertex(e1), Edge.StartVertex(e2)], tolerance=tolerance, silent=silent)
|
443
443
|
faces.append(Face.ByWire(Wire.ByEdges([e1, e2, e3],tolerance=tolerance), tolerance=tolerance))
|
444
444
|
if e3 and e4:
|
445
|
-
e5 = Edge.ByVertices([
|
445
|
+
e5 = Edge.ByVertices([Edge.StartVertex(e1), Edge.EndVertex(e2)], tolerance=tolerance, silent=silent)
|
446
446
|
faces.append(Face.ByWire(Wire.ByEdges([e1, e5, e4], tolerance=tolerance), tolerance=tolerance))
|
447
447
|
faces.append(Face.ByWire(Wire.ByEdges([e2, e5, e3], tolerance=tolerance), tolerance=tolerance))
|
448
448
|
elif e3:
|
@@ -470,17 +470,17 @@ class Shell():
|
|
470
470
|
e3 = None
|
471
471
|
e4 = None
|
472
472
|
try:
|
473
|
-
e3 = Edge.ByVertices([
|
473
|
+
e3 = Edge.ByVertices([Edge.StartVertex(e1), Edge.StartVertex(e2)], tolerance=tolerance, silent=silent)
|
474
474
|
except:
|
475
475
|
try:
|
476
|
-
e4 = Edge.ByVertices([
|
476
|
+
e4 = Edge.ByVertices([Edge.EndVertex(e1), Edge.EndVertex(e2)], tolerance=tolerance, silent=silent)
|
477
477
|
except:
|
478
478
|
pass
|
479
479
|
try:
|
480
|
-
e4 = Edge.ByVertices([
|
480
|
+
e4 = Edge.ByVertices([Edge.EndVertex(e1), Edge.EndVertex(e2)], tolerance=tolerance, silent=silent)
|
481
481
|
except:
|
482
482
|
try:
|
483
|
-
e3 = Edge.ByVertices([
|
483
|
+
e3 = Edge.ByVertices([Edge.StartVertex(e1), Edge.StartVertex(e2)], tolerance=tolerance, silent=silent)
|
484
484
|
except:
|
485
485
|
pass
|
486
486
|
if e3 and e4:
|
topologicpy/Topology.py
CHANGED
@@ -4145,7 +4145,7 @@ class Topology():
|
|
4145
4145
|
if not Topology.IsInstance(topology, "Topology"):
|
4146
4146
|
print("Topology.CenterofMass - Error: the input topology parameter is not a valid topology. Returning None.")
|
4147
4147
|
return None
|
4148
|
-
return topology.CenterOfMass()
|
4148
|
+
return topology.CenterOfMass() # Hook to Core
|
4149
4149
|
|
4150
4150
|
@staticmethod
|
4151
4151
|
def Centroid(topology):
|
@@ -4169,8 +4169,8 @@ class Topology():
|
|
4169
4169
|
print("Topology.Centroid - Error: the input topology parameter is not a valid topology. Returning None.")
|
4170
4170
|
return None
|
4171
4171
|
if Topology.IsInstance(topology, "Aperture"):
|
4172
|
-
return Aperture.Topology(topology).Centroid()
|
4173
|
-
return topology.Centroid()
|
4172
|
+
return Aperture.Topology(topology).Centroid() # Hook to Core
|
4173
|
+
return topology.Centroid() # Hook to Core
|
4174
4174
|
|
4175
4175
|
@staticmethod
|
4176
4176
|
def ClusterByKeys(topologies, *keys, silent=False):
|
@@ -6140,6 +6140,7 @@ class Topology():
|
|
6140
6140
|
|
6141
6141
|
"""
|
6142
6142
|
from topologicpy.Vertex import Vertex
|
6143
|
+
from topologicpy.Edge import Edge
|
6143
6144
|
from topologicpy.Face import Face
|
6144
6145
|
|
6145
6146
|
vertices = []
|
@@ -6164,8 +6165,8 @@ class Topology():
|
|
6164
6165
|
topEdges = Topology.Edges(topology)
|
6165
6166
|
for anEdge in topEdges:
|
6166
6167
|
e = []
|
6167
|
-
sv =
|
6168
|
-
ev =
|
6168
|
+
sv = Edge.StartVertex(anEdge)
|
6169
|
+
ev = Edge.EndVertex(anEdge)
|
6169
6170
|
try:
|
6170
6171
|
svIndex = vertices.index(Vertex.Coordinates(sv, mantissa=mantissa))
|
6171
6172
|
except:
|