Spaces:
Runtime error
Runtime error
feat: add Gradio interfaces for trigonometric functions and remove old trigonometry interface
Browse files- maths/differential_equations/differential_equations_interface.py +0 -106
- maths/equations/equations_interface.py +0 -88
- maths/geometry/cos_degrees.py +9 -0
- maths/geometry/geometry_tab.py +4 -4
- maths/geometry/inverse_trig_functions.py +12 -0
- maths/geometry/sin_degrees.py +9 -0
- maths/geometry/solve_trig_equations.py +24 -0
- maths/geometry/tan_degrees.py +9 -0
- maths/geometry/trig_identities.py +20 -0
- maths/geometry/trigonometry_interface.py +0 -79
maths/differential_equations/differential_equations_interface.py
DELETED
|
@@ -1,106 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
Gradio Interface for Differential Equations solvers.
|
| 3 |
-
|
| 4 |
-
SECURITY WARNING: These interfaces use eval() to parse user-provided Python lambda strings
|
| 5 |
-
for defining ODE functions. This is a potential security risk if arbitrary code is entered.
|
| 6 |
-
Use with caution and only with trusted inputs, especially if deploying this application
|
| 7 |
-
outside a controlled environment.
|
| 8 |
-
"""
|
| 9 |
-
import gradio as gr
|
| 10 |
-
import numpy as np
|
| 11 |
-
import matplotlib.pyplot as plt # For displaying plots if not returned directly by solver
|
| 12 |
-
from typing import Callable, Tuple, List, Dict, Any, Union
|
| 13 |
-
import ast # For safer string literal evaluation if needed for parameters
|
| 14 |
-
import math # To make math functions available in eval scope for ODEs
|
| 15 |
-
|
| 16 |
-
# Import the solver functions
|
| 17 |
-
from maths.differential_equations.solve_first_order_ode import solve_first_order_ode
|
| 18 |
-
from maths.differential_equations.solve_second_order_ode import solve_second_order_ode
|
| 19 |
-
from maths.differential_equations.ode_interface_utils import parse_float_list, parse_time_span, string_to_ode_func
|
| 20 |
-
|
| 21 |
-
# --- Helper Functions ---
|
| 22 |
-
|
| 23 |
-
# (Keep the helper functions here if needed, otherwise they can be removed as they are now in ode_interface_utils.py)
|
| 24 |
-
|
| 25 |
-
# --- Gradio Interface for First-Order ODEs ---
|
| 26 |
-
# first_order_ode_interface = gr.Interface(
|
| 27 |
-
# fn=lambda ode_str, t_span_str, y0_str, t_eval_count, method: solve_first_order_ode(
|
| 28 |
-
# string_to_ode_func(ode_str, ('t', 'y')),
|
| 29 |
-
# parse_time_span(t_span_str),
|
| 30 |
-
# parse_float_list(y0_str), # y0 can be a list for systems
|
| 31 |
-
# int(t_eval_count),
|
| 32 |
-
# method
|
| 33 |
-
# ),
|
| 34 |
-
# inputs=[
|
| 35 |
-
# gr.Textbox(label="ODE Function (lambda t, y: ...)",
|
| 36 |
-
# placeholder="e.g., lambda t, y: -y*t OR for system lambda t, y: [y[1], -0.1*y[1] - y[0]]",
|
| 37 |
-
# info="Define dy/dt or a system [dy1/dt, dy2/dt,...]. `y` is a list/array for systems."),
|
| 38 |
-
# gr.Textbox(label="Time Span (t_start, t_end)", placeholder="e.g., 0,10"),
|
| 39 |
-
# gr.Textbox(label="Initial Condition(s) y(t_start)", placeholder="e.g., 1 OR for system 1,0"),
|
| 40 |
-
# gr.Slider(minimum=10, maximum=1000, value=100, step=10, label="Evaluation Points Count"),
|
| 41 |
-
# gr.Radio(choices=['RK45', 'LSODA', 'BDF', 'RK23', 'DOP853'], value='RK45', label="Solver Method")
|
| 42 |
-
# ],
|
| 43 |
-
# outputs=[
|
| 44 |
-
# gr.Image(label="Solution Plot", type="filepath", show_label=True, visible=lambda res: res['success'] and res['plot_path'] is not None),
|
| 45 |
-
# gr.Textbox(label="Solver Message"),
|
| 46 |
-
# gr.Textbox(label="Success Status"),
|
| 47 |
-
# gr.JSON(label="Raw Data (t, y values)", visible=lambda res: res['success']) # For users to copy if needed
|
| 48 |
-
# ],
|
| 49 |
-
# title="First-Order ODE Solver",
|
| 50 |
-
# description="Solves dy/dt = f(t,y) or a system of first-order ODEs. " \
|
| 51 |
-
# "WARNING: Uses eval() for the ODE function string - potential security risk. " \
|
| 52 |
-
# "For systems, `y` in lambda is `[y1, y2, ...]`, return `[dy1/dt, dy2/dt, ...]`. " \
|
| 53 |
-
# "Example (Damped Oscillator): ODE: lambda t, y: [y[1], -0.5*y[1] - y[0]], y0: 1,0, Timespan: 0,20",
|
| 54 |
-
# flagging_mode="manual"
|
| 55 |
-
# )
|
| 56 |
-
|
| 57 |
-
# # --- Gradio Interface for Second-Order ODEs ---
|
| 58 |
-
# second_order_ode_interface = gr.Interface(
|
| 59 |
-
# fn=lambda ode_str, t_span_str, y0_val_str, dy0_dt_val_str, t_eval_count, method: solve_second_order_ode(
|
| 60 |
-
# string_to_ode_func(ode_str, ('t', 'y', 'dy_dt')), # Note: dy_dt is one variable name here
|
| 61 |
-
# parse_time_span(t_span_str),
|
| 62 |
-
# parse_float_list(y0_val_str, expected_len=1)[0], # y0 is a single float
|
| 63 |
-
# parse_float_list(dy0_dt_val_str, expected_len=1)[0], # dy0_dt is a single float
|
| 64 |
-
# int(t_eval_count),
|
| 65 |
-
# method
|
| 66 |
-
# ),
|
| 67 |
-
# inputs=[
|
| 68 |
-
# gr.Textbox(label="ODE Function (lambda t, y, dy_dt: ...)",
|
| 69 |
-
# placeholder="e.g., lambda t, y, dy_dt: -0.1*dy_dt - math.sin(y)",
|
| 70 |
-
# info="Define d²y/dt². `y` is current value, `dy_dt` is current first derivative."),
|
| 71 |
-
# gr.Textbox(label="Time Span (t_start, t_end)", placeholder="e.g., 0,20"),
|
| 72 |
-
# gr.Textbox(label="Initial y(t_start)", placeholder="e.g., 1.0"),
|
| 73 |
-
# gr.Textbox(label="Initial dy/dt(t_start)", placeholder="e.g., 0.0"),
|
| 74 |
-
# gr.Slider(minimum=10, maximum=1000, value=100, step=10, label="Evaluation Points Count"),
|
| 75 |
-
# gr.Radio(choices=['RK45', 'LSODA', 'BDF', 'RK23', 'DOP853'], value='RK45', label="Solver Method")
|
| 76 |
-
# ],
|
| 77 |
-
# outputs=[
|
| 78 |
-
# gr.Image(label="Solution Plot (y(t) and dy/dt(t))", type="filepath", show_label=True, visible=lambda res: res['success'] and res['plot_path'] is not None),
|
| 79 |
-
# gr.Textbox(label="Solver Message"),
|
| 80 |
-
# gr.Textbox(label="Success Status"),
|
| 81 |
-
# gr.JSON(label="Raw Data (t, y, dy_dt values)", visible=lambda res: res['success'])
|
| 82 |
-
# ],
|
| 83 |
-
# title="Second-Order ODE Solver",
|
| 84 |
-
# description="Solves d²y/dt² = f(t, y, dy/dt). " \
|
| 85 |
-
# "WARNING: Uses eval() for the ODE function string - potential security risk. " \
|
| 86 |
-
# "Example (Pendulum): ODE: lambda t, y, dy_dt: -9.81/1.0 * math.sin(y), y0: math.pi/4, dy0/dt: 0, Timespan: 0,10",
|
| 87 |
-
# flagging_mode="manual"
|
| 88 |
-
# )
|
| 89 |
-
|
| 90 |
-
# Example usage for testing (can be removed)
|
| 91 |
-
if __name__ == '__main__':
|
| 92 |
-
# Test first order
|
| 93 |
-
# result1 = solve_first_order_ode(lambda t,y: -y*t, (0,5), [1])
|
| 94 |
-
# print(result1['success'], result1['message'])
|
| 95 |
-
# if result1['plot_path']: import os; os.system(f"open {result1['plot_path']}")
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
# Test second order
|
| 99 |
-
# result2 = solve_second_order_ode(lambda t,y,dydt: -0.1*dydt - y, (0,20), 1, 0)
|
| 100 |
-
# print(result2['success'], result2['message'])
|
| 101 |
-
# if result2['plot_path']: import os; os.system(f"open {result2['plot_path']}")
|
| 102 |
-
|
| 103 |
-
# To run one of these interfaces for testing:
|
| 104 |
-
# first_order_ode_interface.launch()
|
| 105 |
-
# second_order_ode_interface.launch()
|
| 106 |
-
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maths/equations/equations_interface.py
DELETED
|
@@ -1,88 +0,0 @@
|
|
| 1 |
-
# filepath: c:\Users\visha\Desktop\coding\counting\maths\equations\equations_interface.py
|
| 2 |
-
import gradio as gr
|
| 3 |
-
from maths.equations.solve_quadratic import solve_quadratic
|
| 4 |
-
|
| 5 |
-
# Quadratic Equation Solver Interface
|
| 6 |
-
def quadratic_solver_wrapper(a, b, c, return_format):
|
| 7 |
-
result = solve_quadratic(a, b, c, return_format=return_format)
|
| 8 |
-
if return_format == "dict":
|
| 9 |
-
if "error" in result:
|
| 10 |
-
return result["error"]
|
| 11 |
-
roots = result["roots"]
|
| 12 |
-
vertex = result["vertex"]
|
| 13 |
-
output = ""
|
| 14 |
-
sign_b = "+" if b >= 0 else ""
|
| 15 |
-
sign_c = "+" if c >= 0 else ""
|
| 16 |
-
output += f"Equation: {a}x² {sign_b} {b}x {sign_c} {c} = 0\n\n"
|
| 17 |
-
if roots[1] is None:
|
| 18 |
-
output += f"Root: {roots[0]}\n"
|
| 19 |
-
else:
|
| 20 |
-
output += f"Root 1: {roots[0]}\n"
|
| 21 |
-
output += f"Root 2: {roots[1]}\n"
|
| 22 |
-
if vertex:
|
| 23 |
-
output += f"\nVertex: ({vertex[0]}, {vertex[1]})"
|
| 24 |
-
return output
|
| 25 |
-
else:
|
| 26 |
-
return result
|
| 27 |
-
|
| 28 |
-
def plot_quadratic(a, b, c):
|
| 29 |
-
import numpy as np
|
| 30 |
-
import matplotlib.pyplot as plt
|
| 31 |
-
result = solve_quadratic(a, b, c, return_format="dict")
|
| 32 |
-
vertex_x = -b / (2*a) if a != 0 else 0
|
| 33 |
-
vertex_y = c - (b**2 / (4*a)) if a != 0 else 0
|
| 34 |
-
fig, ax = plt.subplots(figsize=(8, 6))
|
| 35 |
-
if a != 0:
|
| 36 |
-
if "roots" in result and result["roots"][0] is not None and result["roots"][1] is not None:
|
| 37 |
-
root1 = result["roots"][0].real if hasattr(result["roots"][0], "real") else float(result["roots"][0])
|
| 38 |
-
root2 = result["roots"][1].real if hasattr(result["roots"][1], "real") else float(result["roots"][1])
|
| 39 |
-
x_min = min(root1, root2, vertex_x) - 2
|
| 40 |
-
x_max = max(root1, root2, vertex_x) + 2
|
| 41 |
-
else:
|
| 42 |
-
x_min = vertex_x - 5
|
| 43 |
-
x_max = vertex_x + 5
|
| 44 |
-
x = np.linspace(x_min, x_max, 1000)
|
| 45 |
-
y = a * (x**2) + b * x + c
|
| 46 |
-
ax.plot(x, y, 'b-', label=f'f(x) = {a}x² + {b}x + {c}')
|
| 47 |
-
ax.plot(vertex_x, vertex_y, 'ro', label=f'Vertex: ({vertex_x:.2f}, {vertex_y:.2f})')
|
| 48 |
-
if "roots" in result:
|
| 49 |
-
roots = result["roots"]
|
| 50 |
-
if roots[0] is not None and (isinstance(roots[0], (int, float)) or (hasattr(roots[0], "imag") and roots[0].imag == 0)):
|
| 51 |
-
root1 = float(roots[0].real if hasattr(roots[0], "real") else roots[0])
|
| 52 |
-
ax.plot(root1, 0, 'go', label=f'Root 1: {root1:.2f}')
|
| 53 |
-
if roots[1] is not None and (isinstance(roots[1], (int, float)) or (hasattr(roots[1], "imag") and roots[1].imag == 0)):
|
| 54 |
-
root2 = float(roots[1].real if hasattr(roots[1], "real") else roots[1])
|
| 55 |
-
ax.plot(root2, 0, 'go', label=f'Root 2: {root2:.2f}')
|
| 56 |
-
ax.axhline(y=0, color='k', linestyle='-', alpha=0.3)
|
| 57 |
-
ax.axvline(x=0, color='k', linestyle='-', alpha=0.3)
|
| 58 |
-
ax.grid(True, alpha=0.3)
|
| 59 |
-
ax.set_xlabel('x')
|
| 60 |
-
ax.set_ylabel('f(x)')
|
| 61 |
-
ax.set_title(f'Graph of f(x) = {a}x² + {b}x + {c}')
|
| 62 |
-
ax.legend()
|
| 63 |
-
else:
|
| 64 |
-
if b != 0:
|
| 65 |
-
x = np.linspace(-5, 5, 100)
|
| 66 |
-
y = b * x + c
|
| 67 |
-
ax.plot(x, y, 'b-', label=f'f(x) = {b}x + {c} (Linear)')
|
| 68 |
-
root = -c/b
|
| 69 |
-
ax.plot(root, 0, 'go', label=f'Root: {root:.2f}')
|
| 70 |
-
ax.axhline(y=0, color='k', linestyle='-', alpha=0.3)
|
| 71 |
-
ax.axvline(x=0, color='k', linestyle='-', alpha=0.3)
|
| 72 |
-
ax.grid(True, alpha=0.3)
|
| 73 |
-
ax.set_xlabel('x')
|
| 74 |
-
ax.set_ylabel('f(x)')
|
| 75 |
-
ax.set_title(f'Graph of f(x) = {b}x + {c} (Linear)')
|
| 76 |
-
ax.legend()
|
| 77 |
-
else:
|
| 78 |
-
x = np.linspace(-5, 5, 100)
|
| 79 |
-
y = c * np.ones_like(x)
|
| 80 |
-
ax.plot(x, y, 'b-', label=f'f(x) = {c} (Constant)')
|
| 81 |
-
ax.axhline(y=0, color='k', linestyle='-', alpha=0.3)
|
| 82 |
-
ax.axvline(x=0, color='k', linestyle='-', alpha=0.3)
|
| 83 |
-
ax.grid(True, alpha=0.3)
|
| 84 |
-
ax.set_xlabel('x')
|
| 85 |
-
ax.set_ylabel('f(x)')
|
| 86 |
-
ax.set_title(f'Graph of f(x) = {c} (Constant)')
|
| 87 |
-
ax.legend()
|
| 88 |
-
return fig
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maths/geometry/cos_degrees.py
CHANGED
|
@@ -1,5 +1,14 @@
|
|
| 1 |
import math
|
|
|
|
| 2 |
|
| 3 |
def cos_degrees(angle):
|
| 4 |
"""Calculate the cosine of an angle in degrees."""
|
| 5 |
return math.cos(math.radians(angle))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import math
|
| 2 |
+
import gradio as gr
|
| 3 |
|
| 4 |
def cos_degrees(angle):
|
| 5 |
"""Calculate the cosine of an angle in degrees."""
|
| 6 |
return math.cos(math.radians(angle))
|
| 7 |
+
|
| 8 |
+
cos_degrees_interface = gr.Interface(
|
| 9 |
+
fn=cos_degrees,
|
| 10 |
+
inputs=gr.Number(label="Angle (degrees)"),
|
| 11 |
+
outputs="number",
|
| 12 |
+
title="Cosine Calculator",
|
| 13 |
+
description="Calculate cosine of an angle in degrees."
|
| 14 |
+
)
|
maths/geometry/geometry_tab.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
-
from maths.geometry.
|
| 3 |
-
|
| 4 |
-
|
| 5 |
|
| 6 |
-
geometry_interfaces_list = [
|
| 7 |
geometry_tab_names = ["Trig Functions", "Inverse Trig", "Trig Identities"]
|
| 8 |
|
| 9 |
geometry_tab = gr.TabbedInterface(geometry_interfaces_list, geometry_tab_names, title="Geometry")
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
+
from maths.geometry.sin_degrees import sin_degrees_interface
|
| 3 |
+
from maths.geometry.inverse_trig_functions import inverse_trig_interface
|
| 4 |
+
from maths.geometry.trig_identities import trig_identities_interface
|
| 5 |
|
| 6 |
+
geometry_interfaces_list = [sin_degrees_interface, inverse_trig_interface, trig_identities_interface]
|
| 7 |
geometry_tab_names = ["Trig Functions", "Inverse Trig", "Trig Identities"]
|
| 8 |
|
| 9 |
geometry_tab = gr.TabbedInterface(geometry_interfaces_list, geometry_tab_names, title="Geometry")
|
maths/geometry/inverse_trig_functions.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
import math
|
|
|
|
| 2 |
|
| 3 |
def inverse_trig_functions(value: float, function_name: str) -> str:
|
| 4 |
"""
|
|
@@ -29,3 +30,14 @@ def inverse_trig_functions(value: float, function_name: str) -> str:
|
|
| 29 |
else:
|
| 30 |
return "Error: Invalid function name. Choose 'asin', 'acos', or 'atan'."
|
| 31 |
return f"{math.degrees(result_rad):.4f} degrees"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import math
|
| 2 |
+
import gradio as gr
|
| 3 |
|
| 4 |
def inverse_trig_functions(value: float, function_name: str) -> str:
|
| 5 |
"""
|
|
|
|
| 30 |
else:
|
| 31 |
return "Error: Invalid function name. Choose 'asin', 'acos', or 'atan'."
|
| 32 |
return f"{math.degrees(result_rad):.4f} degrees"
|
| 33 |
+
|
| 34 |
+
inverse_trig_interface = gr.Interface(
|
| 35 |
+
fn=inverse_trig_functions,
|
| 36 |
+
inputs=[
|
| 37 |
+
gr.Number(label="Value"),
|
| 38 |
+
gr.Radio(["asin", "acos", "atan"], label="Inverse Function")
|
| 39 |
+
],
|
| 40 |
+
outputs="text",
|
| 41 |
+
title="Inverse Trigonometry Calculator",
|
| 42 |
+
description="Calculate inverse trigonometric functions. Output in degrees."
|
| 43 |
+
)
|
maths/geometry/sin_degrees.py
CHANGED
|
@@ -1,5 +1,14 @@
|
|
| 1 |
import math
|
|
|
|
| 2 |
|
| 3 |
def sin_degrees(angle):
|
| 4 |
"""Calculate the sine of an angle in degrees."""
|
| 5 |
return math.sin(math.radians(angle))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import math
|
| 2 |
+
import gradio as gr
|
| 3 |
|
| 4 |
def sin_degrees(angle):
|
| 5 |
"""Calculate the sine of an angle in degrees."""
|
| 6 |
return math.sin(math.radians(angle))
|
| 7 |
+
|
| 8 |
+
sin_degrees_interface = gr.Interface(
|
| 9 |
+
fn=sin_degrees,
|
| 10 |
+
inputs=gr.Number(label="Angle (degrees)"),
|
| 11 |
+
outputs="number",
|
| 12 |
+
title="Sine Calculator",
|
| 13 |
+
description="Calculate sine of an angle in degrees."
|
| 14 |
+
)
|
maths/geometry/solve_trig_equations.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
import math
|
|
|
|
| 2 |
|
| 3 |
def solve_trig_equations(a: float, b: float, c: float, trig_func: str, interval_degrees: tuple[float, float] = (0, 360)) -> str:
|
| 4 |
"""
|
|
@@ -56,3 +57,26 @@ def solve_trig_equations(a: float, b: float, c: float, trig_func: str, interval_
|
|
| 56 |
if not unique_solutions:
|
| 57 |
return f"No solutions found for {a}*{func}(x) + {b} = {c} in the interval [{min_interval_deg}, {max_interval_deg}] degrees."
|
| 58 |
return f"Solutions for x in [{min_interval_deg}, {max_interval_deg}] degrees: {', '.join(unique_solutions)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import math
|
| 2 |
+
import gradio as gr
|
| 3 |
|
| 4 |
def solve_trig_equations(a: float, b: float, c: float, trig_func: str, interval_degrees: tuple[float, float] = (0, 360)) -> str:
|
| 5 |
"""
|
|
|
|
| 57 |
if not unique_solutions:
|
| 58 |
return f"No solutions found for {a}*{func}(x) + {b} = {c} in the interval [{min_interval_deg}, {max_interval_deg}] degrees."
|
| 59 |
return f"Solutions for x in [{min_interval_deg}, {max_interval_deg}] degrees: {', '.join(unique_solutions)}"
|
| 60 |
+
|
| 61 |
+
def parse_interval(interval_str: str) -> tuple[float, float]:
|
| 62 |
+
try:
|
| 63 |
+
parts = [float(x.strip()) for x in interval_str.split(',')]
|
| 64 |
+
if len(parts) == 2 and parts[0] <= parts[1]:
|
| 65 |
+
return parts[0], parts[1]
|
| 66 |
+
raise ValueError("Interval must be two numbers, min,max.")
|
| 67 |
+
except Exception:
|
| 68 |
+
raise gr.Error("Invalid interval format. Use 'min,max' (e.g., '0,360').")
|
| 69 |
+
|
| 70 |
+
solve_trig_equations_interface = gr.Interface(
|
| 71 |
+
fn=lambda a, b, c, func, interval_str: solve_trig_equations(a, b, c, func, parse_interval(interval_str)),
|
| 72 |
+
inputs=[
|
| 73 |
+
gr.Number(label="a (coefficient of function)"),
|
| 74 |
+
gr.Number(label="b (constant added to function part)"),
|
| 75 |
+
gr.Number(label="c (constant on other side of equation)"),
|
| 76 |
+
gr.Radio(["sin", "cos", "tan"], label="Trigonometric Function"),
|
| 77 |
+
gr.Textbox(label="Interval for x (degrees, comma-separated, e.g., 0,360)", value="0,360")
|
| 78 |
+
],
|
| 79 |
+
outputs="text",
|
| 80 |
+
title="Trigonometric Equation Solver",
|
| 81 |
+
description="Solves equations like a * func(x) + b = c for x in a given interval (degrees)."
|
| 82 |
+
)
|
maths/geometry/tan_degrees.py
CHANGED
|
@@ -1,5 +1,14 @@
|
|
| 1 |
import math
|
|
|
|
| 2 |
|
| 3 |
def tan_degrees(angle):
|
| 4 |
"""Calculate the tangent of an angle in degrees."""
|
| 5 |
return math.tan(math.radians(angle))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import math
|
| 2 |
+
import gradio as gr
|
| 3 |
|
| 4 |
def tan_degrees(angle):
|
| 5 |
"""Calculate the tangent of an angle in degrees."""
|
| 6 |
return math.tan(math.radians(angle))
|
| 7 |
+
|
| 8 |
+
tan_degrees_interface = gr.Interface(
|
| 9 |
+
fn=tan_degrees,
|
| 10 |
+
inputs=gr.Number(label="Angle (degrees)"),
|
| 11 |
+
outputs="number",
|
| 12 |
+
title="Tangent Calculator",
|
| 13 |
+
description="Calculate tangent of an angle in degrees."
|
| 14 |
+
)
|
maths/geometry/trig_identities.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
import math
|
|
|
|
| 2 |
|
| 3 |
def trig_identities(angle_degrees: float, identity_name: str = "pythagorean1") -> str:
|
| 4 |
"""
|
|
@@ -51,3 +52,22 @@ def trig_identities(angle_degrees: float, identity_name: str = "pythagorean1") -
|
|
| 51 |
if not results:
|
| 52 |
return f"Unknown identity: {identity_name}. Available: pythagorean1, pythagorean2, pythagorean3, all."
|
| 53 |
return "\n".join(results)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import math
|
| 2 |
+
import gradio as gr
|
| 3 |
|
| 4 |
def trig_identities(angle_degrees: float, identity_name: str = "pythagorean1") -> str:
|
| 5 |
"""
|
|
|
|
| 52 |
if not results:
|
| 53 |
return f"Unknown identity: {identity_name}. Available: pythagorean1, pythagorean2, pythagorean3, all."
|
| 54 |
return "\n".join(results)
|
| 55 |
+
|
| 56 |
+
trig_identities_interface = gr.Interface(
|
| 57 |
+
fn=trig_identities,
|
| 58 |
+
inputs=[
|
| 59 |
+
gr.Number(label="Angle (degrees)"),
|
| 60 |
+
gr.Radio(
|
| 61 |
+
choices=[
|
| 62 |
+
("sin²(x) + cos²(x) = 1", "pythagorean1"),
|
| 63 |
+
("1 + tan²(x) = sec²(x)", "pythagorean2"),
|
| 64 |
+
("1 + cot²(x) = csc²(x)", "pythagorean3"),
|
| 65 |
+
("All Pythagorean", "all")
|
| 66 |
+
],
|
| 67 |
+
label="Trigonometric Identity to Demonstrate"
|
| 68 |
+
)
|
| 69 |
+
],
|
| 70 |
+
outputs="text",
|
| 71 |
+
title="Trigonometric Identities Demonstrator",
|
| 72 |
+
description="Show common trigonometric identities for a given angle."
|
| 73 |
+
)
|
maths/geometry/trigonometry_interface.py
DELETED
|
@@ -1,79 +0,0 @@
|
|
| 1 |
-
import gradio as gr
|
| 2 |
-
from maths.geometry.sin_degrees import sin_degrees
|
| 3 |
-
from maths.geometry.cos_degrees import cos_degrees
|
| 4 |
-
from maths.geometry.tan_degrees import tan_degrees
|
| 5 |
-
from maths.geometry.inverse_trig_functions import inverse_trig_functions
|
| 6 |
-
from maths.geometry.solve_trig_equations import solve_trig_equations
|
| 7 |
-
from maths.geometry.trig_identities import trig_identities
|
| 8 |
-
|
| 9 |
-
# High School Math Tab
|
| 10 |
-
trig_interface = gr.Interface(
|
| 11 |
-
fn=lambda angle, function: {
|
| 12 |
-
"sin": sin_degrees(angle),
|
| 13 |
-
"cos": cos_degrees(angle),
|
| 14 |
-
"tan": tan_degrees(angle)
|
| 15 |
-
}[function],
|
| 16 |
-
inputs=[
|
| 17 |
-
gr.Number(label="Angle (degrees)"),
|
| 18 |
-
gr.Radio(["sin", "cos", "tan"], label="Trigonometric Function")
|
| 19 |
-
],
|
| 20 |
-
outputs="number",
|
| 21 |
-
title="Trigonometry Calculator",
|
| 22 |
-
description="Calculate trigonometric functions for angles in degrees"
|
| 23 |
-
)
|
| 24 |
-
|
| 25 |
-
inverse_trig_interface = gr.Interface(
|
| 26 |
-
fn=inverse_trig_functions,
|
| 27 |
-
inputs=[
|
| 28 |
-
gr.Number(label="Value"),
|
| 29 |
-
gr.Radio(["asin", "acos", "atan"], label="Inverse Function")
|
| 30 |
-
],
|
| 31 |
-
outputs="text",
|
| 32 |
-
title="Inverse Trigonometry Calculator",
|
| 33 |
-
description="Calculate inverse trigonometric functions. Output in degrees."
|
| 34 |
-
)
|
| 35 |
-
|
| 36 |
-
def parse_interval(interval_str: str) -> tuple[float, float]:
|
| 37 |
-
"""Helper to parse comma-separated interval string (e.g., "0,360") into a tuple."""
|
| 38 |
-
try:
|
| 39 |
-
parts = [float(x.strip()) for x in interval_str.split(',')]
|
| 40 |
-
if len(parts) == 2 and parts[0] <= parts[1]:
|
| 41 |
-
return parts[0], parts[1]
|
| 42 |
-
raise ValueError("Interval must be two numbers, min,max.")
|
| 43 |
-
except Exception:
|
| 44 |
-
# Return a default or raise specific error for Gradio
|
| 45 |
-
raise gr.Error("Invalid interval format. Use 'min,max' (e.g., '0,360').")
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
solve_trig_equations_interface = gr.Interface(
|
| 49 |
-
fn=lambda a, b, c, func, interval_str: solve_trig_equations(a,b,c,func, parse_interval(interval_str)),
|
| 50 |
-
inputs=[
|
| 51 |
-
gr.Number(label="a (coefficient of function)"),
|
| 52 |
-
gr.Number(label="b (constant added to function part)"),
|
| 53 |
-
gr.Number(label="c (constant on other side of equation)"),
|
| 54 |
-
gr.Radio(["sin", "cos", "tan"], label="Trigonometric Function"),
|
| 55 |
-
gr.Textbox(label="Interval for x (degrees, comma-separated, e.g., 0,360)", value="0,360")
|
| 56 |
-
],
|
| 57 |
-
outputs="text",
|
| 58 |
-
title="Trigonometric Equation Solver",
|
| 59 |
-
description="Solves equations like a * func(x) + b = c for x in a given interval (degrees)."
|
| 60 |
-
)
|
| 61 |
-
|
| 62 |
-
trig_identities_interface = gr.Interface(
|
| 63 |
-
fn=trig_identities,
|
| 64 |
-
inputs=[
|
| 65 |
-
gr.Number(label="Angle (degrees)"),
|
| 66 |
-
gr.Radio(
|
| 67 |
-
choices=[
|
| 68 |
-
("sin²(x) + cos²(x) = 1", "pythagorean1"),
|
| 69 |
-
("1 + tan²(x) = sec²(x)", "pythagorean2"),
|
| 70 |
-
("1 + cot²(x) = csc²(x)", "pythagorean3"),
|
| 71 |
-
("All Pythagorean", "all")
|
| 72 |
-
],
|
| 73 |
-
label="Trigonometric Identity to Demonstrate"
|
| 74 |
-
)
|
| 75 |
-
],
|
| 76 |
-
outputs="text",
|
| 77 |
-
title="Trigonometric Identities Demonstrator",
|
| 78 |
-
description="Show common trigonometric identities for a given angle."
|
| 79 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|