update
This commit is contained in:
parent
9865095c17
commit
6d4d726447
File diff suppressed because one or more lines are too long
|
@ -7,24 +7,24 @@
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"from optimization.gd import *"
|
"from optimization.gd_new import *"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 2,
|
"execution_count": 2,
|
||||||
"id": "0a5c51d2-8b18-4143-b6f1-73a909ccb623",
|
"id": "8ce3dbbd-a698-448b-a2c6-772286c745d5",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "0bcac263607a46d19fead8b1cf79e498",
|
"model_id": "5715c7beff3c4ab58a001fecee2e6ba9",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"VBox(children=(HBox(children=(VBox(children=(Text(value='x**3 - x**(1/2)', description='Expression:', style=Te…"
|
"VBox(children=(HBox(children=(VBox(children=(Text(value='-2 * x * sin(-(pi/4) * x)+10', description='Expressio…"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "3f64c031482d41799291390431aa3264",
|
"model_id": "60025f1dfc974c4ba4765136faa526e8",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "0504d25c3aab477ca0acf3d054dbaf92",
|
"model_id": "52d1cde962ba4b7dad5c4e581fc5aee1",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
@ -60,24 +60,24 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"gd1 = gradient_descent_1d(environ=\"jupyterlab\")"
|
"gd1 = gd_1d()"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 5,
|
"execution_count": 3,
|
||||||
"id": "15c6e757-cde3-422b-be7e-3f55b7752142",
|
"id": "a1765810-6cd8-4e1a-aaa6-7691a7b2a42e",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "fca48b98af304f1d821c948d8dcc8629",
|
"model_id": "f6ef2a67373b4552b4d866c633e8b9a7",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"VBox(children=(HBox(children=(Dropdown(index=2, options=(('(sin(x1) - 2) + (sin(x2) - 2) ** 2', '(sin(x1) - 2)…"
|
"VBox(children=(HBox(children=(Dropdown(options=(('(1 - 8 * x1 + 7 * x1**2 - (7/3) * x1**3 + (1/4) * x1**4) * x…"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
|
@ -86,7 +86,7 @@
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "f25a00c1bb294530973475c7a5c8bb10",
|
"model_id": "ece751b11bc643a196bc17d87d90499e",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
@ -100,7 +100,21 @@
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "4afc98f7c6954a58aba389526ba09164",
|
"model_id": "17c95b2c789044439b3e4412a41cdff4",
|
||||||
|
"version_major": 2,
|
||||||
|
"version_minor": 0
|
||||||
|
},
|
||||||
|
"text/plain": [
|
||||||
|
"Output()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
|
"model_id": "8452902c477d4e25a51e0cb937babf6e",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
|
@ -113,66 +127,13 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"gd2 = gradient_descent_2d(environ=\"jupyterlab\")"
|
"gd2 = gd_2d()"
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 4,
|
|
||||||
"id": "694b7e27-cc21-44f4-9a89-7a6b97725a64",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
|
||||||
"model_id": "f1d170fccfee4e5891a3c33ad564c197",
|
|
||||||
"version_major": 2,
|
|
||||||
"version_minor": 0
|
|
||||||
},
|
|
||||||
"text/plain": [
|
|
||||||
"VBox(children=(Text(value='(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2', description='Expression:'), Text(value='(…"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "display_data"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
|
||||||
"model_id": "e6a5a98d84b54da7b1ac6deaa408ed5d",
|
|
||||||
"version_major": 2,
|
|
||||||
"version_minor": 0
|
|
||||||
},
|
|
||||||
"text/plain": [
|
|
||||||
"Output()"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "display_data"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
|
||||||
"model_id": "5b35d3e6383947cfb24f1663388ef556",
|
|
||||||
"version_major": 2,
|
|
||||||
"version_minor": 0
|
|
||||||
},
|
|
||||||
"text/plain": [
|
|
||||||
"Output()"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "display_data"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"gd2_race = gradient_descent_2d_race(environ=\"jupyterlab\")"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": null,
|
||||||
"id": "d6001078-5cf2-402e-b37e-a6dad90674a6",
|
"id": "48944e3c-932a-4733-b77d-a2b50cee2e5a",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": []
|
"source": []
|
||||||
|
|
|
@ -17,88 +17,6 @@ import plotly.io as pio
|
||||||
import warnings
|
import warnings
|
||||||
warnings.filterwarnings("ignore")
|
warnings.filterwarnings("ignore")
|
||||||
|
|
||||||
class gradient_descent_1d(object):
|
|
||||||
def __init__(self, environ:str="jupyterlab"):
|
|
||||||
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
|
||||||
self.wg_expr = widgets.Text(value="x**3 - x**(1/2)",
|
|
||||||
description="Expression:",
|
|
||||||
style={'description_width': 'initial'})
|
|
||||||
self.wg_x0 = widgets.FloatText(value="2",
|
|
||||||
description="Startpoint:",
|
|
||||||
style={'description_width': 'initial'})
|
|
||||||
self.wg_lr = widgets.FloatText(value="1e-1",
|
|
||||||
description="step size:",
|
|
||||||
style={'description_width': 'initial'})
|
|
||||||
self.wg_epsilon = widgets.FloatText(value="1e-5",
|
|
||||||
description="criterion:",
|
|
||||||
style={'description_width': 'initial'})
|
|
||||||
self.wg_max_iter = widgets.IntText(value="1000",
|
|
||||||
description="max iteration",
|
|
||||||
style={'description_width': 'initial'})
|
|
||||||
|
|
||||||
self.button_compute = widgets.Button(description="Compute")
|
|
||||||
self.button_plot = widgets.Button(description="Plot")
|
|
||||||
|
|
||||||
self.compute_output = widgets.Output()
|
|
||||||
self.plot_output = widgets.Output()
|
|
||||||
self.params_lvbox = widgets.VBox([self.wg_expr, self.wg_x0, self.wg_lr])
|
|
||||||
self.params_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter])
|
|
||||||
self.params_box = widgets.HBox([self.params_lvbox, self.params_rvbox], description="Parameters")
|
|
||||||
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
|
||||||
self.config = widgets.VBox([self.params_box, self.button_box])
|
|
||||||
self.initialization()
|
|
||||||
|
|
||||||
|
|
||||||
def initialization(self):
|
|
||||||
display(self.config)
|
|
||||||
self.button_compute.on_click(self.compute)
|
|
||||||
display(self.compute_output)
|
|
||||||
self.button_plot.on_click(self.plot)
|
|
||||||
display(self.plot_output)
|
|
||||||
|
|
||||||
def compute(self, *args):
|
|
||||||
with self.compute_output:
|
|
||||||
xn = self.wg_x0.value
|
|
||||||
x = symbols("x")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
f = lambdify(x, expr)
|
|
||||||
df = lambdify(x, diff(expr, x))
|
|
||||||
self.xn_list, self.df_list = [], []
|
|
||||||
|
|
||||||
for n in tqdm(range(0, self.wg_max_iter.value)):
|
|
||||||
gradient = df(xn)
|
|
||||||
self.xn_list.append(xn)
|
|
||||||
self.df_list.append(gradient)
|
|
||||||
if abs (gradient < self.wg_epsilon.value):
|
|
||||||
clear_output(wait=True)
|
|
||||||
print("Found solution of {} after".format(expr), n, "iterations")
|
|
||||||
print("x* = {}".format(xn))
|
|
||||||
return None
|
|
||||||
xn = xn - self.wg_lr.value * gradient
|
|
||||||
clear_output(wait=True)
|
|
||||||
display("Exceeded maximum iterations. No solution found.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def plot(self, *args):
|
|
||||||
with self.plot_output:
|
|
||||||
clear_output(wait=True)
|
|
||||||
x0 = float(self.wg_x0.value)
|
|
||||||
x = symbols("x")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
f = lambdify(x, sympify(expr), "numpy")
|
|
||||||
xx1 = np.arange(np.array(self.xn_list).min()*0.5, np.array(self.xn_list).max()*1.5, 0.05)
|
|
||||||
fx = f(xx1)
|
|
||||||
f_xn = f(np.array(self.xn_list))
|
|
||||||
|
|
||||||
fig = go.Figure()
|
|
||||||
fig.add_scatter(x=xx1, y=fx)
|
|
||||||
frames = []
|
|
||||||
frames.append({'data':copy.deepcopy(fig['data']),'name':f'frame{0}'})
|
|
||||||
fig.add_traces(go.Scatter(x=None, y=None, mode="lines + markers", line={"color":"#de1032", "width":5}))
|
|
||||||
frames = [go.Frame(data= [go.Scatter(x=np.array(self.xn_list)[:k], y=f_xn)],traces= [1],name=f'frame{k+2}')for k in range(len(f_xn))]
|
|
||||||
fig.update(frames=frames)
|
|
||||||
fig.update_layout(updatemenus=[dict(type="buttons",buttons=[dict(label="Play",method="animate",args=[None])])])
|
|
||||||
fig.show()
|
|
||||||
|
|
||||||
class gradient_descent_2d(object):
|
class gradient_descent_2d(object):
|
||||||
def __init__(self, environ:str="jupyterlab"):
|
def __init__(self, environ:str="jupyterlab"):
|
||||||
|
@ -178,7 +96,7 @@ class gradient_descent_2d(object):
|
||||||
f_xn = f(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
f_xn = f(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
||||||
partial_x1 = lambdify((x1, x2), diff(expr, x1), "numpy")
|
partial_x1 = lambdify((x1, x2), diff(expr, x1), "numpy")
|
||||||
partial_x2 = lambdify((x1, x2), diff(expr, x2), "numpy")
|
partial_x2 = lambdify((x1, x2), diff(expr, x2), "numpy")
|
||||||
plane = partial_x1(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x1 - np.array(self.xn_list)[:, 0]) + partial_x2(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x2 - np.array(self.xn_list)[:, 0]) + f_xn
|
plane = partial_x1(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x1 - np.array(self.xn_list)[:, 0]) + partial_x2(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x2 - np.array(self.xn_list)[:, 1]) + f_xn
|
||||||
z = [lambdify((x1, x2), plane[i], "numpy")(xx1_tangent, xx2_tangent) for i in range(0, len(plane))]
|
z = [lambdify((x1, x2), plane[i], "numpy")(xx1_tangent, xx2_tangent) for i in range(0, len(plane))]
|
||||||
|
|
||||||
frames, steps = [], []
|
frames, steps = [], []
|
||||||
|
@ -210,229 +128,11 @@ class gradient_descent_2d(object):
|
||||||
len=1.0)
|
len=1.0)
|
||||||
]
|
]
|
||||||
|
|
||||||
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=False, opacity=0.8)
|
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=False, opacity=0.6)
|
||||||
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
||||||
trace3 = go.Surface(x=None, y=None, z=None, showscale=False, opacity=0.5, colorscale='Blues')
|
fig = go.Figure(data=[trace1, trace2], frames=frames)
|
||||||
fig = go.Figure(data=[trace1, trace2, trace3], frames=frames)
|
|
||||||
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
||||||
dict(label="Pause", method="animate", args=[[None], \
|
dict(label="Pause", method="animate", args=[[None], \
|
||||||
dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
||||||
margin=dict(r=20, l=10, b=10, t=10), sliders=sliders)
|
margin=dict(r=20, l=10, b=10, t=10), sliders=sliders)
|
||||||
fig.show()
|
fig.show()
|
||||||
|
|
||||||
class gradient_descent_2d_custom(object):
|
|
||||||
def __init__(self, environ:str="jupyterlab"):
|
|
||||||
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
|
||||||
|
|
||||||
self.wg_expr = widgets.Text(value="(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2", description="Expression:")
|
|
||||||
self.wg_x0 = widgets.Text(value="5,5", description="Startpoint:")
|
|
||||||
self.wg_lr = widgets.FloatText(value="1e-1", description="step size:")
|
|
||||||
self.wg_epsilon = widgets.FloatText(value="1e-5", description="criterion:")
|
|
||||||
self.wg_max_iter = widgets.IntText(value="1000", description="max iteration")
|
|
||||||
self.button_compute = widgets.Button(description="Compute")
|
|
||||||
self.button_plot = widgets.Button(description="Plot")
|
|
||||||
|
|
||||||
self.compute_output = widgets.Output()
|
|
||||||
self.plot_output = widgets.Output()
|
|
||||||
self.params_lvbox = widgets.VBox([self.wg_expr, self.wg_x0, self.wg_lr])
|
|
||||||
self.params_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter])
|
|
||||||
self.params_box = widgets.HBox([self.params_lvbox, self.params_rvbox], description="Parameters")
|
|
||||||
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
|
||||||
self.config = widgets.VBox([self.params_box, self.button_box])
|
|
||||||
self.initialization()
|
|
||||||
|
|
||||||
def initialization(self):
|
|
||||||
display(self.config)
|
|
||||||
self.button_compute.on_click(self.compute)
|
|
||||||
display(self.compute_output)
|
|
||||||
self.button_plot.on_click(self.plot)
|
|
||||||
display(self.plot_output)
|
|
||||||
|
|
||||||
def compute(self, *args):
|
|
||||||
with self.compute_output:
|
|
||||||
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
|
||||||
xn = x0
|
|
||||||
x1 = symbols("x1")
|
|
||||||
x2 = symbols("x2")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
self.xn_list, self.df_list = [], []
|
|
||||||
for n in tqdm(range(0, self.wg_max_iter.value)):
|
|
||||||
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
|
||||||
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
|
||||||
self.xn_list.append(xn)
|
|
||||||
self.df_list.append(gradient)
|
|
||||||
if np.linalg.norm(gradient, ord=2) < self.wg_epsilon.value:
|
|
||||||
clear_output(wait=True)
|
|
||||||
print("Found solution of {} after".format(expr), n, "iterations")
|
|
||||||
print("x* = [{}, {}]".format(xn[0], xn[1]))
|
|
||||||
return None
|
|
||||||
xn = xn - self.wg_lr.value * gradient
|
|
||||||
clear_output(wait=True)
|
|
||||||
display("Exceeded maximum iterations. No solution found.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def plot(self, *args):
|
|
||||||
with self.plot_output:
|
|
||||||
clear_output(wait=True)
|
|
||||||
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
|
||||||
x1 = symbols("x1")
|
|
||||||
x2 = symbols("x2")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
xx1 = np.arange(np.array(self.xn_list)[:, 0].min()*0.5, np.array(self.xn_list)[:, 0].max()*1.5, 0.05)
|
|
||||||
xx2 = np.arange(np.array(self.xn_list)[:, 1].min()*0.5, np.array(self.xn_list)[:, 1].max()*1.5, 0.05)
|
|
||||||
xx1, xx2 = np.meshgrid(xx1, xx2)
|
|
||||||
|
|
||||||
f = lambdify((x1, x2), expr, "numpy")
|
|
||||||
fx = f(xx1, xx2)
|
|
||||||
f_xn = f(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
|
||||||
|
|
||||||
frames, steps = [], []
|
|
||||||
for k in range(len(f_xn)):
|
|
||||||
#frame = go.Frame(data=[go.Surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.8)])
|
|
||||||
#fig.add_trace(go.Scatter3d(x=np.array(self.xn_list)[:k, 0], y=np.array(self.xn_list)[:k, 1], z=f_xn))
|
|
||||||
frame = go.Frame(dict(data=[go.Scatter3d(x=np.array(self.xn_list)[:k,0], y=np.array(self.xn_list)[:k,1], z=f_xn)], name=f'frame{k+1}'), traces=[1])
|
|
||||||
frames.append(frame)
|
|
||||||
step = dict(
|
|
||||||
method="update",
|
|
||||||
args=[{"visible": [True]},
|
|
||||||
{"title": "Slider switched to step: " + str(k+1)}], # layout attribute
|
|
||||||
)
|
|
||||||
steps.append(step)
|
|
||||||
|
|
||||||
sliders = [dict(steps= [dict(method= 'animate',
|
|
||||||
args= [[f'frame{k+1}'],
|
|
||||||
dict(mode= 'immediate',
|
|
||||||
frame= dict( duration=0, redraw= True ),
|
|
||||||
transition=dict( duration=0)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
#label='Date : {}'.format(date_range[k])
|
|
||||||
) for k in range(0,len(frames))],
|
|
||||||
transition= dict(duration=0),
|
|
||||||
x=0,
|
|
||||||
y=0,
|
|
||||||
currentvalue=dict(font=dict(size=12), visible=True, xanchor= 'center'),
|
|
||||||
len=1.0)
|
|
||||||
]
|
|
||||||
|
|
||||||
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.8)
|
|
||||||
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
|
||||||
fig = go.Figure(data=[trace1, trace2], frames=frames)
|
|
||||||
#fig.add_surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.9)
|
|
||||||
#fig.update_traces(contours_z=dict(show=True, usecolormap=True, highlightcolor="limegreen", project_z=True))
|
|
||||||
#fig.update(frames=frames)
|
|
||||||
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
|
||||||
dict(label="Pause", method="animate", args=[[None], dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
|
||||||
margin=dict(l=0, r=0, b=0, t=0), sliders=sliders)
|
|
||||||
fig.show()
|
|
||||||
|
|
||||||
class gradient_descent_2d_race(object):
|
|
||||||
def __init__(self, environ:str="jupyterlab"):
|
|
||||||
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
|
||||||
self.wg_expr = widgets.Text(value="(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2", description="Expression:")
|
|
||||||
self.wg_person_one = widgets.Text(value="(5, 5)", description="candidate 1:")
|
|
||||||
self.wg_person_two = widgets.Text(value="(5, 5)", description="candidate 2:")
|
|
||||||
self.button_compute = widgets.Button(description="Compute")
|
|
||||||
self.button_plot = widgets.Button(description="Plot")
|
|
||||||
|
|
||||||
self.compute_output = widgets.Output()
|
|
||||||
self.plot_output = widgets.Output()
|
|
||||||
|
|
||||||
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
|
||||||
self.config = widgets.VBox([self.wg_expr, self.wg_person_one, self.wg_person_two, self.button_box])
|
|
||||||
self.xn_list_p1, self.df_list_p1 = [], []
|
|
||||||
self.xn_list_p2, self.df_list_p2 = [], []
|
|
||||||
self.initialization()
|
|
||||||
|
|
||||||
def initialization(self):
|
|
||||||
display(self.config)
|
|
||||||
self.button_compute.on_click(self.compute)
|
|
||||||
display(self.compute_output)
|
|
||||||
self.button_plot.on_click(self.plot)
|
|
||||||
display(self.plot_output)
|
|
||||||
|
|
||||||
def compute(self, *args):
|
|
||||||
with self.compute_output:
|
|
||||||
# person_one
|
|
||||||
x0 = np.array(self.wg_person_one.value.split("(")[1].split(")")[0].split(","), dtype=float)
|
|
||||||
xn = x0
|
|
||||||
x1 = symbols("x1")
|
|
||||||
x2 = symbols("x2")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
|
||||||
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
|
||||||
self.xn_list_p1.append(xn)
|
|
||||||
self.df_list_p1.append(gradient)
|
|
||||||
print("player one: x = [{}, {}]".format(xn[0], xn[1]))
|
|
||||||
print("player one: gradient= {}".format(gradient))
|
|
||||||
# person_two
|
|
||||||
x0 = np.array(self.wg_person_two.value.split("(")[1].split(")")[0].split(","), dtype=float)
|
|
||||||
xn = x0
|
|
||||||
x1 = symbols("x1")
|
|
||||||
x2 = symbols("x2")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
|
||||||
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
|
||||||
self.xn_list_p2.append(xn)
|
|
||||||
self.df_list_p2.append(gradient)
|
|
||||||
print("player two: x = [{}, {}]".format(xn[0], xn[1]))
|
|
||||||
print("player two: gradient= {}".format(gradient))
|
|
||||||
clear_output(wait=True)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def plot(self, *args):
|
|
||||||
with self.plot_output:
|
|
||||||
clear_output(wait=True)
|
|
||||||
#x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
|
||||||
x1 = symbols("x1")
|
|
||||||
x2 = symbols("x2")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
xx1 = np.arange(np.array(self.xn_list_p1)[:, 0].min()*0.5, np.array(self.xn_list_p1)[:, 0].max()*1.5, 0.1)
|
|
||||||
xx2 = np.arange(np.array(self.xn_list_p1)[:, 1].min()*0.5, np.array(self.xn_list_p1)[:, 1].max()*1.5, 0.1)
|
|
||||||
xx1, xx2 = np.meshgrid(xx1, xx2)
|
|
||||||
|
|
||||||
f = lambdify((x1, x2), expr, "numpy")
|
|
||||||
fx = f(xx1, xx2)
|
|
||||||
f_xn_p1 = f(np.array(self.xn_list_p1)[:, 0], np.array(self.xn_list_p1)[:, 1])
|
|
||||||
f_xn_p2 = f(np.array(self.xn_list_p2)[:, 0], np.array(self.xn_list_p2)[:, 1])
|
|
||||||
|
|
||||||
frames, steps = [], []
|
|
||||||
for k in range(len(f_xn_p1)):
|
|
||||||
tmp_trace1 = go.Scatter3d(x=np.array(self.xn_list_p1)[:k,0], y=np.array(self.xn_list_p1)[:k,1], z=f_xn_p1)
|
|
||||||
tmp_trace2 = go.Scatter3d(x=np.array(self.xn_list_p2)[:k,0], y=np.array(self.xn_list_p2)[:k,1], z=f_xn_p2)
|
|
||||||
frame = go.Frame(dict(data=[tmp_trace1, tmp_trace2], name=f'frame{k+1}'), traces=[1, 2])
|
|
||||||
frames.append(frame)
|
|
||||||
step = dict(
|
|
||||||
method="update",
|
|
||||||
args=[{"visible": [True]},
|
|
||||||
{"title": "Slider switched to step: " + str(k+1)}], # layout attribute
|
|
||||||
)
|
|
||||||
steps.append(step)
|
|
||||||
|
|
||||||
sliders = [dict(steps= [dict(method= 'animate',
|
|
||||||
args= [[f'frame{k+1}'],
|
|
||||||
dict(mode= 'immediate',
|
|
||||||
frame= dict( duration=0, redraw= True ),
|
|
||||||
transition=dict( duration=0)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
#label='Date : {}'.format(date_range[k])
|
|
||||||
) for k in range(0,len(frames))],
|
|
||||||
transition= dict(duration=0),
|
|
||||||
x=0,
|
|
||||||
y=0,
|
|
||||||
currentvalue=dict(font=dict(size=12), visible=True, xanchor= 'center'),
|
|
||||||
len=1.0)
|
|
||||||
]
|
|
||||||
|
|
||||||
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.4)
|
|
||||||
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
|
||||||
trace3 = go.Scatter3d(x=None, y=None, z=None)
|
|
||||||
fig = go.Figure(data=[trace1, trace2, trace3], frames=frames)
|
|
||||||
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
|
||||||
dict(label="Pause", method="animate", args=[[None], dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
|
||||||
margin=dict(l=20, r=20, b=20, t=20), sliders=sliders)
|
|
||||||
fig.show()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -17,88 +17,6 @@ import plotly.io as pio
|
||||||
import warnings
|
import warnings
|
||||||
warnings.filterwarnings("ignore")
|
warnings.filterwarnings("ignore")
|
||||||
|
|
||||||
class gradient_descent_1d(object):
|
|
||||||
def __init__(self, environ:str="jupyterlab"):
|
|
||||||
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
|
||||||
self.wg_expr = widgets.Text(value="x**3 - x**(1/2)",
|
|
||||||
description="Expression:",
|
|
||||||
style={'description_width': 'initial'})
|
|
||||||
self.wg_x0 = widgets.FloatText(value="2",
|
|
||||||
description="Startpoint:",
|
|
||||||
style={'description_width': 'initial'})
|
|
||||||
self.wg_lr = widgets.FloatText(value="1e-1",
|
|
||||||
description="step size:",
|
|
||||||
style={'description_width': 'initial'})
|
|
||||||
self.wg_epsilon = widgets.FloatText(value="1e-5",
|
|
||||||
description="criterion:",
|
|
||||||
style={'description_width': 'initial'})
|
|
||||||
self.wg_max_iter = widgets.IntText(value="1000",
|
|
||||||
description="max iteration",
|
|
||||||
style={'description_width': 'initial'})
|
|
||||||
|
|
||||||
self.button_compute = widgets.Button(description="Compute")
|
|
||||||
self.button_plot = widgets.Button(description="Plot")
|
|
||||||
|
|
||||||
self.compute_output = widgets.Output()
|
|
||||||
self.plot_output = widgets.Output()
|
|
||||||
self.params_lvbox = widgets.VBox([self.wg_expr, self.wg_x0, self.wg_lr])
|
|
||||||
self.params_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter])
|
|
||||||
self.params_box = widgets.HBox([self.params_lvbox, self.params_rvbox], description="Parameters")
|
|
||||||
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
|
||||||
self.config = widgets.VBox([self.params_box, self.button_box])
|
|
||||||
self.initialization()
|
|
||||||
|
|
||||||
|
|
||||||
def initialization(self):
|
|
||||||
display(self.config)
|
|
||||||
self.button_compute.on_click(self.compute)
|
|
||||||
display(self.compute_output)
|
|
||||||
self.button_plot.on_click(self.plot)
|
|
||||||
display(self.plot_output)
|
|
||||||
|
|
||||||
def compute(self, *args):
|
|
||||||
with self.compute_output:
|
|
||||||
xn = self.wg_x0.value
|
|
||||||
x = symbols("x")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
f = lambdify(x, expr)
|
|
||||||
df = lambdify(x, diff(expr, x))
|
|
||||||
self.xn_list, self.df_list = [], []
|
|
||||||
|
|
||||||
for n in tqdm(range(0, self.wg_max_iter.value)):
|
|
||||||
gradient = df(xn)
|
|
||||||
self.xn_list.append(xn)
|
|
||||||
self.df_list.append(gradient)
|
|
||||||
if abs (gradient < self.wg_epsilon.value):
|
|
||||||
clear_output(wait=True)
|
|
||||||
print("Found solution of {} after".format(expr), n, "iterations")
|
|
||||||
print("x* = {}".format(xn))
|
|
||||||
return None
|
|
||||||
xn = xn - self.wg_lr.value * gradient
|
|
||||||
clear_output(wait=True)
|
|
||||||
display("Exceeded maximum iterations. No solution found.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def plot(self, *args):
|
|
||||||
with self.plot_output:
|
|
||||||
clear_output(wait=True)
|
|
||||||
x0 = float(self.wg_x0.value)
|
|
||||||
x = symbols("x")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
f = lambdify(x, sympify(expr), "numpy")
|
|
||||||
xx1 = np.arange(np.array(self.xn_list).min()*0.5, np.array(self.xn_list).max()*1.5, 0.05)
|
|
||||||
fx = f(xx1)
|
|
||||||
f_xn = f(np.array(self.xn_list))
|
|
||||||
|
|
||||||
fig = go.Figure()
|
|
||||||
fig.add_scatter(x=xx1, y=fx)
|
|
||||||
frames = []
|
|
||||||
frames.append({'data':copy.deepcopy(fig['data']),'name':f'frame{0}'})
|
|
||||||
fig.add_traces(go.Scatter(x=None, y=None, mode="lines + markers", line={"color":"#de1032", "width":5}))
|
|
||||||
frames = [go.Frame(data= [go.Scatter(x=np.array(self.xn_list)[:k], y=f_xn)],traces= [1],name=f'frame{k+2}')for k in range(len(f_xn))]
|
|
||||||
fig.update(frames=frames)
|
|
||||||
fig.update_layout(updatemenus=[dict(type="buttons",buttons=[dict(label="Play",method="animate",args=[None])])])
|
|
||||||
fig.show()
|
|
||||||
|
|
||||||
class gradient_descent_2d(object):
|
class gradient_descent_2d(object):
|
||||||
def __init__(self, environ:str="jupyterlab"):
|
def __init__(self, environ:str="jupyterlab"):
|
||||||
|
@ -178,7 +96,7 @@ class gradient_descent_2d(object):
|
||||||
f_xn = f(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
f_xn = f(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
||||||
partial_x1 = lambdify((x1, x2), diff(expr, x1), "numpy")
|
partial_x1 = lambdify((x1, x2), diff(expr, x1), "numpy")
|
||||||
partial_x2 = lambdify((x1, x2), diff(expr, x2), "numpy")
|
partial_x2 = lambdify((x1, x2), diff(expr, x2), "numpy")
|
||||||
plane = partial_x1(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x1 - np.array(self.xn_list)[:, 0]) + partial_x2(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x2 - np.array(self.xn_list)[:, 0]) + f_xn
|
plane = partial_x1(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x1 - np.array(self.xn_list)[:, 0]) + partial_x2(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x2 - np.array(self.xn_list)[:, 1]) + f_xn
|
||||||
z = [lambdify((x1, x2), plane[i], "numpy")(xx1_tangent, xx2_tangent) for i in range(0, len(plane))]
|
z = [lambdify((x1, x2), plane[i], "numpy")(xx1_tangent, xx2_tangent) for i in range(0, len(plane))]
|
||||||
|
|
||||||
frames, steps = [], []
|
frames, steps = [], []
|
||||||
|
@ -210,229 +128,11 @@ class gradient_descent_2d(object):
|
||||||
len=1.0)
|
len=1.0)
|
||||||
]
|
]
|
||||||
|
|
||||||
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=False, opacity=0.8)
|
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=False, opacity=0.6)
|
||||||
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
||||||
trace3 = go.Surface(x=None, y=None, z=None, showscale=False, opacity=0.5, colorscale='Blues')
|
fig = go.Figure(data=[trace1, trace2], frames=frames)
|
||||||
fig = go.Figure(data=[trace1, trace2, trace3], frames=frames)
|
|
||||||
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
||||||
dict(label="Pause", method="animate", args=[[None], \
|
dict(label="Pause", method="animate", args=[[None], \
|
||||||
dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
||||||
margin=dict(r=20, l=10, b=10, t=10), sliders=sliders)
|
margin=dict(r=20, l=10, b=10, t=10), sliders=sliders)
|
||||||
fig.show()
|
fig.show()
|
||||||
|
|
||||||
class gradient_descent_2d_custom(object):
|
|
||||||
def __init__(self, environ:str="jupyterlab"):
|
|
||||||
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
|
||||||
|
|
||||||
self.wg_expr = widgets.Text(value="(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2", description="Expression:")
|
|
||||||
self.wg_x0 = widgets.Text(value="5,5", description="Startpoint:")
|
|
||||||
self.wg_lr = widgets.FloatText(value="1e-1", description="step size:")
|
|
||||||
self.wg_epsilon = widgets.FloatText(value="1e-5", description="criterion:")
|
|
||||||
self.wg_max_iter = widgets.IntText(value="1000", description="max iteration")
|
|
||||||
self.button_compute = widgets.Button(description="Compute")
|
|
||||||
self.button_plot = widgets.Button(description="Plot")
|
|
||||||
|
|
||||||
self.compute_output = widgets.Output()
|
|
||||||
self.plot_output = widgets.Output()
|
|
||||||
self.params_lvbox = widgets.VBox([self.wg_expr, self.wg_x0, self.wg_lr])
|
|
||||||
self.params_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter])
|
|
||||||
self.params_box = widgets.HBox([self.params_lvbox, self.params_rvbox], description="Parameters")
|
|
||||||
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
|
||||||
self.config = widgets.VBox([self.params_box, self.button_box])
|
|
||||||
self.initialization()
|
|
||||||
|
|
||||||
def initialization(self):
|
|
||||||
display(self.config)
|
|
||||||
self.button_compute.on_click(self.compute)
|
|
||||||
display(self.compute_output)
|
|
||||||
self.button_plot.on_click(self.plot)
|
|
||||||
display(self.plot_output)
|
|
||||||
|
|
||||||
def compute(self, *args):
|
|
||||||
with self.compute_output:
|
|
||||||
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
|
||||||
xn = x0
|
|
||||||
x1 = symbols("x1")
|
|
||||||
x2 = symbols("x2")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
self.xn_list, self.df_list = [], []
|
|
||||||
for n in tqdm(range(0, self.wg_max_iter.value)):
|
|
||||||
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
|
||||||
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
|
||||||
self.xn_list.append(xn)
|
|
||||||
self.df_list.append(gradient)
|
|
||||||
if np.linalg.norm(gradient, ord=2) < self.wg_epsilon.value:
|
|
||||||
clear_output(wait=True)
|
|
||||||
print("Found solution of {} after".format(expr), n, "iterations")
|
|
||||||
print("x* = [{}, {}]".format(xn[0], xn[1]))
|
|
||||||
return None
|
|
||||||
xn = xn - self.wg_lr.value * gradient
|
|
||||||
clear_output(wait=True)
|
|
||||||
display("Exceeded maximum iterations. No solution found.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def plot(self, *args):
|
|
||||||
with self.plot_output:
|
|
||||||
clear_output(wait=True)
|
|
||||||
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
|
||||||
x1 = symbols("x1")
|
|
||||||
x2 = symbols("x2")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
xx1 = np.arange(np.array(self.xn_list)[:, 0].min()*0.5, np.array(self.xn_list)[:, 0].max()*1.5, 0.05)
|
|
||||||
xx2 = np.arange(np.array(self.xn_list)[:, 1].min()*0.5, np.array(self.xn_list)[:, 1].max()*1.5, 0.05)
|
|
||||||
xx1, xx2 = np.meshgrid(xx1, xx2)
|
|
||||||
|
|
||||||
f = lambdify((x1, x2), expr, "numpy")
|
|
||||||
fx = f(xx1, xx2)
|
|
||||||
f_xn = f(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
|
||||||
|
|
||||||
frames, steps = [], []
|
|
||||||
for k in range(len(f_xn)):
|
|
||||||
#frame = go.Frame(data=[go.Surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.8)])
|
|
||||||
#fig.add_trace(go.Scatter3d(x=np.array(self.xn_list)[:k, 0], y=np.array(self.xn_list)[:k, 1], z=f_xn))
|
|
||||||
frame = go.Frame(dict(data=[go.Scatter3d(x=np.array(self.xn_list)[:k,0], y=np.array(self.xn_list)[:k,1], z=f_xn)], name=f'frame{k+1}'), traces=[1])
|
|
||||||
frames.append(frame)
|
|
||||||
step = dict(
|
|
||||||
method="update",
|
|
||||||
args=[{"visible": [True]},
|
|
||||||
{"title": "Slider switched to step: " + str(k+1)}], # layout attribute
|
|
||||||
)
|
|
||||||
steps.append(step)
|
|
||||||
|
|
||||||
sliders = [dict(steps= [dict(method= 'animate',
|
|
||||||
args= [[f'frame{k+1}'],
|
|
||||||
dict(mode= 'immediate',
|
|
||||||
frame= dict( duration=0, redraw= True ),
|
|
||||||
transition=dict( duration=0)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
#label='Date : {}'.format(date_range[k])
|
|
||||||
) for k in range(0,len(frames))],
|
|
||||||
transition= dict(duration=0),
|
|
||||||
x=0,
|
|
||||||
y=0,
|
|
||||||
currentvalue=dict(font=dict(size=12), visible=True, xanchor= 'center'),
|
|
||||||
len=1.0)
|
|
||||||
]
|
|
||||||
|
|
||||||
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.8)
|
|
||||||
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
|
||||||
fig = go.Figure(data=[trace1, trace2], frames=frames)
|
|
||||||
#fig.add_surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.9)
|
|
||||||
#fig.update_traces(contours_z=dict(show=True, usecolormap=True, highlightcolor="limegreen", project_z=True))
|
|
||||||
#fig.update(frames=frames)
|
|
||||||
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
|
||||||
dict(label="Pause", method="animate", args=[[None], dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
|
||||||
margin=dict(l=0, r=0, b=0, t=0), sliders=sliders)
|
|
||||||
fig.show()
|
|
||||||
|
|
||||||
class gradient_descent_2d_race(object):
|
|
||||||
def __init__(self, environ:str="jupyterlab"):
|
|
||||||
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
|
||||||
self.wg_expr = widgets.Text(value="(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2", description="Expression:")
|
|
||||||
self.wg_person_one = widgets.Text(value="(5, 5)", description="candidate 1:")
|
|
||||||
self.wg_person_two = widgets.Text(value="(5, 5)", description="candidate 2:")
|
|
||||||
self.button_compute = widgets.Button(description="Compute")
|
|
||||||
self.button_plot = widgets.Button(description="Plot")
|
|
||||||
|
|
||||||
self.compute_output = widgets.Output()
|
|
||||||
self.plot_output = widgets.Output()
|
|
||||||
|
|
||||||
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
|
||||||
self.config = widgets.VBox([self.wg_expr, self.wg_person_one, self.wg_person_two, self.button_box])
|
|
||||||
self.xn_list_p1, self.df_list_p1 = [], []
|
|
||||||
self.xn_list_p2, self.df_list_p2 = [], []
|
|
||||||
self.initialization()
|
|
||||||
|
|
||||||
def initialization(self):
|
|
||||||
display(self.config)
|
|
||||||
self.button_compute.on_click(self.compute)
|
|
||||||
display(self.compute_output)
|
|
||||||
self.button_plot.on_click(self.plot)
|
|
||||||
display(self.plot_output)
|
|
||||||
|
|
||||||
def compute(self, *args):
|
|
||||||
with self.compute_output:
|
|
||||||
# person_one
|
|
||||||
x0 = np.array(self.wg_person_one.value.split("(")[1].split(")")[0].split(","), dtype=float)
|
|
||||||
xn = x0
|
|
||||||
x1 = symbols("x1")
|
|
||||||
x2 = symbols("x2")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
|
||||||
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
|
||||||
self.xn_list_p1.append(xn)
|
|
||||||
self.df_list_p1.append(gradient)
|
|
||||||
print("player one: x = [{}, {}]".format(xn[0], xn[1]))
|
|
||||||
print("player one: gradient= {}".format(gradient))
|
|
||||||
# person_two
|
|
||||||
x0 = np.array(self.wg_person_two.value.split("(")[1].split(")")[0].split(","), dtype=float)
|
|
||||||
xn = x0
|
|
||||||
x1 = symbols("x1")
|
|
||||||
x2 = symbols("x2")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
|
||||||
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
|
||||||
self.xn_list_p2.append(xn)
|
|
||||||
self.df_list_p2.append(gradient)
|
|
||||||
print("player two: x = [{}, {}]".format(xn[0], xn[1]))
|
|
||||||
print("player two: gradient= {}".format(gradient))
|
|
||||||
clear_output(wait=True)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def plot(self, *args):
|
|
||||||
with self.plot_output:
|
|
||||||
clear_output(wait=True)
|
|
||||||
#x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
|
||||||
x1 = symbols("x1")
|
|
||||||
x2 = symbols("x2")
|
|
||||||
expr = sympify(self.wg_expr.value)
|
|
||||||
xx1 = np.arange(np.array(self.xn_list_p1)[:, 0].min()*0.5, np.array(self.xn_list_p1)[:, 0].max()*1.5, 0.1)
|
|
||||||
xx2 = np.arange(np.array(self.xn_list_p1)[:, 1].min()*0.5, np.array(self.xn_list_p1)[:, 1].max()*1.5, 0.1)
|
|
||||||
xx1, xx2 = np.meshgrid(xx1, xx2)
|
|
||||||
|
|
||||||
f = lambdify((x1, x2), expr, "numpy")
|
|
||||||
fx = f(xx1, xx2)
|
|
||||||
f_xn_p1 = f(np.array(self.xn_list_p1)[:, 0], np.array(self.xn_list_p1)[:, 1])
|
|
||||||
f_xn_p2 = f(np.array(self.xn_list_p2)[:, 0], np.array(self.xn_list_p2)[:, 1])
|
|
||||||
|
|
||||||
frames, steps = [], []
|
|
||||||
for k in range(len(f_xn_p1)):
|
|
||||||
tmp_trace1 = go.Scatter3d(x=np.array(self.xn_list_p1)[:k,0], y=np.array(self.xn_list_p1)[:k,1], z=f_xn_p1)
|
|
||||||
tmp_trace2 = go.Scatter3d(x=np.array(self.xn_list_p2)[:k,0], y=np.array(self.xn_list_p2)[:k,1], z=f_xn_p2)
|
|
||||||
frame = go.Frame(dict(data=[tmp_trace1, tmp_trace2], name=f'frame{k+1}'), traces=[1, 2])
|
|
||||||
frames.append(frame)
|
|
||||||
step = dict(
|
|
||||||
method="update",
|
|
||||||
args=[{"visible": [True]},
|
|
||||||
{"title": "Slider switched to step: " + str(k+1)}], # layout attribute
|
|
||||||
)
|
|
||||||
steps.append(step)
|
|
||||||
|
|
||||||
sliders = [dict(steps= [dict(method= 'animate',
|
|
||||||
args= [[f'frame{k+1}'],
|
|
||||||
dict(mode= 'immediate',
|
|
||||||
frame= dict( duration=0, redraw= True ),
|
|
||||||
transition=dict( duration=0)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
#label='Date : {}'.format(date_range[k])
|
|
||||||
) for k in range(0,len(frames))],
|
|
||||||
transition= dict(duration=0),
|
|
||||||
x=0,
|
|
||||||
y=0,
|
|
||||||
currentvalue=dict(font=dict(size=12), visible=True, xanchor= 'center'),
|
|
||||||
len=1.0)
|
|
||||||
]
|
|
||||||
|
|
||||||
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.4)
|
|
||||||
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
|
||||||
trace3 = go.Scatter3d(x=None, y=None, z=None)
|
|
||||||
fig = go.Figure(data=[trace1, trace2, trace3], frames=frames)
|
|
||||||
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
|
||||||
dict(label="Pause", method="animate", args=[[None], dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
|
||||||
margin=dict(l=20, r=20, b=20, t=20), sliders=sliders)
|
|
||||||
fig.show()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
import copy
|
||||||
|
import time
|
||||||
|
import sympy
|
||||||
|
import numpy as np
|
||||||
|
from scipy.misc import derivative
|
||||||
|
from sympy import symbols, sympify, lambdify, diff
|
||||||
|
|
||||||
|
import ipywidgets as widgets
|
||||||
|
from IPython.display import display, clear_output
|
||||||
|
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import plotly.graph_objects as go
|
||||||
|
import plotly.io as pio
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings("ignore")
|
||||||
|
|
||||||
|
class gradient_descent_1d(object):
|
||||||
|
def __init__(self, environ:str="jupyterlab"):
|
||||||
|
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
||||||
|
self.wg_expr = widgets.Text(value="x**3 - x**(1/2)",
|
||||||
|
description="Expression:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_x0 = widgets.FloatText(value="2",
|
||||||
|
description="Startpoint:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_lr = widgets.FloatText(value="1e-1",
|
||||||
|
description="step size:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_epsilon = widgets.FloatText(value="1e-5",
|
||||||
|
description="criterion:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_max_iter = widgets.IntText(value="1000",
|
||||||
|
description="max iteration",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
|
||||||
|
self.button_compute = widgets.Button(description="Compute")
|
||||||
|
self.button_plot = widgets.Button(description="Plot")
|
||||||
|
|
||||||
|
self.compute_output = widgets.Output()
|
||||||
|
self.plot_output = widgets.Output()
|
||||||
|
self.params_lvbox = widgets.VBox([self.wg_expr, self.wg_x0, self.wg_lr])
|
||||||
|
self.params_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter])
|
||||||
|
self.params_box = widgets.HBox([self.params_lvbox, self.params_rvbox], description="Parameters")
|
||||||
|
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
||||||
|
self.config = widgets.VBox([self.params_box, self.button_box])
|
||||||
|
self.initialization()
|
||||||
|
|
||||||
|
|
||||||
|
def initialization(self):
|
||||||
|
display(self.config)
|
||||||
|
self.button_compute.on_click(self.compute)
|
||||||
|
display(self.compute_output)
|
||||||
|
self.button_plot.on_click(self.plot)
|
||||||
|
display(self.plot_output)
|
||||||
|
|
||||||
|
def compute(self, *args):
|
||||||
|
with self.compute_output:
|
||||||
|
xn = self.wg_x0.value
|
||||||
|
x = symbols("x")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
f = lambdify(x, expr)
|
||||||
|
df = lambdify(x, diff(expr, x))
|
||||||
|
self.xn_list, self.df_list = [], []
|
||||||
|
|
||||||
|
for n in tqdm(range(0, self.wg_max_iter.value)):
|
||||||
|
gradient = df(xn)
|
||||||
|
self.xn_list.append(xn)
|
||||||
|
self.df_list.append(gradient)
|
||||||
|
if abs (gradient < self.wg_epsilon.value):
|
||||||
|
clear_output(wait=True)
|
||||||
|
print("Found solution of {} after".format(expr), n, "iterations")
|
||||||
|
print("x* = {}".format(xn))
|
||||||
|
return None
|
||||||
|
xn = xn - self.wg_lr.value * gradient
|
||||||
|
clear_output(wait=True)
|
||||||
|
display("Exceeded maximum iterations. No solution found.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def plot(self, *args):
|
||||||
|
with self.plot_output:
|
||||||
|
clear_output(wait=True)
|
||||||
|
x0 = float(self.wg_x0.value)
|
||||||
|
x = symbols("x")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
f = lambdify(x, sympify(expr), "numpy")
|
||||||
|
xx1 = np.arange(np.array(self.xn_list).min()*0.5, np.array(self.xn_list).max()*1.5, 0.05)
|
||||||
|
fx = f(xx1)
|
||||||
|
f_xn = f(np.array(self.xn_list))
|
||||||
|
|
||||||
|
fig = go.Figure()
|
||||||
|
fig.add_scatter(x=xx1, y=fx)
|
||||||
|
frames = []
|
||||||
|
frames.append({'data':copy.deepcopy(fig['data']),'name':f'frame{0}'})
|
||||||
|
fig.add_traces(go.Scatter(x=None, y=None, mode="lines + markers", line={"color":"#de1032", "width":5}))
|
||||||
|
frames = [go.Frame(data= [go.Scatter(x=np.array(self.xn_list)[:k], y=f_xn)],traces= [1],name=f'frame{k+2}')for k in range(len(f_xn))]
|
||||||
|
fig.update(frames=frames)
|
||||||
|
fig.update_layout(updatemenus=[dict(type="buttons",buttons=[dict(label="Play",method="animate",args=[None])])])
|
||||||
|
fig.show()
|
|
@ -0,0 +1,489 @@
|
||||||
|
import copy
|
||||||
|
import time
|
||||||
|
import sympy
|
||||||
|
import numpy as np
|
||||||
|
from scipy.misc import derivative
|
||||||
|
from sympy import symbols, sympify, lambdify, diff
|
||||||
|
|
||||||
|
import ipywidgets as widgets
|
||||||
|
from IPython.display import display, clear_output
|
||||||
|
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import plotly.graph_objects as go
|
||||||
|
import plotly.io as pio
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings("ignore")
|
||||||
|
|
||||||
|
class gradient_descent_1d(object):
|
||||||
|
def __init__(self, environ:str="jupyterlab"):
|
||||||
|
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
||||||
|
self.wg_expr = widgets.Text(value="x**3 - x**(1/2)",
|
||||||
|
description="Expression:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_x0 = widgets.FloatText(value="2",
|
||||||
|
description="Startpoint:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_lr = widgets.FloatText(value="1e-1",
|
||||||
|
description="step size:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_epsilon = widgets.FloatText(value="1e-5",
|
||||||
|
description="criterion:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_max_iter = widgets.IntText(value="1000",
|
||||||
|
description="max iteration",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
|
||||||
|
self.button_compute = widgets.Button(description="Compute")
|
||||||
|
self.button_plot = widgets.Button(description="Plot")
|
||||||
|
|
||||||
|
self.compute_output = widgets.Output()
|
||||||
|
self.plot_output = widgets.Output()
|
||||||
|
self.params_lvbox = widgets.VBox([self.wg_expr, self.wg_x0, self.wg_lr])
|
||||||
|
self.params_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter])
|
||||||
|
self.params_box = widgets.HBox([self.params_lvbox, self.params_rvbox], description="Parameters")
|
||||||
|
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
||||||
|
self.config = widgets.VBox([self.params_box, self.button_box])
|
||||||
|
self.initialization()
|
||||||
|
|
||||||
|
|
||||||
|
def initialization(self):
|
||||||
|
display(self.config)
|
||||||
|
self.button_compute.on_click(self.compute)
|
||||||
|
display(self.compute_output)
|
||||||
|
self.button_plot.on_click(self.plot)
|
||||||
|
display(self.plot_output)
|
||||||
|
|
||||||
|
def compute(self, *args):
|
||||||
|
with self.compute_output:
|
||||||
|
xn = self.wg_x0.value
|
||||||
|
x = symbols("x")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
f = lambdify(x, expr)
|
||||||
|
df = lambdify(x, diff(expr, x))
|
||||||
|
self.xn_list, self.df_list = [], []
|
||||||
|
|
||||||
|
for n in tqdm(range(0, self.wg_max_iter.value)):
|
||||||
|
gradient = df(xn)
|
||||||
|
self.xn_list.append(xn)
|
||||||
|
self.df_list.append(gradient)
|
||||||
|
if abs (gradient < self.wg_epsilon.value):
|
||||||
|
clear_output(wait=True)
|
||||||
|
print("Found solution of {} after".format(expr), n, "iterations")
|
||||||
|
print("x* = {}".format(xn))
|
||||||
|
return None
|
||||||
|
xn = xn - self.wg_lr.value * gradient
|
||||||
|
clear_output(wait=True)
|
||||||
|
display("Exceeded maximum iterations. No solution found.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def plot(self, *args):
|
||||||
|
with self.plot_output:
|
||||||
|
clear_output(wait=True)
|
||||||
|
x0 = float(self.wg_x0.value)
|
||||||
|
x = symbols("x")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
f = lambdify(x, sympify(expr), "numpy")
|
||||||
|
xx1 = np.arange(np.array(self.xn_list).min()*0.5, np.array(self.xn_list).max()*1.5, 0.05)
|
||||||
|
fx = f(xx1)
|
||||||
|
f_xn = f(np.array(self.xn_list))
|
||||||
|
|
||||||
|
fig = go.Figure()
|
||||||
|
fig.add_scatter(x=xx1, y=fx)
|
||||||
|
frames = []
|
||||||
|
frames.append({'data':copy.deepcopy(fig['data']),'name':f'frame{0}'})
|
||||||
|
fig.add_traces(go.Scatter(x=None, y=None, mode="lines + markers", line={"color":"#de1032", "width":5}))
|
||||||
|
frames = [go.Frame(data= [go.Scatter(x=np.array(self.xn_list)[:k], y=f_xn)],traces= [1],name=f'frame{k+2}')for k in range(len(f_xn))]
|
||||||
|
fig.update(frames=frames)
|
||||||
|
fig.update_layout(updatemenus=[dict(type="buttons",buttons=[dict(label="Play",method="animate",args=[None])])])
|
||||||
|
fig.show()
|
||||||
|
|
||||||
|
class gradient_descent_2d(object):
|
||||||
|
def __init__(self, environ:str="jupyterlab"):
|
||||||
|
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
||||||
|
self.wg_expr = widgets.Dropdown(options=[("(sin(x1) - 2) + (sin(x2) - 2) ** 2", "(sin(x1) - 2) + (sin(x2) - 2) ** 2"),
|
||||||
|
("(sin(x1) - 2) ** (1/2) + (sin(x2) - 2) ** 2", "(sin(x1) - 2) ** (1/2) + (sin(x2) - 2) ** 2"),
|
||||||
|
("(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2", "(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2")],
|
||||||
|
value="(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2", descrption="Expression")
|
||||||
|
self.wg_x0 = widgets.Text(value="5,5",
|
||||||
|
description="Startpoint:")
|
||||||
|
self.wg_lr = widgets.FloatText(value="1e-1",
|
||||||
|
description="step size:")
|
||||||
|
self.wg_epsilon = widgets.FloatText(value="1e-5",
|
||||||
|
description="criterion:")
|
||||||
|
self.wg_max_iter = widgets.IntText(value="1000",
|
||||||
|
description="max iteration")
|
||||||
|
self.button_compute = widgets.Button(description="Compute")
|
||||||
|
self.button_plot = widgets.Button(description="Plot")
|
||||||
|
|
||||||
|
self.compute_output = widgets.Output()
|
||||||
|
self.plot_output = widgets.Output()
|
||||||
|
self.params_lvbox = widgets.VBox([self.wg_x0, self.wg_lr])
|
||||||
|
self.params_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter])
|
||||||
|
self.exp_box = widgets.HBox([self.wg_expr])
|
||||||
|
self.params_box = widgets.HBox([self.params_lvbox, self.params_rvbox], description="Parameters")
|
||||||
|
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
||||||
|
self.config = widgets.VBox([self.exp_box, self.params_box, self.button_box])
|
||||||
|
self.initialization()
|
||||||
|
|
||||||
|
def initialization(self):
|
||||||
|
display(self.config)
|
||||||
|
self.button_compute.on_click(self.compute)
|
||||||
|
display(self.compute_output)
|
||||||
|
self.button_plot.on_click(self.plot)
|
||||||
|
display(self.plot_output)
|
||||||
|
|
||||||
|
def compute(self, *args):
|
||||||
|
with self.compute_output:
|
||||||
|
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
||||||
|
xn = x0
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
self.xn_list, self.df_list = [], []
|
||||||
|
|
||||||
|
for n in tqdm(range(0, self.wg_max_iter.value)):
|
||||||
|
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
||||||
|
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
||||||
|
self.xn_list.append(xn)
|
||||||
|
self.df_list.append(gradient)
|
||||||
|
if np.linalg.norm(gradient, ord=2) < self.wg_epsilon.value:
|
||||||
|
clear_output(wait=True)
|
||||||
|
print("Found solution of {} after".format(expr), n, "iterations")
|
||||||
|
print("x* = [{}, {}]".format(xn[0], xn[1]))
|
||||||
|
return None
|
||||||
|
xn = xn - self.wg_lr.value * gradient
|
||||||
|
clear_output(wait=True)
|
||||||
|
display("Exceeded maximum iterations. No solution found.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def plot(self, *args):
|
||||||
|
with self.plot_output:
|
||||||
|
clear_output(wait=True)
|
||||||
|
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
xx1 = np.arange(np.array(self.xn_list)[:, 0].min() * 0.5, np.array(self.xn_list)[:, 0].max() * 1.5, 0.1)
|
||||||
|
xx2 = np.arange(np.array(self.xn_list)[:, 1].min() * 0.5, np.array(self.xn_list)[:, 1].max() * 1.5, 0.1)
|
||||||
|
xx1_tangent = np.arange(np.array(self.xn_list)[:, 0].min(), np.array(self.xn_list)[:, 0].max(), 0.1)
|
||||||
|
xx2_tangent = np.arange(np.array(self.xn_list)[:, 1].min(), np.array(self.xn_list)[:, 1].max(), 0.1)
|
||||||
|
xx1_o, xx2_o = xx1, xx2
|
||||||
|
xx1, xx2 = np.meshgrid(xx1, xx2)
|
||||||
|
xx1_tangent, xx2_tangent = np.meshgrid(xx1_tangent, xx2_tangent)
|
||||||
|
f = lambdify((x1, x2), expr, "numpy")
|
||||||
|
fx = f(xx1, xx2)
|
||||||
|
f_xn = f(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
||||||
|
partial_x1 = lambdify((x1, x2), diff(expr, x1), "numpy")
|
||||||
|
partial_x2 = lambdify((x1, x2), diff(expr, x2), "numpy")
|
||||||
|
plane = partial_x1(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x1 - np.array(self.xn_list)[:, 0]) + partial_x2(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x2 - np.array(self.xn_list)[:, 1]) + f_xn
|
||||||
|
z = [lambdify((x1, x2), plane[i], "numpy")(xx1_tangent, xx2_tangent) for i in range(0, len(plane))]
|
||||||
|
|
||||||
|
frames, steps = [], []
|
||||||
|
for k in range(len(f_xn)):
|
||||||
|
tmp_trace1 = go.Scatter3d(x=np.array(self.xn_list)[:k,0], y=np.array(self.xn_list)[:k,1], z=f_xn)
|
||||||
|
tmp_trace2 = go.Surface(x=xx1_tangent, y=xx2_tangent, z=z[k], showscale=True, opacity=0.5)
|
||||||
|
frame = go.Frame(dict(data=[tmp_trace1, tmp_trace2], name=f'frame{k+1}'), traces=[1, 2])
|
||||||
|
frames.append(frame)
|
||||||
|
step = dict(
|
||||||
|
method="update",
|
||||||
|
args=[{"visible": [True]},
|
||||||
|
{"title": "Slider switched to step: " + str(k+1)}], # layout attribute
|
||||||
|
)
|
||||||
|
steps.append(step)
|
||||||
|
|
||||||
|
sliders = [dict(steps= [dict(method= 'animate',
|
||||||
|
args= [[f'frame{k+1}'],
|
||||||
|
dict(mode= 'immediate',
|
||||||
|
frame= dict( duration=0, redraw= True ),
|
||||||
|
transition=dict( duration=0)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
#label='Date : {}'.format(date_range[k])
|
||||||
|
) for k in range(0,len(frames))],
|
||||||
|
transition= dict(duration=0),
|
||||||
|
x=0,
|
||||||
|
y=0,
|
||||||
|
currentvalue=dict(font=dict(size=12), visible=True, xanchor= 'center'),
|
||||||
|
len=1.0)
|
||||||
|
]
|
||||||
|
|
||||||
|
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=False, opacity=0.6)
|
||||||
|
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
||||||
|
trace3 = go.Surface(x=None, y=None, z=None, showscale=False, opacity=0.9, colorscale='Blues')
|
||||||
|
fig = go.Figure(data=[trace1, trace2, trace3], frames=frames)
|
||||||
|
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
||||||
|
dict(label="Pause", method="animate", args=[[None], \
|
||||||
|
dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
||||||
|
margin=dict(r=20, l=10, b=10, t=10), sliders=sliders)
|
||||||
|
fig.show()
|
||||||
|
|
||||||
|
class gradient_descent_2d_custom(object):
|
||||||
|
def __init__(self, environ:str="jupyterlab"):
|
||||||
|
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
||||||
|
|
||||||
|
self.wg_expr = widgets.Text(value="(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2", description="Expression:")
|
||||||
|
self.wg_x0 = widgets.Text(value="5,5", description="Startpoint:")
|
||||||
|
self.wg_lr = widgets.FloatText(value="1e-1", description="step size:")
|
||||||
|
self.wg_epsilon = widgets.FloatText(value="1e-5", description="criterion:")
|
||||||
|
self.wg_max_iter = widgets.IntText(value="1000", description="max iteration")
|
||||||
|
self.button_compute = widgets.Button(description="Compute")
|
||||||
|
self.button_plot = widgets.Button(description="Plot")
|
||||||
|
|
||||||
|
self.compute_output = widgets.Output()
|
||||||
|
self.plot_output = widgets.Output()
|
||||||
|
self.params_lvbox = widgets.VBox([self.wg_expr, self.wg_x0, self.wg_lr])
|
||||||
|
self.params_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter])
|
||||||
|
self.params_box = widgets.HBox([self.params_lvbox, self.params_rvbox], description="Parameters")
|
||||||
|
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
||||||
|
self.config = widgets.VBox([self.params_box, self.button_box])
|
||||||
|
self.initialization()
|
||||||
|
|
||||||
|
def initialization(self):
|
||||||
|
display(self.config)
|
||||||
|
self.button_compute.on_click(self.compute)
|
||||||
|
display(self.compute_output)
|
||||||
|
self.button_plot.on_click(self.plot)
|
||||||
|
display(self.plot_output)
|
||||||
|
|
||||||
|
def compute(self, *args):
|
||||||
|
with self.compute_output:
|
||||||
|
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
||||||
|
xn = x0
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
self.xn_list, self.df_list = [], []
|
||||||
|
for n in tqdm(range(0, self.wg_max_iter.value)):
|
||||||
|
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
||||||
|
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
||||||
|
self.xn_list.append(xn)
|
||||||
|
self.df_list.append(gradient)
|
||||||
|
if np.linalg.norm(gradient, ord=2) < self.wg_epsilon.value:
|
||||||
|
clear_output(wait=True)
|
||||||
|
print("Found solution of {} after".format(expr), n, "iterations")
|
||||||
|
print("x* = [{}, {}]".format(xn[0], xn[1]))
|
||||||
|
return None
|
||||||
|
xn = xn - self.wg_lr.value * gradient
|
||||||
|
clear_output(wait=True)
|
||||||
|
display("Exceeded maximum iterations. No solution found.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def plot(self, *args):
|
||||||
|
with self.plot_output:
|
||||||
|
clear_output(wait=True)
|
||||||
|
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
xx1 = np.arange(np.array(self.xn_list)[:, 0].min()*0.5, np.array(self.xn_list)[:, 0].max()*1.5, 0.05)
|
||||||
|
xx2 = np.arange(np.array(self.xn_list)[:, 1].min()*0.5, np.array(self.xn_list)[:, 1].max()*1.5, 0.05)
|
||||||
|
xx1, xx2 = np.meshgrid(xx1, xx2)
|
||||||
|
|
||||||
|
f = lambdify((x1, x2), expr, "numpy")
|
||||||
|
fx = f(xx1, xx2)
|
||||||
|
f_xn = f(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
||||||
|
|
||||||
|
frames, steps = [], []
|
||||||
|
for k in range(len(f_xn)):
|
||||||
|
#frame = go.Frame(data=[go.Surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.8)])
|
||||||
|
#fig.add_trace(go.Scatter3d(x=np.array(self.xn_list)[:k, 0], y=np.array(self.xn_list)[:k, 1], z=f_xn))
|
||||||
|
frame = go.Frame(dict(data=[go.Scatter3d(x=np.array(self.xn_list)[:k,0], y=np.array(self.xn_list)[:k,1], z=f_xn)], name=f'frame{k+1}'), traces=[1])
|
||||||
|
frames.append(frame)
|
||||||
|
step = dict(
|
||||||
|
method="update",
|
||||||
|
args=[{"visible": [True]},
|
||||||
|
{"title": "Slider switched to step: " + str(k+1)}], # layout attribute
|
||||||
|
)
|
||||||
|
steps.append(step)
|
||||||
|
|
||||||
|
sliders = [dict(steps= [dict(method= 'animate',
|
||||||
|
args= [[f'frame{k+1}'],
|
||||||
|
dict(mode= 'immediate',
|
||||||
|
frame= dict( duration=0, redraw= True ),
|
||||||
|
transition=dict( duration=0)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
#label='Date : {}'.format(date_range[k])
|
||||||
|
) for k in range(0,len(frames))],
|
||||||
|
transition= dict(duration=0),
|
||||||
|
x=0,
|
||||||
|
y=0,
|
||||||
|
currentvalue=dict(font=dict(size=12), visible=True, xanchor= 'center'),
|
||||||
|
len=1.0)
|
||||||
|
]
|
||||||
|
|
||||||
|
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.8)
|
||||||
|
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
||||||
|
fig = go.Figure(data=[trace1, trace2], frames=frames)
|
||||||
|
#fig.add_surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.9)
|
||||||
|
#fig.update_traces(contours_z=dict(show=True, usecolormap=True, highlightcolor="limegreen", project_z=True))
|
||||||
|
#fig.update(frames=frames)
|
||||||
|
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
||||||
|
dict(label="Pause", method="animate", args=[[None], dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
||||||
|
margin=dict(l=0, r=0, b=0, t=0), sliders=sliders)
|
||||||
|
fig.show()
|
||||||
|
|
||||||
|
class gradient_descent_2d_race(object):
|
||||||
|
def __init__(self, environ:str="jupyterlab"):
|
||||||
|
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
||||||
|
self.wg_expr = widgets.Text(value="(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2", description="Expression:")
|
||||||
|
self.wg_person_one = widgets.Text(value="(5, 5)", description="candidate 1:")
|
||||||
|
self.wg_person_two = widgets.Text(value="(5, 5)", description="candidate 2:")
|
||||||
|
self.button_compute = widgets.Button(description="Compute")
|
||||||
|
self.button_plot = widgets.Button(description="Plot")
|
||||||
|
|
||||||
|
self.compute_output = widgets.Output()
|
||||||
|
self.plot_output = widgets.Output()
|
||||||
|
|
||||||
|
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
||||||
|
self.config = widgets.VBox([self.wg_expr, self.wg_person_one, self.wg_person_two, self.button_box])
|
||||||
|
self.xn_list_p1, self.df_list_p1 = [], []
|
||||||
|
self.xn_list_p2, self.df_list_p2 = [], []
|
||||||
|
self.initialization()
|
||||||
|
|
||||||
|
def initialization(self):
|
||||||
|
display(self.config)
|
||||||
|
self.button_compute.on_click(self.compute)
|
||||||
|
display(self.compute_output)
|
||||||
|
self.button_plot.on_click(self.plot)
|
||||||
|
display(self.plot_output)
|
||||||
|
|
||||||
|
def compute(self, *args):
|
||||||
|
with self.compute_output:
|
||||||
|
# person_one
|
||||||
|
x0 = np.array(self.wg_person_one.value.split("(")[1].split(")")[0].split(","), dtype=float)
|
||||||
|
xn = x0
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
||||||
|
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
||||||
|
self.xn_list_p1.append(xn)
|
||||||
|
self.df_list_p1.append(gradient)
|
||||||
|
print("player one: x = [{}, {}]".format(xn[0], xn[1]))
|
||||||
|
print("player one: gradient= {}".format(gradient))
|
||||||
|
# person_two
|
||||||
|
x0 = np.array(self.wg_person_two.value.split("(")[1].split(")")[0].split(","), dtype=float)
|
||||||
|
xn = x0
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
||||||
|
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
||||||
|
self.xn_list_p2.append(xn)
|
||||||
|
self.df_list_p2.append(gradient)
|
||||||
|
print("player two: x = [{}, {}]".format(xn[0], xn[1]))
|
||||||
|
print("player two: gradient= {}".format(gradient))
|
||||||
|
clear_output(wait=True)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def plot(self, *args):
|
||||||
|
with self.plot_output:
|
||||||
|
clear_output(wait=True)
|
||||||
|
#x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
xx1 = np.arange(np.array(self.xn_list_p1)[:, 0].min()*0.5, np.array(self.xn_list_p1)[:, 0].max()*1.5, 0.1)
|
||||||
|
xx2 = np.arange(np.array(self.xn_list_p1)[:, 1].min()*0.5, np.array(self.xn_list_p1)[:, 1].max()*1.5, 0.1)
|
||||||
|
xx1, xx2 = np.meshgrid(xx1, xx2)
|
||||||
|
|
||||||
|
f = lambdify((x1, x2), expr, "numpy")
|
||||||
|
fx = f(xx1, xx2)
|
||||||
|
f_xn_p1 = f(np.array(self.xn_list_p1)[:, 0], np.array(self.xn_list_p1)[:, 1])
|
||||||
|
f_xn_p2 = f(np.array(self.xn_list_p2)[:, 0], np.array(self.xn_list_p2)[:, 1])
|
||||||
|
|
||||||
|
frames, steps = [], []
|
||||||
|
for k in range(len(f_xn_p1)):
|
||||||
|
tmp_trace1 = go.Scatter3d(x=np.array(self.xn_list_p1)[:k,0], y=np.array(self.xn_list_p1)[:k,1], z=f_xn_p1)
|
||||||
|
tmp_trace2 = go.Scatter3d(x=np.array(self.xn_list_p2)[:k,0], y=np.array(self.xn_list_p2)[:k,1], z=f_xn_p2)
|
||||||
|
frame = go.Frame(dict(data=[tmp_trace1, tmp_trace2], name=f'frame{k+1}'), traces=[1, 2])
|
||||||
|
frames.append(frame)
|
||||||
|
step = dict(
|
||||||
|
method="update",
|
||||||
|
args=[{"visible": [True]},
|
||||||
|
{"title": "Slider switched to step: " + str(k+1)}], # layout attribute
|
||||||
|
)
|
||||||
|
steps.append(step)
|
||||||
|
|
||||||
|
sliders = [dict(steps= [dict(method= 'animate',
|
||||||
|
args= [[f'frame{k+1}'],
|
||||||
|
dict(mode= 'immediate',
|
||||||
|
frame= dict( duration=0, redraw= True ),
|
||||||
|
transition=dict( duration=0)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
#label='Date : {}'.format(date_range[k])
|
||||||
|
) for k in range(0,len(frames))],
|
||||||
|
transition= dict(duration=0),
|
||||||
|
x=0,
|
||||||
|
y=0,
|
||||||
|
currentvalue=dict(font=dict(size=12), visible=True, xanchor= 'center'),
|
||||||
|
len=1.0)
|
||||||
|
]
|
||||||
|
|
||||||
|
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.4)
|
||||||
|
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
||||||
|
trace3 = go.Scatter3d(x=None, y=None, z=None)
|
||||||
|
fig = go.Figure(data=[trace1, trace2, trace3], frames=frames)
|
||||||
|
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
||||||
|
dict(label="Pause", method="animate", args=[[None], dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
||||||
|
margin=dict(l=20, r=20, b=20, t=20), sliders=sliders)
|
||||||
|
fig.show()
|
||||||
|
|
||||||
|
def plot2(self, *args):
|
||||||
|
with self.plot_output:
|
||||||
|
clear_output(wait=True)
|
||||||
|
#x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
xx1 = np.arange(np.array(self.xn_list_p1)[:, 0].min()*0.5, np.array(self.xn_list_p1)[:, 0].max()*1.5, 0.1)
|
||||||
|
xx2 = np.arange(np.array(self.xn_list_p1)[:, 1].min()*0.5, np.array(self.xn_list_p1)[:, 1].max()*1.5, 0.1)
|
||||||
|
xx1, xx2 = np.meshgrid(xx1, xx2)
|
||||||
|
|
||||||
|
f = lambdify((x1, x2), expr, "numpy")
|
||||||
|
fx = f(xx1, xx2)
|
||||||
|
f_xn_p1 = f(np.array(self.xn_list_p1)[:, 0], np.array(self.xn_list_p1)[:, 1])
|
||||||
|
f_xn_p2 = f(np.array(self.xn_list_p2)[:, 0], np.array(self.xn_list_p2)[:, 1])
|
||||||
|
|
||||||
|
frames, steps = [], []
|
||||||
|
for k in range(len(f_xn_p1)):
|
||||||
|
tmp_trace1 = go.Scatter3d(x=np.array(self.xn_list_p1)[:k,0], y=np.array(self.xn_list_p1)[:k,1], z=f_xn_p1)
|
||||||
|
tmp_trace2 = go.Scatter3d(x=np.array(self.xn_list_p2)[:k,0], y=np.array(self.xn_list_p2)[:k,1], z=f_xn_p2)
|
||||||
|
frame = go.Frame(dict(data=[tmp_trace1, tmp_trace2], name=f'frame{k+1}'), traces=[1, 2])
|
||||||
|
frames.append(frame)
|
||||||
|
step = dict(
|
||||||
|
method="update",
|
||||||
|
args=[{"visible": [True]},
|
||||||
|
{"title": "Slider switched to step: " + str(k+1)}], # layout attribute
|
||||||
|
)
|
||||||
|
steps.append(step)
|
||||||
|
|
||||||
|
sliders = [dict(steps= [dict(method= 'animate',
|
||||||
|
args= [[f'frame{k+1}'],
|
||||||
|
dict(mode= 'immediate',
|
||||||
|
frame= dict( duration=0, redraw= True ),
|
||||||
|
transition=dict( duration=0)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
#label='Date : {}'.format(date_range[k])
|
||||||
|
) for k in range(0,len(frames))],
|
||||||
|
transition= dict(duration=0),
|
||||||
|
x=0,
|
||||||
|
y=0,
|
||||||
|
currentvalue=dict(font=dict(size=12), visible=True, xanchor= 'center'),
|
||||||
|
len=1.0)
|
||||||
|
]
|
||||||
|
|
||||||
|
trace1 = go.Surface(x=xx1, y=xx2, z=fx, showscale=True, opacity=0.4)
|
||||||
|
trace2 = go.Scatter3d(x=None, y=None, z=None)
|
||||||
|
trace3 = go.Scatter3d(x=None, y=None, z=None)
|
||||||
|
fig = go.Figure(data=[trace1, trace2, trace3], frames=frames)
|
||||||
|
fig.update_layout(updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True)]), \
|
||||||
|
dict(label="Pause", method="animate", args=[[None], dict(fromcurrent=True, mode='immediate', transition= {'duration': 0}, frame=dict(redraw=True, duration=0))])])],
|
||||||
|
margin=dict(l=20, r=20, b=20, t=20), sliders=sliders)
|
||||||
|
fig.show()
|
|
@ -0,0 +1,129 @@
|
||||||
|
import copy
|
||||||
|
import time
|
||||||
|
import sympy
|
||||||
|
import numpy as np
|
||||||
|
from scipy.misc import derivative
|
||||||
|
from sympy import symbols, sympify, lambdify, diff
|
||||||
|
|
||||||
|
import ipywidgets as widgets
|
||||||
|
from IPython.display import Image, display, clear_output
|
||||||
|
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import plotly.graph_objects as go
|
||||||
|
import plotly.io as pio
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings("ignore")
|
||||||
|
|
||||||
|
class gd_2d_test(object):
|
||||||
|
def __init__(self, environ:str="jupyterlab", type="default"):
|
||||||
|
if type == "default":
|
||||||
|
self.initialization_default(environ=environ)
|
||||||
|
self.compute_default()
|
||||||
|
self.user_step = 1
|
||||||
|
elif type == "custom":
|
||||||
|
self.initlization_custom()
|
||||||
|
self.compute_custom()
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def initialization_default(self, environ):
|
||||||
|
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
||||||
|
self.wg_expr = widgets.Dropdown(options=[("(1 - 8 * x1 + 7 * x1**2 - (7/3) * x1**3 + (1/4) * x1**4) * x2**2 * E**(-x2)", "(1 - 8 * x1 + 7 * x1**2 - (7/3) * x1**3 + (1/4) * x1**4) * x2**2 * E**(-x2)"), ("(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2", "(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2")], value="(1 - 8 * x1 + 7 * x1**2 - (7/3) * x1**3 + (1/4) * x1**4) * x2**2 * E**(-x2)", descrption="Expression")
|
||||||
|
self.wg_x0 = widgets.Text(value="0,2", description="Startpoint:")
|
||||||
|
self.wg_lr = widgets.FloatText(value="1e-1", description="step size:")
|
||||||
|
self.wg_epsilon = widgets.FloatText(value="1e-5", description="criterion:")
|
||||||
|
self.wg_max_iter = widgets.IntText(value="1000", description="max iteration")
|
||||||
|
self.button_compute = widgets.Button(description="Compute")
|
||||||
|
self.button_plot_default = widgets.Button(description="Plot")
|
||||||
|
|
||||||
|
self.compute_output = widgets.Output()
|
||||||
|
self.plot_default_output = widgets.Output()
|
||||||
|
self.params_lvbox = widgets.VBox([self.wg_x0, self.wg_lr])
|
||||||
|
self.params_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter])
|
||||||
|
self.exp_box = widgets.HBox([self.wg_expr])
|
||||||
|
self.params_box = widgets.HBox([self.params_lvbox, self.params_rvbox], description="Parameters")
|
||||||
|
self.button_box = widgets.HBox([self.button_compute, self.button_plot_default], description="operations")
|
||||||
|
self.config = widgets.VBox([self.exp_box, self.params_box, self.button_box])
|
||||||
|
display(self.config)
|
||||||
|
|
||||||
|
self.button_compute.on_click(self.compute_default)
|
||||||
|
display(self.compute_output)
|
||||||
|
self.button_plot_default.on_click(self.plot_default)
|
||||||
|
img1 = self.plot_default_output
|
||||||
|
display(img1)
|
||||||
|
|
||||||
|
|
||||||
|
def compute_default(self, *args):
|
||||||
|
with self.compute_output:
|
||||||
|
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
||||||
|
xn = x0
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
self.xn_list, self.df_list = [], []
|
||||||
|
|
||||||
|
for n in tqdm(range(0, self.wg_max_iter.value)):
|
||||||
|
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
||||||
|
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
||||||
|
self.xn_list.append(xn)
|
||||||
|
self.df_list.append(gradient)
|
||||||
|
if np.linalg.norm(gradient, ord=2) < self.wg_epsilon.value:
|
||||||
|
clear_output(wait=True)
|
||||||
|
print("Found solution of {} after".format(expr), n, "iterations")
|
||||||
|
print("x* = [{}, {}]".format(xn[0], xn[1]))
|
||||||
|
return None
|
||||||
|
xn = xn - self.wg_lr.value * gradient
|
||||||
|
clear_output(wait=True)
|
||||||
|
display("Exceeded maximum iterations. No solution found.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def plot_default(self, *args):
|
||||||
|
with self.plot_default_output:
|
||||||
|
clear_output(wait=True)
|
||||||
|
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
xx1 = np.arange(0, 5, 0.1)
|
||||||
|
xx2 = np.arange(0, 6, 0.1)
|
||||||
|
#xx1 = np.arange(np.array(self.xn_list)[:, 0].min() * 0.5, np.array(self.xn_list)[:, 0].max() * 1.5, 0.1)
|
||||||
|
#xx2 = np.arange(np.array(self.xn_list)[:, 1].min() * 0.5, np.array(self.xn_list)[:, 1].max() * 1.5, 0.1)
|
||||||
|
xx1_tangent = np.arange(np.array(self.xn_list)[:, 0].min(), np.array(self.xn_list)[:, 0].max(), 0.1)
|
||||||
|
xx2_tangent = np.arange(np.array(self.xn_list)[:, 1].min(), np.array(self.xn_list)[:, 1].max(), 0.1)
|
||||||
|
xx1_o, xx2_o = xx1, xx2
|
||||||
|
xx1, xx2 = np.meshgrid(xx1, xx2)
|
||||||
|
xx1_tangent, xx2_tangent = np.meshgrid(xx1_o, xx2_o)
|
||||||
|
f = lambdify((x1, x2), expr, "numpy")
|
||||||
|
fx = f(xx1, xx2)
|
||||||
|
f_xn = f(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
||||||
|
partial_x1 = lambdify((x1, x2), diff(expr, x1), "numpy")
|
||||||
|
partial_x2 = lambdify((x1, x2), diff(expr, x2), "numpy")
|
||||||
|
plane = partial_x1(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x1 - np.array(self.xn_list)[:, 0]) + partial_x2(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x2 - np.array(self.xn_list)[:, 1]) + f_xn
|
||||||
|
z = [lambdify((x1, x2), plane[i], "numpy")(xx1_tangent, xx2_tangent) for i in range(0, len(plane))]
|
||||||
|
|
||||||
|
|
||||||
|
from plotly.subplots import make_subplots
|
||||||
|
import plotly.express as px
|
||||||
|
df = px.data.tips()
|
||||||
|
fig = px.density_contour(df, x="total_bill", y="tip")
|
||||||
|
fig = make_subplots(rows=1, cols=2, specs=[[{'type': 'surface'}, {'type': 'xy'}]])
|
||||||
|
fig.add_trace(go.Surface(contours = {"x": {"show": True}, "y":{"show": True}, "z":{"show": True}},x=xx1, y=xx2, z=fx), row=1, col=1)
|
||||||
|
fig.add_trace(go.Scatter3d(x=None, y=None, z=None), row=1, col=1)
|
||||||
|
fig.add_trace(go.Surface(x=None, y=None, z=None, showscale=False, colorscale='Blues'), row=1, col=1)
|
||||||
|
fig.add_trace(go.Contour(x=xx1_o, y=xx2_o, z=fx), row=1, col=2)
|
||||||
|
fig.add_trace(go.Scatter(x=None, y=None), row=1, col=2)
|
||||||
|
frames = [go.Frame(data=[go.Surface(visible=True, showscale=False, opacity=0.8),
|
||||||
|
go.Scatter3d(x=np.array(self.xn_list)[:k,0], y=np.array(self.xn_list)[:k,1], z=f_xn),
|
||||||
|
go.Surface(x=xx1_tangent, y=xx2_tangent, z=z[k]),
|
||||||
|
go.Contour(visible=True),
|
||||||
|
go.Scatter(x=np.array(self.xn_list)[:k, 0], y=np.array(self.xn_list)[:k, 1])],
|
||||||
|
traces=[0, 1, 2, 3, 4]) for k in range(len(f_xn))]
|
||||||
|
fig.frames = frames
|
||||||
|
fig.update_layout(autosize=False, height=800, updatemenus=[dict(type="buttons", buttons=[dict(label="Play", method="animate", args=[None, dict(fromcurrent=True, transition= {'duration': 0}, frame=dict(redraw=True, duration=500))]), \
|
||||||
|
dict(label="Pause", method="animate", args=[[None], \
|
||||||
|
dict(fromcurrent=True, mode='immediate', transition={'duration': 0}, frame=dict(redraw=True, duration=0))])])])
|
||||||
|
fig.show()
|
|
@ -0,0 +1,276 @@
|
||||||
|
import math
|
||||||
|
import copy
|
||||||
|
import time
|
||||||
|
import sympy
|
||||||
|
import numpy as np
|
||||||
|
from scipy.misc import derivative
|
||||||
|
from sympy import symbols, sympify, lambdify, diff
|
||||||
|
|
||||||
|
import ipywidgets as widgets
|
||||||
|
from IPython.display import Image, display, clear_output
|
||||||
|
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
import plotly.io as pio
|
||||||
|
import plotly.graph_objects as go
|
||||||
|
import plotly.figure_factory as ff
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings("ignore")
|
||||||
|
|
||||||
|
def array_mesh(data, n):
|
||||||
|
array_mesh = []
|
||||||
|
for i in range(len(data) - n):
|
||||||
|
for j in range(len(data[i:i+n])):
|
||||||
|
array_mesh.append(data[i:i+n])
|
||||||
|
return np.vstack(array_mesh)
|
||||||
|
|
||||||
|
class gd_1d(object):
|
||||||
|
def __init__(self, environ:str="jupyterlab"):
|
||||||
|
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
||||||
|
self.wg_expr = widgets.Text(value="-2 * x * sin(-(pi/4) * x)+10",
|
||||||
|
description="Expression:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_x0 = widgets.FloatText(value="2",
|
||||||
|
description="Startpoint:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_lr = widgets.FloatText(value="1e-1",
|
||||||
|
description="step size:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_epsilon = widgets.FloatText(value="1e-5",
|
||||||
|
description="criterion:",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
self.wg_max_iter = widgets.IntText(value="1000",
|
||||||
|
description="max iteration",
|
||||||
|
style={'description_width': 'initial'})
|
||||||
|
|
||||||
|
self.button_compute = widgets.Button(description="Compute")
|
||||||
|
self.button_plot = widgets.Button(description="Plot")
|
||||||
|
|
||||||
|
self.compute_output = widgets.Output()
|
||||||
|
self.plot_output = widgets.Output()
|
||||||
|
self.params_lvbox = widgets.VBox([self.wg_expr, self.wg_x0, self.wg_lr])
|
||||||
|
self.params_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter])
|
||||||
|
self.params_box = widgets.HBox([self.params_lvbox, self.params_rvbox], description="Parameters")
|
||||||
|
self.button_box = widgets.HBox([self.button_compute, self.button_plot], description="operations")
|
||||||
|
self.config = widgets.VBox([self.params_box, self.button_box])
|
||||||
|
self.initialization()
|
||||||
|
|
||||||
|
|
||||||
|
def initialization(self):
|
||||||
|
display(self.config)
|
||||||
|
self.button_compute.on_click(self.compute)
|
||||||
|
display(self.compute_output)
|
||||||
|
self.button_plot.on_click(self.plot)
|
||||||
|
display(self.plot_output)
|
||||||
|
|
||||||
|
def compute(self, *args):
|
||||||
|
with self.compute_output:
|
||||||
|
xn = self.wg_x0.value
|
||||||
|
x = symbols("x")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
f = lambdify(x, expr)
|
||||||
|
df = lambdify(x, diff(expr, x))
|
||||||
|
self.xn_list, self.df_list = [], []
|
||||||
|
|
||||||
|
for n in tqdm(range(0, self.wg_max_iter.value)):
|
||||||
|
gradient = df(xn)
|
||||||
|
self.xn_list.append(xn)
|
||||||
|
self.df_list.append(gradient)
|
||||||
|
if abs (gradient < self.wg_epsilon.value):
|
||||||
|
clear_output(wait=True)
|
||||||
|
print("Found solution of {} after".format(expr), n, "iterations")
|
||||||
|
print("x* = {}".format(xn))
|
||||||
|
return None
|
||||||
|
xn = xn - self.wg_lr.value * gradient
|
||||||
|
clear_output(wait=True)
|
||||||
|
display("Exceeded maximum iterations. No solution found.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def plot(self, *args):
|
||||||
|
with self.plot_output:
|
||||||
|
clear_output(wait=True)
|
||||||
|
x0 = float(self.wg_x0.value)
|
||||||
|
x = symbols("x")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
f = lambdify(x, sympify(expr), "numpy")
|
||||||
|
#xx1 = np.arange(np.array(self.xn_list).min()*0.5, np.array(self.xn_list).max()*1.5, 0.05)
|
||||||
|
xx1 = np.arange(0, 10, 0.05)
|
||||||
|
fx = f(xx1)
|
||||||
|
f_xn = f(np.array(self.xn_list))
|
||||||
|
|
||||||
|
fig = go.Figure()
|
||||||
|
fig.add_scatter(x=xx1, y=fx)
|
||||||
|
frames = []
|
||||||
|
frames.append({'data':copy.deepcopy(fig['data']),'name':f'frame{0}'})
|
||||||
|
fig.add_traces(go.Scatter(x=None, y=None, mode="lines + markers", line={"color":"#de1032", "width":5}))
|
||||||
|
frames = [go.Frame(data= [go.Scatter(x=np.array(self.xn_list)[:k], y=f_xn)],traces= [1],name=f'frame{k+2}')for k in range(len(f_xn))]
|
||||||
|
fig.update(frames=frames)
|
||||||
|
fig.update_layout(updatemenus=[dict(type="buttons",buttons=[dict(label="Play",method="animate",args=[None])])])
|
||||||
|
fig.show()
|
||||||
|
|
||||||
|
|
||||||
|
class gd_2d(object):
|
||||||
|
def __init__(self, environ:str="jupyterlab", type="default"):
|
||||||
|
if type == "default":
|
||||||
|
self.initialization_default(environ=environ)
|
||||||
|
self.compute_default()
|
||||||
|
self.user_step = 1
|
||||||
|
elif type == "custom":
|
||||||
|
self.initlization_custom()
|
||||||
|
self.compute_custom()
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def initialization_default(self, environ):
|
||||||
|
pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab'
|
||||||
|
self.wg_expr = widgets.Dropdown(options=[("(1 - 8 * x1 + 7 * x1**2 - (7/3) * x1**3 + (1/4) * x1**4) * x2**2 * E**(-x2)", "(1 - 8 * x1 + 7 * x1**2 - (7/3) * x1**3 + (1/4) * x1**4) * x2**2 * E**(-x2)"), ("(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2", "(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2")], value="(1 - 8 * x1 + 7 * x1**2 - (7/3) * x1**3 + (1/4) * x1**4) * x2**2 * E**(-x2)", descrption="Expression")
|
||||||
|
self.wg_x0 = widgets.Text(value="0,2", description="Startpoint:")
|
||||||
|
self.wg_lr = widgets.FloatText(value="1e-1", description="step size:")
|
||||||
|
self.wg_epsilon = widgets.FloatText(value="1e-5", description="criterion:")
|
||||||
|
self.wg_max_iter = widgets.IntText(value="1000", description="max iteration")
|
||||||
|
self.button_compute = widgets.Button(description="Compute")
|
||||||
|
self.button_plot_default = widgets.Button(description="Plot")
|
||||||
|
self.button_plot_contour = widgets.Button(description="Plot contour")
|
||||||
|
|
||||||
|
self.compute_output = widgets.Output()
|
||||||
|
self.plot_default_output = widgets.Output()
|
||||||
|
self.plot_contour_output = widgets.Output()
|
||||||
|
self.params_lvbox = widgets.VBox([self.wg_x0, self.wg_lr])
|
||||||
|
self.params_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter])
|
||||||
|
self.exp_box = widgets.HBox([self.wg_expr])
|
||||||
|
self.params_box = widgets.HBox([self.params_lvbox, self.params_rvbox], description="Parameters")
|
||||||
|
self.button_box = widgets.HBox([self.button_compute, self.button_plot_default, self.button_plot_contour], description="operations")
|
||||||
|
self.config = widgets.VBox([self.exp_box, self.params_box, self.button_box])
|
||||||
|
display(self.config)
|
||||||
|
|
||||||
|
self.button_compute.on_click(self.compute_default)
|
||||||
|
display(self.compute_output)
|
||||||
|
self.button_plot_default.on_click(self.plot_default)
|
||||||
|
self.button_plot_contour.on_click(self.plot_contour)
|
||||||
|
img1 = self.plot_default_output
|
||||||
|
img2 = self.plot_contour_output
|
||||||
|
#display(widgets.HBox([img1, img2]))
|
||||||
|
display(img1)
|
||||||
|
display(img2)
|
||||||
|
|
||||||
|
def compute_default(self, *args):
|
||||||
|
with self.compute_output:
|
||||||
|
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
||||||
|
xn = x0
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
self.xn_list, self.df_list = [], []
|
||||||
|
|
||||||
|
for n in tqdm(range(0, self.wg_max_iter.value)):
|
||||||
|
gradient = np.array([diff(expr, x1).subs(x1, xn[0]).subs(x2, xn[1]),
|
||||||
|
diff(expr, x2).subs(x1, xn[0]).subs(x2, xn[1])], dtype=float)
|
||||||
|
self.xn_list.append(xn)
|
||||||
|
self.df_list.append(gradient)
|
||||||
|
if np.linalg.norm(gradient, ord=2) < self.wg_epsilon.value:
|
||||||
|
clear_output(wait=True)
|
||||||
|
print("Found solution of {} after".format(expr), n, "iterations")
|
||||||
|
print("x* = [{}, {}]".format(xn[0], xn[1]))
|
||||||
|
return None
|
||||||
|
xn = xn - self.wg_lr.value * gradient
|
||||||
|
clear_output(wait=True)
|
||||||
|
display("Exceeded maximum iterations. No solution found.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def plot_default(self, *args):
|
||||||
|
with self.plot_default_output:
|
||||||
|
clear_output(wait=True)
|
||||||
|
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
xx1 = np.arange(0, 5, 0.25)
|
||||||
|
xx2 = np.arange(0, 5, 0.25)
|
||||||
|
#xx1 = np.arange(np.array(self.xn_list)[:, 0].min() * 0.5, np.array(self.xn_list)[:, 0].max() * 1.5, 0.1)
|
||||||
|
#xx2 = np.arange(np.array(self.xn_list)[:, 1].min() * 0.5, np.array(self.xn_list)[:, 1].max() * 1.5, 0.1)
|
||||||
|
xx1_tangent = np.arange(np.array(self.xn_list)[:, 0].min(), np.array(self.xn_list)[:, 0].max(), 0.1)
|
||||||
|
xx2_tangent = np.arange(np.array(self.xn_list)[:, 1].min(), np.array(self.xn_list)[:, 1].max(), 0.1)
|
||||||
|
xx1_o, xx2_o = xx1, xx2
|
||||||
|
xx1, xx2 = np.meshgrid(xx1, xx2)
|
||||||
|
xx1_tangent, xx2_tangent = np.meshgrid(xx1_o, xx2_o)
|
||||||
|
self.xx1_tangent, self.xx2_tangent = xx1_tangent, xx2_tangent
|
||||||
|
f = lambdify((x1, x2), expr, "numpy")
|
||||||
|
fx = f(xx1, xx2)
|
||||||
|
f_xn = f(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
||||||
|
partial_x1 = lambdify((x1, x2), diff(expr, x1), "numpy")
|
||||||
|
partial_x2 = lambdify((x1, x2), diff(expr, x2), "numpy")
|
||||||
|
plane = partial_x1(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x1 - np.array(self.xn_list)[:, 0]) + partial_x2(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x2 - np.array(self.xn_list)[:, 1]) + f_xn
|
||||||
|
z = [lambdify((x1, x2), plane[i], "numpy")(xx1_tangent, xx2_tangent) for i in range(0, len(plane))]
|
||||||
|
self.z = z
|
||||||
|
## projection
|
||||||
|
z_offset = (np.min(fx)) * np.ones(fx.shape)
|
||||||
|
proj_z = lambda x, y, z: z
|
||||||
|
colorsurfz = proj_z(xx1, xx2, fx)
|
||||||
|
|
||||||
|
from plotly.subplots import make_subplots
|
||||||
|
fig = make_subplots(rows=1, cols=2, specs=[[{'type': 'surface'}, {'type': 'surface'}]])
|
||||||
|
fig.add_trace(go.Surface(contours = {"x": {"show": True}, "y":{"show": True}, "z":{"show": True}}, x=xx1, y=xx2, z=fx), row=1, col=1)
|
||||||
|
fig.add_trace(go.Scatter3d(x=None, y=None, z=None), row=1, col=1)
|
||||||
|
fig.add_trace(go.Surface(x=xx1_tangent, y=xx2_tangent, z=z[0], showscale=False, colorscale='Blues'), row=1, col=1)
|
||||||
|
fig.add_trace(go.Surface(z=list(z_offset), x=xx1, y=xx2, showlegend=False, showscale=False, surfacecolor=colorsurfz), row=1, col=2)
|
||||||
|
fig.add_trace(go.Scatter3d(x=None, y=None, z=None), row=1, col=2)
|
||||||
|
fig.add_trace(go.Scatter3d(x=None, y=None, z=None), row=1, col=2)
|
||||||
|
frames = [go.Frame(data=[go.Surface(visible=True, showscale=False, opacity=0.8),
|
||||||
|
go.Scatter3d(x=np.array(self.xn_list)[:k,0], y=np.array(self.xn_list)[:k,1], z=f_xn),
|
||||||
|
go.Surface(visible=True, x=xx1_tangent, y=xx2_tangent, z=z[k]),
|
||||||
|
go.Surface(visible=True, showscale=False, opacity=0.8),
|
||||||
|
go.Scatter3d(x=np.array(self.xn_list)[:k, 0], y=np.array(self.xn_list)[:k, 1], z=f_xn),
|
||||||
|
go.Scatter3d(x=np.array(self.xn_list)[:k, 0].flatten(), y=np.array(self.xn_list)[:k, 1].flatten(), z=z_offset.flatten())],
|
||||||
|
traces=[0, 1, 2, 3, 4, 5]) for k in range(len(f_xn))]
|
||||||
|
fig.frames = frames
|
||||||
|
self.fig_frames = frames
|
||||||
|
|
||||||
|
button_play = dict(label="Play", method="animate", args=[None, dict(fromcurrent=True, transition=dict(duration=0), frame=dict(redraw=True, duration=1000))])
|
||||||
|
button_pause = dict(label="Pause", method="animate", args=[[None], dict(fromcurrent=True, mode='immediate', transition={'duration': 0}, frame=dict(redraw=True, duration=0))])
|
||||||
|
button_quiver = dict(label="Quiver", method="update", args=[{"visible": [False, False, False, False, False, True]}])
|
||||||
|
fig.update_layout(scene_aspectmode='manual', scene_aspectratio=dict(x=0, y=0, z=0),
|
||||||
|
height=800, updatemenus=[dict(type="buttons", buttons=[button_play, button_pause])])
|
||||||
|
fig.show()
|
||||||
|
|
||||||
|
def plot_contour(self, *args):
|
||||||
|
with self.plot_contour_output:
|
||||||
|
clear_output(wait=True)
|
||||||
|
x0 = np.array(self.wg_x0.value.split(","), dtype=float)
|
||||||
|
x1 = symbols("x1")
|
||||||
|
x2 = symbols("x2")
|
||||||
|
expr = sympify(self.wg_expr.value)
|
||||||
|
xx1 = np.arange(0, 5, 0.1)
|
||||||
|
xx2 = np.arange(0, 6, 0.1)
|
||||||
|
xx1_tangent = np.arange(np.array(self.xn_list)[:, 0].min(), np.array(self.xn_list)[:, 0].max(), 0.1)
|
||||||
|
xx2_tangent = np.arange(np.array(self.xn_list)[:, 1].min(), np.array(self.xn_list)[:, 1].max(), 0.1)
|
||||||
|
xx1_o, xx2_o = xx1, xx2
|
||||||
|
xx1, xx2 = np.meshgrid(xx1, xx2)
|
||||||
|
xx1_tangent, xx2_tangent = np.meshgrid(xx1_o, xx2_o)
|
||||||
|
f = lambdify((x1, x2), expr, "numpy")
|
||||||
|
fx = f(xx1, xx2)
|
||||||
|
f_xn = f(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
||||||
|
partial_x1 = lambdify((x1, x2), diff(expr, x1), "numpy")
|
||||||
|
partial_x2 = lambdify((x1, x2), diff(expr, x2), "numpy")
|
||||||
|
plane = partial_x1(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x1 - np.array(self.xn_list)[:, 0]) + partial_x2(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1]) * (x2 - np.array(self.xn_list)[:, 1]) + f_xn
|
||||||
|
z = [lambdify((x1, x2), plane[i], "numpy")(xx1_tangent, xx2_tangent) for i in range(0, len(plane))]
|
||||||
|
|
||||||
|
gradfun=[sympy.diff(expr,var) for var in (x1,x2)]
|
||||||
|
numgradfun=sympy.lambdify([x1,x2], gradfun)
|
||||||
|
x1_mesh, x2_mesh = np.meshgrid(np.array(self.xn_list)[:, 0], np.array(self.xn_list)[:, 1])
|
||||||
|
graddat=numgradfun(x1_mesh, x2_mesh)
|
||||||
|
|
||||||
|
vec_field = ff.create_quiver(x1_mesh, x2_mesh, graddat[0], graddat[1],scale=.05, arrow_scale=.1, angle=math.pi/6)
|
||||||
|
vec_field.update_traces(line_color="black")
|
||||||
|
fig = go.Figure()
|
||||||
|
fig.add_trace(go.Contour(x=xx1_o, y=xx2_o, z=fx))
|
||||||
|
for d in vec_field.data:
|
||||||
|
fig.add_trace(go.Scatter(visible=False, x=d['x'], y=d['y'], line_color="black"))
|
||||||
|
fig.update_layout(
|
||||||
|
updatemenus=[dict(type = "buttons",direction = "left",
|
||||||
|
buttons=list([
|
||||||
|
dict(args=[{"visible":["True", "True"]}], label="Quiver", method="update")]))], height=800)
|
||||||
|
fig.show()
|
Loading…
Reference in New Issue