0% found this document useful (0 votes)
15 views

Pjpy

Uploaded by

jerryt2714
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

Pjpy

Uploaded by

jerryt2714
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 4

import dash

from dash import dcc, html, Input, Output, State


import networkx as nx
import plotly.graph_objects as go
import heapq

# Initialize the Dash app


app = dash.Dash(__name__)

# Custom CSS for styling


app.css.append_css({
'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'
})

# Layout of the app


app.layout = html.Div(style={'backgroundColor': '#f8f9fa', 'padding': '20px'}, children=[
html.H1("Routing using Dijkstra's Algorithm", style={'textAlign': 'center', 'color': '#343a40'}),
dcc.Input(id='num-nodes', type='number', value=5, min=1, max=20,
placeholder="Number of Nodes", style={'margin': '10px'}),
dcc.Textarea(id='edges-input', placeholder="Enter edges in the format 'router1 router2 distance' :",
style={'width': '100%', 'height': 150, 'margin': '10px', 'fontFamily': 'monospace'}),
dcc.Input(id='start-node', type='text', placeholder="Enter start node",
style={'margin': '10px'}),
html.Div(children=[
html.Button('Run Dijkstra', id='run-button', style={'margin': '10px', 'backgroundColor': '#007bff',
'color': 'white', 'border': 'none', 'padding': '10px 20px', 'cursor': 'pointer'}),
html.Button('Reset', id='reset-button', style={'margin': '10px', 'backgroundColor': '#dc3545',
'color': 'white', 'border': 'none', 'padding': '10px 20px', 'cursor': 'pointer'}),
], style={'textAlign': 'center'}),
dcc.Graph(id='graph-output', style={'marginTop': '20px'}),
html.Div(id='output', style={'marginTop': '20px', 'fontSize': '16px', 'color': '#343a40'})
])

def dijkstra(graph, start):


# Initialize distances and priority queue
distances = {node: float('inf') for node in graph.nodes()}
distances[start] = 0
priority_queue = [(0, start)]
shortest_path = {node: None for node in graph.nodes()}

while priority_queue:
current_distance, current_node = heapq.heappop(priority_queue)

# Nodes can only be added once to the queue with their shortest distance
if current_distance > distances[current_node]:
continue

for neighbor in graph.neighbors(current_node):


weight = graph[current_node][neighbor]['weight']
distance = current_distance + weight
# If found a shorter path to neighbor
if distance < distances[neighbor]:
distances[neighbor] = distance
shortest_path[neighbor] = current_node
heapq.heappush(priority_queue, (distance, neighbor))

return distances, shortest_path

def find_shortest_paths(shortest_path, start):


paths = {}
for node in shortest_path:
path = []
current = node
while current is not None:
path.append(current)
current = shortest_path[current]
paths[node] = path[::-1] # Reverse the path
return paths

@app.callback(
Output('graph-output', 'figure'),
Output('output', 'children'),
Input('run-button', 'n_clicks'),
State('edges-input', 'value'),
State('start-node', 'value'),
)
def update_output(n_clicks, edges_input, start_node):
if n_clicks is None:
return go.Figure(), ""

# Create the graph


G = nx.Graph()
edges = edges_input.splitlines()
for edge in edges:
if edge.strip():
node1, node2, weight = edge.split()
weight = int(weight)
G.add_edge(node1, node2, weight=weight)

# Run Dijkstra's algorithm


if start_node not in G.nodes():
return go.Figure(), "Start node not in graph!"
distances, shortest_path = dijkstra(G, start_node)

output_text = ["Shortest distances from start node:"]


for node, distance in distances.items():
output_text.append(f"Distance to {node}: {distance}")

# Find all shortest paths from the start node


paths = find_shortest_paths(shortest_path, start_node)
pos = nx.spring_layout(G)
edge_x = []
edge_y = []

for edge in G.edges():


x0, y0 = pos[edge[0]]
x1, y1 = pos[edge[1]]
edge_x.append(x0)
edge_x.append(x1)
edge_x.append(None)
edge_y.append(y0)
edge_y.append(y1)
edge_y.append(None)

edge_trace = go.Scatter(
x=edge_x, y=edge_y,
line=dict(width=0.5, color='#888'),
hoverinfo='none',
mode='lines'
)

node_x = []
node_y = []
node_text = []

for node in G.nodes():


x, y = pos[node]
node_x.append(x)
node_y.append(y)
node_text.append(f"{node}<br>Distance: {distances[node]}")

node_trace = go.Scatter(
x=node_x, y=node_y,
mode='markers+text',
text=node_text,
hoverinfo='text',
marker=dict(
showscale=True,
colorscale='YlGnBu',
size=10,
color=list(distances.values()), # Color by distance
colorbar=dict(title='Distance')
)
)

path_edge_x = []
path_edge_y = []

for node, path in paths.items():


if node == start_node: # Skip the start node itself
continue
for i in range(len(path) - 1):
x0, y0 = pos[path[i]]
x1, y1 = pos[path[i + 1]]
path_edge_x.append(x0)
path_edge_x.append(x1)
path_edge_x.append(None)
path_edge_y.append(y0)
path_edge_y.append(y1)
path_edge_y.append(None)

# Create a trace for the shortest path edges


path_edge_trace = go.Scatter(
x=path_edge_x, y=path_edge_y,
line=dict(width=4, color='red'), # Highlight the shortest path in red
hoverinfo='none',
mode='lines'
)

# Create the figure with all paths highlighted


fig = go.Figure(data=[edge_trace, node_trace, path_edge_trace],
layout=go.Layout(
title='Graph Visualization',
titlefont_size=16,
showlegend=False,
hovermode='closest',
margin=dict(b=0, l=0, r=0, t=40),
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))
)

return fig, output_text

@app.callback(
Output('num-nodes', 'value'),
Output('edges-input', 'value'),
Output('start-node', 'value'),
Input('reset-button', 'n_clicks'),
)
def reset(n_clicks):
if n_clicks is None:
raise dash.exceptions.PreventUpdate
return 5, "", ""

if __name__ == '__main__':
app.run_server(debug=True)

You might also like