diff --git a/algorithm/interactive.ipynb b/algorithm/interactive.ipynb index e5f3c25..914cb85 100644 --- a/algorithm/interactive.ipynb +++ b/algorithm/interactive.ipynb @@ -12,72 +12,39 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "0a5c51d2-8b18-4143-b6f1-73a909ccb623", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "70a42b75bdbf466faf21e0cebc36f929", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HBox(children=(VBox(children=(Text(value='x**3 - x**(1/2)', description='Expression:', style=Te…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d694d1ca0515436ba380b3c1987752c2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "350dce1753724cddbc0c5d5c883a451b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "gd1 = gradient_descent_1d(environ=\"jupyterlab\")" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "15c6e757-cde3-422b-be7e-3f55b7752142", "metadata": {}, + "outputs": [], + "source": [ + "gd2 = gradient_descent_2d(environ=\"jupyterlab\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "694b7e27-cc21-44f4-9a89-7a6b97725a64", + "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "ee383167ceff45b7818279fdfbeb9535", + "model_id": "08df46f6a3b54543a15dd79d71c334bc", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "VBox(children=(HBox(children=(Dropdown(index=2, options=(('(sin(x1) - 2) + (sin(x2) - 2) ** 2', '(sin(x1) - 2)…" + "VBox(children=(Text(value='(sin(x1) - 2) ** 2 + (sin(x2) - 2) ** 2', description='Expression:'), Text(value='(…" ] }, "metadata": {}, @@ -86,21 +53,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "5325cc88a8fa46ffb92b466701a2b8b1", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d76a192e28344ae99821b441b0c74b75", + "model_id": "ee2bc3a3c2b843aeae594ece6e02596e", "version_major": 2, "version_minor": 0 }, @@ -113,13 +66,36 @@ } ], "source": [ - "gd2 = gradient_descent_2d(environ=\"jupyterlab\")" + "gd2_race = gradient_descent_2d_race(environ=\"jupyterlab\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "5a2aec3f-e47b-44ab-b3da-2275578e9636", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[array([-4., -4.]),\n", + " array([-1.2519118 , 0.90778485]),\n", + " array([-2.02500166, 2.8935338 ])]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gd2_race.df_list_p1" ] }, { "cell_type": "code", "execution_count": null, - "id": "52862bf7-6db4-45bc-b963-b140b84795ef", + "id": "b89040ec-4318-419b-95eb-60320f146877", "metadata": {}, "outputs": [], "source": [] diff --git a/algorithm/optimization/.ipynb_checkpoints/gd-checkpoint.py b/algorithm/optimization/.ipynb_checkpoints/gd-checkpoint.py index 3096782..04e5100 100644 --- a/algorithm/optimization/.ipynb_checkpoints/gd-checkpoint.py +++ b/algorithm/optimization/.ipynb_checkpoints/gd-checkpoint.py @@ -99,121 +99,7 @@ class gradient_descent_1d(object): 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_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:") #style={'description_width': 'initial'}) - 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(object): def __init__(self, environ:str="jupyterlab"): pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab' @@ -332,4 +218,162 @@ class gradient_descent_2d(object): 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() \ No newline at end of file + 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="(0, 0)", description="coordinate 1:") + self.wg_person_two = widgets.Text(value="(0, 0)", description="coordinate 2:") + self.button_compute = widgets.Button(description="Compute") + self.button_plot = widgets.Button(description="Plot") + self.compute_output = widgets.Output() + self.config = widgets.VBox([self.wg_expr, self.wg_person_one, self.wg_person_two, self.button_compute]) + 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 + + \ No newline at end of file diff --git a/algorithm/optimization/gd.py b/algorithm/optimization/gd.py index 3096782..04e5100 100644 --- a/algorithm/optimization/gd.py +++ b/algorithm/optimization/gd.py @@ -99,121 +99,7 @@ class gradient_descent_1d(object): 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_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:") #style={'description_width': 'initial'}) - 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(object): def __init__(self, environ:str="jupyterlab"): pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab' @@ -332,4 +218,162 @@ class gradient_descent_2d(object): 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() \ No newline at end of file + 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="(0, 0)", description="coordinate 1:") + self.wg_person_two = widgets.Text(value="(0, 0)", description="coordinate 2:") + self.button_compute = widgets.Button(description="Compute") + self.button_plot = widgets.Button(description="Plot") + self.compute_output = widgets.Output() + self.config = widgets.VBox([self.wg_expr, self.wg_person_one, self.wg_person_two, self.button_compute]) + 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 + + \ No newline at end of file