Spaces:
Runtime error
Runtime error
File size: 17,251 Bytes
b39c815 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
import subprocess
import math
import gradio as gr
# Ensure required packages are installed
def install(package):
subprocess.check_call(["pip", "install", package])
install("gradio")
# =========================
# Mathematical Formulas (from the paper and our implementation)
# =========================
formulas = {
"Wiener Index (W)":
"W = Σ d(u,v)\nwhere d(u,v) is the shortest-path distance between every unordered pair of vertices.",
"First Zagreb Index (M₁)":
"M₁ = Σ [deg(v)] for v ∈ V(G)\n(This sums the degrees of all vertices.)",
"Second Zagreb Index (M₂)":
"M₂ = Σ [deg(u) × deg(v)] for each edge uv ∈ E(G)\n(This sums the product of the degrees for each edge.)",
"Randić Index (R)":
"R = Σ [1 / √(deg(u) × deg(v))] for each edge uv ∈ E(G)\n(This measures connectivity by using the inverse square root of vertex degree products.)",
"Atom-Bond Connectivity Index (ABC)":
"ABC = Σ √((deg(u)+deg(v)-2)/(deg(u)×deg(v))) for each edge uv ∈ E(G)\n(This index relates to the molecular stability in chemical graphs.)",
"Augmented Zagreb Index (AZI)":
"AZI = Σ [(deg(u)×deg(v))/(deg(u)+deg(v)-2)]³ for each edge uv ∈ E(G)\n(This index amplifies the contribution of high-degree vertices.)",
"Geometric-Arithmetic Index (GA)":
"GA = Σ [2×√(deg(u)×deg(v))/(deg(u)+deg(v))] for each edge uv ∈ E(G)\n(This index blends the geometric and arithmetic means of vertex degrees.)",
"Sum-Connectivity Index (SCI)":
"SCI = Σ [1/√(deg(u)+deg(v))] for each edge uv ∈ E(G)\n(This index focuses on the sum of the degrees.)",
"Harmonic Index (Harm)":
"Harm = Σ [2/(deg(u)+deg(v))] for each edge uv ∈ E(G)\n(A measure emphasizing balanced degrees.)",
"Gutman Index (Gut)":
"Gut = Σ [deg(u)×deg(v)×d(u,v)] for every unordered pair u,v\n(This index combines connectivity with distance information.)",
"Eccentric Connectivity Index (ECI)":
"ECI = Σ [deg(v)×ecc(v)] for every vertex v\n(Here, ecc(v) is the maximum distance from v to any other vertex.)",
"Total Eccentricity (TE)":
"TE = Σ [ecc(v)] for every vertex v\n(This sums the eccentricity of each vertex.)",
"Harary Index (H)":
"H = Σ [1/d(u,v)] for every unordered pair u,v\n(This sums the reciprocals of distances for each vertex pair.)"
}
# ==========================
# Functions to update which input groups are visible based on the selected index
# ==========================
def update_inputs(selected_index):
# Indices that use vertex-based values only: M₁, TE, ECI.
vertex_vis = selected_index in ["First Zagreb Index (M₁)", "Total Eccentricity (TE)",
"Eccentric Connectivity Index (ECI)"]
# Indices that use edge-based inputs: M₂, R, ABC, AZI, GA, SCI, Harm.
edge_vis = selected_index in ["Second Zagreb Index (M₂)",
"Randić Index (R)",
"Atom-Bond Connectivity Index (ABC)",
"Augmented Zagreb Index (AZI)",
"Geometric-Arithmetic Index (GA)",
"Sum-Connectivity Index (SCI)",
"Harmonic Index (Harm)"]
# Gutman index uses its own group.
gutman_vis = (selected_index == "Gutman Index (Gut)")
# Wiener and Harary indices use distance inputs.
distance_vis = selected_index in ["Wiener Index (W)", "Harary Index (H)"]
return (
gr.update(visible=vertex_vis),
gr.update(visible=edge_vis),
gr.update(visible=gutman_vis),
gr.update(visible=distance_vis)
)
# ==========================
# Calculation Functions
# (For simplicity, we assume a triangle graph with 3 vertices, 3 edges, and 3 unordered pairs.)
# ==========================
def solve_index(selected_index, vertex_deg1, vertex_deg2, vertex_deg3,
vertex_ecc1, vertex_ecc2, vertex_ecc3,
edge1_a, edge1_b, edge2_a, edge2_b, edge3_a, edge3_b,
gutman_degs, gutman_dists,
distance1, distance2, distance3):
try:
# -----------------------
# Vertex-based Calculations
# -----------------------
if selected_index == "First Zagreb Index (M₁)":
degrees = [vertex_deg1, vertex_deg2, vertex_deg3]
result = sum(degrees)
steps = [
f"Step 1: Record the degree of each vertex: {degrees}.",
f"Step 2: Sum all vertex degrees since M₁ is defined as Σ deg(v): {degrees[0]} + {degrees[1]} + {degrees[2]} = {result}."
]
return f"### First Zagreb Index (M₁)\n{formulas[selected_index]}\n\nDetailed Steps:\n" + "\n".join(steps)
elif selected_index == "Total Eccentricity (TE)":
ecc = [vertex_ecc1, vertex_ecc2, vertex_ecc3]
result = sum(ecc)
steps = [
f"Step 1: Record the eccentricity (maximum distance) for each vertex: {ecc}.",
f"Step 2: Sum all eccentricities since TE is defined as Σ ecc(v): {ecc[0]} + {ecc[1]} + {ecc[2]} = {result}."
]
return f"### Total Eccentricity (TE)\n{formulas[selected_index]}\n\nDetailed Steps:\n" + "\n".join(steps)
elif selected_index == "Eccentric Connectivity Index (ECI)":
pairs = [(vertex_deg1, vertex_ecc1), (vertex_deg2, vertex_ecc2), (vertex_deg3, vertex_ecc3)]
contributions = [d * e for d, e in pairs]
result = sum(contributions)
steps = [
f"Step 1: For each vertex, record the pair (degree, eccentricity): {pairs}.",
f"Step 2: Multiply the degree and eccentricity for each vertex: {contributions} (because ECI = Σ [deg(v)×ecc(v)]).",
f"Step 3: Sum these products: {contributions[0]} + {contributions[1]} + {contributions[2]} = {result}."
]
return f"### Eccentric Connectivity Index (ECI)\n{formulas[selected_index]}\n\nDetailed Steps:\n" + "\n".join(steps)
# -----------------------
# Edge-based Calculations
# -----------------------
elif selected_index in ["Second Zagreb Index (M₂)", "Randić Index (R)",
"Atom-Bond Connectivity Index (ABC)", "Augmented Zagreb Index (AZI)",
"Geometric-Arithmetic Index (GA)", "Sum-Connectivity Index (SCI)",
"Harmonic Index (Harm)"]:
edges = [(edge1_a, edge1_b), (edge2_a, edge2_b), (edge3_a, edge3_b)]
if selected_index == "Second Zagreb Index (M₂)":
products = [a * b for a, b in edges]
result = sum(products)
steps = [
f"Step 1: Each edge connects two vertices with degrees as given: {edges}.",
f"Step 2: For each edge, multiply the degrees: {products} (since M₂ sums the product for each edge).",
f"Step 3: Sum these products: {products[0]} + {products[1]} + {products[2]} = {result}."
]
elif selected_index == "Randić Index (R)":
values = [1 / math.sqrt(a * b) for a, b in edges]
result = sum(values)
steps = [
f"Step 1: Record the degree pairs for each edge: {edges}.",
f"Step 2: For each edge, compute 1/√(deg(u)×deg(v)): {['{:.4f}'.format(v) for v in values]}.",
f"Step 3: Sum these values to obtain R: {result:.4f}."
]
elif selected_index == "Atom-Bond Connectivity Index (ABC)":
values = [math.sqrt((a + b - 2) / (a * b)) for a, b in edges]
result = sum(values)
steps = [
f"Step 1: For each edge, note the degree pair: {edges}.",
f"Step 2: Compute √((deg(u)+deg(v)-2)/(deg(u)×deg(v))) for each edge: {['{:.4f}'.format(v) for v in values]}.",
f"Step 3: Sum the results: {result:.4f}."
]
elif selected_index == "Augmented Zagreb Index (AZI)":
values = []
for a, b in edges:
denom = a + b - 2
val = (a * b / denom) ** 3 if denom != 0 else 0
values.append(val)
result = sum(values)
steps = [
f"Step 1: For each edge, record degrees: {edges}.",
f"Step 2: For each, compute ( (deg(u)×deg(v))/(deg(u)+deg(v)-2) )³: {['{:.4f}'.format(v) for v in values]}.",
f"Step 3: Sum these values: {result:.4f}."
]
elif selected_index == "Geometric-Arithmetic Index (GA)":
values = [(2 * math.sqrt(a * b))/(a + b) for a, b in edges]
result = sum(values)
steps = [
f"Step 1: Record edge degree pairs: {edges}.",
f"Step 2: For each edge, calculate 2×√(deg(u)×deg(v))/(deg(u)+deg(v)): {['{:.4f}'.format(v) for v in values]}.",
f"Step 3: Sum to obtain GA: {result:.4f}."
]
elif selected_index == "Sum-Connectivity Index (SCI)":
values = [1 / math.sqrt(a + b) for a, b in edges]
result = sum(values)
steps = [
f"Step 1: Note the degree pairs for each edge: {edges}.",
f"Step 2: For each edge, compute 1/√(deg(u)+deg(v)): {['{:.4f}'.format(v) for v in values]}.",
f"Step 3: Sum the computed values to get SCI: {result:.4f}."
]
elif selected_index == "Harmonic Index (Harm)":
values = [2 / (a + b) for a, b in edges]
result = sum(values)
steps = [
f"Step 1: Record the edge degree pairs: {edges}.",
f"Step 2: For each edge, compute 2/(deg(u)+deg(v)): {['{:.4f}'.format(v) for v in values]}.",
f"Step 3: Sum these values for the final Harmonic Index: {result:.4f}."
]
return f"### {selected_index}\n{formulas[selected_index]}\n\nDetailed Steps:\n" + "\n".join(steps)
# -----------------------
# Gutman Index: Requires vertex degrees and distances
# -----------------------
elif selected_index == "Gutman Index (Gut)":
degs = [float(x) for x in gutman_degs.split(',')]
dists = [float(x) for x in gutman_dists.split(',')]
# For a triangle, the unordered pairs are (1,2), (1,3), and (2,3)
total = degs[0]*degs[1]*dists[0] + degs[0]*degs[2]*dists[1] + degs[1]*degs[2]*dists[2]
steps = [
f"Step 1: The vertex degrees are recorded as: {degs}.",
f"Step 2: The shortest-path distances for unordered vertex pairs (1,2), (1,3), and (2,3) are: {dists}.",
f"Step 3: For each pair, multiply deg(u)×deg(v)×d(u,v):",
f" For (1,2): {degs[0]}×{degs[1]}×{dists[0]} = {degs[0]*degs[1]*dists[0]},",
f" For (1,3): {degs[0]}×{degs[2]}×{dists[1]} = {degs[0]*degs[2]*dists[1]},",
f" For (2,3): {degs[1]}×{degs[2]}×{dists[2]} = {degs[1]*degs[2]*dists[2]}.",
f"Step 4: Sum all products: {total}."
]
return f"### Gutman Index (Gut)\n{formulas[selected_index]}\n\nDetailed Steps:\n" + "\n".join(steps)
# -----------------------
# Distance-based: Wiener and Harary indices
# -----------------------
elif selected_index in ["Wiener Index (W)", "Harary Index (H)"]:
dists = [distance1, distance2, distance3]
if selected_index == "Wiener Index (W)":
result = sum(dists)
steps = [
f"Step 1: Record the shortest-path distances for each unordered pair: {dists}.",
f"Step 2: Sum all distances: {dists[0]} + {dists[1]} + {dists[2]} = {result}."
]
return f"### Wiener Index (W)\n{formulas[selected_index]}\n\nDetailed Steps:\n" + "\n".join(steps)
else: # Harary Index (H)
values = [1/d if d != 0 else 0 for d in dists]
result = sum(values)
steps = [
f"Step 1: Record the shortest-path distances: {dists}.",
f"Step 2: Compute the reciprocal for each distance (1/d): {['{:.4f}'.format(1/d) if d!=0 else 'undefined' for d in dists]}.",
f"Step 3: Sum these reciprocals: {result:.4f}."
]
return f"### Harary Index (H)\n{formulas[selected_index]}\n\nDetailed Steps:\n" + "\n".join(steps)
else:
return "Index not recognized."
except Exception as e:
return f"Error: {e}"
# ==========================
# Build the Gradio Interface with Dynamic Input Groups
# ==========================
with gr.Blocks() as demo:
gr.Markdown("## Topological Index Calculator\n\nSelect an index and enter the required values in the relevant fields. The fields below will change based on the chosen index. (For illustration, this example uses a fixed triangle graph with 3 vertices, 3 edges, and 3 unordered pairs.)")
index_dropdown = gr.Dropdown(
label="Select an Index",
choices=[
"Wiener Index (W)",
"First Zagreb Index (M₁)",
"Second Zagreb Index (M₂)",
"Randić Index (R)",
"Atom-Bond Connectivity Index (ABC)",
"Augmented Zagreb Index (AZI)",
"Geometric-Arithmetic Index (GA)",
"Sum-Connectivity Index (SCI)",
"Harmonic Index (Harm)",
"Gutman Index (Gut)",
"Eccentric Connectivity Index (ECI)",
"Total Eccentricity (TE)",
"Harary Index (H)"
]
)
# Group 1: Vertex-based inputs (for M₁, TE, ECI)
with gr.Group(visible=False) as vertex_group:
gr.Markdown("### Vertex Inputs\nEnter the degree and/or eccentricity for each vertex.")
vertex_deg1 = gr.Number(label="Vertex 1 Degree", value=2)
vertex_deg2 = gr.Number(label="Vertex 2 Degree", value=2)
vertex_deg3 = gr.Number(label="Vertex 3 Degree", value=2)
vertex_ecc1 = gr.Number(label="Vertex 1 Eccentricity", value=1)
vertex_ecc2 = gr.Number(label="Vertex 2 Eccentricity", value=1)
vertex_ecc3 = gr.Number(label="Vertex 3 Eccentricity", value=1)
# Group 2: Edge-based inputs (for M₂, R, ABC, AZI, GA, SCI, Harm)
with gr.Group(visible=False) as edge_group:
gr.Markdown("### Edge Inputs\nFor each edge, enter the degree of each end vertex.")
with gr.Row():
edge1_a = gr.Number(label="Edge 1: Vertex A Degree", value=2)
edge1_b = gr.Number(label="Edge 1: Vertex B Degree", value=2)
with gr.Row():
edge2_a = gr.Number(label="Edge 2: Vertex A Degree", value=2)
edge2_b = gr.Number(label="Edge 2: Vertex B Degree", value=2)
with gr.Row():
edge3_a = gr.Number(label="Edge 3: Vertex A Degree", value=2)
edge3_b = gr.Number(label="Edge 3: Vertex B Degree", value=2)
# Group 3: Gutman inputs (for Gutman Index)
with gr.Group(visible=False) as gutman_group:
gr.Markdown("### Gutman Index Inputs\nEnter vertex degrees and the distances for each unordered vertex pair.")
gutman_degs = gr.Textbox(label="Vertex Degrees (comma-separated)", value="2,2,2")
gutman_dists = gr.Textbox(label="Distances for pairs ((1,2), (1,3), (2,3)) (comma-separated)", value="1,1,1")
# Group 4: Distance-based inputs (for Wiener and Harary indices)
with gr.Group(visible=False) as distance_group:
gr.Markdown("### Distance Inputs\nEnter the shortest-path distance for each unordered vertex pair.")
distance1 = gr.Number(label="Distance for Pair 1", value=1)
distance2 = gr.Number(label="Distance for Pair 2", value=1)
distance3 = gr.Number(label="Distance for Pair 3", value=1)
output_box = gr.Textbox(label="Step-by-Step Detailed Solution", lines=20)
solve_btn = gr.Button("Solve")
# Update input group visibility when index is selected
index_dropdown.change(fn=update_inputs,
inputs=index_dropdown,
outputs=[vertex_group, edge_group, gutman_group, distance_group])
# Run calculations when Solve is clicked
solve_btn.click(fn=solve_index,
inputs=[index_dropdown,
vertex_deg1, vertex_deg2, vertex_deg3,
vertex_ecc1, vertex_ecc2, vertex_ecc3,
edge1_a, edge1_b, edge2_a, edge2_b, edge3_a, edge3_b,
gutman_degs, gutman_dists,
distance1, distance2, distance3],
outputs=output_box)
demo.launch()
|