File size: 18,178 Bytes
e45ae96
06dd295
1368bc1
06dd295
e45ae96
 
06dd295
1368bc1
e45ae96
 
 
 
1368bc1
e45ae96
06dd295
e45ae96
 
 
06dd295
 
1368bc1
06dd295
1368bc1
 
 
 
 
 
 
 
 
 
 
 
 
06dd295
 
 
 
 
1368bc1
 
06dd295
 
1368bc1
 
06dd295
 
1368bc1
 
 
 
06dd295
 
 
1368bc1
 
 
06dd295
1368bc1
 
06dd295
 
 
1368bc1
 
 
06dd295
 
 
1368bc1
 
 
06dd295
 
1368bc1
 
 
06dd295
 
1368bc1
 
 
 
06dd295
 
 
1368bc1
 
 
06dd295
1368bc1
06dd295
1368bc1
 
06dd295
1368bc1
 
 
 
06dd295
 
1368bc1
 
 
 
 
 
06dd295
1368bc1
 
 
 
 
 
 
06dd295
 
1368bc1
 
 
 
 
 
 
 
06dd295
1368bc1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
06dd295
1368bc1
 
 
06dd295
1368bc1
 
 
 
 
06dd295
 
1368bc1
 
 
 
06dd295
 
1368bc1
 
06dd295
1368bc1
 
 
 
 
06dd295
 
1368bc1
 
 
 
06dd295
1368bc1
 
06dd295
1368bc1
 
 
 
 
06dd295
 
1368bc1
 
 
 
06dd295
 
1368bc1
 
06dd295
1368bc1
 
 
 
 
06dd295
 
 
 
 
 
 
 
 
1368bc1
06dd295
1368bc1
 
 
 
 
 
 
 
 
 
 
06dd295
1368bc1
06dd295
1368bc1
e45ae96
 
 
 
 
 
1368bc1
 
 
 
 
 
 
 
e45ae96
06dd295
 
1368bc1
e45ae96
 
 
 
1368bc1
e45ae96
1368bc1
06dd295
 
e45ae96
 
 
06dd295
 
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
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
import os
import subprocess
import math

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

# Install required libraries
install("numpy")
install("pandas")
install("torch")
install("transformers")
install("gradio")

import numpy as np
import pandas as pd
import torch
from transformers import AutoModel, AutoTokenizer
import gradio as gr

# Updated formulas in clear mathematical notation
formulas = {
    "Wiener Index (W)": "W = Σ₍u,v₎ d(u,v)\nwhere d(u,v) is the shortest path distance between vertices u and v.",
    "First Zagreb Index (M₁)": "M₁ = Σ₍v ∈ V(G)₎ deg(v)",
    "Second Zagreb Index (M₂)": "M₂ = Σ₍uv ∈ E(G)₎ [deg(u) × deg(v)]",
    "Randić Index (R)": "R = Σ₍uv ∈ E(G)₎ 1/√(deg(u) × deg(v))",
    "Atom-Bond Connectivity Index (ABC)": "ABC = Σ₍uv ∈ E(G)₎ √((deg(u) + deg(v) - 2)/(deg(u) × deg(v)))",
    "Augmented Zagreb Index (AZI)": "AZI = Σ₍uv ∈ E(G)₎ [ (deg(u) × deg(v))/(deg(u) + deg(v) - 2) ]³",
    "Geometric-Arithmetic Index (GA)": "GA = Σ₍uv ∈ E(G)₎ [2×√(deg(u)×deg(v))/(deg(u)+deg(v))]",
    "Sum-Connectivity Index (SCI)": "SCI = Σ₍uv ∈ E(G)₎ 1/√(deg(u) + deg(v))",
    "Harmonic Index (Harm)": "Harm = Σ₍uv ∈ E(G)₎ [2/(deg(u)+deg(v))]",
    "Gutman Index (Gut)": "Gut = Σ₍u,v, u<v₎ [deg(u) × deg(v) × d(u,v)]",
    "Eccentric Connectivity Index (ECI)": "ECI = Σ₍v ∈ V(G)₎ [deg(v) × ecc(v)]",
    "Total Eccentricity (TE)": "TE = Σ₍v ∈ V(G)₎ ecc(v)",
    "Harary Index (H)": "H = Σ₍u,v₎ 1/d(u,v)"
}

def solve_index(index, user_input):
    try:
        if index == "Wiener Index (W)":
            # Expected input: Comma-separated shortest-path distances, e.g. "1,1,1"
            distances = list(map(float, user_input.split(',')))
            result = sum(distances)
            steps = [
                f"1. **Extract the shortest-path distances:**  {distances}",
                f"2. **Sum all distances:**  " + " + ".join(map(str, distances)) + f" = {result}"
            ]
            output = "### **Wiener Index (W)**\n\n"
            output += "**Formula:**\n" + formulas["Wiener Index (W)"] + "\n\n"
            output += "**Required Input:** List of shortest-path distances between every vertex pair (comma-separated).\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** W = {result}."
            return output

        elif index == "First Zagreb Index (M₁)":
            # Expected input: Comma-separated vertex degrees, e.g. "2,3,4"
            degrees = list(map(float, user_input.split(',')))
            result = sum(degrees)
            steps = [
                f"1. **Vertex degrees:**  {degrees}",
                f"2. **Sum the degrees:**  " + " + ".join(map(str, degrees)) + f" = {result}"
            ]
            output = "### **First Zagreb Index (M₁)**\n\n"
            output += "**Formula:**\n" + formulas["First Zagreb Index (M₁)"] + "\n\n"
            output += "**Required Input:** List of vertex degrees (comma-separated).\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** M₁ = {result}."
            return output

        elif index == "Second Zagreb Index (M₂)":
            # Expected input: Comma-separated edge degree pairs, e.g. "2-3,3-2"
            edge_degrees = [tuple(map(float, pair.split('-'))) for pair in user_input.split(',')]
            products = [d1 * d2 for d1, d2 in edge_degrees]
            result = sum(products)
            steps = [
                f"1. **Edge degree pairs:**  {edge_degrees}",
                f"2. **Products:**  {products}",
                f"3. **Sum products:**  " + " + ".join(map(str, products)) + f" = {result}"
            ]
            output = "### **Second Zagreb Index (M₂)**\n\n"
            output += "**Formula:**\n" + formulas["Second Zagreb Index (M₂)"] + "\n\n"
            output += "**Required Input:** Edge degree pairs in the form d(u)-d(v) (comma-separated).\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** M₂ = {result}."
            return output

        elif index == "Randić Index (R)":
            # Expected input: Comma-separated edge degree pairs, e.g. "2-3,3-2"
            edge_degrees = [tuple(map(float, pair.split('-'))) for pair in user_input.split(',')]
            values = [1 / math.sqrt(d1 * d2) for d1, d2 in edge_degrees]
            result = sum(values)
            steps = [f"1. **Edge degree pairs:**  {edge_degrees}"]
            for (d1, d2), v in zip(edge_degrees, values):
                steps.append(f"2. **For edge {d1}-{d2}:** 1/√({d1}×{d2}) = {v:.4f}")
            steps.append("3. **Sum:**  " + " + ".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\n"
            output += "**Required Input:** Edge degree pairs (e.g., 2-3,3-2).\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** R = {result:.4f}."
            return output

        elif index == "Atom-Bond Connectivity Index (ABC)":
            # Expected input: Comma-separated edge degree pairs, e.g. "2-3,3-2"
            edge_degrees = [tuple(map(float, pair.split('-'))) for pair in user_input.split(',')]
            values = [ math.sqrt((d1 + d2 - 2) / (d1 * d2)) for d1, d2 in edge_degrees ]
            result = sum(values)
            steps = [f"1. **Edge degree pairs:**  {edge_degrees}"]
            for (d1, d2), v in zip(edge_degrees, values):
                steps.append(f"2. **For edge {d1}-{d2}:** √(({d1}+{d2}-2)/({d1}×{d2})) = {v:.4f}")
            steps.append("3. **Sum:**  " + " + ".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 += "**Required Input:** Edge degree pairs (e.g., 2-3,3-2).\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** ABC = {result:.4f}."
            return output

        elif index == "Augmented Zagreb Index (AZI)":
            # Expected input: Comma-separated edge degree pairs, e.g. "2-3,3-2"
            edge_degrees = [tuple(map(float, pair.split('-'))) for pair in user_input.split(',')]
            values = []
            for d1, d2 in edge_degrees:
                denominator = d1 + d2 - 2
                val = (d1 * d2 / denominator) ** 3 if denominator != 0 else 0
                values.append(val)
            result = sum(values)
            steps = [f"1. **Edge degree pairs:**  {edge_degrees}"]
            for (d1, d2), v in zip(edge_degrees, values):
                denominator = d1 + d2 - 2
                steps.append(f"2. **For edge {d1}-{d2}:** Compute ( {d1}×{d2} / ({d1}+{d2}-2) )³ with denominator={denominator}{v:.4f}")
            steps.append("3. **Sum:**  " + " + ".join(f"{v:.4f}" for v in values) + f" = {result:.4f}")
            output = "### **Augmented Zagreb Index (AZI)**\n\n"
            output += "**Formula:**\n" + formulas["Augmented Zagreb Index (AZI)"] + "\n\n"
            output += "**Required Input:** Edge degree pairs (e.g., 2-3,3-2); ensure (deg(u)+deg(v)-2) ≠ 0.\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** AZI = {result:.4f}."
            return output

        elif index == "Geometric-Arithmetic Index (GA)":
            # Expected input: Comma-separated edge degree pairs, e.g. "2-3,3-2"
            edge_degrees = [tuple(map(float, pair.split('-'))) for pair in user_input.split(',')]
            values = [ (2 * math.sqrt(d1 * d2))/(d1 + d2) for d1, d2 in edge_degrees ]
            result = sum(values)
            steps = [f"1. **Edge degree pairs:**  {edge_degrees}"]
            for (d1, d2), v in zip(edge_degrees, values):
                steps.append(f"2. **For edge {d1}-{d2}:**  2×√({d1}×{d2})/({d1}+{d2}) = {v:.4f}")
            steps.append("3. **Sum:**  " + " + ".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 += "**Required Input:** Edge degree pairs (e.g., 2-3,3-2).\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** GA = {result:.4f}."
            return output

        elif index == "Sum-Connectivity Index (SCI)":
            # Expected input: Comma-separated edge degree pairs, e.g. "2-3,3-2"
            edge_degrees = [tuple(map(float, pair.split('-'))) for pair in user_input.split(',')]
            values = [ 1 / math.sqrt(d1 + d2) for d1, d2 in edge_degrees ]
            result = sum(values)
            steps = [f"1. **Edge degree pairs:**  {edge_degrees}"]
            for (d1, d2), v in zip(edge_degrees, values):
                steps.append(f"2. **For edge {d1}-{d2}:**  1/√({d1}+{d2}) = {v:.4f}")
            steps.append("3. **Sum:**  " + " + ".join(f"{v:.4f}" for v in values) + f" = {result:.4f}")
            output = "### **Sum-Connectivity Index (SCI)**\n\n"
            output += "**Formula:**\n" + formulas["Sum-Connectivity Index (SCI)"] + "\n\n"
            output += "**Required Input:** Edge degree pairs (e.g., 2-3,3-2).\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** SCI = {result:.4f}."
            return output

        elif index == "Harmonic Index (Harm)":
            # Expected input: Comma-separated edge degree pairs, e.g. "2-3,3-2"
            edge_degrees = [tuple(map(float, pair.split('-'))) for pair in user_input.split(',')]
            values = [ 2 / (d1 + d2) for d1, d2 in edge_degrees ]
            result = sum(values)
            steps = [f"1. **Edge degree pairs:**  {edge_degrees}"]
            for (d1, d2), v in zip(edge_degrees, values):
                steps.append(f"2. **For edge {d1}-{d2}:**  2/({d1}+{d2}) = {v:.4f}")
            steps.append("3. **Sum:**  " + " + ".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 += "**Required Input:** Edge degree pairs (e.g., 2-3,3-2).\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** Harm = {result:.4f}."
            return output

        elif index == "Gutman Index (Gut)":
            # Expected input: Two lists separated by a semicolon.
            # First list: vertex degrees (comma-separated), e.g. "2,2,2"
            # Second list: distances for each unordered vertex pair in lex order (comma-separated), e.g. "1,1,1"
            parts = user_input.split(';')
            if len(parts) != 2:
                return "Invalid input. Use format: degrees;distances  e.g., 2,2,2;1,1,1"
            degrees = list(map(float, parts[0].strip().split(',')))
            distances = list(map(float, parts[1].strip().split(',')))
            # For n vertices the unordered pairs are n choose 2. Check count:
            n = len(degrees)
            if len(distances) != (n*(n-1))//2:
                return f"Invalid number of distances. For {n} vertices, you must provide {(n*(n-1))//2} distances."
            # Sum over pairs in lex order: pairs: (0,1), (0,2), ..., (n-2,n-1)
            total = 0
            pair_index = 0
            for i in range(n):
                for j in range(i+1, n):
                    total += degrees[i] * degrees[j] * distances[pair_index]
                    pair_index += 1
            steps = [
                f"1. **Vertex Degrees:**  {degrees}",
                f"2. **Distances for unordered pairs (in order):**  {distances}",
                f"3. **Computed Gutman sum:**  Gut = {total}"
            ]
            output = "### **Gutman Index (Gut)**\n\n"
            output += "**Formula:**\n" + formulas["Gutman Index (Gut)"] + "\n\n"
            output += "**Required Input:** Enter vertex degrees and distances as: `deg₁,deg₂,...,degₙ; d(1,2),d(1,3),...,d(n-1,n)`\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** Gut = {total}"
            return output

        elif index == "Eccentric Connectivity Index (ECI)":
            # Expected input: Comma-separated vertex pairs as "deg-ecc" (e.g., "2-1,3-1,2-1")
            pairs = [tuple(map(float, pair.split('-'))) for pair in user_input.split(',')]
            values = [deg * ecc for deg, ecc in pairs]
            result = sum(values)
            steps = [
                f"1. **Extract the (deg, ecc) pairs for vertices:**  {pairs}",
                f"2. **Multiply each pair:**  " + " + ".join(f"{deg}×{ecc}" for deg, ecc in pairs) + f" = {result}"
            ]
            output = "### **Eccentric Connectivity Index (ECI)**\n\n"
            output += "**Formula:**\n" + formulas["Eccentric Connectivity Index (ECI)"] + "\n\n"
            output += "**Required Input:** Enter each vertex as deg-ecc (comma-separated), e.g., 2-1,3-1,2-1\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** ECI = {result}"
            return output

        elif index == "Total Eccentricity (TE)":
            # Expected input: Comma-separated eccentricities of all vertices, e.g. "1,1,2"
            ecc_values = list(map(float, user_input.split(',')))
            result = sum(ecc_values)
            steps = [
                f"1. **Eccentricities:**  {ecc_values}",
                f"2. **Sum the eccentricities:**  " + " + ".join(map(str, ecc_values)) + f" = {result}"
            ]
            output = "### **Total Eccentricity (TE)**\n\n"
            output += "**Formula:**\n" + formulas["Total Eccentricity (TE)"] + "\n\n"
            output += "**Required Input:** List of vertex eccentricities (comma-separated), e.g., 1,1,2\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** TE = {result}"
            return output

        elif index == "Harary Index (H)":
            # Expected input: Comma-separated shortest-path distances, e.g. "1,1,1"
            distances = list(map(float, user_input.split(',')))
            values = [1/d for d in distances if d > 0]
            result = sum(values)
            steps = [
                f"1. **Shortest-path distances:**  {distances}",
                f"2. **Reciprocals:**  " + " + ".join(f"1/{d}" for d in distances if d > 0) + f" = {result:.4f}"
            ]
            output = "### **Harary Index (H)**\n\n"
            output += "**Formula:**\n" + formulas["Harary Index (H)"] + "\n\n"
            output += "**Required Input:** List of shortest-path distances between each vertex pair (comma-separated), e.g., 1,1,1\n\n"
            output += "**Step-by-step solution:**\n" + "\n".join(steps) + "\n\n"
            output += f"**Answer:** H = {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 distances (e.g., 1,1,1)",
        "First Zagreb Index (M₁)": "Enter vertex degrees (e.g., 2,3,4)",
        "Second Zagreb Index (M₂)": "Enter edge degree pairs (e.g., 2-3,3-2)",
        "Randić Index (R)": "Enter edge degree pairs (e.g., 2-3,3-2)",
        "Atom-Bond Connectivity Index (ABC)": "Enter edge degree pairs (e.g., 2-3,3-2)",
        "Augmented Zagreb Index (AZI)": "Enter edge degree pairs (e.g., 2-3,3-2)",
        "Geometric-Arithmetic Index (GA)": "Enter edge degree pairs (e.g., 2-3,3-2)",
        "Sum-Connectivity Index (SCI)": "Enter edge degree pairs (e.g., 2-3,3-2)",
        "Harmonic Index (Harm)": "Enter edge degree pairs (e.g., 2-3,3-2)",
        "Gutman Index (Gut)": "Enter degrees;distances (e.g., 2,2,2;1,1,1)",
        "Eccentric Connectivity Index (ECI)": "Enter deg-ecc pairs (e.g., 2-1,3-1,2-1)",
        "Total Eccentricity (TE)": "Enter eccentricities (e.g., 1,1,2)",
        "Harary Index (H)": "Enter distances (e.g., 1,1,1)"
    }
    return placeholders.get(index, "Enter input as required"), formulas.get(index, "")

# Updated list of indices for the dropdown
index_options = [
    "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)"
]

with gr.Blocks() as demo:
    gr.Markdown("## Topological Index Calculator\n\nSelect an index, review its formula, enter the required values as described, and click **Solve** to see a detailed, step-by-step solution.")
    index_dropdown = gr.Dropdown(index_options, label="Select an Index")
    formula_box = gr.Textbox(label="Formula", interactive=False)
    input_box = gr.Textbox(label="Enter Values")
    solve_button = gr.Button("Solve")
    output_box = gr.Textbox(label="Step-by-Step Solution", interactive=False, lines=20)

    index_dropdown.change(fn=lambda idx: update_input_placeholder(idx),
                          inputs=[index_dropdown],
                          outputs=[input_box, formula_box])
    solve_button.click(fn=solve_index,
                       inputs=[index_dropdown, input_box],
                       outputs=[output_box])

demo.launch()