summrs commited on
Commit
e45ae96
·
verified ·
1 Parent(s): 002192d

import gradio as gr

# Formulas for the indices (written in a typical mathematical style)
formulas = {
"Wiener Index (W)": "W = Σ d(u,v) for all pairs (u,v)",
"First Zagreb Index (M₁)": "M₁ = Σ [d(v)]² for all vertices v",
"Second Zagreb Index (M₂)": "M₂ = Σ [d(u) * d(v)] for all adjacent vertices (u,v)",
"Randić Index (R)": "R = Σ [1 / √(d(u) * d(v))] for all edges (u,v)",
"Balaban Index (J)": "J = (m / (q + 1)) Σ [1 / √(d(u) * d(v))]",
"Harary Index (H)": "H = Σ [1 / d(u,v)] for all pairs (u,v)",
"Atom-Bond Connectivity Index (ABC)": "ABC = Σ [(√d(u) + √d(v))/(d(u) + d(v))] for all edges (u,v)",
"Geometric Arithmetic Index (GA)": "GA = Σ [√(d(u) * d(v))] for all edges (u,v)",
"Harmonic Index (Harm)": "Harm = Σ [1 / d(v)] for all vertices v"
}

def solve_index(index, user_input):
try:
if index == "Wiener Index (W)":
distances = list(map(int, user_input.split(',')))
result = sum(distances)
steps = [
"1. **Extract the shortest path distances:**\n - Distances = " + f"{distances}",
"2. **Sum the distances:**\n - W = " + " + ".join(map(str, distances)) + f" = {result}"
]
output = "### **Wiener Index (W)**\n\n"
output += "**Formula:**\n" + formulas["Wiener Index (W)"] + "\n"
output += "Where d(u,v) is the shortest path distance between vertices u and v.\n\n"
output += "**Step-by-step solution:**\n\n" + "\n".join(steps) + "\n\n"
output += f"**Answer:** The Wiener Index W = {result}."
return output

elif index == "First Zagreb Index (M₁)":
degrees = list(map(int, user_input.split(',')))
squared_degrees = [d**2 for d in degrees]
result = sum(squared_degrees)
steps = [
"1. **Retrieve the vertex degrees:**\n - Degrees = " + f"{degrees}",
"2. **Square each degree:**\n - Squared degrees = " + f"{squared_degrees}",
"3. **Sum the squared degrees:**\n - M₁ = " + " + ".join(map(str, squared_degrees)) + f" = {result}"
]
output = "### **First Zagreb Index (M₁)**\n\n"
output += "**Formula:**\n" + formulas["First Zagreb Index (M₁)"] + "\n\n"
output += "**Step-by-step solution:**\n\n" + "\n".join(steps) + "\n\n"
output += f"**Answer:** The First Zagreb Index M₁ = {result}."
return output

elif index == "Second Zagreb Index (M₂)":
adj_degrees = [tuple(map(int, pair.split('-'))) for pair in user_input.split(',')]
products = [d1 * d2 for d1, d2 in adj_degrees]
result = sum(products)
steps = [
"1. **Extract the degree pairs for adjacent vertices:**\n - Pairs = " + f"{adj_degrees}",
"2. **Multiply each pair:**\n - Products = " + f"{products}",
"3. **Sum the products:**\n - M₂ = " + " + ".join(map(str, products)) + f" = {result}"
]
output = "### **Second Zagreb Index (M₂)**\n\n"
output += "**Formula:**\n" + formulas["Second Zagreb Index (M₂)"] + "\n"
output += "Where d(u) and d(v) are the degrees of adjacent vertices u and v.\n\n"
output += "**Step-by-step solution:**\n\n" + "\n".join(steps) + "\n\n"
output += f"**Answer:** The Second Zagreb Index M₂ = {result}."
return output

elif index == "Randić Index (R)":
edge_degrees = [tuple(map(int, pair.split('-'))) for pair in user_input.split(',')]
values = [1 / (d1 * d2) ** 0.5 for d1, d2 in edge_degrees]
result = sum(values)
steps = [
"1. **Extract the degree pairs for each edge:**\n - Edge pairs = " + f"{edge_degrees}"
]
for (d1, d2), v in zip(edge_degrees, values):
steps.append(f"2. **For edge {d1}-{d2}:**\n - 1/√({d1}×{d2}) = {v:.4f}")
steps.append("3. **Sum the values:**\n - R = " + " + ".join(f"{v:.4f}" for v in values) + f" = {result:.4f}")
output = "### **Randić Index (R)**\n\n"
output += "**Formula:**\n" + formulas["Randić Index (R)"] + "\n"
output += "Where the sum is taken over all edges (u,v) and d(u) and d(v) are their degrees.\n\n"
output += "**Step-by-step solution:**\n\n" + "\n".join(steps) + "\n\n"
output += f"**Answer:** The Randić Index R = {result:.4f}."
return output

elif index == "Balaban Index (J)":
parts = user_input.split(';')
if len(parts) < 3:
return "Invalid input format. Use m;q;edge pairs like 6;4;2-3,3-4."
m = int(parts[0])
q = int(parts[1])
edge_degrees = [tuple(map(int, pair.split('-'))) for pair in parts[2].split(',')]
values = [1 / (d1 * d2) ** 0.5 for d1, d2 in edge_degrees]
numerator = sum(values)
result = (m / (q + 1)) * numerator
steps = [
"1. **Extract parameters and edge pairs:**",
f" - m = {m}, q = {q}",
f" - Edge pairs = {edge_degrees}"
]
for (d1, d2), v in zip(edge_degrees, values):
steps.append(f"2. **For edge {d1}-{d2}:**\n - 1/√({d1}×{d2}) = {v:.4f}")
steps.append("3. **Sum the computed values:**\n - Sum = " + f"{numerator:.4f}")
steps.append("4. **Multiply by m/(q+1):**\n - J = ({m}/({q}+1)) × {numerator:.4f} = {result:.4f}")
output = "### **Balaban Index (J)**\n\n"
output += "**Formula:**\n" + formulas["Balaban Index (J)"] + "\n"
output += "Where m and q are given parameters and the sum is taken over all edges.\n\n"
output += "**Step-by-step solution:**\n\n" + "\n".join(steps) + "\n\n"
output += f"**Answer:** The Balaban Index J = {result:.4f}."
return output

elif index == "Harary Index (H)":
distances = list(map(int, user_input.split(',')))
values = [1 / d for d in distances if d > 0]
result = sum(values)
steps = [
"1. **Extract the shortest path distances:**\n - Distances = " + f"{distances}"
]
for d, v in zip(distances, values):
steps.append(f"2. **For distance {d}:**\n - 1/{d} = {v:.4f}")
steps.append("3. **Sum the reciprocals:**\n - H = " + " + ".join(f"{v:.4f}" for v in values) + f" = {result:.4f}")
output = "### **Harary Index (H)**\n\n"
output += "**Formula:**\n" + formulas["Harary Index (H)"] + "\n"
output += "Where d(u,v) is the shortest path distance between vertices u and v.\n\n"
output += "**Step-by-step solution:**\n\n" + "\n".join(steps) + "\n\n"
output += f"**Answer:** The Harary Index H = {result:.4f}."
return output

elif index == "Atom-Bond Connectivity Index (ABC)":
edge_degrees = [tuple(map(int, pair.split('-'))) for pair in user_input.split(',')]
values = [ ( (d1**0.5 + d2**0.5) / (d1 + d2) ) for d1, d2 in edge_degrees ]
result = sum(values)
steps = [
"1. **Extract the edge pairs:**\n - Pairs = " + f"{edge_degrees}"
]
for (d1, d2), v in zip(edge_degrees, values):
steps.append(f"2. **For edge {d1}-{d2}:**\n - (√{d1} + √{d2})/( {d1} + {d2} ) = {v:.4f}")
steps.append("3. **Sum the values:**\n - ABC = " + " + ".join(f"{v:.4f}" for v in values) + f" = {result:.4f}")
output = "### **Atom-Bond Connectivity Index (ABC)**\n\n"
output += "**Formula:**\n" + formulas["Atom-Bond Connectivity Index (ABC)"] + "\n\n"
output += "**Step-by-step solution:**\n\n" + "\n".join(steps) + "\n\n"
output += f"**Answer:** The ABC Index = {result:.4f}."
return output

elif index == "Geometric Arithmetic Index (GA)":
edge_degrees = [tuple(map(int, pair.split('-'))) for pair in user_input.split(',')]
values = [ (d1 * d2)**0.5 for d1, d2 in edge_degrees ]
result = sum(values)
steps = [
"1. **Extract the edge pairs:**\n - Pairs = " + f"{edge_degrees}"
]
for (d1, d2), v in zip(edge_degrees, values):
steps.append(f"2. **For edge {d1}-{d2}:**\n - √({d1}×{d2}) = {v:.4f}")
steps.append("3. **Sum the values:**\n - GA = " + " + ".join(f"{v:.4f}" for v in values) + f" = {result:.4f}")
output = "### **Geometric Arithmetic Index (GA)**\n\n"
output += "**Formula:**\n" + formulas["Geometric Arithmetic Index (GA)"] + "\n\n"
output += "**Step-by-step solution:**\n\n" + "\n".join(steps) + "\n\n"
output += f"**Answer:** The GA Index = {result:.4f}."
return output

elif index == "Harmonic Index (Harm)":
degrees = list(map(int, user_input.split(',')))
values = [1 / d for d in degrees]
result = sum(values)
steps = [
"1. **Extract the vertex degrees:**\n - Degrees = " + f"{degrees}"
]
for d, v in zip(degrees, values):
steps.append(f"2. **For degree {d}:**\n - 1/{d} = {v:.4f}")
steps.append("3. **Sum the reciprocals:**\n - Harm = " + " + ".join(f"{v:.4f}" for v in values) + f" = {result:.4f}")
output = "### **Harmonic Index (Harm)**\n\n"
output += "**Formula:**\n" + formulas["Harmonic Index (Harm)"] + "\n\n"
output += "**Step-by-step solution:**\n\n" + "\n".join(steps) + "\n\n"
output += f"**Answer:** The Harmonic Index = {result:.4f}."
return output

else:
return "Index not recognized."
except Exception as e:
return f"Error in processing input: {e}"

def update_input_placeholder(index):
placeholders = {
"Wiener Index (W)": "Enter shortest path d

Files changed (1) hide show
  1. app.py +43 -131
app.py CHANGED
@@ -1,25 +1,22 @@
 
1
  import subprocess
2
- import sys
3
 
4
- # Manually install required libraries (each installed separately)
5
- subprocess.check_call([sys.executable, "-m", "pip", "install", "gradio"])
6
- subprocess.check_call([sys.executable, "-m", "pip", "install", "networkx"])
7
- subprocess.check_call([sys.executable, "-m", "pip", "install", "matplotlib"])
8
- subprocess.check_call([sys.executable, "-m", "pip", "install", "numpy"])
9
- subprocess.check_call([sys.executable, "-m", "pip", "install", "scipy"])
10
 
11
- import os
12
- import math
13
- import itertools
 
 
 
 
 
14
  import numpy as np
15
- import networkx as nx
16
- import matplotlib.pyplot as plt
 
17
  import gradio as gr
18
- from scipy.spatial import distance
19
-
20
- # -------------------------------
21
- # Step-by-Step Index Calculation Functions
22
- # -------------------------------
23
 
24
  # Formulas for the indices (written in a typical mathematical style)
25
  formulas = {
@@ -83,7 +80,7 @@ def solve_index(index, user_input):
83
 
84
  elif index == "Randić Index (R)":
85
  edge_degrees = [tuple(map(int, pair.split('-'))) for pair in user_input.split(',')]
86
- values = [1 / (d1 * d2)**0.5 for d1, d2 in edge_degrees]
87
  result = sum(values)
88
  steps = [
89
  "1. **Extract the degree pairs for each edge:**\n - Edge pairs = " + f"{edge_degrees}"
@@ -105,7 +102,7 @@ def solve_index(index, user_input):
105
  m = int(parts[0])
106
  q = int(parts[1])
107
  edge_degrees = [tuple(map(int, pair.split('-'))) for pair in parts[2].split(',')]
108
- values = [1 / (d1 * d2)**0.5 for d1, d2 in edge_degrees]
109
  numerator = sum(values)
110
  result = (m / (q + 1)) * numerator
111
  steps = [
@@ -143,7 +140,7 @@ def solve_index(index, user_input):
143
 
144
  elif index == "Atom-Bond Connectivity Index (ABC)":
145
  edge_degrees = [tuple(map(int, pair.split('-'))) for pair in user_input.split(',')]
146
- values = [((d1**0.5 + d2**0.5) / (d1 + d2)) for d1, d2 in edge_degrees]
147
  result = sum(values)
148
  steps = [
149
  "1. **Extract the edge pairs:**\n - Pairs = " + f"{edge_degrees}"
@@ -159,7 +156,7 @@ def solve_index(index, user_input):
159
 
160
  elif index == "Geometric Arithmetic Index (GA)":
161
  edge_degrees = [tuple(map(int, pair.split('-'))) for pair in user_input.split(',')]
162
- values = [(d1 * d2)**0.5 for d1, d2 in edge_degrees]
163
  result = sum(values)
164
  steps = [
165
  "1. **Extract the edge pairs:**\n - Pairs = " + f"{edge_degrees}"
@@ -206,122 +203,37 @@ def update_input_placeholder(index):
206
  "Geometric Arithmetic Index (GA)": "Enter edge pairs (e.g., 2-3,3-4)",
207
  "Harmonic Index (Harm)": "Enter vertex degrees (e.g., 2,3,4)"
208
  }
 
209
  return placeholders[index], formulas.get(index, "")
210
 
211
- # -------------------------------
212
- # Graph Visualization Section
213
- # -------------------------------
214
-
215
- def parse_edges(edge_str):
216
- """Parses a comma-separated list of edges formatted as 'u-v' and returns a list of tuple edges."""
217
- try:
218
- edges = [tuple(map(int, e.strip().split("-"))) for e in edge_str.split(",") if e.strip() != ""]
219
- return edges
220
- except Exception as e:
221
- raise ValueError("Error parsing edges. Ensure format is 'u-v, x-y, ...'")
222
-
223
- def ensure_connectivity(G, pos):
224
- """If the graph is disconnected, connects the components using a minimum spanning tree on node positions."""
225
- if nx.is_connected(G):
226
- return G, pos
227
- components = list(nx.connected_components(G))
228
- for i in range(len(components) - 1):
229
- comp1 = components[i]
230
- comp2 = components[i + 1]
231
- min_dist = float('inf')
232
- best_pair = None
233
- for u in comp1:
234
- for v in comp2:
235
- d = distance.euclidean(pos[u], pos[v])
236
- if d < min_dist:
237
- min_dist = d
238
- best_pair = (u, v)
239
- if best_pair is not None:
240
- G.add_edge(*best_pair)
241
- return G, pos
242
-
243
- def draw_graph_from_edges(edge_str):
244
- """Constructs a graph from edge_str, ensures connectivity, and returns the saved image filename."""
245
- try:
246
- edges = parse_edges(edge_str)
247
- except Exception as e:
248
- return None, f"Error: {e}"
249
- nodes = set()
250
- for u, v in edges:
251
- nodes.update([u, v])
252
- G = nx.Graph()
253
- G.add_nodes_from(sorted(nodes))
254
- G.add_edges_from(edges)
255
- pos = nx.spring_layout(G, seed=42)
256
- G, pos = ensure_connectivity(G, pos)
257
- plt.figure(figsize=(6, 6))
258
- node_sizes = [300 + 100 * G.degree(n) for n in G.nodes()]
259
- nx.draw(G, pos, with_labels=True, node_color="lightblue", node_size=node_sizes, edge_color="gray", font_size=10)
260
- plt.title("Graph Visualization", fontsize=14)
261
- filename = "graph.png"
262
- plt.savefig(filename)
263
- plt.close()
264
- return filename, "Graph drawn successfully."
265
-
266
- # -------------------------------
267
- # Combined Function: Solve Index and Visualize Graph
268
- # -------------------------------
269
-
270
- def solve_index_and_visualize(index, user_input, custom_edges):
271
- """
272
- Computes the selected index step-by-step and, if custom_edges is provided,
273
- draws the corresponding graph. Returns the text explanation and the graph image.
274
- """
275
- explanation = solve_index(index, user_input)
276
- image_file = ""
277
- # Define which indices are graph-related (require edge-based inputs)
278
- graph_related = ["Randić Index (R)", "Balaban Index (J)", "Atom-Bond Connectivity Index (ABC)", "Geometric Arithmetic Index (GA)", "Harary Index (H)"]
279
- if custom_edges.strip() != "" and index in graph_related:
280
- img, msg = draw_graph_from_edges(custom_edges)
281
- if img is None:
282
- image_file = None
283
- explanation += "\n\n" + msg
284
- else:
285
- image_file = img
286
- explanation += "\n\nGraph visualization based on custom edges is provided below."
287
- else:
288
- explanation += "\n\n(No graph visualization available for the given input.)"
289
- return explanation, image_file
290
-
291
- # -------------------------------
292
- # Gradio Interface Setup
293
- # -------------------------------
294
 
295
  with gr.Blocks() as demo:
296
- gr.Markdown("# Topological Index Calculator with Graph Visualization")
297
-
298
- with gr.Row():
299
- index_dropdown = gr.Dropdown(choices=[
300
- "Wiener Index (W)",
301
- "First Zagreb Index (M₁)",
302
- "Second Zagreb Index (M₂)",
303
- "Randić Index (R)",
304
- "Balaban Index (J)",
305
- "Harary Index (H)",
306
- "Atom-Bond Connectivity Index (ABC)",
307
- "Geometric Arithmetic Index (GA)",
308
- "Harmonic Index (Harm)"
309
- ], label="Select an Index")
310
- formula_box = gr.Textbox(label="Formula", interactive=False)
311
-
312
- input_box = gr.Textbox(label="Enter Values", placeholder="For example, for Wiener: 3,4,5; for Zagreb M2: 2-3,3-4")
313
- custom_edges = gr.Textbox(label="Graph Edges (Optional)", placeholder="Format: 0-1,1-2,2-3")
314
-
315
- solve_button = gr.Button("Solve & Visualize")
316
- output_text = gr.Textbox(label="Step-by-Step Explanation", interactive=False, lines=15)
317
- output_graph = gr.Image(label="Graph Visualization", interactive=False)
318
-
319
- # When the dropdown changes, update the input placeholder and formula box.
320
  index_dropdown.change(fn=lambda index: update_input_placeholder(index),
321
  inputs=[index_dropdown],
322
  outputs=[input_box, formula_box])
323
- solve_button.click(fn=solve_index_and_visualize,
324
- inputs=[index_dropdown, input_box, custom_edges],
325
- outputs=[output_text, output_graph])
326
 
327
  demo.launch()
 
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("pandas")
10
+ install("torch")
11
+ install("transformers")
12
+ install("gradio") # Add any other required libraries here
13
+
14
+ # Now import the installed libraries
15
  import numpy as np
16
+ import pandas as pd
17
+ import torch
18
+ from transformers import AutoModel, AutoTokenizer
19
  import gradio as gr
 
 
 
 
 
20
 
21
  # Formulas for the indices (written in a typical mathematical style)
22
  formulas = {
 
80
 
81
  elif index == "Randić Index (R)":
82
  edge_degrees = [tuple(map(int, pair.split('-'))) for pair in user_input.split(',')]
83
+ values = [1 / (d1 * d2) ** 0.5 for d1, d2 in edge_degrees]
84
  result = sum(values)
85
  steps = [
86
  "1. **Extract the degree pairs for each edge:**\n - Edge pairs = " + f"{edge_degrees}"
 
102
  m = int(parts[0])
103
  q = int(parts[1])
104
  edge_degrees = [tuple(map(int, pair.split('-'))) for pair in parts[2].split(',')]
105
+ values = [1 / (d1 * d2) ** 0.5 for d1, d2 in edge_degrees]
106
  numerator = sum(values)
107
  result = (m / (q + 1)) * numerator
108
  steps = [
 
140
 
141
  elif index == "Atom-Bond Connectivity Index (ABC)":
142
  edge_degrees = [tuple(map(int, pair.split('-'))) for pair in user_input.split(',')]
143
+ values = [ ( (d1**0.5 + d2**0.5) / (d1 + d2) ) for d1, d2 in edge_degrees ]
144
  result = sum(values)
145
  steps = [
146
  "1. **Extract the edge pairs:**\n - Pairs = " + f"{edge_degrees}"
 
156
 
157
  elif index == "Geometric Arithmetic Index (GA)":
158
  edge_degrees = [tuple(map(int, pair.split('-'))) for pair in user_input.split(',')]
159
+ values = [ (d1 * d2)**0.5 for d1, d2 in edge_degrees ]
160
  result = sum(values)
161
  steps = [
162
  "1. **Extract the edge pairs:**\n - Pairs = " + f"{edge_degrees}"
 
203
  "Geometric Arithmetic Index (GA)": "Enter edge pairs (e.g., 2-3,3-4)",
204
  "Harmonic Index (Harm)": "Enter vertex degrees (e.g., 2,3,4)"
205
  }
206
+ # Also return the corresponding formula for the selected index.
207
  return placeholders[index], formulas.get(index, "")
208
 
209
+ # List of indices for the dropdown
210
+ index_options = [
211
+ "Wiener Index (W)",
212
+ "First Zagreb Index (M₁)",
213
+ "Second Zagreb Index (M₂)",
214
+ "Randić Index (R)",
215
+ "Balaban Index (J)",
216
+ "Harary Index (H)",
217
+ "Atom-Bond Connectivity Index (ABC)",
218
+ "Geometric Arithmetic Index (GA)",
219
+ "Harmonic Index (Harm)"
220
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
 
222
  with gr.Blocks() as demo:
223
+ gr.Markdown("## Topological Index Calculator\n\nSelect an index, view the formula, enter the required values, and click **Solve** to see a detailed, step-by-step solution with explanations.")
224
+ index_dropdown = gr.Dropdown(index_options, label="Select an Index")
225
+ # Create a formula box (read-only) to display the formula for the selected index.
226
+ formula_box = gr.Textbox(label="Formula", interactive=False)
227
+ input_box = gr.Textbox(label="Enter Values")
228
+ solve_button = gr.Button("Solve")
229
+ output_box = gr.Textbox(label="Step-by-Step Solution", interactive=False, lines=15)
230
+
231
+ # When the dropdown changes, update the input placeholder and the formula box.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  index_dropdown.change(fn=lambda index: update_input_placeholder(index),
233
  inputs=[index_dropdown],
234
  outputs=[input_box, formula_box])
235
+ solve_button.click(fn=solve_index,
236
+ inputs=[index_dropdown, input_box],
237
+ outputs=[output_box])
238
 
239
  demo.launch()