summrs commited on
Commit
fa40aaf
·
verified ·
1 Parent(s): 6cf8f94

import subprocess
import sys

# Function to install dependencies if not already installed
def install_dependencies():
required_libraries = [
"matplotlib",
"numpy",
"sympy",
"google-generativeai",
]
for library in required_libraries:
try:
__import__(library)
except ImportError:
print(f"Installing {library}...")
subprocess.check_call([sys.executable, "-m", "pip", "install", library])

# Install dependencies before proceeding
install_dependencies()

# Import libraries after ensuring they are installed
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
from sympy import symbols, Eq, solve, re, im
import google.generativeai as genai

# Initialize Gemini API
API_KEY = "AIzaSyCsC6o08neNA3AipT-iP7qSJUWfqjbpSRI" # Replace with your API key
genai.configure(api_key=API_KEY)
model = genai.GenerativeModel('gemini-pro') # Use the Gemini Pro model

# Initialize GUI window
root = tk.Tk()
root.title("Graph Theory AI with Gemini Integration")
root.geometry("1200x800") # Increase window size for better layout
root.configure(bg='#2c3e50')

# Graph Setup
fig, ax = plt.subplots(figsize=(6, 5))
ax.set_facecolor("white") # Set background color
ax.set_xticks(np.arange(-10, 11, 1)) # Add numbers for X-axis
ax.set_yticks(np.arange(-10, 11, 1)) # Add numbers for Y-axis
ax.grid(True, linestyle='-', linewidth=0.5, color='gray') # Add gridlines
ax.axhline(0, color='black', linewidth=1) # Horizontal axis line
ax.axvline(0, color='black', linewidth=1) # Vertical axis line
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

points = [] # Stores user input points
annotations = [] # Stores text annotations for roots

# Smaller and Better-Designed Explanation Box
explanation_frame = tk.Frame(root, bg='#ecf0f1', padx=10, pady=10, relief=tk.RIDGE, borderwidth=2)
explanation_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=10, pady=10)
explanation_label = tk.Label(explanation_frame, text="Explanation:", font=("Arial", 12, "bold"), bg='#ecf0f1', fg='#2c3e50')
explanation_label.pack(anchor=tk.W)
explanation_text = tk.Text(explanation_frame, height=8, width=35, wrap=tk.WORD, font=("Arial", 10), bg='#ffffff', fg='#2c3e50', relief=tk.FLAT)
explanation_text.pack(fill=tk.BOTH, expand=True)

# --- Graph Plotting Function ---
def plot_point():
try:
x = float(entry_x.get())
y = float(entry_y.get())
points.append((x, y))

# Plot all points
if len(points) > 1:
# Extract x and y coordinates from points
x_vals, y_vals = zip(*points)
ax.clear()
ax.set_facecolor("white") # Retain background color
ax.set_xticks(np.arange(-10, 11, 1)) # Retain X-axis numbers
ax.set_yticks(np.arange(-10, 11, 1)) # Retain Y-axis numbers
ax.grid(True, linestyle='-', linewidth=0.5, color='gray') # Retain gridlines
ax.axhline(0, color='black', linewidth=1) # Retain horizontal axis line
ax.axvline(0, color='black', linewidth=1) # Retain vertical axis line
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.plot(x_vals, y_vals, 'bo-', markersize=8, linewidth=2) # Connect points with a line
else:
ax.plot(x, y, 'bo', markersize=8) # Single point (no line yet)

canvas.draw()
entry_x.delete(0, tk.END) # Clear input fields
entry_y.delete(0, tk.END)
except ValueError:
messagebox.showerror("Error", "Enter valid numbers for x and y")

# --- Clear Graph Function ---
def clear_graph():
global points, annotations
points = []

# Remove all plotted elements (points, lines, etc.)
for artist in ax.lines + ax.collections: # Remove lines and scatter points
artist.remove()

# Remove all text annotations (roots)
for annotation in annotations:
annotation.remove()
annotations.clear()

# Ensure the background, gridlines, and axis numbers remain intact
ax.set_facecolor("white") # Retain background color
ax.set_xticks(np.arange(-10, 11, 1)) # Retain X-axis numbers
ax.set_yticks(np.arange(-10, 11, 1)) # Retain Y-axis numbers
ax.grid(True, linestyle='-', linewidth=0.5, color='gray') # Retain gridlines
ax.axhline(0, color='black', linewidth=1) # Retain horizontal axis line
ax.axvline(0, color='black', linewidth=1) # Retain vertical axis line
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)

# Clear the explanation box
explanation_text.delete(1.0, tk.END)

canvas.draw()

# --- Solve Graph Equation ---
def solve_graph_equation():
equation_str = equation_entry.get()
if not equation_str:
messagebox.showerror("Error", "Please enter an equation.")
return

try:
# Parse the equation using SymPy
x = symbols('x')
y_expr = eval(equation_str, {"x": x}) # Safely evaluate the equation string
solutions = solve(Eq(y_expr, 0), x) # Solve for roots

# Generate points for plotting
x_vals = np.linspace(-10, 10, 500)
y_vals = [y_expr.subs(x, xi) for xi in x_vals] # Evaluate the equation at each x value

# Clear previous plots
for artist in ax.lines + ax.collections: # Remove lines and scatter points
artist.remove()

# Remove all text annotations (roots)
for annotation in annotations:
annotation.remove()
annotations.clear()

# Retain the background, gridlines, and axis numbers
ax.set_facecolor("white") # Retain background color
ax.set_xticks(np.arange(-10, 11, 1)) # Retain X-axis numbers
ax.set_yticks(np.arange(-10, 11, 1)) # Retain Y-axis numbers
ax.grid(True, linestyle='-', linewidth=0.5, color='gray') # Retain gridlines
ax.axhline(0, color='black', linewidth=1) # Retain horizontal axis line
ax.axvline(0, color='black', linewidth=1) # Retain vertical axis line
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)

# Plot the equation
ax.plot(x_vals, y_vals, label=f"y = {equation_str}", color='blue', linewidth=2)

# Filter real roots and highlight them on the graph
real_solutions = []
for sol in solutions:
if im(sol) == 0: # Check if the solution is real
real_solutions.append(sol)
ax.plot(sol, 0, 'ro', markersize=8) # Mark roots with red dots
annotation = ax.text(sol, 0.5, f"({sol:.2f}, 0)", fontsize=10, ha='center') # Label roots
annotations.append(annotation)

ax.legend(loc="upper right")
canvas.draw()

# Automatically refresh the explanation box
explanation_text.delete(1.0, tk.END)
explanation_text.insert(tk.END, f"Equation: y = {equation_str}\n\n")
if real_solutions:
explanation_text.insert(tk.END, f"Solutions (real roots): {real_solutions}\n")
explanation_text.insert(tk.END, "\nExplanation:\nThe equation was solved by finding the values of x where y = 0.\n")
explanation_text.insert(tk.END, "The graph shows the curve of the equation and highlights the real roots on the x-axis.")
else:
explanation_text.insert(tk.END, "No real roots found.\n")
explanation_text.insert(tk.END, "\nExplanation:\nThe equation has no real solutions. All roots are complex numbers.")

except SyntaxError:
messagebox.showerror("Error", "Invalid syntax in the equation. Please check your input.")
except NameError:
messagebox.showerror("Error", "Undefined variable in the equation. Use 'x' as the variable.")
except Exception as e:
messagebox.showerror("Error", f"Failed to solve or plot the equation: {e}")

# --- Ask the AI Anything ---
def ask_ai():
question = ai_question.get("1.0", tk.END).strip() # Get the user's question
if not question:
messagebox.showerror("Error", "Please enter a question for the AI.")
return

try:
# Query the Gemini API
response = model.generate_content(question)
ai_response = response.text.strip()

# Display the AI's response in the output box
ai_output.config(state=tk.NORMAL) # Enable editing
ai_output.delete("1.0", tk.END) # Clear previous content
ai_output.insert(tk.END, ai_response) # Insert new response
ai_output.config(state=tk.DISABLED) # Disable editing
except Exception as e:
messagebox.showerror("Error", f"Failed to get AI response: {e}")

# Sidebar UI (Control Panel)
frame = tk.Frame(root, bg='#34495e', padx=10, pady=10)
frame.pack(side=tk.RIGHT, fill=tk.Y)
tk.Label(frame, text="Graph Theory AI", font=("Arial", 16, "bold"), bg='#34495e', fg='white').pack(pady=10)
tk.Label(frame, text="X:", bg='#34495e', fg='white').pack()
entry_x = ttk.Entry(frame)
entry_x.pack()
tk.Label(frame, text="Y:", bg='#34495e', fg='white').pack()
entry_y = ttk.Entry(frame)
entry_y.pack()
plot_button = ttk.Button(frame, text="Plot Point", command=plot_point)
plot_button.pack(pady=5)
clear_button = ttk.Button(frame, text="Clear Graph", command=clear_graph)
clear_button.pack(pady=5)

# Equation Solver UI
tk.Label(frame, text="Enter Equation (e.g., x**2 - 4):", bg='#34495e', fg='white').pack()
equation_entry = ttk.Entry(frame, width=30)
equation_entry.pack()
solve_equation_button = ttk.Button(frame, text="Solve & Plot Equation", command=solve_graph_equation)
solve_equation_button.pack(pady=5)

# Ask the AI Anything UI
tk.Label(frame, text="Ask the AI Anything:", bg='#34495e', fg='white', font=("Arial", 12, "bold")).pack(pady=10)
ai_question = scrolledtext.ScrolledText(frame, height=10, width=50, wrap=tk.WORD, font=("Arial", 10), bg='#ffffff', fg='#2c3e50')
ai_question.pack(pady=5)
ask_button = ttk.Button(frame, text="Ask AI", command=ask_ai)
ask_button.pack(pady=5)
tk.Label(frame, text="AI Response:", bg='#34495e', fg='white', font=("A

Files changed (1) hide show
  1. app.py +247 -0
app.py ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import sys
3
+
4
+ # Function to install dependencies if not already installed
5
+ def install_dependencies():
6
+ required_libraries = [
7
+ "matplotlib",
8
+ "numpy",
9
+ "sympy",
10
+ "google-generativeai",
11
+ ]
12
+ for library in required_libraries:
13
+ try:
14
+ __import__(library)
15
+ except ImportError:
16
+ print(f"Installing {library}...")
17
+ subprocess.check_call([sys.executable, "-m", "pip", "install", library])
18
+
19
+ # Install dependencies before proceeding
20
+ install_dependencies()
21
+
22
+ # Import libraries after ensuring they are installed
23
+ import tkinter as tk
24
+ from tkinter import ttk, messagebox, scrolledtext
25
+ import matplotlib.pyplot as plt
26
+ from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
27
+ import numpy as np
28
+ from sympy import symbols, Eq, solve, re, im
29
+ import google.generativeai as genai
30
+
31
+ # Initialize Gemini API
32
+ API_KEY = "AIzaSyCsC6o08neNA3AipT-iP7qSJUWfqjbpSRI" # Replace with your API key
33
+ genai.configure(api_key=API_KEY)
34
+ model = genai.GenerativeModel('gemini-pro') # Use the Gemini Pro model
35
+
36
+ # Initialize GUI window
37
+ root = tk.Tk()
38
+ root.title("Graph Theory AI with Gemini Integration")
39
+ root.geometry("1200x800") # Increase window size for better layout
40
+ root.configure(bg='#2c3e50')
41
+
42
+ # Graph Setup
43
+ fig, ax = plt.subplots(figsize=(6, 5))
44
+ ax.set_facecolor("white") # Set background color
45
+ ax.set_xticks(np.arange(-10, 11, 1)) # Add numbers for X-axis
46
+ ax.set_yticks(np.arange(-10, 11, 1)) # Add numbers for Y-axis
47
+ ax.grid(True, linestyle='-', linewidth=0.5, color='gray') # Add gridlines
48
+ ax.axhline(0, color='black', linewidth=1) # Horizontal axis line
49
+ ax.axvline(0, color='black', linewidth=1) # Vertical axis line
50
+ ax.set_xlim(-10, 10)
51
+ ax.set_ylim(-10, 10)
52
+ canvas = FigureCanvasTkAgg(fig, master=root)
53
+ canvas.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
54
+
55
+ points = [] # Stores user input points
56
+ annotations = [] # Stores text annotations for roots
57
+
58
+ # Smaller and Better-Designed Explanation Box
59
+ explanation_frame = tk.Frame(root, bg='#ecf0f1', padx=10, pady=10, relief=tk.RIDGE, borderwidth=2)
60
+ explanation_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=10, pady=10)
61
+ explanation_label = tk.Label(explanation_frame, text="Explanation:", font=("Arial", 12, "bold"), bg='#ecf0f1', fg='#2c3e50')
62
+ explanation_label.pack(anchor=tk.W)
63
+ explanation_text = tk.Text(explanation_frame, height=8, width=35, wrap=tk.WORD, font=("Arial", 10), bg='#ffffff', fg='#2c3e50', relief=tk.FLAT)
64
+ explanation_text.pack(fill=tk.BOTH, expand=True)
65
+
66
+ # --- Graph Plotting Function ---
67
+ def plot_point():
68
+ try:
69
+ x = float(entry_x.get())
70
+ y = float(entry_y.get())
71
+ points.append((x, y))
72
+
73
+ # Plot all points
74
+ if len(points) > 1:
75
+ # Extract x and y coordinates from points
76
+ x_vals, y_vals = zip(*points)
77
+ ax.clear()
78
+ ax.set_facecolor("white") # Retain background color
79
+ ax.set_xticks(np.arange(-10, 11, 1)) # Retain X-axis numbers
80
+ ax.set_yticks(np.arange(-10, 11, 1)) # Retain Y-axis numbers
81
+ ax.grid(True, linestyle='-', linewidth=0.5, color='gray') # Retain gridlines
82
+ ax.axhline(0, color='black', linewidth=1) # Retain horizontal axis line
83
+ ax.axvline(0, color='black', linewidth=1) # Retain vertical axis line
84
+ ax.set_xlim(-10, 10)
85
+ ax.set_ylim(-10, 10)
86
+ ax.plot(x_vals, y_vals, 'bo-', markersize=8, linewidth=2) # Connect points with a line
87
+ else:
88
+ ax.plot(x, y, 'bo', markersize=8) # Single point (no line yet)
89
+
90
+ canvas.draw()
91
+ entry_x.delete(0, tk.END) # Clear input fields
92
+ entry_y.delete(0, tk.END)
93
+ except ValueError:
94
+ messagebox.showerror("Error", "Enter valid numbers for x and y")
95
+
96
+ # --- Clear Graph Function ---
97
+ def clear_graph():
98
+ global points, annotations
99
+ points = []
100
+
101
+ # Remove all plotted elements (points, lines, etc.)
102
+ for artist in ax.lines + ax.collections: # Remove lines and scatter points
103
+ artist.remove()
104
+
105
+ # Remove all text annotations (roots)
106
+ for annotation in annotations:
107
+ annotation.remove()
108
+ annotations.clear()
109
+
110
+ # Ensure the background, gridlines, and axis numbers remain intact
111
+ ax.set_facecolor("white") # Retain background color
112
+ ax.set_xticks(np.arange(-10, 11, 1)) # Retain X-axis numbers
113
+ ax.set_yticks(np.arange(-10, 11, 1)) # Retain Y-axis numbers
114
+ ax.grid(True, linestyle='-', linewidth=0.5, color='gray') # Retain gridlines
115
+ ax.axhline(0, color='black', linewidth=1) # Retain horizontal axis line
116
+ ax.axvline(0, color='black', linewidth=1) # Retain vertical axis line
117
+ ax.set_xlim(-10, 10)
118
+ ax.set_ylim(-10, 10)
119
+
120
+ # Clear the explanation box
121
+ explanation_text.delete(1.0, tk.END)
122
+
123
+ canvas.draw()
124
+
125
+ # --- Solve Graph Equation ---
126
+ def solve_graph_equation():
127
+ equation_str = equation_entry.get()
128
+ if not equation_str:
129
+ messagebox.showerror("Error", "Please enter an equation.")
130
+ return
131
+
132
+ try:
133
+ # Parse the equation using SymPy
134
+ x = symbols('x')
135
+ y_expr = eval(equation_str, {"x": x}) # Safely evaluate the equation string
136
+ solutions = solve(Eq(y_expr, 0), x) # Solve for roots
137
+
138
+ # Generate points for plotting
139
+ x_vals = np.linspace(-10, 10, 500)
140
+ y_vals = [y_expr.subs(x, xi) for xi in x_vals] # Evaluate the equation at each x value
141
+
142
+ # Clear previous plots
143
+ for artist in ax.lines + ax.collections: # Remove lines and scatter points
144
+ artist.remove()
145
+
146
+ # Remove all text annotations (roots)
147
+ for annotation in annotations:
148
+ annotation.remove()
149
+ annotations.clear()
150
+
151
+ # Retain the background, gridlines, and axis numbers
152
+ ax.set_facecolor("white") # Retain background color
153
+ ax.set_xticks(np.arange(-10, 11, 1)) # Retain X-axis numbers
154
+ ax.set_yticks(np.arange(-10, 11, 1)) # Retain Y-axis numbers
155
+ ax.grid(True, linestyle='-', linewidth=0.5, color='gray') # Retain gridlines
156
+ ax.axhline(0, color='black', linewidth=1) # Retain horizontal axis line
157
+ ax.axvline(0, color='black', linewidth=1) # Retain vertical axis line
158
+ ax.set_xlim(-10, 10)
159
+ ax.set_ylim(-10, 10)
160
+
161
+ # Plot the equation
162
+ ax.plot(x_vals, y_vals, label=f"y = {equation_str}", color='blue', linewidth=2)
163
+
164
+ # Filter real roots and highlight them on the graph
165
+ real_solutions = []
166
+ for sol in solutions:
167
+ if im(sol) == 0: # Check if the solution is real
168
+ real_solutions.append(sol)
169
+ ax.plot(sol, 0, 'ro', markersize=8) # Mark roots with red dots
170
+ annotation = ax.text(sol, 0.5, f"({sol:.2f}, 0)", fontsize=10, ha='center') # Label roots
171
+ annotations.append(annotation)
172
+
173
+ ax.legend(loc="upper right")
174
+ canvas.draw()
175
+
176
+ # Automatically refresh the explanation box
177
+ explanation_text.delete(1.0, tk.END)
178
+ explanation_text.insert(tk.END, f"Equation: y = {equation_str}\n\n")
179
+ if real_solutions:
180
+ explanation_text.insert(tk.END, f"Solutions (real roots): {real_solutions}\n")
181
+ explanation_text.insert(tk.END, "\nExplanation:\nThe equation was solved by finding the values of x where y = 0.\n")
182
+ explanation_text.insert(tk.END, "The graph shows the curve of the equation and highlights the real roots on the x-axis.")
183
+ else:
184
+ explanation_text.insert(tk.END, "No real roots found.\n")
185
+ explanation_text.insert(tk.END, "\nExplanation:\nThe equation has no real solutions. All roots are complex numbers.")
186
+
187
+ except SyntaxError:
188
+ messagebox.showerror("Error", "Invalid syntax in the equation. Please check your input.")
189
+ except NameError:
190
+ messagebox.showerror("Error", "Undefined variable in the equation. Use 'x' as the variable.")
191
+ except Exception as e:
192
+ messagebox.showerror("Error", f"Failed to solve or plot the equation: {e}")
193
+
194
+ # --- Ask the AI Anything ---
195
+ def ask_ai():
196
+ question = ai_question.get("1.0", tk.END).strip() # Get the user's question
197
+ if not question:
198
+ messagebox.showerror("Error", "Please enter a question for the AI.")
199
+ return
200
+
201
+ try:
202
+ # Query the Gemini API
203
+ response = model.generate_content(question)
204
+ ai_response = response.text.strip()
205
+
206
+ # Display the AI's response in the output box
207
+ ai_output.config(state=tk.NORMAL) # Enable editing
208
+ ai_output.delete("1.0", tk.END) # Clear previous content
209
+ ai_output.insert(tk.END, ai_response) # Insert new response
210
+ ai_output.config(state=tk.DISABLED) # Disable editing
211
+ except Exception as e:
212
+ messagebox.showerror("Error", f"Failed to get AI response: {e}")
213
+
214
+ # Sidebar UI (Control Panel)
215
+ frame = tk.Frame(root, bg='#34495e', padx=10, pady=10)
216
+ frame.pack(side=tk.RIGHT, fill=tk.Y)
217
+ tk.Label(frame, text="Graph Theory AI", font=("Arial", 16, "bold"), bg='#34495e', fg='white').pack(pady=10)
218
+ tk.Label(frame, text="X:", bg='#34495e', fg='white').pack()
219
+ entry_x = ttk.Entry(frame)
220
+ entry_x.pack()
221
+ tk.Label(frame, text="Y:", bg='#34495e', fg='white').pack()
222
+ entry_y = ttk.Entry(frame)
223
+ entry_y.pack()
224
+ plot_button = ttk.Button(frame, text="Plot Point", command=plot_point)
225
+ plot_button.pack(pady=5)
226
+ clear_button = ttk.Button(frame, text="Clear Graph", command=clear_graph)
227
+ clear_button.pack(pady=5)
228
+
229
+ # Equation Solver UI
230
+ tk.Label(frame, text="Enter Equation (e.g., x**2 - 4):", bg='#34495e', fg='white').pack()
231
+ equation_entry = ttk.Entry(frame, width=30)
232
+ equation_entry.pack()
233
+ solve_equation_button = ttk.Button(frame, text="Solve & Plot Equation", command=solve_graph_equation)
234
+ solve_equation_button.pack(pady=5)
235
+
236
+ # Ask the AI Anything UI
237
+ tk.Label(frame, text="Ask the AI Anything:", bg='#34495e', fg='white', font=("Arial", 12, "bold")).pack(pady=10)
238
+ ai_question = scrolledtext.ScrolledText(frame, height=10, width=50, wrap=tk.WORD, font=("Arial", 10), bg='#ffffff', fg='#2c3e50')
239
+ ai_question.pack(pady=5)
240
+ ask_button = ttk.Button(frame, text="Ask AI", command=ask_ai)
241
+ ask_button.pack(pady=5)
242
+ tk.Label(frame, text="AI Response:", bg='#34495e', fg='white', font=("Arial", 12, "bold")).pack(pady=5)
243
+ ai_output = scrolledtext.ScrolledText(frame, height=15, width=50, wrap=tk.WORD, font=("Arial", 10), bg='#ffffff', fg='#2c3e50', state=tk.DISABLED)
244
+ ai_output.pack(pady=5)
245
+
246
+ # Run the GUI
247
+ root.mainloop()