aboutsummaryrefslogtreecommitdiff
path: root/circuitpython/extmod/ulab/docs/scipy-optimize.ipynb
diff options
context:
space:
mode:
authorRaghuram Subramani <raghus2247@gmail.com>2022-06-19 19:47:51 +0530
committerRaghuram Subramani <raghus2247@gmail.com>2022-06-19 19:47:51 +0530
commit4fd287655a72b9aea14cdac715ad5b90ed082ed2 (patch)
tree65d393bc0e699dd12d05b29ba568e04cea666207 /circuitpython/extmod/ulab/docs/scipy-optimize.ipynb
parent0150f70ce9c39e9e6dd878766c0620c85e47bed0 (diff)
add circuitpython code
Diffstat (limited to '')
-rw-r--r--circuitpython/extmod/ulab/docs/scipy-optimize.ipynb515
1 files changed, 515 insertions, 0 deletions
diff --git a/circuitpython/extmod/ulab/docs/scipy-optimize.ipynb b/circuitpython/extmod/ulab/docs/scipy-optimize.ipynb
new file mode 100644
index 0000000..eea97b7
--- /dev/null
+++ b/circuitpython/extmod/ulab/docs/scipy-optimize.ipynb
@@ -0,0 +1,515 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2021-01-08T12:50:51.417613Z",
+ "start_time": "2021-01-08T12:50:51.208257Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Populating the interactive namespace from numpy and matplotlib\n"
+ ]
+ }
+ ],
+ "source": [
+ "%pylab inline"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Notebook magic"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2021-01-08T12:50:52.581876Z",
+ "start_time": "2021-01-08T12:50:52.567901Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "from IPython.core.magic import Magics, magics_class, line_cell_magic\n",
+ "from IPython.core.magic import cell_magic, register_cell_magic, register_line_magic\n",
+ "from IPython.core.magic_arguments import argument, magic_arguments, parse_argstring\n",
+ "import subprocess\n",
+ "import os"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2021-01-08T12:50:53.516712Z",
+ "start_time": "2021-01-08T12:50:53.454984Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "@magics_class\n",
+ "class PyboardMagic(Magics):\n",
+ " @cell_magic\n",
+ " @magic_arguments()\n",
+ " @argument('-skip')\n",
+ " @argument('-unix')\n",
+ " @argument('-pyboard')\n",
+ " @argument('-file')\n",
+ " @argument('-data')\n",
+ " @argument('-time')\n",
+ " @argument('-memory')\n",
+ " def micropython(self, line='', cell=None):\n",
+ " args = parse_argstring(self.micropython, line)\n",
+ " if args.skip: # doesn't care about the cell's content\n",
+ " print('skipped execution')\n",
+ " return None # do not parse the rest\n",
+ " if args.unix: # tests the code on the unix port. Note that this works on unix only\n",
+ " with open('/dev/shm/micropython.py', 'w') as fout:\n",
+ " fout.write(cell)\n",
+ " proc = subprocess.Popen([\"../../micropython/ports/unix/micropython\", \"/dev/shm/micropython.py\"], \n",
+ " stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n",
+ " print(proc.stdout.read().decode(\"utf-8\"))\n",
+ " print(proc.stderr.read().decode(\"utf-8\"))\n",
+ " return None\n",
+ " if args.file: # can be used to copy the cell content onto the pyboard's flash\n",
+ " spaces = \" \"\n",
+ " try:\n",
+ " with open(args.file, 'w') as fout:\n",
+ " fout.write(cell.replace('\\t', spaces))\n",
+ " printf('written cell to {}'.format(args.file))\n",
+ " except:\n",
+ " print('Failed to write to disc!')\n",
+ " return None # do not parse the rest\n",
+ " if args.data: # can be used to load data from the pyboard directly into kernel space\n",
+ " message = pyb.exec(cell)\n",
+ " if len(message) == 0:\n",
+ " print('pyboard >>>')\n",
+ " else:\n",
+ " print(message.decode('utf-8'))\n",
+ " # register new variable in user namespace\n",
+ " self.shell.user_ns[args.data] = string_to_matrix(message.decode(\"utf-8\"))\n",
+ " \n",
+ " if args.time: # measures the time of executions\n",
+ " pyb.exec('import utime')\n",
+ " message = pyb.exec('t = utime.ticks_us()\\n' + cell + '\\ndelta = utime.ticks_diff(utime.ticks_us(), t)' + \n",
+ " \"\\nprint('execution time: {:d} us'.format(delta))\")\n",
+ " print(message.decode('utf-8'))\n",
+ " \n",
+ " if args.memory: # prints out memory information \n",
+ " message = pyb.exec('from micropython import mem_info\\nprint(mem_info())\\n')\n",
+ " print(\"memory before execution:\\n========================\\n\", message.decode('utf-8'))\n",
+ " message = pyb.exec(cell)\n",
+ " print(\">>> \", message.decode('utf-8'))\n",
+ " message = pyb.exec('print(mem_info())')\n",
+ " print(\"memory after execution:\\n========================\\n\", message.decode('utf-8'))\n",
+ "\n",
+ " if args.pyboard:\n",
+ " message = pyb.exec(cell)\n",
+ " print(message.decode('utf-8'))\n",
+ "\n",
+ "ip = get_ipython()\n",
+ "ip.register_magics(PyboardMagic)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## pyboard"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 57,
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2020-05-07T07:35:35.126401Z",
+ "start_time": "2020-05-07T07:35:35.105824Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "import pyboard\n",
+ "pyb = pyboard.Pyboard('/dev/ttyACM0')\n",
+ "pyb.enter_raw_repl()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2020-05-19T19:11:18.145548Z",
+ "start_time": "2020-05-19T19:11:18.137468Z"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "pyb.exit_raw_repl()\n",
+ "pyb.close()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 58,
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2020-05-07T07:35:38.725924Z",
+ "start_time": "2020-05-07T07:35:38.645488Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%micropython -pyboard 1\n",
+ "\n",
+ "import utime\n",
+ "import ulab as np\n",
+ "\n",
+ "def timeit(n=1000):\n",
+ " def wrapper(f, *args, **kwargs):\n",
+ " func_name = str(f).split(' ')[1]\n",
+ " def new_func(*args, **kwargs):\n",
+ " run_times = np.zeros(n, dtype=np.uint16)\n",
+ " for i in range(n):\n",
+ " t = utime.ticks_us()\n",
+ " result = f(*args, **kwargs)\n",
+ " run_times[i] = utime.ticks_diff(utime.ticks_us(), t)\n",
+ " print('{}() execution times based on {} cycles'.format(func_name, n, (delta2-delta1)/n))\n",
+ " print('\\tbest: %d us'%np.min(run_times))\n",
+ " print('\\tworst: %d us'%np.max(run_times))\n",
+ " print('\\taverage: %d us'%np.mean(run_times))\n",
+ " print('\\tdeviation: +/-%.3f us'%np.std(run_times)) \n",
+ " return result\n",
+ " return new_func\n",
+ " return wrapper\n",
+ "\n",
+ "def timeit(f, *args, **kwargs):\n",
+ " func_name = str(f).split(' ')[1]\n",
+ " def new_func(*args, **kwargs):\n",
+ " t = utime.ticks_us()\n",
+ " result = f(*args, **kwargs)\n",
+ " print('execution time: ', utime.ticks_diff(utime.ticks_us(), t), ' us')\n",
+ " return result\n",
+ " return new_func"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "__END_OF_DEFS__"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# scipy.optimize\n",
+ "\n",
+ "Functions in the `optimize` module can be called by prepending them by `scipy.optimize.`. The module defines the following three functions:\n",
+ "\n",
+ "1. [scipy.optimize.bisect](#bisect)\n",
+ "1. [scipy.optimize.fmin](#fmin)\n",
+ "1. [scipy.optimize.newton](#newton)\n",
+ "\n",
+ "Note that routines that work with user-defined functions still have to call the underlying `python` code, and therefore, gains in speed are not as significant as with other vectorised operations. As a rule of thumb, a factor of two can be expected, when compared to an optimised `python` implementation."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## bisect \n",
+ "\n",
+ "`scipy`: https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.bisect.html\n",
+ "\n",
+ "`bisect` finds the root of a function of one variable using a simple bisection routine. It takes three positional arguments, the function itself, and two starting points. The function must have opposite signs\n",
+ "at the starting points. Returned is the position of the root.\n",
+ "\n",
+ "Two keyword arguments, `xtol`, and `maxiter` can be supplied to control the accuracy, and the number of bisections, respectively."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2021-01-08T12:58:28.444300Z",
+ "start_time": "2021-01-08T12:58:28.421989Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0.9999997615814209\n",
+ "only 8 bisections: 0.984375\n",
+ "with 0.1 accuracy: 0.9375\n",
+ "\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%micropython -unix 1\n",
+ "\n",
+ "from ulab import scipy as spy\n",
+ " \n",
+ "def f(x):\n",
+ " return x*x - 1\n",
+ "\n",
+ "print(spy.optimize.bisect(f, 0, 4))\n",
+ "\n",
+ "print('only 8 bisections: ', spy.optimize.bisect(f, 0, 4, maxiter=8))\n",
+ "\n",
+ "print('with 0.1 accuracy: ', spy.optimize.bisect(f, 0, 4, xtol=0.1))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Performance\n",
+ "\n",
+ "Since the `bisect` routine calls user-defined `python` functions, the speed gain is only about a factor of two, if compared to a purely `python` implementation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2020-05-19T19:08:24.750562Z",
+ "start_time": "2020-05-19T19:08:24.682959Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "bisect running in python\r\n",
+ "execution time: 1270 us\r\n",
+ "bisect running in C\r\n",
+ "execution time: 642 us\r\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%micropython -pyboard 1\n",
+ "\n",
+ "from ulab import scipy as spy\n",
+ "\n",
+ "def f(x):\n",
+ " return (x-1)*(x-1) - 2.0\n",
+ "\n",
+ "def bisect(f, a, b, xtol=2.4e-7, maxiter=100):\n",
+ " if f(a) * f(b) > 0:\n",
+ " raise ValueError\n",
+ "\n",
+ " rtb = a if f(a) < 0.0 else b\n",
+ " dx = b - a if f(a) < 0.0 else a - b\n",
+ " for i in range(maxiter):\n",
+ " dx *= 0.5\n",
+ " x_mid = rtb + dx\n",
+ " mid_value = f(x_mid)\n",
+ " if mid_value < 0:\n",
+ " rtb = x_mid\n",
+ " if abs(dx) < xtol:\n",
+ " break\n",
+ "\n",
+ " return rtb\n",
+ "\n",
+ "@timeit\n",
+ "def bisect_scipy(f, a, b):\n",
+ " return spy.optimize.bisect(f, a, b)\n",
+ "\n",
+ "@timeit\n",
+ "def bisect_timed(f, a, b):\n",
+ " return bisect(f, a, b)\n",
+ "\n",
+ "print('bisect running in python')\n",
+ "bisect_timed(f, 3, 2)\n",
+ "\n",
+ "print('bisect running in C')\n",
+ "bisect_scipy(f, 3, 2)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## fmin\n",
+ "\n",
+ "`scipy`: https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin.html\n",
+ "\n",
+ "The `fmin` function finds the position of the minimum of a user-defined function by using the downhill simplex method. Requires two positional arguments, the function, and the initial value. Three keyword arguments, `xatol`, `fatol`, and `maxiter` stipulate conditions for stopping."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2021-01-08T13:00:26.729947Z",
+ "start_time": "2021-01-08T13:00:26.702748Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0.9996093749999952\n",
+ "1.199999999999996\n",
+ "\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%micropython -unix 1\n",
+ "\n",
+ "from ulab import scipy as spy\n",
+ "\n",
+ "def f(x):\n",
+ " return (x-1)**2 - 1\n",
+ "\n",
+ "print(spy.optimize.fmin(f, 3.0))\n",
+ "print(spy.optimize.fmin(f, 3.0, xatol=0.1))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## newton\n",
+ "\n",
+ "`scipy`:https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.newton.html\n",
+ "\n",
+ "`newton` finds a zero of a real, user-defined function using the Newton-Raphson (or secant or Halley’s) method. The routine requires two positional arguments, the function, and the initial value. Three keyword\n",
+ "arguments can be supplied to control the iteration. These are the absolute and relative tolerances `tol`, and `rtol`, respectively, and the number of iterations before stopping, `maxiter`. The function retuns a single scalar, the position of the root."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2021-01-08T12:56:35.139958Z",
+ "start_time": "2021-01-08T12:56:35.119712Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "1.260135727246117\n",
+ "\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "%%micropython -unix 1\n",
+ "\n",
+ "from ulab import scipy as spy\n",
+ " \n",
+ "def f(x):\n",
+ " return x*x*x - 2.0\n",
+ "\n",
+ "print(spy.optimize.newton(f, 3., tol=0.001, rtol=0.01))"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "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.8.5"
+ },
+ "toc": {
+ "base_numbering": 1,
+ "nav_menu": {},
+ "number_sections": true,
+ "sideBar": true,
+ "skip_h1_title": false,
+ "title_cell": "Table of Contents",
+ "title_sidebar": "Contents",
+ "toc_cell": false,
+ "toc_position": {
+ "height": "calc(100% - 180px)",
+ "left": "10px",
+ "top": "150px",
+ "width": "382.797px"
+ },
+ "toc_section_display": true,
+ "toc_window_display": true
+ },
+ "varInspector": {
+ "cols": {
+ "lenName": 16,
+ "lenType": 16,
+ "lenVar": 40
+ },
+ "kernels_config": {
+ "python": {
+ "delete_cmd_postfix": "",
+ "delete_cmd_prefix": "del ",
+ "library": "var_list.py",
+ "varRefreshCmd": "print(var_dic_list())"
+ },
+ "r": {
+ "delete_cmd_postfix": ") ",
+ "delete_cmd_prefix": "rm(",
+ "library": "var_list.r",
+ "varRefreshCmd": "cat(var_dic_list()) "
+ }
+ },
+ "types_to_exclude": [
+ "module",
+ "function",
+ "builtin_function_or_method",
+ "instance",
+ "_Feature"
+ ],
+ "window_display": false
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}