I'm trying to create a simulation (powered by python) to analyze density and curvature of Hyperbolic Lattices and also their realtions with Anti-de Sitter (AdS) Spaces and AdS/CFT Correspondence for a research. I'm using matplotlib, numpy, networkx, random and collections. While everything seems fine when I try to run the code, I get an error about the values. I tried to change the node_size
, edge_color
and with_labels
values, but the error still didn't vanish.
Here is the code:
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
import random
from collections import deque
# Parameters for hyperbolic lattice
p = 7 # Sides per polygon (heptagon)
q = 3 # Polygons per vertex
depth = 4 # Depth of recursion
# Initialize graph for lattice
G = nx.Graph()
# Define recursive function to create the lattice
def hyperbolic_polygon_vertices(sides, center, radius):
angles = np.linspace(0, 2 * np.pi, sides, endpoint=False)
vertices = []
for angle in angles:
x = center[0] + radius * np.cos(angle)
y = center[1] + radius * np.sin(angle)
vertices.append((x, y))
return vertices
def add_hyperbolic_lattice(G, center, radius, depth, max_depth):
if depth >= max_depth:
return
# Add current center node
G.add_node(center, pos=(radius * np.cos(center[0]), radius * np.sin(center[1])))
# Generate neighboring nodes
angle_offset = 2 * np.pi / q
for i in range(q):
angle = i * angle_offset
new_radius = radius * 0.8 # Adjust radius to create depth effect
new_center = (center[0] + new_radius * np.cos(angle),
center[1] + new_radius * np.sin(angle))
# Add edge to graph and recursive call
G.add_edge(center, new_center)
add_hyperbolic_lattice(G, new_center, new_radius, depth + 1, max_depth)
# Initialize lattice with central node
initial_center = (0, 0)
initial_radius = 0.3
add_hyperbolic_lattice(G, initial_center, initial_radius, 0, depth)
# Plotting the hyperbolic lattice
pos = nx.get_node_attributes(G, 'pos')
nx.draw(G, pos, node_size=10, edge_color="blue", with_labels=False)
plt.title("Hyperbolic Lattice (Poincaré Disk)")
plt.show()
# Function to calculate density by distance
def calculate_density_by_distance(G, center, max_distance):
distances = nx.single_source_shortest_path_length(G, center)
density_by_distance = {}
for distance in range(1, max_distance + 1):
nodes_in_ring = [node for node, dist in distances.items() if dist == distance]
if nodes_in_ring:
area = np.pi * ((distance + 1)**2 - distance**2) # Approximate area for each ring
density_by_distance[distance] = len(nodes_in_ring) / area
return density_by_distance
# Calculate and plot density vs. distance
center_node = initial_center
density_data = calculate_density_by_distance(G, center_node, max_distance=5)
plt.plot(density_data.keys(), density_data.values())
plt.xlabel("Distance from Center")
plt.ylabel("Density")
plt.title("Density vs Distance in Hyperbolic Lattice")
plt.show()
# Analyzing boundary connectivity (AdS/CFT analogy)
distances = nx.single_source_shortest_path_length(G, center_node)
max_distance = max(distances.values())
boundary_nodes = [node for node, dist in distances.items() if dist == max_distance]
boundary_connectivity = np.mean([G.degree(node) for node in boundary_nodes])
print("Average connectivity at boundary (AdS/CFT analogy):", boundary_connectivity)
# Simulating network flow to boundary (black hole thermodynamics analogy)
boundary_node = random.choice(boundary_nodes)
try:
flow_value, _ = nx.maximum_flow(G, center_node, boundary_node)
print("Simulated flow value (energy transfer to boundary):", flow_value)
except:
print("Error calculating flow, nodes may not be fully connected in hyperbolic space.")
And here is the error:
Traceback (most recent call last):
File "C:\Users\zorty\Masaüstü\.venv\Lib\site-packages\networkx\drawing\nx_pylab.py", line 445, in draw_networkx_nodes
xy = np.asarray([pos[v] for v in nodelist])
~~~^^^
KeyError: (np.float64(0.70848), np.float64(0.0))
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "c:\Users\zorty\Masaüstü\Project.py", line 51, in <module>
nx.draw(G, pos, node_size=10, edge_color="blue", with_labels=False)
File "C:\Users\zorty\Masaüstü\.venv\Lib\site-packages\networkx\drawing\nx_pylab.py", line 126, in draw
draw_networkx(G, pos=pos, ax=ax, **kwds)
File "C:\Users\zorty\Masaüstü\.venv\Lib\site-packages\networkx\drawing\nx_pylab.py", line 314, in draw_networkx
draw_networkx_nodes(G, pos, **node_kwds)
File "C:\Users\zorty\Masaüstü\.venv\Lib\site-packages\networkx\drawing\nx_pylab.py", line 447, in draw_networkx_nodes
raise nx.NetworkXError(f"Node {err} has no position.") from err
networkx.exception.NetworkXError: Node (np.float64(0.70848), np.float64(0.0)) has no position.
Your current code does not assign positions to the nodes at depth == max_depth
, resulting in nodes without defined positions. Switching the first two statements in add_hyperbolic_lattice
resolves the issue.
def add_hyperbolic_lattice(G, center, radius, depth, max_depth):
# Add current center node
G.add_node(center, pos=(radius * np.cos(center[0]), radius * np.sin(center[1])))
if depth >= max_depth:
return
...