Spaces:
Runtime error
Runtime error
| 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() | |