File size: 4,601 Bytes
fdfa161
f908f04
 
 
 
 
779056a
fdfa161
f908f04
 
 
 
779056a
f908f04
 
 
 
 
 
779056a
 
f908f04
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dbdfd6d
f908f04
dbdfd6d
f908f04
dbdfd6d
f908f04
 
 
 
 
 
 
 
 
779056a
 
f908f04
 
779056a
 
dbdfd6d
779056a
 
dbdfd6d
779056a
f908f04
dbdfd6d
 
779056a
 
f908f04
779056a
 
 
f908f04
 
 
779056a
f908f04
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
779056a
 
f908f04
dbdfd6d
779056a
f908f04
 
 
dbdfd6d
f908f04
779056a
f908f04
 
 
dbdfd6d
 
 
 
 
 
f908f04
 
 
dbdfd6d
f908f04
 
 
 
 
 
779056a
 
f908f04
779056a
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
import os
import subprocess

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

# Install dependencies
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):
    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":
        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":
        return sum(d**2 for _, d in graph.degree())
    elif index_type == "Zagreb Index M2":
        return sum(graph.degree(u) * graph.degree(v) for u, v in graph.edges())
    elif index_type == "Harary Index":
        return sum(1 / nx.shortest_path_length(graph, u, v) for u, v in itertools.combinations(graph.nodes(), 2))
    elif index_type == "Schultz Index":
        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":
        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":
        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":
        return graph.number_of_edges()
    else:
        return "Invalid Index Type"

# --- Graph Drawing Function ---

def draw_graph(graph, index_type, index_value):
    plt.figure(figsize=(6, 6))
    
    # Fixed layout for more consistent shapes
    pos = nx.spring_layout(graph, seed=42)

    # Draw only edges (no nodes, no labels)
    nx.draw_networkx_edges(graph, pos, edge_color="gray", width=2)

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

    filename = "graph.png"
    plt.savefig(filename, bbox_inches='tight')
    plt.close()
    return filename

# --- Main Logic ---

def process_graph(node_count, edge_count, index_type, custom_edges):
    G = nx.Graph()
    
    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.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 App ---

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()