summrs commited on
Commit
4dfd40a
·
verified ·
1 Parent(s): c02efd4

import os
import subprocess

def install(package):
subprocess.check_call(["pip", "install", package])

# Manually install each required library
install("numpy")
install("networkx")
install("matplotlib")
install("gradio")

# Now import the installed libraries
import math
import itertools
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
import gradio as gr

# --- Topological Index Functions ---

def wiener_index(graph):
"""
Wiener Index: Sum of shortest path distances between all pairs of vertices.
"""
sp = dict(nx.all_pairs_shortest_path_length(graph))
total = 0
for u in sp:
for v in sp[u]:
if u < v:
total += sp[u][v]
return total

def compute_indices(graph, index_type):
if index_type == "Wiener Index":
return wiener_index(graph)

elif index_type == "Randić Index":
# Randić Index = Σ[1/√(d(u)*d(v))] for every edge (u,v)
return sum(1 / math.sqrt(graph.degree(u) * graph.degree(v)) for u, v in graph.edges())

elif index_type == "Balaban Index":
n = graph.number_of_nodes()
m = graph.number_of_edges()
if m == 0 or n <= 1:
return 0
return (m / (n - 1)) * sum(1 / math.sqrt(graph.degree(u) * graph.degree(v)) for u, v in graph.edges())

elif index_type == "Zagreb Index M1":
# M1 = Σ[d(v)]² over all vertices
return sum(d**2 for _, d in graph.degree())

elif index_type == "Zagreb Index M2":
# M2 = Σ[d(u)*d(v)] for every edge (u,v)
return sum(graph.degree(u) * graph.degree(v) for u, v in graph.edges())

elif index_type == "Harary Index":
# H = Σ[1 / d(u,v)] for all distinct vertex pairs
return sum(1 / nx.shortest_path_length(graph, u, v)
for u, v in itertools.combinations(graph.nodes(), 2))

elif index_type == "Schultz Index":
# Schultz Index = Σ[(d(u)+d(v))*d(u,v)] over all edges (as a simplified version)
return sum((graph.degree(u) + graph.degree(v)) * nx.shortest_path_length(graph, u, v)
for u, v in graph.edges())

elif index_type == "Gutman Index":
# Gutman Index = Σ[d(u)*d(v)*d(u,v)] over all edges
return sum(graph.degree(u) * graph.degree(v) * nx.shortest_path_length(graph, u, v)
for u, v in graph.edges())

elif index_type == "Estrada Index":
# Estrada Index = Σ(exp(λ)) over all eigenvalues of the adjacency matrix.
A = nx.adjacency_matrix(graph).todense()
eigenvalues = np.linalg.eigvals(A)
return sum(math.exp(ev) for ev in eigenvalues)

elif index_type == "Hosoya Index":
# Hosoya Index counts the number of matchings in a graph.
# For simplicity, we use a dummy value: the number of edges.
return graph.number_of_edges()

else:
return "Invalid Index Type"

# --- Graph Visualization Function ---

def draw_graph(graph, index_type, index_value):
"""
Draws the graph using a spring layout.
Only the edges are drawn (removing the blue nodes with numbers).
The title shows the index type and computed value.
"""
plt.figure(figsize=(6, 6))
pos = nx.spring_layout(graph, seed=42)

# Draw only the edges
nx.draw_networkx_edges(graph, pos, edge_color="gray")

plt.title(f"{index_type}: {round(index_value, 3)}", fontsize=14)

# Save the plot as an image and return its filename.
filename = "graph.png"
plt.savefig(filename)
plt.close()
return filename

# --- Main Processing Function ---

def process_graph(node_count, edge_count, index_type, custom_edges):
"""
Creates a graph either from random generation or from custom edge input.
Then computes the selected topological index and draws the graph.
"""
G = nx.Graph()
# If custom_edges is empty, generate a random graph with given node and edge counts.
if not custom_edges.strip():
G = nx.gnm_random_graph(int(node_count), int(edge_count))
else:
try:
edges = [tuple(map(int, e.strip().split("-"))) for e in custom_edges.split(",")]
all_nodes = set()
for u, v in edges:
all_nodes.update([u, v])
n = max(all_nodes) + 1
G = nx.Graph()
G.add_nodes_from(range(n))
G.add_edges_from(edges)
except Exception as e:
return f"Error in custom edges input: {e}", None

index_value = compute_indices(G, index_type)
graph_img = draw_graph(G, index_type, index_value)
return index_value, graph_img

# --- Gradio Interface Setup ---

with gr.Blocks() as demo:
gr.Markdown("# Topological Index Calculator with Graph Visualization")

with gr.Row():
node_count = gr.Number(label="Number of Nodes", value=5, minimum=1)
edge_count = gr.Number(label="Number of Edges", value=5, minimum=0)

index_type = gr.Dropdown(
choices=["Wiener Index", "Randić Index", "Balaban Index", "Zagreb Index M1", "Zagreb Index M2",
"Harary Index", "Schultz Index", "Gutman Index", "Estrada Index", "Hosoya Index"],
label="Select Topological Index"
)

custom_edges = gr.Textbox(label="Custom Edges (e.g., 0-1,1-2,2-3)", placeholder="Leave blank for random graph")

calc_button = gr.Button("Calculate & Visualize")
result_box = gr.Textbox(label="Computed Index Value", interactive=False)
graph_output = gr.Image(label="Graph Visualization", interactive=False)

calc_button.click(
fn=process_graph,
inputs=[node_count, edge_count, index_type, custom_edges],
outputs=[result_box, graph_output]
)

# --- Run the App ---

if __name__ == "__main__":
demo.launch()

Files changed (1) hide show
  1. app.py +167 -0
app.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import subprocess
3
+
4
+ def install(package):
5
+ subprocess.check_call(["pip", "install", package])
6
+
7
+ # Manually install each required library
8
+ install("numpy")
9
+ install("networkx")
10
+ install("matplotlib")
11
+ install("gradio")
12
+
13
+ # Now import the installed libraries
14
+ import math
15
+ import itertools
16
+ import numpy as np
17
+ import networkx as nx
18
+ import matplotlib.pyplot as plt
19
+ import gradio as gr
20
+
21
+ # --- Topological Index Functions ---
22
+
23
+ def wiener_index(graph):
24
+ """
25
+ Wiener Index: Sum of shortest path distances between all pairs of vertices.
26
+ """
27
+ sp = dict(nx.all_pairs_shortest_path_length(graph))
28
+ total = 0
29
+ for u in sp:
30
+ for v in sp[u]:
31
+ if u < v:
32
+ total += sp[u][v]
33
+ return total
34
+
35
+ def compute_indices(graph, index_type):
36
+ if index_type == "Wiener Index":
37
+ return wiener_index(graph)
38
+
39
+ elif index_type == "Randić Index":
40
+ # Randić Index = Σ[1/√(d(u)*d(v))] for every edge (u,v)
41
+ return sum(1 / math.sqrt(graph.degree(u) * graph.degree(v)) for u, v in graph.edges())
42
+
43
+ elif index_type == "Balaban Index":
44
+ n = graph.number_of_nodes()
45
+ m = graph.number_of_edges()
46
+ if m == 0 or n <= 1:
47
+ return 0
48
+ return (m / (n - 1)) * sum(1 / math.sqrt(graph.degree(u) * graph.degree(v)) for u, v in graph.edges())
49
+
50
+ elif index_type == "Zagreb Index M1":
51
+ # M1 = Σ[d(v)]² over all vertices
52
+ return sum(d**2 for _, d in graph.degree())
53
+
54
+ elif index_type == "Zagreb Index M2":
55
+ # M2 = Σ[d(u)*d(v)] for every edge (u,v)
56
+ return sum(graph.degree(u) * graph.degree(v) for u, v in graph.edges())
57
+
58
+ elif index_type == "Harary Index":
59
+ # H = Σ[1 / d(u,v)] for all distinct vertex pairs
60
+ return sum(1 / nx.shortest_path_length(graph, u, v)
61
+ for u, v in itertools.combinations(graph.nodes(), 2))
62
+
63
+ elif index_type == "Schultz Index":
64
+ # Schultz Index = Σ[(d(u)+d(v))*d(u,v)] over all edges (as a simplified version)
65
+ return sum((graph.degree(u) + graph.degree(v)) * nx.shortest_path_length(graph, u, v)
66
+ for u, v in graph.edges())
67
+
68
+ elif index_type == "Gutman Index":
69
+ # Gutman Index = Σ[d(u)*d(v)*d(u,v)] over all edges
70
+ return sum(graph.degree(u) * graph.degree(v) * nx.shortest_path_length(graph, u, v)
71
+ for u, v in graph.edges())
72
+
73
+ elif index_type == "Estrada Index":
74
+ # Estrada Index = Σ(exp(λ)) over all eigenvalues of the adjacency matrix.
75
+ A = nx.adjacency_matrix(graph).todense()
76
+ eigenvalues = np.linalg.eigvals(A)
77
+ return sum(math.exp(ev) for ev in eigenvalues)
78
+
79
+ elif index_type == "Hosoya Index":
80
+ # Hosoya Index counts the number of matchings in a graph.
81
+ # For simplicity, we use a dummy value: the number of edges.
82
+ return graph.number_of_edges()
83
+
84
+ else:
85
+ return "Invalid Index Type"
86
+
87
+ # --- Graph Visualization Function ---
88
+
89
+ def draw_graph(graph, index_type, index_value):
90
+ """
91
+ Draws the graph using a spring layout.
92
+ Only the edges are drawn (removing the blue nodes with numbers).
93
+ The title shows the index type and computed value.
94
+ """
95
+ plt.figure(figsize=(6, 6))
96
+ pos = nx.spring_layout(graph, seed=42)
97
+
98
+ # Draw only the edges
99
+ nx.draw_networkx_edges(graph, pos, edge_color="gray")
100
+
101
+ plt.title(f"{index_type}: {round(index_value, 3)}", fontsize=14)
102
+
103
+ # Save the plot as an image and return its filename.
104
+ filename = "graph.png"
105
+ plt.savefig(filename)
106
+ plt.close()
107
+ return filename
108
+
109
+ # --- Main Processing Function ---
110
+
111
+ def process_graph(node_count, edge_count, index_type, custom_edges):
112
+ """
113
+ Creates a graph either from random generation or from custom edge input.
114
+ Then computes the selected topological index and draws the graph.
115
+ """
116
+ G = nx.Graph()
117
+ # If custom_edges is empty, generate a random graph with given node and edge counts.
118
+ if not custom_edges.strip():
119
+ G = nx.gnm_random_graph(int(node_count), int(edge_count))
120
+ else:
121
+ try:
122
+ edges = [tuple(map(int, e.strip().split("-"))) for e in custom_edges.split(",")]
123
+ all_nodes = set()
124
+ for u, v in edges:
125
+ all_nodes.update([u, v])
126
+ n = max(all_nodes) + 1
127
+ G = nx.Graph()
128
+ G.add_nodes_from(range(n))
129
+ G.add_edges_from(edges)
130
+ except Exception as e:
131
+ return f"Error in custom edges input: {e}", None
132
+
133
+ index_value = compute_indices(G, index_type)
134
+ graph_img = draw_graph(G, index_type, index_value)
135
+ return index_value, graph_img
136
+
137
+ # --- Gradio Interface Setup ---
138
+
139
+ with gr.Blocks() as demo:
140
+ gr.Markdown("# Topological Index Calculator with Graph Visualization")
141
+
142
+ with gr.Row():
143
+ node_count = gr.Number(label="Number of Nodes", value=5, minimum=1)
144
+ edge_count = gr.Number(label="Number of Edges", value=5, minimum=0)
145
+
146
+ index_type = gr.Dropdown(
147
+ choices=["Wiener Index", "Randić Index", "Balaban Index", "Zagreb Index M1", "Zagreb Index M2",
148
+ "Harary Index", "Schultz Index", "Gutman Index", "Estrada Index", "Hosoya Index"],
149
+ label="Select Topological Index"
150
+ )
151
+
152
+ custom_edges = gr.Textbox(label="Custom Edges (e.g., 0-1,1-2,2-3)", placeholder="Leave blank for random graph")
153
+
154
+ calc_button = gr.Button("Calculate & Visualize")
155
+ result_box = gr.Textbox(label="Computed Index Value", interactive=False)
156
+ graph_output = gr.Image(label="Graph Visualization", interactive=False)
157
+
158
+ calc_button.click(
159
+ fn=process_graph,
160
+ inputs=[node_count, edge_count, index_type, custom_edges],
161
+ outputs=[result_box, graph_output]
162
+ )
163
+
164
+ # --- Run the App ---
165
+
166
+ if __name__ == "__main__":
167
+ demo.launch()