diff --git a/algorithm/.ipynb_checkpoints/interactive-checkpoint.ipynb b/algorithm/.ipynb_checkpoints/interactive-checkpoint.ipynb index 987e34b..c7a5307 100644 --- a/algorithm/.ipynb_checkpoints/interactive-checkpoint.ipynb +++ b/algorithm/.ipynb_checkpoints/interactive-checkpoint.ipynb @@ -1,8 +1,62 @@ { "cells": [ + { + "cell_type": "markdown", + "id": "b705b060", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Steepest Descent Method\n", + "\n", + "Instructor: Dr.Yuhui Deng\n", + "\n", + "![level_gradient](figure/level_gradient.png)" + ] + }, + { + "cell_type": "markdown", + "id": "f576c3bd", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Problem Description\n", + "\n", + "Problem: \n", + "\n", + "$\\begin{align*} \n", + "min(fx) \\\\\n", + "s.t. \\ x \\in \\mathbb{R}^n\n", + "\\end{align*}$\n", + "where\n", + "\n", + "* $f: \\mathbb{R}^n \\rightarrow \\mathbb{R}$\n", + "* No constraints are placed on the variables $X$\n" + ] + }, + { + "cell_type": "markdown", + "id": "c6e94df1", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# One Dimential Function\n", + "\n", + "$$min \\ f(x)=x^2 - 4x + 7$$\n", + "\n" + ] + }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "af1d5646-4b13-4039-9f76-8042bc9dbda3", "metadata": {}, "outputs": [], @@ -12,283 +66,132 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "8ce3dbbd-a698-448b-a2c6-772286c745d5", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f63728b9362047df80c1bf76167f6bf5", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HBox(children=(VBox(children=(Text(value='-2 * x * sin(-(pi/4) * x)+10', description='Expressio…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "2ded251d4d034c058f83d613618e3a7d", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "b9e00497c1cd4bc484bf7ea793aa3d78", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "gd1 = gd_1d()" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "a1765810-6cd8-4e1a-aaa6-7691a7b2a42e", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "4101fea885e6435e8283e6da6f4f68e9", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HBox(children=(Dropdown(options=(('(1 - 8 * x1 + 7 * x1**2 - (7/3) * x1**3 + (1/4) * x1**4) * x…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1a7d3fe1bd72408684d18ad75e2754ce", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "be733631b99b4b09939ed99c1723b03b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "41c863b04c314bbd8df1353e7fc92ec1", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "gd2 = gd_2d()" ] }, { "cell_type": "code", - "execution_count": 7, - "id": "88e5e47f-3a02-4919-a74e-a4758c56390a", + "execution_count": null, + "id": "06b73a46-f6d5-420d-a668-abaf2c6127a3", + "metadata": {}, + "outputs": [], + "source": [ + "expr = sympify(gd2.wg_expr.value)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7504cf8-514c-444a-bd62-91a13b067cf6", + "metadata": {}, + "outputs": [], + "source": [ + "expr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ff3f9fa9-9071-45c5-a939-d5f0bbe7b37e", + "metadata": {}, + "outputs": [], + "source": [ + "from sympy import *\n", + "from sympy.abc import x\n", + "expr = \"(x - 2)**2 + 3\"\n", + "ex = sympify(expr)\n", + "solve(ex, x)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "61e0d2b8-41c8-4790-8b25-2df6ba4c3625", + "metadata": {}, + "outputs": [], + "source": [ + "from optimization.common import *" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "cc84e26c-7135-427b-9a5b-c39b6b495fe5", "metadata": {}, "outputs": [ { "data": { - "text/latex": [ - "$\\displaystyle \\operatorname{Plane}\\left(\\operatorname{Point3D}\\left(1, 1, 1\\right), \\left( 1, \\ 4, \\ 7\\right)\\right)$" - ], + "application/vnd.jupyter.widget-view+json": { + "model_id": "e2a6bc45f7354f529c8475f034416135", + "version_major": 2, + "version_minor": 0 + }, "text/plain": [ - "Plane(Point3D(1, 1, 1), (1, 4, 7))" + "VBox(children=(HBox(children=(Text(value='-2 * x * sin(-(pi/4) * x)+10', description='Expression:', style=Text…" ] }, - "execution_count": 7, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c2c3118f55d241e68649a094a6bb3836", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "cdc830df33fe4705b448245a1d64c335", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ - "from sympy import Plane, Point3D\n", - "Plane(Point3D(1, 1, 1), Point3D(2, 3, 4), Point3D(2, 2, 2))\n", - "Plane((1, 1, 1), (2, 3, 4), (2, 2, 2))\n", - "Plane(Point3D(1, 1, 1), normal_vector=(1,4,7))" + "a = func_1d()" ] }, { "cell_type": "code", "execution_count": null, - "id": "b0563398-5a79-47aa-9c31-474a518daa0d", - "metadata": {}, - "outputs": [], - "source": [ - "from sympy import Point3D, Plane\n", - "a = Plane(Point3D(1, 1, 1), Point3D(2, 3, 4), Point3D(2, 2, 2))\n", - "a.normal_vector\n", - "a = Plane(Point3D(1, 1, 1), normal_vector=(1, 4, 7))\n", - "a.normal_vector" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cf7ed01e-f42a-4a3d-8c2f-e0e7dfa682c5", - "metadata": {}, - "outputs": [], - "source": [ - "from sympy.vector import CoordSys3D, gradient\n", - "from sympy import symbols, sympify, lambdify, diff\n", - "expr = sympify(\"(1 - 8 * x1 + 7 * x1**2 - (7/3) * x1**3 + (1/4) * x1**4) * x2**2 * E**(-x2)\")\n", - "x1, x2 = symbols(\"x1\"), symbols(\"x2\")\n", - "gradient(expr)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bdbceb9a-42f0-42e3-a2cb-573b4d82e4af", - "metadata": {}, - "outputs": [], - "source": [ - "from sympy.vector import CoordSys3D\n", - "R = CoordSys3D('R')\n", - "v = (1 - 8*R.x +7*R.x**2 - (7/3)*R.x**3 + (1/4 * R.x**4) * R.y**2 * np.exp(1)**(-R.y))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "af76a657-c281-41b4-83c3-c3f73376d948", - "metadata": {}, - "outputs": [], - "source": [ - "from sympy.vector import CoordSys3D, Del\n", - "R = CoordSys3D('R')\n", - "delop = Del()\n", - "gradient_field = delop((1 - 8*R.x +7*R.x**2 - (7/3)*R.x**3 + (1/4 * R.x**4) * R.y**2 * np.exp(1)**(-R.y)))\n", - "gradient_field" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d987886f-1231-487a-88dc-47e8a45d728c", - "metadata": {}, - "outputs": [], - "source": [ - "import sympy\n", - "\n", - "#define symbolic vars, function\n", - "x,y=sympy.symbols('x y')\n", - "fun= sympify(\"(1 - 8 * x + 7 * x**2 - (7/3) * x**3 + (1/4) * x**4) * y**2 * E**(-y)\")\n", - "#fun=3*x**2-5*y**2\n", - "#take the gradient symbolically\n", - "gradfun=[sympy.diff(fun,var) for var in (x1,x2)]\n", - "numgradfun=sympy.lambdify([x,y],gradfun)\n", - "graddat=numgradfun(xx1_o,xx2_o)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "da34c7be-025f-4326-8138-9e78e2043b7e", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import plotly.figure_factory as ff\n", - "import math\n", - "\n", - "X,Y=np.meshgrid(np.arange(0,5, 0.25),np.arange(0,5, 0.25))\n", - "graddat=numgradfun(X,Y)\n", - "\n", - "\n", - "fig = ff.create_quiver(X, Y, graddat[0], graddat[1],scale=.05, arrow_scale=.1, angle=math.pi/6)\n", - "fig.update_traces(line_color=\"red\")\n", - "fig.update_layout(height=800)\n", - "fig.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "62504d86-9dc8-42b2-b052-d7acfe8be5e0", - "metadata": {}, - "outputs": [], - "source": [ - "fig.data[0][\"x\"]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "415a2abd-3ea4-48ee-9923-c9897105ad27", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "\n", - "X,Y=np.meshgrid(np.arange(0,5, 0.1),np.arange(0,5,0.1))\n", - "graddat=numgradfun(X,Y)\n", - "\n", - "plt.figure()\n", - "plt.quiver(X,Y,graddat[0],graddat[1])\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2c60be92-8c74-4f46-b7fc-bb9d7150cbe0", + "id": "98061d97-555e-486a-a07d-1b8c37cd2471", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { + "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", diff --git a/algorithm/figure/level_gradient.png b/algorithm/figure/level_gradient.png new file mode 100644 index 0000000..dccb10d Binary files /dev/null and b/algorithm/figure/level_gradient.png differ diff --git a/algorithm/interactive.ipynb b/algorithm/interactive.ipynb index 31aa33f..c7a5307 100644 --- a/algorithm/interactive.ipynb +++ b/algorithm/interactive.ipynb @@ -1,8 +1,62 @@ { "cells": [ + { + "cell_type": "markdown", + "id": "b705b060", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Steepest Descent Method\n", + "\n", + "Instructor: Dr.Yuhui Deng\n", + "\n", + "![level_gradient](figure/level_gradient.png)" + ] + }, + { + "cell_type": "markdown", + "id": "f576c3bd", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "## Problem Description\n", + "\n", + "Problem: \n", + "\n", + "$\\begin{align*} \n", + "min(fx) \\\\\n", + "s.t. \\ x \\in \\mathbb{R}^n\n", + "\\end{align*}$\n", + "where\n", + "\n", + "* $f: \\mathbb{R}^n \\rightarrow \\mathbb{R}$\n", + "* No constraints are placed on the variables $X$\n" + ] + }, + { + "cell_type": "markdown", + "id": "c6e94df1", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# One Dimential Function\n", + "\n", + "$$min \\ f(x)=x^2 - 4x + 7$$\n", + "\n" + ] + }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "af1d5646-4b13-4039-9f76-8042bc9dbda3", "metadata": {}, "outputs": [], @@ -12,120 +66,20 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "8ce3dbbd-a698-448b-a2c6-772286c745d5", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "5715c7beff3c4ab58a001fecee2e6ba9", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HBox(children=(VBox(children=(Text(value='-2 * x * sin(-(pi/4) * x)+10', description='Expressio…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "60025f1dfc974c4ba4765136faa526e8", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "52d1cde962ba4b7dad5c4e581fc5aee1", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "gd1 = gd_1d()" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "a1765810-6cd8-4e1a-aaa6-7691a7b2a42e", "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f6ef2a67373b4552b4d866c633e8b9a7", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "VBox(children=(HBox(children=(Dropdown(options=(('(1 - 8 * x1 + 7 * x1**2 - (7/3) * x1**3 + (1/4) * x1**4) * x…" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ece751b11bc643a196bc17d87d90499e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "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_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "gd2 = gd_2d()" ] @@ -133,13 +87,111 @@ { "cell_type": "code", "execution_count": null, - "id": "48944e3c-932a-4733-b77d-a2b50cee2e5a", + "id": "06b73a46-f6d5-420d-a668-abaf2c6127a3", + "metadata": {}, + "outputs": [], + "source": [ + "expr = sympify(gd2.wg_expr.value)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7504cf8-514c-444a-bd62-91a13b067cf6", + "metadata": {}, + "outputs": [], + "source": [ + "expr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ff3f9fa9-9071-45c5-a939-d5f0bbe7b37e", + "metadata": {}, + "outputs": [], + "source": [ + "from sympy import *\n", + "from sympy.abc import x\n", + "expr = \"(x - 2)**2 + 3\"\n", + "ex = sympify(expr)\n", + "solve(ex, x)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "61e0d2b8-41c8-4790-8b25-2df6ba4c3625", + "metadata": {}, + "outputs": [], + "source": [ + "from optimization.common import *" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "cc84e26c-7135-427b-9a5b-c39b6b495fe5", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e2a6bc45f7354f529c8475f034416135", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(Text(value='-2 * x * sin(-(pi/4) * x)+10', description='Expression:', style=Text…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c2c3118f55d241e68649a094a6bb3836", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "cdc830df33fe4705b448245a1d64c335", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "a = func_1d()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "98061d97-555e-486a-a07d-1b8c37cd2471", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { + "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", diff --git a/algorithm/lecture.ipynb b/algorithm/lecture.ipynb new file mode 100644 index 0000000..a901c84 --- /dev/null +++ b/algorithm/lecture.ipynb @@ -0,0 +1,506 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9b492ee6", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Steepest Descent Method\n", + "\n", + "Instructor: Dr.Yuhui Deng" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "2472b8ca", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f7a7d3f014ca4f599b561ca1e4e5e9ff", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(Text(value='x1^2 + x2^2', description='Expression:', style=TextStyle(description…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5739708475934a0aa0fc6172f98ec6be", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from optimization.common import *\n", + "contourPlot2d(environ=\"notebook\")" + ] + }, + { + "cell_type": "markdown", + "id": "1d34025b", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Problem Description\n", + "\n", + "$\\textbf{Problem:}\\left\\{\\begin{align*}\n", + "\\min \\ f(x) \\\\\n", + "s.t. \\ x \\in \\mathbb{R}^n\n", + "\\end{align*} \\right.$\n", + "\n", + "where: \n", + "* $f: \\mathbb{R}^n \\mapsto \\mathbb{R}$\n", + "* No constraints are placed on the variables $x$" + ] + }, + { + "cell_type": "markdown", + "id": "6f867a65", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### One Dimentional Function\n", + "\n", + "$$\\min \\ f(x) = x^2 - 4x + 7$$" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "302d9c60", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "cf33688620c54a4d85cb0f9dbce63fe3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(Text(value='(x - 2)**2 + 3', description='Expression:', style=TextStyle(descript…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "aa0a66db4d33470fbe7a091588bb27a6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3a84ef2c3bd14854b81d4cb48005991f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "funcPlot1d(environ=\"notebook\")" + ] + }, + { + "cell_type": "markdown", + "id": "e2ce7e95", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "source": [ + "$$x_{k+1} = x_{k} + a \\cdot d \\quad d = \\left\\{\\begin{align*} +1 &\\text{ left} \\\\ -1 &\\text{ right}\\end{align*}\\right. \\ a \\geq 0$$" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "a4827f0c", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "578d548bc16c45caa29f47f60b58acf0", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(VBox(children=(Text(value='sin(x) + sin((10.0 / 3.0) * x)', description='Express…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ead520028b844ef78e0932d537ac7172", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "16060b8b5ae04f31833395b3b1f4259c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gd_1d(environ=\"notebook\")" + ] + }, + { + "cell_type": "markdown", + "id": "f55e58dd", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Multi Dimentional Function\n", + "\n", + "$$(1 - 8 \\cdot x_1 + 7 \\cdot x_1^2 - \\frac{7x_{1}^{3}}{3} + \\frac{x^{4}}{4}) \\cdot x_2^2 \\cdot e^{(-x_2)}$$" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "7c589589", + "metadata": { + "slideshow": { + "slide_type": "fragment" + } + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5d9c8974d7c04f4dbdb7aa333ae7d172", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(Text(value='(1 - 8 * x1 + 7 * x1^2 - (7/3) * x1^3 + (1/4) * x1^4) * x2^2 * E^(-x…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "909764ee6cd94053a17da64592bb11e5", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ba448ff14b8f454b8f4b6d3cb8f92c9e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "funcPlot2d(environ=\"notebook\")" + ] + }, + { + "cell_type": "markdown", + "id": "1a5b2203", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "Some Questions:\n", + "\n", + "1. How many choices for the searching direction?\n", + "2. Which direction will you choose?\n", + "3. How far will you walk?\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "f28bd167", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "bd08d4c9d0014062a1e0654177dfbd55", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(Dropdown(options=(('(1 - 8 * x1 + 7 * x1**2 - (7/3) * x1**3 + (1/4) * x1**4) * x…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "26123777d5214fa28d4bfd16d9afe3b8", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "176568fccd1f49d79abc66fff51859d6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7f1d7ace2eef4a5480c72444f52fd4c1", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gd_2d(environ=\"notebook\")" + ] + }, + { + "cell_type": "markdown", + "id": "d585d6de", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Multi Dimentional Function\n", + "\n", + "**Descent Direction** If a direction vector $d$ has the property that at least for sufficiently small $\\alpha > 0$, \n", + "$$f(x + \\alpha d) < f(x)$$\n", + "then $d$ is said a **descent direction** for function $f$ at point $x$." + ] + }, + { + "cell_type": "markdown", + "id": "3adf3a40", + "metadata": { + "slideshow": { + "slide_type": "subslide" + } + }, + "source": [ + "### Multi Dimentional Function\n", + "\n", + "梯度取极值" + ] + }, + { + "cell_type": "markdown", + "id": "49f800ef", + "metadata": {}, + "source": [ + "### Multi Dimentional Function\n", + "\n", + "**When exact line search is used**, the steepest descent method obtains\n", + "$$x^{k+1} = x^{k} - \\alpha_{k} \\nabla f(x^k)$$\n", + "where $\\alpha_k$ is the solution of the one-dimensional minimization problem: \n", + "$$\\min_{\\alpha > 0} F(\\alpha) \\equiv f(x^{k} - \\alpha \\nabla f(x^k))$$\n", + "So,\n", + "$$\\begin{align*}F^{\\prime} = 0 \\Rightarrow - \\nabla f(x^k - \\alpha_k \\nabla f(x^k))^T \\nabla f(x^k) = 0 \\\\\n", + "\\Rightarrow \\nabla f(x^{k+1})^T \\nabla f(x^k) = 0\n", + "\\end{align*}$$\n", + "\n", + "This means that **every pair of $\\nabla f(x^{k+1})$ and $\\nabla f(x^k)$ are vertical.** Hence $\\{x^k\\}$ usually takes a zigzag path to approach the solution $x^{*}$. By this fact, we may better understand the reason why steepest descent method progresses slowly when the contours of $f$ are flat, see Section 4.7 (Appendix 2)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1b5fb35c", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "celltoolbar": "Slideshow", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/algorithm/optimization/.ipynb_checkpoints/gd-checkpoint.py b/algorithm/optimization/.ipynb_checkpoints/gd-checkpoint.py deleted file mode 100644 index 572adfe..0000000 --- a/algorithm/optimization/.ipynb_checkpoints/gd-checkpoint.py +++ /dev/null @@ -1,138 +0,0 @@ -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_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) - fig = go.Figure(data=[trace1, trace2], 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() \ No newline at end of file diff --git a/algorithm/optimization/common.py b/algorithm/optimization/common.py new file mode 100644 index 0000000..cb6997e --- /dev/null +++ b/algorithm/optimization/common.py @@ -0,0 +1,188 @@ +import math +import copy +import time +import sympy +import numpy as np +from scipy.misc import derivative +from sympy import symbols, sympify, lambdify, diff, solve + +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 + +class funcPlot1d(object): + def __init__(self, environ:str="jupyterlab"): + pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab' + self.wg_expr = widgets.Text(value="(x - 2)**2 + 3", + description="Expression:", + style={'description_width': 'initial'}) + self.wg_x_range = widgets.Text(value="-10,10", + description="X-axis range", + 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_box = widgets.HBox([self.wg_expr, self.wg_x_range]) + 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: + x = symbols("x") + expr = sympify(self.wg_expr.value) + f = lambdify(x, expr) + clear_output(wait=True) + print(solve(expr, x)) + + + def plot(self, *args): + with self.plot_output: + fig = go.Figure() + x_range = np.array(self.wg_x_range.value.split(","), dtype=float) + x_num = np.arange(x_range[0], x_range[1], 0.1) + expr = sympify(self.wg_expr.value) + x = symbols("x") + f = lambdify(x, expr) + fx = f(x_num) + fig.add_scatter(x=x_num, y=fx) + clear_output(wait=True) + fig.show() + +class funcPlot2d(object): + def __init__(self, environ:str="jupyterlab", type="default"): + if type == "default": + self.initialization_default(environ=environ) + 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.Text(value="(1 - 8 * x1 + 7 * x1^2 - (7/3) * x1^3 + (1/4) * x1^4) * x2^2 * E^(-x2)", + description="Expression:", + style={'description_width': 'initial'}) + self.button_plot_default = widgets.Button(description="3D Plot") + + self.compute_output = widgets.Output() + self.plot_default_output = widgets.Output() + self.plot_contour_output = widgets.Output() + self.exp_box = widgets.HBox([self.wg_expr]) + self.button_box = widgets.HBox([self.button_plot_default], description="operations") + self.config = widgets.VBox([self.exp_box, self.button_box]) + display(self.config) + + display(self.compute_output) + self.button_plot_default.on_click(self.plot_default) + img1 = self.plot_default_output + display(img1) + + def plot_default(self, *args): + with self.plot_default_output: + clear_output(wait=True) + 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_o, xx2_o = xx1, xx2 + xx1, xx2 = np.meshgrid(xx1, xx2) + xx1_tangent, xx2_tangent = np.meshgrid(xx1_o, xx2_o) + #xx1_tangent, xx2_tangent = array_mesh(np.arange(0, 5, 0.25), 10), array_mesh(np.arange(0, 5, 0.25), 10) + f = lambdify((x1, x2), expr, "numpy") + fx = f(xx1, xx2) + ## 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=1, specs=[[{'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=None, y=None, z=None, showlegend=False, showscale=False, colorscale='Blues'), row=1, col=1) + frames = [go.Frame(data=[go.Surface(visible=True, showscale=False, opacity=0.8)], + traces=[0])] + fig.frames = frames + self.fig_frames = frames + + fig.update_layout(height=600, scene_aspectmode='manual', scene_aspectratio=dict(x=0, y=0, z=0), updatemenus=[dict(type="buttons")]) + fig.update_scenes(xaxis_visible=False, + yaxis_visible=False, + zaxis_visible=False) + fig.update_scenes(camera_projection_type = "orthographic") + fig.show() + +class contourPlot2d(object): + def __init__(self, environ:str="jupyterlab"): + pio.renderers.default = environ # 'notebook' or 'colab' or 'jupyterlab' + self.wg_expr = widgets.Text(value="x1^2 + x2^2", + description="Expression:", + style={'description_width': 'initial'}) + + self.button_plot = widgets.Button(description="Plot") + + self.plot_output = widgets.Output() + + self.params_box = widgets.HBox([self.wg_expr]) + self.button_box = widgets.HBox([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_plot.on_click(self.plot) + display(self.plot_output) + + + def plot(self, *args): + with self.plot_output: + clear_output(wait=True) + x1 = symbols("x1") + x2 = symbols("x2") + expr = sympify(self.wg_expr.value) + xx1 = np.arange(-5, 5, 0.5) + xx2 = np.arange(-5, 5, 0.5) + xx1_o, xx2_o = xx1, xx2 #np.arange(-5, 5, 0.5), np.arange(-5, 5, 0.5) + xx1, xx2 = np.meshgrid(xx1, xx2) + f = lambdify((x1, x2), expr, "numpy") + fx = f(xx1, xx2) + partial_x1 = lambdify((x1, x2), diff(expr, x1), "numpy") + partial_x2 = lambdify((x1, x2), diff(expr, x2), "numpy") + + gradfun=[sympy.diff(expr,var) for var in (x1,x2)] + numgradfun=sympy.lambdify([x1,x2], gradfun) + x1_mesh, x2_mesh = np.meshgrid(xx1_o, xx2_o) + 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/4) + 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="Gradient", method="update")]))], height=800) + fig.show() \ No newline at end of file diff --git a/algorithm/optimization/gd.py b/algorithm/optimization/gd.py deleted file mode 100644 index 572adfe..0000000 --- a/algorithm/optimization/gd.py +++ /dev/null @@ -1,138 +0,0 @@ -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_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) - fig = go.Figure(data=[trace1, trace2], 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() \ No newline at end of file diff --git a/algorithm/optimization/gd1d.py b/algorithm/optimization/gd1d.py deleted file mode 100644 index 72dc349..0000000 --- a/algorithm/optimization/gd1d.py +++ /dev/null @@ -1,101 +0,0 @@ -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() \ No newline at end of file diff --git a/algorithm/optimization/gd2d.py b/algorithm/optimization/gd2d.py deleted file mode 100644 index 5002200..0000000 --- a/algorithm/optimization/gd2d.py +++ /dev/null @@ -1,489 +0,0 @@ -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() \ No newline at end of file diff --git a/algorithm/optimization/gd2d_test.py b/algorithm/optimization/gd2d_test.py deleted file mode 100644 index 2b373a5..0000000 --- a/algorithm/optimization/gd2d_test.py +++ /dev/null @@ -1,129 +0,0 @@ -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() diff --git a/algorithm/optimization/gd_new.py b/algorithm/optimization/gd_new.py index 31eef8a..dc18fa0 100644 --- a/algorithm/optimization/gd_new.py +++ b/algorithm/optimization/gd_new.py @@ -30,7 +30,7 @@ def array_mesh(data, n): 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", + self.wg_expr = widgets.Text(value="sin(x) + sin((10.0 / 3.0) * x)", description="Expression:", style={'description_width': 'initial'}) self.wg_x0 = widgets.FloatText(value="2", @@ -45,6 +45,9 @@ class gd_1d(object): self.wg_max_iter = widgets.IntText(value="1000", description="max iteration", style={'description_width': 'initial'}) + self.wg_x_range = widgets.Text(value="-5,5", + description="X-axis range", + style={"description_width": "initial"}) self.button_compute = widgets.Button(description="Compute") self.button_plot = widgets.Button(description="Plot") @@ -52,7 +55,7 @@ class gd_1d(object): 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_rvbox = widgets.VBox([self.wg_epsilon, self.wg_max_iter, self.wg_x_range]) 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]) @@ -79,7 +82,7 @@ class gd_1d(object): gradient = df(xn) self.xn_list.append(xn) self.df_list.append(gradient) - if abs (gradient < self.wg_epsilon.value): + if abs(gradient < self.wg_epsilon.value): clear_output(wait=True) print("Found solution of {} after".format(expr), n, "iterations") print("x* = {}".format(xn)) @@ -93,11 +96,11 @@ class gd_1d(object): with self.plot_output: clear_output(wait=True) x0 = float(self.wg_x0.value) + x_range = np.array(self.wg_x_range.value.split(","), dtype=float) 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) + xx1 = np.arange(x_range[0], x_range[1], 0.05) fx = f(xx1) f_xn = f(np.array(self.xn_list)) @@ -133,8 +136,8 @@ class gd_2d(object): 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.button_plot_default = widgets.Button(description="3D Plot") + self.button_plot_contour = widgets.Button(description="Contour") self.compute_output = widgets.Output() self.plot_default_output = widgets.Output() @@ -197,13 +200,16 @@ class gd_2d(object): xx1_o, xx2_o = xx1, xx2 xx1, xx2 = np.meshgrid(xx1, xx2) xx1_tangent, xx2_tangent = np.meshgrid(xx1_o, xx2_o) + #xx1_tangent, xx2_tangent = array_mesh(np.arange(0, 5, 0.25), 10), array_mesh(np.arange(0, 5, 0.25), 10) 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") + self.partial_x1, self.partial_x2 = partial_x1, partial_x2 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 @@ -215,13 +221,13 @@ class gd_2d(object): 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(x=None, y=None, z=None, showlegend=False, 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=False, 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())], @@ -231,9 +237,13 @@ class gd_2d(object): 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]}]) + button_tangent = dict(label="Tangent Plane", method="update", args=[{"visible": [True, True, True, True, True, 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])]) + height=800, updatemenus=[dict(type="buttons", buttons=[button_play, button_pause, button_tangent])]) + fig.update_scenes(xaxis_visible=True, + yaxis_visible=True, + zaxis_visible=True) + fig.update_scenes(camera_projection_type = "orthographic") fig.show() def plot_contour(self, *args): @@ -260,10 +270,10 @@ class gd_2d(object): 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]) + x1_mesh, x2_mesh = np.meshgrid(xx1_o, xx2_o)#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 = ff.create_quiver(x1_mesh, x2_mesh, graddat[0], graddat[1], scale=.05, arrow_scale=.4, angle=math.pi/3) vec_field.update_traces(line_color="black") fig = go.Figure() fig.add_trace(go.Contour(x=xx1_o, y=xx2_o, z=fx)) @@ -272,5 +282,5 @@ class gd_2d(object): fig.update_layout( updatemenus=[dict(type = "buttons",direction = "left", buttons=list([ - dict(args=[{"visible":["True", "True"]}], label="Quiver", method="update")]))], height=800) + dict(args=[{"visible":["True", "True"]}], label="Gradient", method="update")]))], height=800) fig.show() \ No newline at end of file