topologicpy 0.8.50__py3-none-any.whl → 0.8.51__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
@@ -6255,53 +6255,79 @@ class Graph:
6255
6255
  return scores
6256
6256
 
6257
6257
  @staticmethod
6258
- def Diameter(graph):
6258
+ def Diameter(graph, silent: bool = False):
6259
6259
  """
6260
- Returns the diameter of the input graph. See https://mathworld.wolfram.com/GraphDiameter.html.
6260
+ Returns the diameter of the input (unweighted, undirected) graph.
6261
+
6262
+ The diameter is the maximum, over all pairs of vertices, of the length of a
6263
+ shortest path between them. If the graph is disconnected, this returns the
6264
+ maximum finite eccentricity across connected components and prints a warning
6265
+ unless `silent=True`.
6261
6266
 
6262
6267
  Parameters
6263
6268
  ----------
6264
6269
  graph : topologic_core.Graph
6265
6270
  The input graph.
6271
+ silent : bool , optional
6272
+ If set to True, error and warning messages are suppressed. Default is False.
6266
6273
 
6267
6274
  Returns
6268
6275
  -------
6269
6276
  int
6270
- The diameter of the input graph.
6271
-
6277
+ The diameter of the input graph, or None if the graph is empty.
6272
6278
  """
6279
+ from collections import deque
6273
6280
  from topologicpy.Topology import Topology
6274
6281
 
6282
+ # Basic checks
6275
6283
  if not Topology.IsInstance(graph, "Graph"):
6276
- print("Graph.Diameter - Error: The input graph is not a valid graph. Returning None.")
6284
+ if not silent:
6285
+ print("Graph.Diameter - Error: The input graph is not a valid graph. Returning None.")
6277
6286
  return None
6278
-
6279
- def dfs(node, visited):
6280
- visited.add(node)
6281
- max_depth = 0
6282
- farthest_node = node
6283
- for neighbor in adj_dict[node]:
6284
- if neighbor not in visited:
6285
- depth, end_node = dfs(neighbor, visited)
6286
- if depth + 1 > max_depth:
6287
- max_depth = depth + 1
6288
- farthest_node = end_node
6289
- return max_depth, farthest_node
6290
6287
 
6291
- adj_dict = Graph.AdjacencyDictionary(graph, includeWeights=False)
6292
-
6293
- # Step 1: Pick an arbitrary starting node (first node in the graph)
6294
- start_node = next(iter(adj_dict))
6295
-
6296
- # Step 2: Run DFS to find the farthest node from the start_node
6297
- visited = set()
6298
- _, farthest_node = dfs(start_node, visited)
6299
-
6300
- # Step 3: Run DFS from the farthest node found to get the maximum depth
6301
- visited.clear()
6302
- diameter, _ = dfs(farthest_node, visited)
6288
+ # Build adjacency dictionary (as sets) and force undirected symmetry
6289
+ adj_raw = Graph.AdjacencyDictionary(graph, includeWeights=False)
6290
+ if not adj_raw: # empty graph
6291
+ if not silent:
6292
+ print("Graph.Diameter - Warning: The graph has no vertices. Returning None.")
6293
+ return None
6294
+
6295
+ adj = {u: set(neighbors) for u, neighbors in adj_raw.items()}
6296
+ # Ensure symmetry (in case the underlying graph stored directed edges)
6297
+ for u, nbrs in list(adj.items()):
6298
+ for v in nbrs:
6299
+ adj.setdefault(v, set()).add(u)
6300
+ adj[u].add(v)
6301
+
6302
+ def bfs_eccentricity(start):
6303
+ """Return distances map from start and its eccentricity."""
6304
+ dist = {start: 0}
6305
+ q = deque([start])
6306
+ while q:
6307
+ u = q.popleft()
6308
+ for v in adj.get(u, ()):
6309
+ if v not in dist:
6310
+ dist[v] = dist[u] + 1
6311
+ q.append(v)
6312
+ ecc = max(dist.values()) if dist else 0
6313
+ return dist, ecc
6314
+
6315
+ diameter = 0
6316
+ n = len(adj)
6317
+ disconnected = False
6318
+
6319
+ for s in adj:
6320
+ dist, ecc = bfs_eccentricity(s)
6321
+ if len(dist) < n:
6322
+ disconnected = True
6323
+ if ecc > diameter:
6324
+ diameter = ecc
6325
+
6326
+ if disconnected and not silent:
6327
+ print("Graph.Diameter - Warning: The graph is disconnected. Returning the maximum finite diameter across connected components.")
6303
6328
 
6304
6329
  return diameter
6330
+
6305
6331
 
6306
6332
  @staticmethod
6307
6333
  def Dictionary(graph):
@@ -13454,7 +13480,85 @@ class Graph:
13454
13480
  queue.append((neighbor, distance + 1))
13455
13481
 
13456
13482
  return None # Target not reachable
13457
-
13483
+
13484
+ @staticmethod
13485
+ def Tietze(radius: float = 0.5, height: float = 1):
13486
+ """
13487
+ Creates a Tietze's graph mapped on a mobius strip of the same input radius and height. See https://en.wikipedia.org/wiki/Tietze%27s_graph
13488
+
13489
+ Parameters
13490
+ ----------
13491
+ radius : float , optional
13492
+ The desired radius of the mobius strip on which the graph is mapped. Default is 0.5.
13493
+ height : float , optional
13494
+ The desired height of the mobius strip on which the graph is mapped. Default is 1.
13495
+
13496
+ Returns
13497
+ -------
13498
+ topologicpy.Graph
13499
+ The created Tietze's graph.
13500
+
13501
+ """
13502
+ from topologicpy.Dictionary import Dictionary
13503
+ from topologicpy.Edge import Edge
13504
+ from topologicpy.Shell import Shell
13505
+ from topologicpy.Graph import Graph
13506
+ from topologicpy.Topology import Topology
13507
+
13508
+ m = Shell.MobiusStrip(radius=radius, height=height, uSides=12, vSides=3)
13509
+ eb = Shell.ExternalBoundary(m)
13510
+ verts = Topology.Vertices(eb)
13511
+ new_verts = []
13512
+ for i in range(0, len(verts), 2): #The mobius strip has 24 edges, we need half of that (12).
13513
+ new_verts.append(verts[i])
13514
+
13515
+ graph_edges = []
13516
+ for r in range(0,6):
13517
+ s = (r + 6)
13518
+ e = Edge.ByVertices(new_verts[r], new_verts[s])
13519
+ if r == 0:
13520
+ v1 = Edge.VertexByParameter(e, 2/3)
13521
+ v2 = Edge.EndVertex(e)
13522
+ e = Edge.ByVertices(v1, v2)
13523
+ elif r == 1:
13524
+ v3 = Edge.VertexByParameter(e, 1/3)
13525
+ v4 = Edge.VertexByParameter(e, 2/3)
13526
+ e = Edge.ByVertices(v3, v4)
13527
+ elif r == 2:
13528
+ v5 = Edge.StartVertex(e)
13529
+ v6 = Edge.VertexByParameter(e, 1/3)
13530
+ e = Edge.ByVertices(v5, v6)
13531
+ elif r == 3:
13532
+ v7 = Edge.VertexByParameter(e, 1/3)
13533
+ v8 = Edge.VertexByParameter(e, 2/3)
13534
+ e = Edge.ByVertices(v7, v8)
13535
+ elif r == 4:
13536
+ v9 = Edge.VertexByParameter(e, 2/3)
13537
+ v10 = Edge.EndVertex(e)
13538
+ e = Edge.ByVertices(v9, v10)
13539
+ elif r == 5:
13540
+ v11 = Edge.VertexByParameter(e, 1/3)
13541
+ v12 = Edge.VertexByParameter(e, 2/3)
13542
+ e = Edge.ByVertices(v11, v12)
13543
+ graph_edges.append(e)
13544
+
13545
+ graph_vertices= [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12]
13546
+ graph_edges.append(Edge.ByVertices(v10, v2))
13547
+ graph_edges.append(Edge.ByVertices(v5, v10))
13548
+ graph_edges.append(Edge.ByVertices(v2, v5))
13549
+ graph_edges.append(Edge.ByVertices(v1, v4))
13550
+ graph_edges.append(Edge.ByVertices(v4, v8))
13551
+ graph_edges.append(Edge.ByVertices(v8, v9))
13552
+ graph_edges.append(Edge.ByVertices(v9, v12))
13553
+ graph_edges.append(Edge.ByVertices(v12, v3))
13554
+ graph_edges.append(Edge.ByVertices(v3, v6))
13555
+ graph_edges.append(Edge.ByVertices(v6, v7))
13556
+ graph_edges.append(Edge.ByVertices(v7, v11))
13557
+ graph_edges.append(Edge.ByVertices(v11, v1))
13558
+ graph_edges = [Edge.Reverse(e) for e in graph_edges] #This makes them look better when sagitta is applied.
13559
+ graph = Graph.ByVerticesEdges(graph_vertices, graph_edges)
13560
+ return graph
13561
+
13458
13562
  @staticmethod
13459
13563
  def TopologicalDistance(graph, vertexA, vertexB, tolerance=0.0001):
13460
13564
  """
topologicpy/Shell.py CHANGED
@@ -1175,7 +1175,7 @@ class Shell():
1175
1175
  if not silent:
1176
1176
  print("Shell.MobiusStrip - Error: The height input parameter must be a positive number greater than the tolerance input parameter. Returning None.")
1177
1177
  return None
1178
- if uSides <= 3:
1178
+ if uSides < 3:
1179
1179
  if not silent:
1180
1180
  print("Shell.MobiusStrip - Error: The uSides input parameter must be a positive integer greater than 2. Returning None.")
1181
1181
  return None
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.8.50'
1
+ __version__ = '0.8.51'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: topologicpy
3
- Version: 0.8.50
3
+ Version: 0.8.51
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
@@ -12,7 +12,7 @@ topologicpy/Dictionary.py,sha256=Z4YQ88tONWd-0X0dENQ8IZqIOa9mbBqhJkTBsHmft2g,446
12
12
  topologicpy/Edge.py,sha256=DifItuyabFDUFC7CVMlt2DeMFMNaGOqCg43iU9CPP0A,74029
13
13
  topologicpy/EnergyModel.py,sha256=IiBJNx7F9-8TPMaQn1iQON1ZtTv2nT5kbZHxM_gBCTQ,53773
14
14
  topologicpy/Face.py,sha256=aX9EcR3JGbLITElhd25J0Z8m9U8KkmbYivGg3oZN-Uw,202296
15
- topologicpy/Graph.py,sha256=Idp-Wmm_ziofg_mJyJHhw6Qm0xRd-etTzaVNxp3EreU,686857
15
+ topologicpy/Graph.py,sha256=o6aK18tCTkfzsNFOTAU-wIPG2p3g_vpm6n7YHc44bYU,691239
16
16
  topologicpy/Grid.py,sha256=3OsBMyHh4w8gpFOTMKHMNTpo62V0CwRNu5cwm87yDUA,18421
17
17
  topologicpy/Helper.py,sha256=aGmndgmEztjVNU-wW9OoHDel7wzapprM0TjA7f2AoS8,31188
18
18
  topologicpy/Honeybee.py,sha256=C7Am0kCK3a5rt7Jpu2EIgqeR114ZJWtsx4_DBcr5hQA,21716
@@ -22,7 +22,7 @@ topologicpy/Plotly.py,sha256=RXGeEBwVs8unJaT9vv_FBmAFfKd-1Z5x3V8oeKE43Bs,122924
22
22
  topologicpy/Polyskel.py,sha256=oVfM4lqSMPTjnkHfsRU9VI8Blt6Vf0LVPkD9ebz7Wmw,27082
23
23
  topologicpy/PyG.py,sha256=wOsoBFxMgwZYWjj86OMkz_PJuQ02locV_djhSDD6dVc,109644
24
24
  topologicpy/ShapeGrammar.py,sha256=KYsKDLXWdflAcYMAIz84AUF-GMkbTmaBDd2-ovbilqU,23336
25
- topologicpy/Shell.py,sha256=e6R7JdzYL1ubO0xXJs5P_UiiNHccN5SjQhQfGPPgHBg,96793
25
+ topologicpy/Shell.py,sha256=ioO4raCJfXtYldQg-adpcLVeJPEA6od6cAA5ro7t6r4,96792
26
26
  topologicpy/Speckle.py,sha256=-eiTqJugd7pHiHpD3pDUcDO6CGhVyPV14HFRzaqEoaw,18187
27
27
  topologicpy/Sun.py,sha256=8S6dhCKfOhUGVny-jEk87Q08anLYMB1JEBKRGCklvbQ,36670
28
28
  topologicpy/Topology.py,sha256=MoEszjDhEiCVYTO4IFxYsYjYj4Vg5TnWUcnoPMNj-Nc,471350
@@ -30,9 +30,9 @@ topologicpy/Vector.py,sha256=pEC8YY3TeHGfGdeNgvdHjgMDwxGabp5aWjwYC1HSvMk,42236
30
30
  topologicpy/Vertex.py,sha256=0f6HouARKaCuxhdxsUEYi8T9giJycnWhQ8Cn70YILBA,84885
31
31
  topologicpy/Wire.py,sha256=gjgQUGHdBdXUIijgZc_VIW0E39w-smaVhhdl0jF63fQ,230466
32
32
  topologicpy/__init__.py,sha256=RMftibjgAnHB1vdL-muo71RwMS4972JCxHuRHOlU428,928
33
- topologicpy/version.py,sha256=jLQwp8ZJ2hrMvKdSSwJuigGT_jHflNoJKrmd0A0MBrM,23
34
- topologicpy-0.8.50.dist-info/licenses/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
35
- topologicpy-0.8.50.dist-info/METADATA,sha256=bOOGHTn6e-sOwgpqkBLm1YWvhnNNUMdjgfQZzqLHM9g,10535
36
- topologicpy-0.8.50.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
- topologicpy-0.8.50.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
38
- topologicpy-0.8.50.dist-info/RECORD,,
33
+ topologicpy/version.py,sha256=xWa9BLlvIYvhh3MnyCUV3ug10L4hsf2fDMNf9z_dCY4,23
34
+ topologicpy-0.8.51.dist-info/licenses/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
35
+ topologicpy-0.8.51.dist-info/METADATA,sha256=6kYuhs7iebTG3MIvoPQyA558AmaRzFkRce7CKgKBgr0,10535
36
+ topologicpy-0.8.51.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
+ topologicpy-0.8.51.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
38
+ topologicpy-0.8.51.dist-info/RECORD,,