Update app.py
Browse files
app.py
CHANGED
|
@@ -9,12 +9,15 @@ sidebar_option = st.sidebar.radio("Select an option",
|
|
| 9 |
"Basic: Read and write graphs", "Basic: Simple graph",
|
| 10 |
"Basic: Simple graph Directed", "Drawing: Custom Node Position"])
|
| 11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
# Function to display properties and graph for Basic: Properties
|
| 13 |
def display_graph_properties(G):
|
| 14 |
-
# Initialize a list for path lengths
|
| 15 |
pathlengths = []
|
| 16 |
-
|
| 17 |
-
# Display the source-target shortest path lengths
|
| 18 |
st.write("### Source vertex {target:length, }")
|
| 19 |
for v in G.nodes():
|
| 20 |
spl = dict(nx.single_source_shortest_path_length(G, v))
|
|
@@ -22,23 +25,16 @@ def display_graph_properties(G):
|
|
| 22 |
for p in spl:
|
| 23 |
pathlengths.append(spl[p])
|
| 24 |
|
| 25 |
-
# Calculate and display the average shortest path length
|
| 26 |
avg_path_length = sum(pathlengths) / len(pathlengths)
|
| 27 |
st.write(f"### Average shortest path length: {avg_path_length}")
|
| 28 |
|
| 29 |
-
# Calculate and display the distribution of path lengths
|
| 30 |
dist = {}
|
| 31 |
for p in pathlengths:
|
| 32 |
-
|
| 33 |
-
dist[p] += 1
|
| 34 |
-
else:
|
| 35 |
-
dist[p] = 1
|
| 36 |
-
|
| 37 |
st.write("### Length #paths")
|
| 38 |
for d in sorted(dist.keys()):
|
| 39 |
st.write(f"Length {d}: {dist[d]} paths")
|
| 40 |
|
| 41 |
-
# Display the graph metrics with a "Properties" heading
|
| 42 |
st.write("### Properties")
|
| 43 |
st.write(f"Radius: {nx.radius(G)}")
|
| 44 |
st.write(f"Diameter: {nx.diameter(G)}")
|
|
@@ -50,13 +46,10 @@ def display_graph_properties(G):
|
|
| 50 |
# Visualize the graph
|
| 51 |
st.write("### Graph Visualization")
|
| 52 |
pos = nx.spring_layout(G, seed=3068) # Seed layout for reproducibility
|
| 53 |
-
|
| 54 |
-
nx.draw(G, pos=pos, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_weight='bold')
|
| 55 |
-
st.pyplot(plt)
|
| 56 |
|
| 57 |
# Function to display graph for Basic: Read and write graphs
|
| 58 |
def display_read_write_graph(G):
|
| 59 |
-
# Print the adjacency list of the graph
|
| 60 |
st.write("### Adjacency List:")
|
| 61 |
for line in nx.generate_adjlist(G):
|
| 62 |
st.write(line)
|
|
@@ -74,9 +67,7 @@ def display_read_write_graph(G):
|
|
| 74 |
# Visualize the graph
|
| 75 |
st.write("### Graph Visualization:")
|
| 76 |
pos = nx.spring_layout(H, seed=200) # Seed for reproducibility
|
| 77 |
-
|
| 78 |
-
nx.draw(H, pos, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_weight='bold')
|
| 79 |
-
st.pyplot(plt)
|
| 80 |
|
| 81 |
# Function to display Simple Graphs for Basic: Simple graph
|
| 82 |
def display_simple_graph(G, pos=None):
|
|
@@ -131,25 +122,21 @@ def display_custom_node_position():
|
|
| 131 |
pos[center_node] = np.array([0, 0]) # Manually specify node position
|
| 132 |
|
| 133 |
# Draw the graph
|
| 134 |
-
|
| 135 |
-
st.pyplot(plt)
|
| 136 |
|
| 137 |
# Display Basic: Properties if selected
|
| 138 |
if sidebar_option == "Basic: Properties":
|
| 139 |
st.title("Basic: Properties")
|
| 140 |
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
|
| 141 |
|
| 142 |
-
# Default example: 5x5 grid graph
|
| 143 |
if option == "Default Example":
|
| 144 |
G = nx.lollipop_graph(4, 6)
|
| 145 |
display_graph_properties(G)
|
| 146 |
|
| 147 |
-
# Create your own graph
|
| 148 |
elif option == "Create your own":
|
| 149 |
num_nodes = st.number_input("Number of nodes:", min_value=2, max_value=50, value=5)
|
| 150 |
num_edges = st.number_input("Number of edges per group (for lollipop graph):", min_value=1, max_value=10, value=3)
|
| 151 |
|
| 152 |
-
# Button to generate the graph
|
| 153 |
if st.button("Generate"):
|
| 154 |
if num_nodes >= 2 and num_edges >= 1:
|
| 155 |
G_custom = nx.lollipop_graph(num_nodes, num_edges)
|
|
@@ -160,17 +147,14 @@ elif sidebar_option == "Basic: Read and write graphs":
|
|
| 160 |
st.title("Basic: Read and write graphs")
|
| 161 |
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
|
| 162 |
|
| 163 |
-
# Default example: 5x5 grid graph
|
| 164 |
if option == "Default Example":
|
| 165 |
-
G = nx.grid_2d_graph(5, 5)
|
| 166 |
display_read_write_graph(G)
|
| 167 |
|
| 168 |
-
# Create your own graph
|
| 169 |
elif option == "Create your own":
|
| 170 |
rows = st.number_input("Number of rows:", min_value=2, max_value=20, value=5)
|
| 171 |
cols = st.number_input("Number of columns:", min_value=2, max_value=20, value=5)
|
| 172 |
|
| 173 |
-
# Button to generate the graph
|
| 174 |
if st.button("Generate"):
|
| 175 |
if rows >= 2 and cols >= 2:
|
| 176 |
G_custom = nx.grid_2d_graph(rows, cols)
|
|
@@ -181,7 +165,6 @@ elif sidebar_option == "Basic: Simple graph":
|
|
| 181 |
st.title("Basic: Simple graph")
|
| 182 |
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
|
| 183 |
|
| 184 |
-
# Default example: simple undirected graph
|
| 185 |
if option == "Default Example":
|
| 186 |
G = nx.Graph()
|
| 187 |
G.add_edge(1, 2)
|
|
@@ -191,32 +174,21 @@ elif sidebar_option == "Basic: Simple graph":
|
|
| 191 |
G.add_edge(3, 4)
|
| 192 |
G.add_edge(4, 5)
|
| 193 |
|
| 194 |
-
# explicitly set positions for visualization
|
| 195 |
pos = {1: (0, 0), 2: (-1, 0.3), 3: (2, 0.17), 4: (4, 0.255), 5: (5, 0.03)}
|
| 196 |
display_simple_graph(G, pos)
|
| 197 |
|
| 198 |
-
# Create your own graph
|
| 199 |
elif option == "Create your own":
|
| 200 |
-
# num_nodes = st.number_input("Number of nodes:", min_value=2, max_value=20, value=5)
|
| 201 |
edges = []
|
| 202 |
-
|
| 203 |
-
# Let the user define edges
|
| 204 |
-
st.write("Enter the edges (as pairs of nodes) separated by commas. For example, 1,2 or 3,4.")
|
| 205 |
edge_input = st.text_area("Edges:", value="1,2\n1,3\n2,3")
|
| 206 |
-
|
| 207 |
-
# Parse the edges
|
| 208 |
if edge_input:
|
| 209 |
edge_list = edge_input.split("\n")
|
| 210 |
for edge in edge_list:
|
| 211 |
u, v = map(int, edge.split(","))
|
| 212 |
edges.append((u, v))
|
| 213 |
|
| 214 |
-
# Button to generate the graph
|
| 215 |
if st.button("Generate"):
|
| 216 |
G_custom = nx.Graph()
|
| 217 |
G_custom.add_edges_from(edges)
|
| 218 |
-
|
| 219 |
-
# Set a basic layout (spring layout as default)
|
| 220 |
pos = nx.spring_layout(G_custom, seed=42)
|
| 221 |
display_simple_graph(G_custom, pos)
|
| 222 |
|
|
@@ -225,45 +197,31 @@ elif sidebar_option == "Basic: Simple graph Directed":
|
|
| 225 |
st.title("Basic: Simple graph Directed")
|
| 226 |
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
|
| 227 |
|
| 228 |
-
# Default example: simple directed graph
|
| 229 |
if option == "Default Example":
|
| 230 |
G = nx.DiGraph([(0, 3), (1, 3), (2, 4), (3, 5), (3, 6), (4, 6), (5, 6)])
|
| 231 |
|
| 232 |
-
# Group nodes by column
|
| 233 |
left_nodes = [0, 1, 2]
|
| 234 |
middle_nodes = [3, 4]
|
| 235 |
right_nodes = [5, 6]
|
| 236 |
|
| 237 |
-
# Set the position according to column (x-coord)
|
| 238 |
pos = {n: (0, i) for i, n in enumerate(left_nodes)}
|
| 239 |
pos.update({n: (1, i + 0.5) for i, n in enumerate(middle_nodes)})
|
| 240 |
pos.update({n: (2, i + 0.5) for i, n in enumerate(right_nodes)})
|
| 241 |
|
| 242 |
-
# Draw the directed graph
|
| 243 |
display_simple_directed_graph(G, pos)
|
| 244 |
|
| 245 |
-
# Create your own directed graph
|
| 246 |
elif option == "Create your own":
|
| 247 |
-
# num_nodes = st.number_input("Number of nodes:", min_value=2, max_value=20, value=5)
|
| 248 |
edges = []
|
| 249 |
-
|
| 250 |
-
# Let the user define directed edges
|
| 251 |
-
st.write("Enter the directed edges (as pairs of nodes) separated by commas. For example, 1,2 or 3,4.")
|
| 252 |
edge_input = st.text_area("Edges:", value="1,2\n1,3\n2,3")
|
| 253 |
-
|
| 254 |
-
# Parse the edges
|
| 255 |
if edge_input:
|
| 256 |
edge_list = edge_input.split("\n")
|
| 257 |
for edge in edge_list:
|
| 258 |
u, v = map(int, edge.split(","))
|
| 259 |
edges.append((u, v))
|
| 260 |
|
| 261 |
-
# Button to generate the directed graph
|
| 262 |
if st.button("Generate"):
|
| 263 |
G_custom = nx.DiGraph()
|
| 264 |
G_custom.add_edges_from(edges)
|
| 265 |
-
|
| 266 |
-
# Set a basic layout (spring layout as default)
|
| 267 |
pos = nx.spring_layout(G_custom, seed=42)
|
| 268 |
display_simple_directed_graph(G_custom, pos)
|
| 269 |
|
|
|
|
| 9 |
"Basic: Read and write graphs", "Basic: Simple graph",
|
| 10 |
"Basic: Simple graph Directed", "Drawing: Custom Node Position"])
|
| 11 |
|
| 12 |
+
# Helper function to draw and display graph
|
| 13 |
+
def draw_graph(G, pos=None, title="Graph Visualization"):
|
| 14 |
+
plt.figure(figsize=(8, 6))
|
| 15 |
+
nx.draw(G, pos=pos, with_labels=True, node_color='lightblue', node_size=500, font_size=10, font_weight='bold')
|
| 16 |
+
st.pyplot(plt)
|
| 17 |
+
|
| 18 |
# Function to display properties and graph for Basic: Properties
|
| 19 |
def display_graph_properties(G):
|
|
|
|
| 20 |
pathlengths = []
|
|
|
|
|
|
|
| 21 |
st.write("### Source vertex {target:length, }")
|
| 22 |
for v in G.nodes():
|
| 23 |
spl = dict(nx.single_source_shortest_path_length(G, v))
|
|
|
|
| 25 |
for p in spl:
|
| 26 |
pathlengths.append(spl[p])
|
| 27 |
|
|
|
|
| 28 |
avg_path_length = sum(pathlengths) / len(pathlengths)
|
| 29 |
st.write(f"### Average shortest path length: {avg_path_length}")
|
| 30 |
|
|
|
|
| 31 |
dist = {}
|
| 32 |
for p in pathlengths:
|
| 33 |
+
dist[p] = dist.get(p, 0) + 1
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
st.write("### Length #paths")
|
| 35 |
for d in sorted(dist.keys()):
|
| 36 |
st.write(f"Length {d}: {dist[d]} paths")
|
| 37 |
|
|
|
|
| 38 |
st.write("### Properties")
|
| 39 |
st.write(f"Radius: {nx.radius(G)}")
|
| 40 |
st.write(f"Diameter: {nx.diameter(G)}")
|
|
|
|
| 46 |
# Visualize the graph
|
| 47 |
st.write("### Graph Visualization")
|
| 48 |
pos = nx.spring_layout(G, seed=3068) # Seed layout for reproducibility
|
| 49 |
+
draw_graph(G, pos)
|
|
|
|
|
|
|
| 50 |
|
| 51 |
# Function to display graph for Basic: Read and write graphs
|
| 52 |
def display_read_write_graph(G):
|
|
|
|
| 53 |
st.write("### Adjacency List:")
|
| 54 |
for line in nx.generate_adjlist(G):
|
| 55 |
st.write(line)
|
|
|
|
| 67 |
# Visualize the graph
|
| 68 |
st.write("### Graph Visualization:")
|
| 69 |
pos = nx.spring_layout(H, seed=200) # Seed for reproducibility
|
| 70 |
+
draw_graph(H, pos)
|
|
|
|
|
|
|
| 71 |
|
| 72 |
# Function to display Simple Graphs for Basic: Simple graph
|
| 73 |
def display_simple_graph(G, pos=None):
|
|
|
|
| 122 |
pos[center_node] = np.array([0, 0]) # Manually specify node position
|
| 123 |
|
| 124 |
# Draw the graph
|
| 125 |
+
draw_graph(G, pos)
|
|
|
|
| 126 |
|
| 127 |
# Display Basic: Properties if selected
|
| 128 |
if sidebar_option == "Basic: Properties":
|
| 129 |
st.title("Basic: Properties")
|
| 130 |
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
|
| 131 |
|
|
|
|
| 132 |
if option == "Default Example":
|
| 133 |
G = nx.lollipop_graph(4, 6)
|
| 134 |
display_graph_properties(G)
|
| 135 |
|
|
|
|
| 136 |
elif option == "Create your own":
|
| 137 |
num_nodes = st.number_input("Number of nodes:", min_value=2, max_value=50, value=5)
|
| 138 |
num_edges = st.number_input("Number of edges per group (for lollipop graph):", min_value=1, max_value=10, value=3)
|
| 139 |
|
|
|
|
| 140 |
if st.button("Generate"):
|
| 141 |
if num_nodes >= 2 and num_edges >= 1:
|
| 142 |
G_custom = nx.lollipop_graph(num_nodes, num_edges)
|
|
|
|
| 147 |
st.title("Basic: Read and write graphs")
|
| 148 |
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
|
| 149 |
|
|
|
|
| 150 |
if option == "Default Example":
|
| 151 |
+
G = nx.grid_2d_graph(5, 5)
|
| 152 |
display_read_write_graph(G)
|
| 153 |
|
|
|
|
| 154 |
elif option == "Create your own":
|
| 155 |
rows = st.number_input("Number of rows:", min_value=2, max_value=20, value=5)
|
| 156 |
cols = st.number_input("Number of columns:", min_value=2, max_value=20, value=5)
|
| 157 |
|
|
|
|
| 158 |
if st.button("Generate"):
|
| 159 |
if rows >= 2 and cols >= 2:
|
| 160 |
G_custom = nx.grid_2d_graph(rows, cols)
|
|
|
|
| 165 |
st.title("Basic: Simple graph")
|
| 166 |
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
|
| 167 |
|
|
|
|
| 168 |
if option == "Default Example":
|
| 169 |
G = nx.Graph()
|
| 170 |
G.add_edge(1, 2)
|
|
|
|
| 174 |
G.add_edge(3, 4)
|
| 175 |
G.add_edge(4, 5)
|
| 176 |
|
|
|
|
| 177 |
pos = {1: (0, 0), 2: (-1, 0.3), 3: (2, 0.17), 4: (4, 0.255), 5: (5, 0.03)}
|
| 178 |
display_simple_graph(G, pos)
|
| 179 |
|
|
|
|
| 180 |
elif option == "Create your own":
|
|
|
|
| 181 |
edges = []
|
|
|
|
|
|
|
|
|
|
| 182 |
edge_input = st.text_area("Edges:", value="1,2\n1,3\n2,3")
|
|
|
|
|
|
|
| 183 |
if edge_input:
|
| 184 |
edge_list = edge_input.split("\n")
|
| 185 |
for edge in edge_list:
|
| 186 |
u, v = map(int, edge.split(","))
|
| 187 |
edges.append((u, v))
|
| 188 |
|
|
|
|
| 189 |
if st.button("Generate"):
|
| 190 |
G_custom = nx.Graph()
|
| 191 |
G_custom.add_edges_from(edges)
|
|
|
|
|
|
|
| 192 |
pos = nx.spring_layout(G_custom, seed=42)
|
| 193 |
display_simple_graph(G_custom, pos)
|
| 194 |
|
|
|
|
| 197 |
st.title("Basic: Simple graph Directed")
|
| 198 |
option = st.radio("Choose a graph type:", ("Default Example", "Create your own"))
|
| 199 |
|
|
|
|
| 200 |
if option == "Default Example":
|
| 201 |
G = nx.DiGraph([(0, 3), (1, 3), (2, 4), (3, 5), (3, 6), (4, 6), (5, 6)])
|
| 202 |
|
|
|
|
| 203 |
left_nodes = [0, 1, 2]
|
| 204 |
middle_nodes = [3, 4]
|
| 205 |
right_nodes = [5, 6]
|
| 206 |
|
|
|
|
| 207 |
pos = {n: (0, i) for i, n in enumerate(left_nodes)}
|
| 208 |
pos.update({n: (1, i + 0.5) for i, n in enumerate(middle_nodes)})
|
| 209 |
pos.update({n: (2, i + 0.5) for i, n in enumerate(right_nodes)})
|
| 210 |
|
|
|
|
| 211 |
display_simple_directed_graph(G, pos)
|
| 212 |
|
|
|
|
| 213 |
elif option == "Create your own":
|
|
|
|
| 214 |
edges = []
|
|
|
|
|
|
|
|
|
|
| 215 |
edge_input = st.text_area("Edges:", value="1,2\n1,3\n2,3")
|
|
|
|
|
|
|
| 216 |
if edge_input:
|
| 217 |
edge_list = edge_input.split("\n")
|
| 218 |
for edge in edge_list:
|
| 219 |
u, v = map(int, edge.split(","))
|
| 220 |
edges.append((u, v))
|
| 221 |
|
|
|
|
| 222 |
if st.button("Generate"):
|
| 223 |
G_custom = nx.DiGraph()
|
| 224 |
G_custom.add_edges_from(edges)
|
|
|
|
|
|
|
| 225 |
pos = nx.spring_layout(G_custom, seed=42)
|
| 226 |
display_simple_directed_graph(G_custom, pos)
|
| 227 |
|