buoyrina
commited on
Commit
·
02dd72e
1
Parent(s):
d0154da
consolidate
Browse files
app.py
CHANGED
@@ -59,27 +59,247 @@ def matrix_vector_multiplication_visualization(matrix, vector):
|
|
59 |
except Exception as e:
|
60 |
return f"Error: {str(e)}", None
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
# Create the Gradio app
|
63 |
with gr.Blocks() as app:
|
64 |
-
gr.
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
|
85 |
app.launch()
|
|
|
59 |
except Exception as e:
|
60 |
return f"Error: {str(e)}", None
|
61 |
|
62 |
+
def visualize_points_and_vectors_with_start(points, vectors):
|
63 |
+
try:
|
64 |
+
# Parse points
|
65 |
+
points = [list(map(float, p.split(','))) for p in points.split(';') if p.strip()]
|
66 |
+
|
67 |
+
# Parse vectors with starting points
|
68 |
+
vectors_with_start = [
|
69 |
+
list(map(float, v.split(','))) for v in vectors.split(';') if v.strip()
|
70 |
+
]
|
71 |
+
|
72 |
+
# Create the plot
|
73 |
+
fig, ax = plt.subplots(figsize=(6, 6))
|
74 |
+
|
75 |
+
# Plot points
|
76 |
+
for point in points:
|
77 |
+
ax.plot(point[0], point[1], 'o', label=f"Point ({point[0]}, {point[1]})")
|
78 |
+
|
79 |
+
# Plot vectors with starting points
|
80 |
+
for vector in vectors_with_start:
|
81 |
+
if len(vector) == 4: # Check format [start_x, start_y, vector_x, vector_y]
|
82 |
+
start_x, start_y, vec_x, vec_y = vector
|
83 |
+
ax.quiver(
|
84 |
+
start_x, start_y, vec_x, vec_y, angles='xy', scale_units='xy', scale=1,
|
85 |
+
color='r', label=f"Vector from ({start_x},{start_y}) to ({start_x+vec_x},{start_y+vec_y})"
|
86 |
+
)
|
87 |
+
|
88 |
+
# Plot settings
|
89 |
+
ax.axhline(0, color='black', linewidth=0.5)
|
90 |
+
ax.axvline(0, color='black', linewidth=0.5)
|
91 |
+
ax.set_xlim(-10, 10)
|
92 |
+
ax.set_ylim(-10, 10)
|
93 |
+
ax.set_aspect('equal')
|
94 |
+
ax.grid(True)
|
95 |
+
ax.legend()
|
96 |
+
ax.set_title("Points and Vectors Visualization")
|
97 |
+
|
98 |
+
# Save the plot to a BytesIO object
|
99 |
+
buf = BytesIO()
|
100 |
+
plt.savefig(buf, format='png')
|
101 |
+
buf.seek(0)
|
102 |
+
plt.close(fig)
|
103 |
+
|
104 |
+
return Image.open(buf)
|
105 |
+
except Exception as e:
|
106 |
+
return f"Error: {str(e)}"
|
107 |
+
|
108 |
+
def calculate_dot_product_and_angle(vector1, vector2):
|
109 |
+
try:
|
110 |
+
# Convert input strings to numpy arrays
|
111 |
+
vec1 = np.array([float(x) for x in vector1.split(",")])
|
112 |
+
vec2 = np.array([float(x) for x in vector2.split(",")])
|
113 |
+
|
114 |
+
# Check if vectors have the same length
|
115 |
+
if len(vec1) != len(vec2):
|
116 |
+
return "Error: Vectors must have the same length.", None
|
117 |
+
|
118 |
+
# Compute the dot product
|
119 |
+
dot_product = np.dot(vec1, vec2)
|
120 |
+
|
121 |
+
# Compute magnitudes of vectors
|
122 |
+
magnitude_vec1 = np.linalg.norm(vec1)
|
123 |
+
magnitude_vec2 = np.linalg.norm(vec2)
|
124 |
+
|
125 |
+
# Normalized dot product
|
126 |
+
normalized_dot_product = dot_product / (magnitude_vec1 * magnitude_vec2)
|
127 |
+
|
128 |
+
# Compute the angle in radians and convert to degrees
|
129 |
+
angle_radians = np.arccos(np.clip(normalized_dot_product, -1.0, 1.0))
|
130 |
+
angle_degrees = np.degrees(angle_radians)
|
131 |
+
|
132 |
+
explanation = (
|
133 |
+
f"Dot product: {dot_product}\n"
|
134 |
+
f"Normalized dot product: {normalized_dot_product:.4f}\n"
|
135 |
+
f"Angle (radians): {angle_radians:.4f}\n"
|
136 |
+
f"Angle (degrees): {angle_degrees:.4f}"
|
137 |
+
)
|
138 |
+
|
139 |
+
# Plot the vectors
|
140 |
+
fig, ax = plt.subplots(figsize=(6, 6))
|
141 |
+
ax.quiver(0, 0, vec1[0], vec1[1], angles='xy', scale_units='xy', scale=1, color='r', label="Vector 1")
|
142 |
+
ax.quiver(0, 0, vec2[0], vec2[1], angles='xy', scale_units='xy', scale=1, color='b', label="Vector 2")
|
143 |
+
|
144 |
+
# Plot settings
|
145 |
+
ax.set_xlim(-max(abs(vec1[0]), abs(vec2[0])) - 1, max(abs(vec1[0]), abs(vec2[0])) + 1)
|
146 |
+
ax.set_ylim(-max(abs(vec1[1]), abs(vec2[1])) - 1, max(abs(vec1[1]), abs(vec2[1])) + 1)
|
147 |
+
ax.axhline(0, color='black', linewidth=0.5)
|
148 |
+
ax.axvline(0, color='black', linewidth=0.5)
|
149 |
+
ax.set_aspect('equal')
|
150 |
+
ax.grid(True)
|
151 |
+
ax.legend()
|
152 |
+
ax.set_title("Vector Visualization")
|
153 |
+
|
154 |
+
|
155 |
+
# Save plot to a BytesIO object
|
156 |
+
buf = BytesIO()
|
157 |
+
plt.savefig(buf, format='png')
|
158 |
+
buf.seek(0)
|
159 |
+
plt.close(fig)
|
160 |
+
|
161 |
+
return explanation, Image.open(buf)
|
162 |
+
except ValueError:
|
163 |
+
return "Error: Please enter valid numeric values separated by commas.", None
|
164 |
+
|
165 |
+
def transformation_composition_with_vectors(matrix1, matrix2, vectors):
|
166 |
+
try:
|
167 |
+
# Parse input matrices
|
168 |
+
matrix1 = np.array([[float(x) for x in row.split(",")] for row in matrix1.split(";")])
|
169 |
+
matrix2 = np.array([[float(x) for x in row.split(",")] for row in matrix2.split(";")])
|
170 |
+
|
171 |
+
# Ensure both matrices are 2x2
|
172 |
+
if matrix1.shape != (2, 2) or matrix2.shape != (2, 2):
|
173 |
+
return "Error: Both matrices must be 2x2.", None
|
174 |
+
|
175 |
+
# Parse vectors
|
176 |
+
vectors = np.array([[float(x) for x in vector.split(",")] for vector in vectors.split(";")]).T
|
177 |
+
if vectors.shape[0] != 2:
|
178 |
+
return "Error: Vectors must be 2D (two components per vector).", None
|
179 |
+
|
180 |
+
# Compute the transformations
|
181 |
+
vectors_after_matrix1 = np.dot(matrix1, vectors)
|
182 |
+
vectors_after_composition = np.dot(np.dot(matrix2, matrix1), vectors)
|
183 |
+
|
184 |
+
# Plot the transformations
|
185 |
+
fig, ax = plt.subplots(figsize=(8, 8))
|
186 |
+
|
187 |
+
# Plot original vectors
|
188 |
+
for vector in vectors.T:
|
189 |
+
ax.quiver(0, 0, vector[0], vector[1], angles='xy', scale_units='xy', scale=1, color="gray", alpha=0.7)
|
190 |
+
|
191 |
+
# Plot vectors after Matrix 1
|
192 |
+
for vector in vectors_after_matrix1.T:
|
193 |
+
ax.quiver(0, 0, vector[0], vector[1], angles='xy', scale_units='xy', scale=1, color="orange", alpha=0.7)
|
194 |
+
|
195 |
+
# Plot vectors after composition
|
196 |
+
for vector in vectors_after_composition.T:
|
197 |
+
ax.quiver(0, 0, vector[0], vector[1], angles='xy', scale_units='xy', scale=1, color="blue", alpha=0.7)
|
198 |
+
|
199 |
+
# Add legend
|
200 |
+
ax.legend(["Original Vectors", "After Matrix 1", "After Matrix 2 × Matrix 1"], loc="upper left")
|
201 |
+
|
202 |
+
# Axes settings
|
203 |
+
ax.axhline(0, color="black", linewidth=0.5)
|
204 |
+
ax.axvline(0, color="black", linewidth=0.5)
|
205 |
+
ax.set_xlim(-3, 3)
|
206 |
+
ax.set_ylim(-3, 3)
|
207 |
+
ax.set_aspect("equal")
|
208 |
+
ax.grid(True)
|
209 |
+
ax.set_title("Matrix-Matrix Multiplication as Transformation Composition")
|
210 |
+
|
211 |
+
# Save the plot
|
212 |
+
buf = BytesIO()
|
213 |
+
plt.savefig(buf, format="png")
|
214 |
+
buf.seek(0)
|
215 |
+
plt.close(fig)
|
216 |
+
|
217 |
+
return "Success", Image.open(buf)
|
218 |
+
except Exception as e:
|
219 |
+
return f"Error: {str(e)}", None
|
220 |
# Create the Gradio app
|
221 |
with gr.Blocks() as app:
|
222 |
+
with gr.Tab("Points vs. Vectors"):
|
223 |
+
gr.Markdown("## Points and Vectors Visualization with Starting Points")
|
224 |
+
gr.Markdown("""
|
225 |
+
- **Points**: Enter semicolon-separated 2D points, e.g., `1,2; 3,4`.
|
226 |
+
- **Vectors**: Enter vectors with starting points in the format `start_x,start_y,vector_x,vector_y; ...`, e.g., `0,0,2,1; 3,4,-1,2`.
|
227 |
+
""")
|
228 |
+
|
229 |
+
with gr.Row():
|
230 |
+
points_input = gr.Textbox(label="Points (semicolon-separated)", placeholder="e.g., 1,2; 3,4")
|
231 |
+
vectors_input = gr.Textbox(label="Vectors (with starting points)", placeholder="e.g., 0,0,2,1; 3,4,-1,2")
|
232 |
+
|
233 |
+
output_image = gr.Image(label="Visualization")
|
234 |
+
|
235 |
+
visualize_button = gr.Button("Visualize")
|
236 |
+
visualize_button.click(
|
237 |
+
fn=visualize_points_and_vectors_with_start,
|
238 |
+
inputs=[points_input, vectors_input],
|
239 |
+
outputs=output_image
|
240 |
+
)
|
241 |
+
with gr.Tab("Vector Dot Product"):
|
242 |
+
gr.Markdown("## Dot Product, Normalized Dot Product, and Angle Calculator")
|
243 |
+
gr.Markdown("Enter two vectors (comma-separated) to calculate their dot product, normalized dot product, and angle.")
|
244 |
|
245 |
+
with gr.Row():
|
246 |
+
vector1_input = gr.Textbox(label="Vector 1", placeholder="e.g., 1, 2")
|
247 |
+
vector2_input = gr.Textbox(label="Vector 2", placeholder="e.g., 4, 5")
|
248 |
+
|
249 |
+
output_text = gr.Textbox(label="Result", lines=6)
|
250 |
+
output_image = gr.Image(label="Visualization")
|
251 |
+
|
252 |
+
calculate_button = gr.Button("Calculate and Visualize")
|
253 |
+
calculate_button.click(
|
254 |
+
fn=calculate_dot_product_and_angle,
|
255 |
+
inputs=[vector1_input, vector2_input],
|
256 |
+
outputs=[output_text, output_image]
|
257 |
+
)
|
258 |
+
with gr.Tab("Matrix-Vector Multiplication"):
|
259 |
+
gr.Markdown("## Matrix-Vector Multiplication Visualization")
|
260 |
+
gr.Markdown("""
|
261 |
+
- Enter a **2x2 matrix** as `a,b;c,d` (rows separated by semicolons).
|
262 |
+
- Enter a **2D vector** as `x,y`.
|
263 |
+
- See the original vector (red), transformed vector (blue), and grid transformation.
|
264 |
+
""")
|
265 |
+
with gr.Row():
|
266 |
+
matrix_input = gr.Textbox(label="Matrix (2x2, e.g., 1,0;0,1)", placeholder="e.g., 1,0;0,1")
|
267 |
+
vector_input = gr.Textbox(label="Vector (2D, e.g., 1,1)", placeholder="e.g., 1,1")
|
268 |
+
|
269 |
+
output_text = gr.Textbox(label="Result")
|
270 |
+
output_image = gr.Image(label="Visualization")
|
271 |
+
|
272 |
+
calculate_button = gr.Button("Visualize")
|
273 |
+
calculate_button.click(
|
274 |
+
fn=matrix_vector_multiplication_visualization,
|
275 |
+
inputs=[matrix_input, vector_input],
|
276 |
+
outputs=[output_text, output_image]
|
277 |
+
)
|
278 |
+
|
279 |
+
with gr.Tab('Matrix-Matrix Multiplication'):
|
280 |
+
gr.Markdown("## Matrix Multiplication as Transformation Composition (Using Vectors)")
|
281 |
+
gr.Markdown("""
|
282 |
+
- Enter two **2x2 matrices** in the format `a,b;c,d` (rows separated by semicolons).
|
283 |
+
- Enter vectors in the format `x1,y1;x2,y2;...` (semicolon-separated pairs).
|
284 |
+
- The app will show:
|
285 |
+
- The original vectors.
|
286 |
+
- The vectors after applying **Matrix 1**.
|
287 |
+
- The vectors after applying the composition (**Matrix 2 × Matrix 1**).
|
288 |
+
""")
|
289 |
+
|
290 |
+
with gr.Row():
|
291 |
+
matrix1_input = gr.Textbox(label="Matrix 1 (2x2, e.g., 1,0;0,1)", placeholder="e.g., 1,0;0,1")
|
292 |
+
matrix2_input = gr.Textbox(label="Matrix 2 (2x2, e.g., 2,0;0,1)", placeholder="e.g., 2,0;0,1")
|
293 |
+
vectors_input = gr.Textbox(label="Vectors (e.g., 1,0;0,1)", placeholder="e.g., 1,0;0,1")
|
294 |
+
|
295 |
+
output_text = gr.Textbox(label="Output")
|
296 |
+
output_image = gr.Image(label="Visualization")
|
297 |
+
|
298 |
+
calculate_button = gr.Button("Visualize")
|
299 |
+
calculate_button.click(
|
300 |
+
fn=transformation_composition_with_vectors,
|
301 |
+
inputs=[matrix1_input, matrix2_input, vectors_input],
|
302 |
+
outputs=[output_text, output_image]
|
303 |
+
)
|
304 |
|
305 |
app.launch()
|