summrs commited on
Commit
0819e52
Β·
verified Β·
1 Parent(s): f350df8

I have this code what libires I should use import gradio as gr
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from scipy.sparse.linalg import eigsh
from scipy.sparse import csgraph
import ast

# Helper Functions
def parse_graph_input(graph_input):
"""Parse user input to create an adjacency list."""
try:
# Try interpreting as a dictionary (adjacency list)
graph = ast.literal_eval(graph_input)
if isinstance(graph, dict):
return graph
except:
pass
try:
# Try interpreting as an edge list
edges = ast.literal_eval(graph_input)
if not isinstance(edges, list):
raise ValueError("Invalid graph input. Please use an adjacency list or edge list.")

graph = {}
for u, v in edges:
graph.setdefault(u, []).append(v)
graph.setdefault(v, []).append(u)
return graph
except:
raise ValueError("Invalid graph input. Please use a valid adjacency list or edge list.")

def visualize_graph(graph):
"""Generate a visualization of the graph using a circular layout."""
if len(graph) > 50: # Skip visualization for large graphs
return None

plt.figure()
nodes = list(graph.keys())
edges = [(u, v) for u in graph for v in graph[u]]

pos = nx.circular_layout(nx.Graph(edges))
nx.draw(
nx.Graph(edges),
pos,
with_labels=True,
node_color='lightblue',
edge_color='gray',
node_size=500,
font_size=10
)
return plt.gcf()

def calculate_spectrum(matrix, k=6, which='LM'):
"""Calculate the largest k eigenvalues of a sparse matrix."""
eigenvalues, _ = eigsh(matrix, k=k, which=which)
return sorted(eigenvalues.real)

def spectral_isomorphism_test(graph1, graph2):
"""Perform spectral isomorphism test with step-by-step explanation."""
adj_matrix1 = nx.adjacency_matrix(nx.Graph(graph1))
adj_matrix2 = nx.adjacency_matrix(nx.Graph(graph2))
lap_matrix1 = nx.laplacian_matrix(nx.Graph(graph1))
lap_matrix2 = nx.laplacian_matrix(nx.Graph(graph2))
adj_spectrum1 = calculate_spectrum(adj_matrix1, k=min(6, len(graph1) - 1))
adj_spectrum2 = calculate_spectrum(adj_matrix2, k=min(6, len(graph2) - 1))
lap_spectrum1 = calculate_spectrum(lap_matrix1, k=min(6, len(graph1) - 1), which='SM')
lap_spectrum2 = calculate_spectrum(lap_matrix2, k=min(6, len(graph2) - 1), which='SM')
adj_spectrum1 = [round(float(x), 2) for x in adj_spectrum1]
adj_spectrum2 = [round(float(x), 2) for x in adj_spectrum2]
lap_spectrum1 = [round(float(x), 2) for x in lap_spectrum1]
lap_spectrum2 = [round(float(x), 2) for x in lap_spectrum2]
output = (
f"### **Spectral Isomorphism Test Results**\n\n"

f"#### **Step 1: Node and Edge Counts**\n"
f"- **Graph 1**: Nodes: {len(graph1)}, Edges: {sum(len(neighbors) for neighbors in graph1.values()) // 2}\n"
f"- **Graph 2**: Nodes: {len(graph2)}, Edges: {sum(len(neighbors) for neighbors in graph2.values()) // 2}\n\n"

f"#### **Step 2: Adjacency Spectra**\n"
f"- Graph 1: {adj_spectrum1}\n"
f"- Graph 2: {adj_spectrum2}\n"
f"- Are the adjacency spectra approximately equal? {'βœ… Yes' if np.allclose(adj_spectrum1, adj_spectrum2) else '❌ No'}\n\n"

f"#### **Step 3: Laplacian Spectra**\n"
f"- Graph 1: {lap_spectrum1}\n"
f"- Graph 2: {lap_spectrum2}\n"
f"- Are the Laplacian spectra approximately equal? {'βœ… Yes' if np.allclose(lap_spectrum1, lap_spectrum2) else '❌ No'}\n\n"

f"#### **Final Result**\n"
f"- Outcome: {'βœ… PASS' if np.allclose(adj_spectrum1, adj_spectrum2) and np.allclose(lap_spectrum1, lap_spectrum2) else '❌ FAIL'}\n"
f"- Conclusion: The graphs are {'isomorphic' if np.allclose(adj_spectrum1, adj_spectrum2) and np.allclose(lap_spectrum1, lap_spectrum2) else 'NOT isomorphic'}.\n"
)
return output

def check_graph_homomorphism(graph1, graph2, mapping):
"""Check if a mapping defines a graph homomorphism."""
result = []
for u, v in graph1.edges():
mapped_u, mapped_v = mapping.get(u), mapping.get(v)
if mapped_u is None or mapped_v is None:
result.append(f"Mapping is incomplete. Missing vertex {u} or {v}.")
continue
if (mapped_u, mapped_v) not in graph2.edges() and (mapped_v, mapped_u) not in graph2.edges():
result.append(f"Edge ({u}, {v}) in Graph 1 maps to ({mapped_u}, {mapped_v}) in Graph 2. Edge does NOT exist in Graph 2.")
else:
result.append(f"Edge ({u}, {v}) in Graph 1 maps to ({mapped_u}, {mapped_v}) in Graph 2. Edge exists in Graph 2.")

is_homomorphism = all(("exists" in line) for line in result)
final_result = (
f"**Final Result:** {'βœ… Mapping IS a Graph Homomorphism.' if is_homomorphism else '❌ Mapping IS NOT a Graph Homomorphism.'}\n"
f"Explanation: A graph homomorphism must preserve all adjacencies. If any edge fails to map correctly, the mapping is invalid."
)
return "\n".join(result) + "\n\n" + final_result

def demonstrate_matrix_representations(graph):
"""Display adjacency matrix, Laplacian matrix, and spectra."""
adj_matrix = nx.adjacency_matrix(nx.Graph(graph)).todense()
laplacian_matrix = nx.laplacian_matrix(nx.Graph(graph)).todense()
degree_matrix = np.diag([len(graph[v]) for v in graph])

adj_spectrum = calculate_spectrum(nx.adjacency_matrix(nx.Graph(graph)), k=min(6, len(graph) - 1))
lap_spectrum = calculate_spectrum(nx.laplacian_matrix(nx.Graph(graph)), k=min(6, len(graph) - 1), which='SM')

algebraic_connectivity = lap_spectrum[1] if len(lap_spectrum) > 1 else 0 # Second smallest eigenvalue

output = (
f"### **Matrix Representations and Spectra**\n\n"

f"#### **Adjacency Matrix**\n"
f"```\n{adj_matrix}\n```\n\n"

f"#### **Laplacian Matrix**\n"
f"```\n{laplacian_matrix}\n```\n\n"

f"#### **Degree Matrix**\n"
f"```\n{degree_matrix}\n```\n\n"

f"#### **Adjacency Spectrum**\n"
f"```{[round(x, 2) for x in adj_spectrum]}```\n\n"

f"#### **Laplacian Spectrum**\n"
f"```{[round(x, 2) for x in lap_spectrum]}```\n\n"

f"#### **Algebraic Connectivity**\n"
f"The second smallest eigenvalue (Algebraic Connectivity): {round(algebraic_connectivity, 2)}\n\n"

f"**Explanation:** These matrices and spectra provide insights into the graph's structure. Algebraic connectivity measures robustness."
)
return output

def process_inputs(graph1_input, graph2_input, question_type, mapping=None):
"""Process user inputs and perform the selected operation."""
# Parse graphs
graph1 = parse_graph_input(graph1_input)
graph2 = parse_graph_input(graph2_input)
# Determine operation based on question type
if question_type == "Spectral Isomorphism Test":
result = spectral_isomorphism_test(graph1, graph2)
elif question_type == "Graph Homomorphism Check":
if mapping is None:
result = "Error: Mapping is required for Graph Homomorphism Check."
else:
result = check_graph_homomorphism(nx.Graph(graph1), nx.Graph(graph2), eval(mapping))
elif question_type == "Matrix Representations and Spectra":
result = demonstrate_matrix_representations(graph1)
else:
result = "Unsupported question type."
# Visualize graphs
graph1_plot = visualize_graph(graph1)
graph2_plot = visualize_graph(graph2)
return graph1_plot, graph2_plot, result

# Gradio Interface
with gr.Blocks(title="Graph Theory Project") as demo:
gr.Markdown("# Graph Theory Project")
gr.Markdown("Analyze graphs using algebraic methods!")
with gr.Row():
graph1_input = gr.Textbox(label="Graph 1 Input (e.g., '{0: [1], 1: [0, 2], 2: [1]}' or edge list)")
graph2_input = gr.Textbox(label="Graph 2 Input (e.g., '{0: [1], 1: [0, 2], 2: [1]}' or edge list)")
question_type = gr.Dropdown(
choices=["Spectral Isomorphism Test", "Graph Homomorphism Check", "Matrix Representations and Spectra"],
label="Select Question Type"
)
mapping_input = gr.Textbox(label="Mapping (for Graph Homomorphism Check, e.g., '{0: 0, 1: 1, 2: 2}')", visible=False)
def toggle_mapping_visibility(question_type):
return {"visible": question_type == "Graph Homomorphism Check"}
question_type.change(toggle_mapping_visibility, inputs=question_type, outputs=mapping_input)
with gr.Row():
graph1_output = gr.Plot(label="Graph 1 Visualization")
graph2_output = gr.Plot(label="Graph 2 Visualization")
result_output = gr.Textbox(label="Results", lines=20)
submit_button = gr.Button("Run")
submit_button.click(
lambda g1, g2, qt, m: process_inputs(g1, g2, qt, m),
inputs=[graph1_input, graph2_input, question_type, mapping_input],
outputs=[graph1_output, graph2_output, result_output]
)

# Launch the app with share=True to make it publicly accessible
demo.launch(share=True)

Files changed (1) hide show
  1. app.py +201 -0
app.py ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ I have this code what libires I should use import gradio as gr
2
+ import numpy as np
3
+ import matplotlib.pyplot as plt
4
+ import networkx as nx
5
+ from scipy.sparse.linalg import eigsh
6
+ from scipy.sparse import csgraph
7
+ import ast
8
+
9
+ # Helper Functions
10
+ def parse_graph_input(graph_input):
11
+ """Parse user input to create an adjacency list."""
12
+ try:
13
+ # Try interpreting as a dictionary (adjacency list)
14
+ graph = ast.literal_eval(graph_input)
15
+ if isinstance(graph, dict):
16
+ return graph
17
+ except:
18
+ pass
19
+ try:
20
+ # Try interpreting as an edge list
21
+ edges = ast.literal_eval(graph_input)
22
+ if not isinstance(edges, list):
23
+ raise ValueError("Invalid graph input. Please use an adjacency list or edge list.")
24
+
25
+ graph = {}
26
+ for u, v in edges:
27
+ graph.setdefault(u, []).append(v)
28
+ graph.setdefault(v, []).append(u)
29
+ return graph
30
+ except:
31
+ raise ValueError("Invalid graph input. Please use a valid adjacency list or edge list.")
32
+
33
+ def visualize_graph(graph):
34
+ """Generate a visualization of the graph using a circular layout."""
35
+ if len(graph) > 50: # Skip visualization for large graphs
36
+ return None
37
+
38
+ plt.figure()
39
+ nodes = list(graph.keys())
40
+ edges = [(u, v) for u in graph for v in graph[u]]
41
+
42
+ pos = nx.circular_layout(nx.Graph(edges))
43
+ nx.draw(
44
+ nx.Graph(edges),
45
+ pos,
46
+ with_labels=True,
47
+ node_color='lightblue',
48
+ edge_color='gray',
49
+ node_size=500,
50
+ font_size=10
51
+ )
52
+ return plt.gcf()
53
+
54
+ def calculate_spectrum(matrix, k=6, which='LM'):
55
+ """Calculate the largest k eigenvalues of a sparse matrix."""
56
+ eigenvalues, _ = eigsh(matrix, k=k, which=which)
57
+ return sorted(eigenvalues.real)
58
+
59
+ def spectral_isomorphism_test(graph1, graph2):
60
+ """Perform spectral isomorphism test with step-by-step explanation."""
61
+ adj_matrix1 = nx.adjacency_matrix(nx.Graph(graph1))
62
+ adj_matrix2 = nx.adjacency_matrix(nx.Graph(graph2))
63
+ lap_matrix1 = nx.laplacian_matrix(nx.Graph(graph1))
64
+ lap_matrix2 = nx.laplacian_matrix(nx.Graph(graph2))
65
+ adj_spectrum1 = calculate_spectrum(adj_matrix1, k=min(6, len(graph1) - 1))
66
+ adj_spectrum2 = calculate_spectrum(adj_matrix2, k=min(6, len(graph2) - 1))
67
+ lap_spectrum1 = calculate_spectrum(lap_matrix1, k=min(6, len(graph1) - 1), which='SM')
68
+ lap_spectrum2 = calculate_spectrum(lap_matrix2, k=min(6, len(graph2) - 1), which='SM')
69
+ adj_spectrum1 = [round(float(x), 2) for x in adj_spectrum1]
70
+ adj_spectrum2 = [round(float(x), 2) for x in adj_spectrum2]
71
+ lap_spectrum1 = [round(float(x), 2) for x in lap_spectrum1]
72
+ lap_spectrum2 = [round(float(x), 2) for x in lap_spectrum2]
73
+ output = (
74
+ f"### **Spectral Isomorphism Test Results**\n\n"
75
+
76
+ f"#### **Step 1: Node and Edge Counts**\n"
77
+ f"- **Graph 1**: Nodes: {len(graph1)}, Edges: {sum(len(neighbors) for neighbors in graph1.values()) // 2}\n"
78
+ f"- **Graph 2**: Nodes: {len(graph2)}, Edges: {sum(len(neighbors) for neighbors in graph2.values()) // 2}\n\n"
79
+
80
+ f"#### **Step 2: Adjacency Spectra**\n"
81
+ f"- Graph 1: {adj_spectrum1}\n"
82
+ f"- Graph 2: {adj_spectrum2}\n"
83
+ f"- Are the adjacency spectra approximately equal? {'βœ… Yes' if np.allclose(adj_spectrum1, adj_spectrum2) else '❌ No'}\n\n"
84
+
85
+ f"#### **Step 3: Laplacian Spectra**\n"
86
+ f"- Graph 1: {lap_spectrum1}\n"
87
+ f"- Graph 2: {lap_spectrum2}\n"
88
+ f"- Are the Laplacian spectra approximately equal? {'βœ… Yes' if np.allclose(lap_spectrum1, lap_spectrum2) else '❌ No'}\n\n"
89
+
90
+ f"#### **Final Result**\n"
91
+ f"- Outcome: {'βœ… PASS' if np.allclose(adj_spectrum1, adj_spectrum2) and np.allclose(lap_spectrum1, lap_spectrum2) else '❌ FAIL'}\n"
92
+ f"- Conclusion: The graphs are {'isomorphic' if np.allclose(adj_spectrum1, adj_spectrum2) and np.allclose(lap_spectrum1, lap_spectrum2) else 'NOT isomorphic'}.\n"
93
+ )
94
+ return output
95
+
96
+ def check_graph_homomorphism(graph1, graph2, mapping):
97
+ """Check if a mapping defines a graph homomorphism."""
98
+ result = []
99
+ for u, v in graph1.edges():
100
+ mapped_u, mapped_v = mapping.get(u), mapping.get(v)
101
+ if mapped_u is None or mapped_v is None:
102
+ result.append(f"Mapping is incomplete. Missing vertex {u} or {v}.")
103
+ continue
104
+ if (mapped_u, mapped_v) not in graph2.edges() and (mapped_v, mapped_u) not in graph2.edges():
105
+ result.append(f"Edge ({u}, {v}) in Graph 1 maps to ({mapped_u}, {mapped_v}) in Graph 2. Edge does NOT exist in Graph 2.")
106
+ else:
107
+ result.append(f"Edge ({u}, {v}) in Graph 1 maps to ({mapped_u}, {mapped_v}) in Graph 2. Edge exists in Graph 2.")
108
+
109
+ is_homomorphism = all(("exists" in line) for line in result)
110
+ final_result = (
111
+ f"**Final Result:** {'βœ… Mapping IS a Graph Homomorphism.' if is_homomorphism else '❌ Mapping IS NOT a Graph Homomorphism.'}\n"
112
+ f"Explanation: A graph homomorphism must preserve all adjacencies. If any edge fails to map correctly, the mapping is invalid."
113
+ )
114
+ return "\n".join(result) + "\n\n" + final_result
115
+
116
+ def demonstrate_matrix_representations(graph):
117
+ """Display adjacency matrix, Laplacian matrix, and spectra."""
118
+ adj_matrix = nx.adjacency_matrix(nx.Graph(graph)).todense()
119
+ laplacian_matrix = nx.laplacian_matrix(nx.Graph(graph)).todense()
120
+ degree_matrix = np.diag([len(graph[v]) for v in graph])
121
+
122
+ adj_spectrum = calculate_spectrum(nx.adjacency_matrix(nx.Graph(graph)), k=min(6, len(graph) - 1))
123
+ lap_spectrum = calculate_spectrum(nx.laplacian_matrix(nx.Graph(graph)), k=min(6, len(graph) - 1), which='SM')
124
+
125
+ algebraic_connectivity = lap_spectrum[1] if len(lap_spectrum) > 1 else 0 # Second smallest eigenvalue
126
+
127
+ output = (
128
+ f"### **Matrix Representations and Spectra**\n\n"
129
+
130
+ f"#### **Adjacency Matrix**\n"
131
+ f"```\n{adj_matrix}\n```\n\n"
132
+
133
+ f"#### **Laplacian Matrix**\n"
134
+ f"```\n{laplacian_matrix}\n```\n\n"
135
+
136
+ f"#### **Degree Matrix**\n"
137
+ f"```\n{degree_matrix}\n```\n\n"
138
+
139
+ f"#### **Adjacency Spectrum**\n"
140
+ f"```{[round(x, 2) for x in adj_spectrum]}```\n\n"
141
+
142
+ f"#### **Laplacian Spectrum**\n"
143
+ f"```{[round(x, 2) for x in lap_spectrum]}```\n\n"
144
+
145
+ f"#### **Algebraic Connectivity**\n"
146
+ f"The second smallest eigenvalue (Algebraic Connectivity): {round(algebraic_connectivity, 2)}\n\n"
147
+
148
+ f"**Explanation:** These matrices and spectra provide insights into the graph's structure. Algebraic connectivity measures robustness."
149
+ )
150
+ return output
151
+
152
+ def process_inputs(graph1_input, graph2_input, question_type, mapping=None):
153
+ """Process user inputs and perform the selected operation."""
154
+ # Parse graphs
155
+ graph1 = parse_graph_input(graph1_input)
156
+ graph2 = parse_graph_input(graph2_input)
157
+ # Determine operation based on question type
158
+ if question_type == "Spectral Isomorphism Test":
159
+ result = spectral_isomorphism_test(graph1, graph2)
160
+ elif question_type == "Graph Homomorphism Check":
161
+ if mapping is None:
162
+ result = "Error: Mapping is required for Graph Homomorphism Check."
163
+ else:
164
+ result = check_graph_homomorphism(nx.Graph(graph1), nx.Graph(graph2), eval(mapping))
165
+ elif question_type == "Matrix Representations and Spectra":
166
+ result = demonstrate_matrix_representations(graph1)
167
+ else:
168
+ result = "Unsupported question type."
169
+ # Visualize graphs
170
+ graph1_plot = visualize_graph(graph1)
171
+ graph2_plot = visualize_graph(graph2)
172
+ return graph1_plot, graph2_plot, result
173
+
174
+ # Gradio Interface
175
+ with gr.Blocks(title="Graph Theory Project") as demo:
176
+ gr.Markdown("# Graph Theory Project")
177
+ gr.Markdown("Analyze graphs using algebraic methods!")
178
+ with gr.Row():
179
+ graph1_input = gr.Textbox(label="Graph 1 Input (e.g., '{0: [1], 1: [0, 2], 2: [1]}' or edge list)")
180
+ graph2_input = gr.Textbox(label="Graph 2 Input (e.g., '{0: [1], 1: [0, 2], 2: [1]}' or edge list)")
181
+ question_type = gr.Dropdown(
182
+ choices=["Spectral Isomorphism Test", "Graph Homomorphism Check", "Matrix Representations and Spectra"],
183
+ label="Select Question Type"
184
+ )
185
+ mapping_input = gr.Textbox(label="Mapping (for Graph Homomorphism Check, e.g., '{0: 0, 1: 1, 2: 2}')", visible=False)
186
+ def toggle_mapping_visibility(question_type):
187
+ return {"visible": question_type == "Graph Homomorphism Check"}
188
+ question_type.change(toggle_mapping_visibility, inputs=question_type, outputs=mapping_input)
189
+ with gr.Row():
190
+ graph1_output = gr.Plot(label="Graph 1 Visualization")
191
+ graph2_output = gr.Plot(label="Graph 2 Visualization")
192
+ result_output = gr.Textbox(label="Results", lines=20)
193
+ submit_button = gr.Button("Run")
194
+ submit_button.click(
195
+ lambda g1, g2, qt, m: process_inputs(g1, g2, qt, m),
196
+ inputs=[graph1_input, graph2_input, question_type, mapping_input],
197
+ outputs=[graph1_output, graph2_output, result_output]
198
+ )
199
+
200
+ # Launch the app with share=True to make it publicly accessible
201
+ demo.launch(share=True)