Spaces:
Sleeping
Sleeping
Commit
·
79402cb
1
Parent(s):
8bc3098
Initial Commit
Browse files- .gitignore +0 -0
- README.md +2 -0
- app.py +117 -0
- src/main.py +101 -0
- src/piecewise.py +50 -0
- src/product_rule.py +50 -0
.gitignore
ADDED
File without changes
|
README.md
CHANGED
@@ -11,3 +11,5 @@ license: apache-2.0
|
|
11 |
---
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
|
|
11 |
---
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
14 |
+
|
15 |
+
Just a space to visualise single variable calculus things
|
app.py
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from src.main import get_fn, get_dev, get_tangent_line
|
3 |
+
from src.piecewise import get_piecewise_fn, get_piecewise_dev
|
4 |
+
from src.product_rule import get_pr_fn, get_pr_dev
|
5 |
+
|
6 |
+
# to run app: python -m gr_app or gradio gr_app.py
|
7 |
+
|
8 |
+
fn_fig, dev_fig = None, None
|
9 |
+
tl_plot = None
|
10 |
+
|
11 |
+
with gr.Blocks() as scatterplot:
|
12 |
+
with gr.Column():
|
13 |
+
with gr.Row():
|
14 |
+
inp = gr.Textbox(value = "x**2",
|
15 |
+
info = "eg 'np.sqrt(x)'",
|
16 |
+
label = "Enter Your Expression here")
|
17 |
+
inp_2 = gr.Textbox(value = "2",
|
18 |
+
info = "e.g. 2",
|
19 |
+
label = "Which point on x do you want to draw the tangent line?")
|
20 |
+
btn = gr.Button("Run!")
|
21 |
+
|
22 |
+
with gr.Row():
|
23 |
+
fn_scatter = gr.Plot(fn_fig)
|
24 |
+
dev_scatter = gr.Plot(dev_fig)
|
25 |
+
|
26 |
+
tl_scatter = gr.Plot(tl_plot)
|
27 |
+
|
28 |
+
gr.on(triggers = [inp.submit, btn.click],
|
29 |
+
fn=get_fn,
|
30 |
+
inputs = inp,
|
31 |
+
outputs = fn_scatter)
|
32 |
+
gr.on(triggers = [inp.submit, btn.click],
|
33 |
+
fn=get_dev,
|
34 |
+
inputs = inp,
|
35 |
+
outputs = dev_scatter)
|
36 |
+
gr.on(triggers = [inp.submit, inp_2.submit, btn.click],
|
37 |
+
fn=get_tangent_line,
|
38 |
+
inputs = [inp, inp_2],
|
39 |
+
outputs=tl_scatter)
|
40 |
+
|
41 |
+
# dev_obj = None
|
42 |
+
piecewise_fn_fig, piecewise_dev_fig = None, None
|
43 |
+
|
44 |
+
with gr.Blocks() as piecewise:
|
45 |
+
with gr.Column():
|
46 |
+
with gr.Row():
|
47 |
+
with gr.Column():
|
48 |
+
inp_func_1 = gr.Textbox(value = "x**2",
|
49 |
+
info = "eg 'np.sqrt(x)'",
|
50 |
+
label = "Enter Your Expression here")
|
51 |
+
|
52 |
+
inp_sign_1 = gr.Textbox(value = "<",
|
53 |
+
info = "eg <",
|
54 |
+
label = "Enter Your Sign Here")
|
55 |
+
|
56 |
+
with gr.Column():
|
57 |
+
|
58 |
+
inp_func_2 = gr.Textbox(value = "x**3",
|
59 |
+
info = "e.g. x**3",
|
60 |
+
label = "Enter Your Expression here")
|
61 |
+
|
62 |
+
inp_sign_2 = gr.Textbox(value = ">=",
|
63 |
+
info = "eg >=",
|
64 |
+
label = "Enter Your Sign Here")
|
65 |
+
|
66 |
+
inp_point = gr.Textbox(value = "2",
|
67 |
+
info = "e.g. 2",
|
68 |
+
label = "Enter where your point will be separating your piecewise function")
|
69 |
+
|
70 |
+
btn_3 = gr.Button("Run!")
|
71 |
+
|
72 |
+
with gr.Row():
|
73 |
+
piecewise_fn_scatter = gr.Plot(piecewise_fn_fig)
|
74 |
+
piecewise_dev_scatter = gr.Plot(piecewise_dev_fig)
|
75 |
+
|
76 |
+
gr.on(triggers = [inp_func_1.submit, inp_func_2.submit, inp_point.submit, inp_sign_1.submit, inp_sign_2.submit, btn_3.click],
|
77 |
+
fn=get_piecewise_fn,
|
78 |
+
inputs = [inp_func_1, inp_func_2, inp_point, inp_sign_1, inp_sign_2],
|
79 |
+
outputs = piecewise_fn_scatter)
|
80 |
+
|
81 |
+
gr.on(triggers = [inp_func_1.submit, inp_func_2.submit, inp_point.submit, inp_sign_1.submit, inp_sign_2.submit, btn_3.click],
|
82 |
+
fn=get_piecewise_dev,
|
83 |
+
inputs = [inp_func_1, inp_func_2, inp_point, inp_sign_1, inp_sign_2],
|
84 |
+
outputs = piecewise_dev_scatter)
|
85 |
+
|
86 |
+
pr_fn_fig, pr_dev_fig = None, None
|
87 |
+
|
88 |
+
with gr.Blocks() as product_rule:
|
89 |
+
with gr.Column():
|
90 |
+
with gr.Row():
|
91 |
+
inp = gr.Textbox(value = "x**2",
|
92 |
+
info = "eg 'np.sqrt(x)'",
|
93 |
+
label = "Enter Your First Expression here")
|
94 |
+
inp_2 = gr.Textbox(value = "x**3",
|
95 |
+
info = "e.g. x**3",
|
96 |
+
label = "Enter Your Second Expression Here")
|
97 |
+
btn = gr.Button("Run!")
|
98 |
+
|
99 |
+
with gr.Row():
|
100 |
+
pr_fn_scatter = gr.Plot(pr_fn_fig)
|
101 |
+
dev_scatter = gr.Plot(pr_dev_fig)
|
102 |
+
|
103 |
+
gr.on(triggers = [inp.submit, inp_2.submit, btn.click],
|
104 |
+
fn=get_pr_fn,
|
105 |
+
inputs = [inp, inp_2],
|
106 |
+
outputs = pr_fn_scatter)
|
107 |
+
|
108 |
+
gr.on(triggers = [inp.submit, inp_2.submit, btn.click],
|
109 |
+
fn=get_pr_dev,
|
110 |
+
inputs = [inp, inp_2],
|
111 |
+
outputs = dev_scatter)
|
112 |
+
|
113 |
+
demo = gr.TabbedInterface([scatterplot, piecewise, product_rule], ["Single Function", "Piecewise Function", "Product Rule"])
|
114 |
+
|
115 |
+
if __name__ == "__main__":
|
116 |
+
|
117 |
+
demo.launch()
|
src/main.py
ADDED
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import annotations
|
2 |
+
import numpy as np
|
3 |
+
import plotly.express as px
|
4 |
+
import math
|
5 |
+
import plotly.graph_objects as go
|
6 |
+
|
7 |
+
class Derivative:
|
8 |
+
def __init__(self, start_stop_num: List[int, int, int] = [-10, 10, 200], expression: str = "x", function_name: str = None):
|
9 |
+
start, stop, num = start_stop_num
|
10 |
+
|
11 |
+
self.x = np.linspace(start= start, stop= stop, num = num)
|
12 |
+
self.function_name = function_name if function_name else expression
|
13 |
+
self.expression = expression
|
14 |
+
self.h = 0.0001
|
15 |
+
self.y = None
|
16 |
+
self.delta_y = None
|
17 |
+
|
18 |
+
def _function(self):
|
19 |
+
|
20 |
+
def _make_function(x):
|
21 |
+
return eval(self.expression)
|
22 |
+
|
23 |
+
self.y = _make_function(self.x)
|
24 |
+
self.delta_y = _make_function(self.x + self.h)
|
25 |
+
|
26 |
+
def _get_derivative(self):
|
27 |
+
|
28 |
+
if self.delta_y is None or self.y is None:
|
29 |
+
raise Exception("Define your y and delta_y first")
|
30 |
+
|
31 |
+
self.derivative = (self.delta_y - self.y) / self.h
|
32 |
+
return self.derivative
|
33 |
+
|
34 |
+
def _plot_f(self):
|
35 |
+
|
36 |
+
fig = px.scatter(x = self.x, y = self.y, title = self.function_name)
|
37 |
+
return fig
|
38 |
+
|
39 |
+
def _plot_derivative(self):
|
40 |
+
|
41 |
+
fig = px.scatter(x = self.x, y = self.derivative, title = f"Derivative of {self.function_name}")
|
42 |
+
return fig
|
43 |
+
|
44 |
+
def get_slope_one_point(self, x):
|
45 |
+
# using x and y, obtain the slope
|
46 |
+
# y = eval(self.expression)
|
47 |
+
math_expression = self.expression.replace("np", "math")
|
48 |
+
|
49 |
+
def _make_function(x):
|
50 |
+
return eval(math_expression)
|
51 |
+
|
52 |
+
y = _make_function(x)
|
53 |
+
delta_y = _make_function(x + self.h)
|
54 |
+
slope = (delta_y - y) / self.h
|
55 |
+
|
56 |
+
return slope, y
|
57 |
+
|
58 |
+
def get_tangent_line_vals(self, x):
|
59 |
+
slope, y = self.get_slope_one_point(x)
|
60 |
+
tangent_line_y_vals = slope * (self.x - x) + y
|
61 |
+
return y, tangent_line_y_vals
|
62 |
+
|
63 |
+
def draw_tangent_line(self, x):
|
64 |
+
y, tl_y_vals = self.get_tangent_line_vals(x)
|
65 |
+
|
66 |
+
title = f"Tangent line at point({x},{round(y, 2)}) of {self.function_name}"
|
67 |
+
|
68 |
+
if self.y is None:
|
69 |
+
self._function()
|
70 |
+
|
71 |
+
fig = go.Figure()
|
72 |
+
fig.update_layout(title = title)
|
73 |
+
fig.add_trace(go.Scatter(x = self.x, y = tl_y_vals, name = f"Tangent Line at ({x},{round(y, 2)})"))
|
74 |
+
fig.add_trace(go.Scatter(x = self.x, y = self.y, name = self.function_name))
|
75 |
+
|
76 |
+
return fig
|
77 |
+
|
78 |
+
def get_plots(self):
|
79 |
+
return self._plot_f(), self._plot_derivative()
|
80 |
+
|
81 |
+
def __call__(self):
|
82 |
+
|
83 |
+
self._function()
|
84 |
+
self._get_derivative()
|
85 |
+
|
86 |
+
def get_fn(input: str):
|
87 |
+
dev_obj = Derivative(expression = input)
|
88 |
+
dev_obj()
|
89 |
+
fn_fig, _ = dev_obj.get_plots()
|
90 |
+
return fn_fig
|
91 |
+
|
92 |
+
def get_dev(input: str):
|
93 |
+
dev_obj = Derivative(expression = input)
|
94 |
+
dev_obj()
|
95 |
+
_, dev_fig = dev_obj.get_plots()
|
96 |
+
return dev_fig
|
97 |
+
|
98 |
+
def get_tangent_line(input_1: str, input_2: str):
|
99 |
+
dev_obj = Derivative(expression = input_1)
|
100 |
+
tl_fig = dev_obj.draw_tangent_line(int(input_2))
|
101 |
+
return tl_fig
|
src/piecewise.py
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import annotations
|
2 |
+
from src.main import Derivative
|
3 |
+
import numpy as np
|
4 |
+
import plotly.express as px
|
5 |
+
from varname import nameof
|
6 |
+
|
7 |
+
|
8 |
+
class Piecewise():
|
9 |
+
def __init__(self, func_1: str, func_2: str, point: float, signs = ["<", ">="], start_stop_num: List[int, int, int] = [-10, 10, 200]):
|
10 |
+
start, stop, num = start_stop_num
|
11 |
+
x_values = np.linspace(start= start, stop= stop, num = num)
|
12 |
+
left_x_values_range = f"{nameof(x_values)} {signs[0]} {str(point)}"
|
13 |
+
right_x_values_range = f"{nameof(x_values)} {signs[1]} {str(point)}"
|
14 |
+
left_x_values = x_values[eval(left_x_values_range)]
|
15 |
+
right_x_values = x_values[eval(right_x_values_range)]
|
16 |
+
|
17 |
+
self.left_func = Derivative(expression = func_1)
|
18 |
+
self.right_func = Derivative(expression = func_2)
|
19 |
+
|
20 |
+
self.left_func.x = left_x_values
|
21 |
+
self.right_func.x = right_x_values
|
22 |
+
|
23 |
+
self.left_func()
|
24 |
+
self.right_func()
|
25 |
+
|
26 |
+
self.piecewise_func_x = x_values
|
27 |
+
self.piecewise_func_y = np.append(self.left_func.y, self.right_func.y)
|
28 |
+
self.piecewise_func_derivative = np.append(self.left_func.derivative, self.right_func.derivative)
|
29 |
+
|
30 |
+
def _plot_f(self):
|
31 |
+
|
32 |
+
fig = px.scatter(x = self.piecewise_func_x, y = self.piecewise_func_y, title = "Piecewise Function")
|
33 |
+
return fig
|
34 |
+
|
35 |
+
def _plot_dev(self):
|
36 |
+
fig = px.scatter(x = self.piecewise_func_x, y = self.piecewise_func_derivative, title = "Derivative")
|
37 |
+
return fig
|
38 |
+
|
39 |
+
def plot(self):
|
40 |
+
return self._plot_f(), self._plot_dev()
|
41 |
+
|
42 |
+
def get_piecewise_fn(input_1: str, input_2: str, input_3: str, sign_1: str, sign_2: str):
|
43 |
+
piecewise_obj = Piecewise(input_1, input_2, float(input_3), [sign_1, sign_2])
|
44 |
+
f_fig, _ = piecewise_obj.plot()
|
45 |
+
return f_fig
|
46 |
+
|
47 |
+
def get_piecewise_dev(input_1: str, input_2: str, input_3: str, sign_1: str, sign_2: str):
|
48 |
+
piecewise_obj = Piecewise(input_1, input_2, float(input_3), [sign_1, sign_2])
|
49 |
+
_, dev_fig = piecewise_obj.plot()
|
50 |
+
return dev_fig
|
src/product_rule.py
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import annotations
|
2 |
+
|
3 |
+
from src.main import Derivative
|
4 |
+
import plotly.express as px
|
5 |
+
|
6 |
+
class ProductRule:
|
7 |
+
|
8 |
+
def __init__(self, func1_expression, func2_expression, start_stop_num: List[int, int, int] = [-10, 10, 200]):
|
9 |
+
|
10 |
+
self.func1 = Derivative(expression = func1_expression)
|
11 |
+
self.func2 = Derivative(expression = func2_expression)
|
12 |
+
|
13 |
+
self.func1()
|
14 |
+
self.func2()
|
15 |
+
|
16 |
+
self.derivative = self._get_derivative()
|
17 |
+
self.y_values = self._get_y_values()
|
18 |
+
|
19 |
+
def _get_derivative(self):
|
20 |
+
|
21 |
+
product_rule = self.func1.y * self.func2.derivative + self.func1.derivative * self.func2.y
|
22 |
+
|
23 |
+
return product_rule
|
24 |
+
|
25 |
+
def _get_y_values(self):
|
26 |
+
|
27 |
+
return self.func1.y * self.func2.y
|
28 |
+
|
29 |
+
def _plot_f(self):
|
30 |
+
|
31 |
+
fig = px.scatter(x = self.func1.x, y = self.y_values, title = "Product Function")
|
32 |
+
return fig
|
33 |
+
|
34 |
+
def _plot_dev(self):
|
35 |
+
fig = px.scatter(x = self.func1.x, y = self.derivative, title = "Derivative")
|
36 |
+
return fig
|
37 |
+
|
38 |
+
def plot(self):
|
39 |
+
|
40 |
+
return self._plot_f(), self._plot_dev()
|
41 |
+
|
42 |
+
def get_pr_fn(input1: str, input2: str):
|
43 |
+
pr_obj = ProductRule(input1, input2)
|
44 |
+
f_fig, _ = pr_obj.plot()
|
45 |
+
return f_fig
|
46 |
+
|
47 |
+
def get_pr_dev(input1: str, input2: str):
|
48 |
+
pr_obj = ProductRule(input1, input2)
|
49 |
+
_, dev_fig = pr_obj.plot()
|
50 |
+
return dev_fig
|