Spaces:
Sleeping
Sleeping
import streamlit as st | |
import networkx as nx | |
import plotly.graph_objects as go | |
import string | |
import random | |
import heapq | |
# generate the graph | |
def generate_graph(): | |
alphabet = list(string.ascii_uppercase) | |
node_labels = alphabet + ['A' + letter for letter in alphabet[:22]] | |
G = nx.Graph() | |
G.add_nodes_from(node_labels) | |
for _ in range(94): | |
node1, node2 = random.sample(node_labels, 2) | |
weight = random.randint(1, 10) | |
G.add_edge(node1, node2, weight=weight) | |
pos = {node: (random.uniform(-10, 10), random.uniform(-10, 10), random.uniform(-10, 10)) for node in node_labels} | |
return G, pos | |
# visualise the 3D graph | |
def visualize_3d_graph_plotly(G, pos, path=None): | |
edge_trace = [] | |
path_edge_trace = [] | |
node_x, node_y, node_z = [], [], [] | |
node_text = [] | |
for node in G.nodes(): | |
x, y, z = pos[node] | |
node_x.append(x) | |
node_y.append(y) | |
node_z.append(z) | |
node_text.append(node) | |
for edge in G.edges(): | |
x0, y0, z0 = pos[edge[0]] | |
x1, y1, z1 = pos[edge[1]] | |
edge_trace.append(go.Scatter3d(x=[x0, x1], y=[y0, y1], z=[z0, z1], | |
mode='lines', line=dict(color='gray', width=2))) | |
if path: | |
path_edges = list(zip(path, path[1:])) | |
for edge in path_edges: | |
x0, y0, z0 = pos[edge[0]] | |
x1, y1, z1 = pos[edge[1]] | |
path_edge_trace.append(go.Scatter3d(x=[x0, x1], y=[y0, y1], z=[z0, z1], | |
mode='lines', line=dict(color='blue', width=4))) | |
node_trace = go.Scatter3d(x=node_x, y=node_y, z=node_z, | |
mode='markers+text', | |
text=node_text, | |
textposition='top center', | |
marker=dict(size=8, color='skyblue'), | |
hoverinfo='text') | |
fig = go.Figure(data=edge_trace + path_edge_trace + [node_trace], | |
layout=go.Layout(title='Use mouse to rotate & zoom on graph', | |
showlegend=False, | |
width=1000, | |
height=800, | |
scene=dict(xaxis=dict(showbackground=False), | |
yaxis=dict(showbackground=False), | |
zaxis=dict(showbackground=False)))) | |
return fig | |
# Dijkstra's Algorithm implementation | |
def dijkstra_3d(graph, start, goal): | |
queue = [(0, start)] | |
distances = {node: float('inf') for node in graph.nodes} | |
distances[start] = 0 | |
previous_nodes = {node: None for node in graph.nodes} | |
while queue: | |
current_distance, current_node = heapq.heappop(queue) | |
if current_node == goal: | |
break | |
for neighbor, attributes in graph[current_node].items(): | |
weight = attributes['weight'] | |
distance = current_distance + weight | |
if distance < distances[neighbor]: | |
distances[neighbor] = distance | |
previous_nodes[neighbor] = current_node | |
heapq.heappush(queue, (distance, neighbor)) | |
path = [] | |
current_node = goal | |
while current_node is not None: | |
path.insert(0, current_node) | |
current_node = previous_nodes[current_node] | |
return path, distances[goal] | |
# Streamlit app | |
def main(): | |
st.title("3D Graph Dijkstra's Algorithm Demo") | |
st.sidebar.header("Graph Options") | |
G, pos = generate_graph() | |
nodes = list(G.nodes) | |
start_node = st.sidebar.selectbox("Select Start Point:", nodes) | |
goal_node = st.sidebar.selectbox("Select Goal Point:", nodes) | |
if st.sidebar.button("Run Algorithm"): | |
shortest_path, shortest_distance = dijkstra_3d(G, start_node, goal_node) | |
st.write(f"**Shortest path from {start_node} to {goal_node}:** {shortest_path}") | |
st.write(f"**Shortest distance:** {shortest_distance}") | |
fig = visualize_3d_graph_plotly(G, pos, path=shortest_path) | |
else: | |
fig = visualize_3d_graph_plotly(G, pos) | |
st.plotly_chart(fig) | |
if __name__ == "__main__": | |
main() |