├── .gitignore ├── jkernel ├── __init__.py ├── jkernel.py └── jinter.py ├── kernel_definition ├── logo-32x32.png ├── logo-64x64.png └── kernel.json ├── Jupyter_Notebook_J_Example_Data ├── moon.bmp ├── galaxy.bmp ├── assembly1.bmp ├── assembly2.bmp └── Weather_Stations.txt ├── README.md ├── setup.py ├── syntax └── J.js └── Jupyter_Notebook_J_Labs ├── math ├── Spirals.ipynb ├── Frame's_Method.ipynb ├── Binomial_Coefficients.ipynb ├── Rotations.ipynb ├── Iteration_and_the_Power_Operator.ipynb ├── Best_Fit.ipynb └── Catalan_Numbers.ipynb ├── core ├── Monad_Dyad.ipynb └── A_Taste_of_J_(2).ipynb ├── graphics └── Plot_Package.ipynb └── general ├── The_Tower_of_Hanoi.ipynb └── Huffman_Coding.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints/ 2 | build/ 3 | dist/ 4 | *.swp 5 | *.egg-info 6 | -------------------------------------------------------------------------------- /jkernel/__init__.py: -------------------------------------------------------------------------------- 1 | # Dummy __init__.py for Python2.7 package initialization 2 | -------------------------------------------------------------------------------- /kernel_definition/logo-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastai/jkernel/master/kernel_definition/logo-32x32.png -------------------------------------------------------------------------------- /kernel_definition/logo-64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastai/jkernel/master/kernel_definition/logo-64x64.png -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Example_Data/moon.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastai/jkernel/master/Jupyter_Notebook_J_Example_Data/moon.bmp -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Example_Data/galaxy.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastai/jkernel/master/Jupyter_Notebook_J_Example_Data/galaxy.bmp -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Example_Data/assembly1.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastai/jkernel/master/Jupyter_Notebook_J_Example_Data/assembly1.bmp -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Example_Data/assembly2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fastai/jkernel/master/Jupyter_Notebook_J_Example_Data/assembly2.bmp -------------------------------------------------------------------------------- /kernel_definition/kernel.json: -------------------------------------------------------------------------------- 1 | { 2 | "argv" : ["python","-m","jkernel.jkernel", "-f", "{connection_file}"], 3 | "display_name" : "J", 4 | "language" : "J" 5 | } 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jupyter Notebook/Lab jkernel 2 | 3 | The jkernel is a J programming language integration for the [Jupyter Notebook](http://jupyter.org) 4 | 5 | ## What's new (August 2020) 6 | 7 | * Updated for J901 8 | * Windows 10 64bit compatibility 9 | 10 | ## Prerequisites 11 | 12 | * [Jupyter Notebook](http://jupyter.org) Version 4.x (or greater) 13 | 14 | * Recommended: [Anaconda from Anaconda Inc.](https://www.anaconda.com/distribution) 15 | 16 | * Or: [Miniconda](https://conda.io/miniconda.html) (Jupyter must be installed manually) 17 | 18 | * A working [J 901](http://www.jsoftware.com) (or greater) 19 | 20 | ## Installation / Uninstallation / Installation Check 21 | 22 | **Please Note:** 23 | It is mandatory to use the **python** command from Anaconda or Miniconda! 24 | 25 | NOT the python command that probably comes pre-installed on your operating system. 26 | 27 | On *nix OS, the command **which python** shows you the path of the python interpreter. 28 | 29 | * python setup.py **install** 30 | 31 | * python setup.py **uninstall** 32 | 33 | * python setup.py **check** 34 | 35 | ## Examples 36 | 37 | The sub-directories **Jupyter_Notebook_J_Labs** and **Jupyter_Notebook_J_Examples** contain some example notebooks 38 | 39 | The sub-directory **Jupyter_Notebook_J_Example_Data** should be copied to the J user directory to run the example notebooks in **Jupyter_Notebook_J_Examples** 40 | 41 | ## Run 42 | 43 | Run: **jupyter notebook** (from the command line) 44 | 45 | Run: **jupyter lab** (from the command line) 46 | 47 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import glob,setuptools,os 2 | from pathlib import Path 3 | from setuptools import setup 4 | 5 | DISTNAME = 'j_kernel' 6 | DESCRIPTION = 'A Jupyter kernel for J.' 7 | LONG_DESCRIPTION = open('README.md').read() 8 | MAINTAINER = 'Jeremy Howard' 9 | MAINTAINER_EMAIL = 'info@howard.fm' 10 | URL = 'http://github.com/fastai/j_kernel' 11 | LICENSE = 'GPL' 12 | REQUIRES = ["jupyter_client (>=4.3.0)", "ipykernel"] 13 | INSTALL_REQUIRES = REQUIRES 14 | 15 | CLASSIFIERS = """\ 16 | Intended Audience :: Science/Research 17 | License :: OSI Approved :: GPL License 18 | Operating System :: OS Independent 19 | Programming Language :: Python 20 | Programming Language :: Python :: 3.6 21 | Programming Language :: Python :: 3.7 22 | Programming Language :: Python :: 3.8 23 | Topic :: Scientific/Engineering 24 | Topic :: Software Development 25 | Topic :: System :: Shells 26 | """ 27 | 28 | import notebook 29 | nb_dir = Path(notebook.__file__).parent.relative_to(os.environ['CONDA_PREFIX']) 30 | DATA_FILES = [ 31 | (f'{nb_dir}/static/components/codemirror/mode/j', ['syntax/J.js']), 32 | ('share/jupyter/kernels/j', glob.glob('kernel_definition/*.*')), 33 | ] 34 | 35 | setup( 36 | name=DISTNAME, 37 | version='0.0.1', 38 | maintainer=MAINTAINER, maintainer_email=MAINTAINER_EMAIL, 39 | packages = setuptools.find_packages(), 40 | data_files=DATA_FILES, 41 | url=URL, download_url=URL, 42 | license=LICENSE, 43 | platforms=["Any"], 44 | description=DESCRIPTION, long_description=LONG_DESCRIPTION, long_description_content_type='text/x-rst', 45 | classifiers=list(filter(None, CLASSIFIERS.split('\n'))), 46 | install_requires=INSTALL_REQUIRES 47 | ) 48 | 49 | -------------------------------------------------------------------------------- /syntax/J.js: -------------------------------------------------------------------------------- 1 | // J syntax definition for CodeMirror 2 | 3 | (function(mod) 4 | { 5 | if(typeof exports == "object" && typeof module == "object") // CommonJS 6 | { 7 | mod(require("../../lib/codemirror")); 8 | } 9 | else if(typeof define == "function" && define.amd) // AMD 10 | { 11 | define(["../../lib/codemirror"],mod); 12 | } 13 | else // Plain browser env 14 | { 15 | mod(CodeMirror); 16 | } 17 | }) 18 | 19 | (function(CodeMirror) 20 | { 21 | "use strict"; 22 | 23 | CodeMirror.defineMode('J',function(config) 24 | { 25 | 26 | var c; 27 | var words = {}; 28 | 29 | function define(style,string) 30 | { 31 | var split = string.split(' '); 32 | for(var i=0;i'): 48 | try: 49 | prefix = '', '') \ 74 | .replace('canvas1', f'canvas{canvasnum}') 75 | htmnam.unlink(missing_ok=False) 76 | 77 | canvasnum += 1 78 | content['data']['text/html'] = htmdat 79 | self.send_response(self.iopub_socket, 'display_data', content) 80 | 81 | except Exception as e: 82 | content = { 'name': 'stdout', 'text': f'JKernel: Internal Error.\n{e}\n' } 83 | self.send_response(self.iopub_socket,'stream',content) 84 | 85 | # Is it an html output 86 | elif output.startswith(''): 87 | content['data']['text/html'] = output 88 | self.send_response(self.iopub_socket, 'display_data', content) 89 | else: 90 | # Normal text output 91 | content = { 'name': 'stdout', 'text': output } 92 | self.send_response(self.iopub_socket,'stream',content) 93 | 94 | def do_execute(self, code, silent, *args, **kwargs): 95 | global canvasnum 96 | 97 | # Pass input to J (new version) 98 | # Multi-line statements (like verb definitions) are now possible 99 | # Only the output of the last line (statement) is printed 100 | lines = [line for line in code.splitlines() if line.strip()] 101 | lastline = '' 102 | # Check last line (end of multiline statement) 103 | if lines: 104 | lastline = lines.pop().strip() 105 | if not lastline == ')': code = '\n'.join(lines) 106 | 107 | code = code.replace("'","''") 108 | self.J.Exec(f"input_jinter_ =: '{code}'") 109 | self.J.Exec('0!:110 input_jinter_') 110 | 111 | # Process last line (receive output) 112 | if lastline: 113 | self.J.Exec(lastline) 114 | output = self.J.Recv() 115 | if output: self._retr(output, silent) 116 | 117 | return { 118 | 'status': 'ok', 119 | 'execution_count': self.execution_count, 120 | 'payload': [], 121 | 'user_expressions': {}, 122 | } 123 | 124 | def do_shutdown(self,restart): pass 125 | def do_inspect(self,code,cursor_pos,detail_level=0): pass 126 | 127 | if __name__ == '__main__': 128 | from ipykernel.kernelapp import IPKernelApp 129 | IPKernelApp.launch_instance(kernel_class=JKernel) 130 | 131 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/math/Spirals.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# J Labs\n", 8 | "\n", 9 | "### Spirals" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "### (1 of 5) LINK AND PLOT\n", 17 | "\n", 18 | "The function ; links its vector arguments to form a list of boxed vectors. Thus:" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": null, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "load 'trig'" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "cos 1 NB. Cosine of radian arguments" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "cos 1 2 3.14" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "cosd 0 30 45 60 NB. Cosine of degree arguments" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "(sind 0 30 45 60) ; (cosd 0 30 45 60)" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "circle=: cosd ; sind" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": null, 78 | "metadata": {}, 79 | "outputs": [], 80 | "source": [ 81 | "circle 0 30 45 60" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "### (2 of 5) LINK AND PLOT (ctd)\n", 89 | "\n", 90 | "The function circle yields coordinates of points on a unit circle, as may be seen in the following plot for angles from 0 to 12 degrees:\n", 91 | "\n", 92 | "After viewing the plot, press Alt F4 to return focus from the plot window:" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": null, 98 | "metadata": {}, 99 | "outputs": [], 100 | "source": [ 101 | "load 'plot'" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "plot circle 10 * 0 1 2 3 4 5 6 7 8 9 10 11 12" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "### (3 of 5) INTEGER LISTS\n", 118 | "\n", 119 | "The function i. produces a vector of the first non-negative integers, as in the next example shown.\n", 120 | "\n", 121 | "Note that the plot of the circle is correct according to the scales of the plot, although it may appear flattened because of the aspect ratio of the screen." 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": null, 127 | "metadata": {}, 128 | "outputs": [], 129 | "source": [ 130 | "i. 13 NB. First 13 non-negative integers" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": null, 136 | "metadata": {}, 137 | "outputs": [], 138 | "source": [ 139 | "plot circle i. 270" 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "### (4 of 5) THREE DIMENSIONS\n", 147 | "\n", 148 | "The function:\n", 149 | "\n", 150 | " ```spiral=: cosd ; sind ; %:```
\n", 151 | "\n", 152 | "produces tables of vectors in three dimensions, the z coordinate being the square root (%:) of the argument. For example:" 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": null, 158 | "metadata": {}, 159 | "outputs": [], 160 | "source": [ 161 | "spiral=: cosd ; sind ; %:" 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": null, 167 | "metadata": {}, 168 | "outputs": [], 169 | "source": [ 170 | "spiral 0 10 20 30" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": null, 176 | "metadata": {}, 177 | "outputs": [], 178 | "source": [ 179 | "plot spiral i. 1000" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "### (5 of 5) NON-CIRCULAR SPIRALS\n", 187 | "\n", 188 | "Functions other than sine and cosine may be used. In particular, the exponential (^) applied to negative arguments can be used to produce a decaying spiral. For example:" 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "execution_count": null, 194 | "metadata": {}, 195 | "outputs": [], 196 | "source": [ 197 | "decay=: ^@(%&_500)" 198 | ] 199 | }, 200 | { 201 | "cell_type": "code", 202 | "execution_count": null, 203 | "metadata": {}, 204 | "outputs": [], 205 | "source": [ 206 | "desin=: decay * sind" 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": null, 212 | "metadata": {}, 213 | "outputs": [], 214 | "source": [ 215 | "decos=: decay * cosd" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": null, 221 | "metadata": {}, 222 | "outputs": [], 223 | "source": [ 224 | "despi=: decos ; desin ; %:" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": null, 230 | "metadata": {}, 231 | "outputs": [], 232 | "source": [ 233 | "plot despi i. 1000" 234 | ] 235 | }, 236 | { 237 | "cell_type": "markdown", 238 | "metadata": {}, 239 | "source": [ 240 | "### End of Lab" 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": null, 246 | "metadata": {}, 247 | "outputs": [], 248 | "source": [] 249 | } 250 | ], 251 | "metadata": { 252 | "kernelspec": { 253 | "display_name": "J", 254 | "language": "J", 255 | "name": "jkernel" 256 | }, 257 | "language_info": { 258 | "file_extension": "ijs", 259 | "mimetype": "text/x-J", 260 | "name": "J" 261 | } 262 | }, 263 | "nbformat": 4, 264 | "nbformat_minor": 2 265 | } 266 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/core/Monad_Dyad.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# J Labs\n", 11 | "\n", 12 | "### Monad/Dyad" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": { 18 | "deletable": true, 19 | "editable": true 20 | }, 21 | "source": [ 22 | "### (1 of 4) INTRODUCTION\n", 23 | "\n", 24 | "If u and v are functions, then f=: u : v defines f to be a function whose monadic case is u and whose dyadic case is v\n", 25 | "\n", 26 | "For example, if v=: +, then 3 v 4 is 7 and v 4 is 4, i.e. since the monadic case of + is the conjugate, which produces an effect only on a complex argument such as 6j10.\n", 27 | "\n", 28 | "We may, however, define a function add that performs addition on two arguments, and increments a single argument. Thus:" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": null, 34 | "metadata": { 35 | "collapsed": false, 36 | "deletable": true, 37 | "editable": true 38 | }, 39 | "outputs": [], 40 | "source": [ 41 | "add=: >: : +" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": { 48 | "collapsed": false, 49 | "deletable": true, 50 | "editable": true 51 | }, 52 | "outputs": [], 53 | "source": [ 54 | "3 add 4" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "metadata": { 61 | "collapsed": false, 62 | "deletable": true, 63 | "editable": true 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "add 4" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": { 74 | "collapsed": false, 75 | "deletable": true, 76 | "editable": true 77 | }, 78 | "outputs": [], 79 | "source": [ 80 | "add 4 5 6 7 8" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "metadata": { 87 | "collapsed": false, 88 | "deletable": true, 89 | "editable": true 90 | }, 91 | "outputs": [], 92 | "source": [ 93 | "v=: +" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": null, 99 | "metadata": { 100 | "collapsed": false, 101 | "deletable": true, 102 | "editable": true 103 | }, 104 | "outputs": [], 105 | "source": [ 106 | "3 v 4" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "metadata": { 113 | "collapsed": false, 114 | "deletable": true, 115 | "editable": true 116 | }, 117 | "outputs": [], 118 | "source": [ 119 | "v 4" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": { 125 | "deletable": true, 126 | "editable": true 127 | }, 128 | "source": [ 129 | "### (2 of 4) INTRODUCTION (ctd)\n", 130 | "\n", 131 | "Mnemonic names may be assigned to functions for the absolute value (or magnitude) and remainder (or residue) as shown below. However, the fact that these functions may each be used either monadically or dyadically can lead to some confusion. Thus:" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": null, 137 | "metadata": { 138 | "collapsed": false, 139 | "deletable": true, 140 | "editable": true 141 | }, 142 | "outputs": [], 143 | "source": [ 144 | "mag=: |" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": null, 150 | "metadata": { 151 | "collapsed": false, 152 | "deletable": true, 153 | "editable": true 154 | }, 155 | "outputs": [], 156 | "source": [ 157 | "res=: |" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": null, 163 | "metadata": { 164 | "collapsed": false, 165 | "deletable": true, 166 | "editable": true 167 | }, 168 | "outputs": [], 169 | "source": [ 170 | "y=: 3 _4 5 _6" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": null, 176 | "metadata": { 177 | "collapsed": false, 178 | "deletable": true, 179 | "editable": true 180 | }, 181 | "outputs": [], 182 | "source": [ 183 | "mag y" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": null, 189 | "metadata": { 190 | "collapsed": false, 191 | "deletable": true, 192 | "editable": true 193 | }, 194 | "outputs": [], 195 | "source": [ 196 | "4 res y" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": null, 202 | "metadata": { 203 | "collapsed": false, 204 | "deletable": true, 205 | "editable": true 206 | }, 207 | "outputs": [], 208 | "source": [ 209 | "4 mag y" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": null, 215 | "metadata": { 216 | "collapsed": false, 217 | "deletable": true, 218 | "editable": true 219 | }, 220 | "outputs": [], 221 | "source": [ 222 | "res y" 223 | ] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "metadata": { 228 | "deletable": true, 229 | "editable": true 230 | }, 231 | "source": [ 232 | "### (3 of 4) THE CAP FUNCTION\n", 233 | "\n", 234 | "The cap function (denoted by [:) has empty domains, and therefore yields errors for any arguments. It may be used to define functions such as mag and res which yield errors unless used with the intended valence.\n", 235 | "\n", 236 | "Illustrate this by experimenting with the following functions:" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": { 243 | "collapsed": false, 244 | "deletable": true, 245 | "editable": true 246 | }, 247 | "outputs": [], 248 | "source": [ 249 | "mag=: | : [:" 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "execution_count": null, 255 | "metadata": { 256 | "collapsed": false, 257 | "deletable": true, 258 | "editable": true 259 | }, 260 | "outputs": [], 261 | "source": [ 262 | "res=: [: : |" 263 | ] 264 | }, 265 | { 266 | "cell_type": "markdown", 267 | "metadata": { 268 | "deletable": true, 269 | "editable": true 270 | }, 271 | "source": [ 272 | "### (4 of 4) THE CAP FUNCTION (ctd)\n", 273 | "\n", 274 | "The cap function may also be used in a train to cause a verb that follows it to be applied monadically.\n", 275 | "\n", 276 | "For example, a vector may be scaled to unit length by dividing it by its length, the length being the square root (%:) of the sum (+/) of the squares (*:) of its elements. Thus:" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": null, 282 | "metadata": { 283 | "collapsed": false, 284 | "deletable": true, 285 | "editable": true 286 | }, 287 | "outputs": [], 288 | "source": [ 289 | "scale=: ] % [: %: [: +/ *:" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": null, 295 | "metadata": { 296 | "collapsed": false, 297 | "deletable": true, 298 | "editable": true 299 | }, 300 | "outputs": [], 301 | "source": [ 302 | "scale y" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": null, 308 | "metadata": { 309 | "collapsed": false, 310 | "deletable": true, 311 | "editable": true 312 | }, 313 | "outputs": [], 314 | "source": [ 315 | "%: +/ *: scale y" 316 | ] 317 | }, 318 | { 319 | "cell_type": "markdown", 320 | "metadata": { 321 | "deletable": true, 322 | "editable": true 323 | }, 324 | "source": [ 325 | "### End of Lab" 326 | ] 327 | }, 328 | { 329 | "cell_type": "code", 330 | "execution_count": null, 331 | "metadata": { 332 | "collapsed": false, 333 | "deletable": true, 334 | "editable": true 335 | }, 336 | "outputs": [], 337 | "source": [] 338 | } 339 | ], 340 | "metadata": { 341 | "kernelspec": { 342 | "display_name": "J", 343 | "language": "J", 344 | "name": "jkernel" 345 | }, 346 | "language_info": { 347 | "file_extension": "ijs", 348 | "mimetype": "text/x-J", 349 | "name": "J" 350 | } 351 | }, 352 | "nbformat": 4, 353 | "nbformat_minor": 2 354 | } 355 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/math/Frame's_Method.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# J Labs\n", 11 | "\n", 12 | "### Frame's Method" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": { 18 | "deletable": true, 19 | "editable": true 20 | }, 21 | "source": [ 22 | "### (1 of 8) Introduction\n", 23 | "J. S. Frame developed an iterative method of computing the coefficients of the characteristic polynomial of a matrix (including the determinant) and also the inverse of the matrix. This lab illustrates the method of Frame using two different programming styles." 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": { 29 | "deletable": true, 30 | "editable": true 31 | }, 32 | "source": [ 33 | "### (2 of 8) Frame's Method\n", 34 | "This lab shows how to compute the trace of a matrix using J. Then the trace is used in an iterative method, due to J. S. Frame, to compute the other coefficients of the charateristic polynomial of the matrix (including the determinant) and to also compute the inverse of the matrix.\n", 35 | "\n", 36 | "First, enter a sample 3 by 3 matrix M." 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": { 43 | "collapsed": false, 44 | "deletable": true, 45 | "editable": true 46 | }, 47 | "outputs": [], 48 | "source": [ 49 | "M =: 3 3 $ 2 0 _7 3 1 4 0 5 8" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": null, 55 | "metadata": { 56 | "collapsed": false, 57 | "deletable": true, 58 | "editable": true 59 | }, 60 | "outputs": [], 61 | "source": [ 62 | "M" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": { 68 | "deletable": true, 69 | "editable": true 70 | }, 71 | "source": [ 72 | "### (3 of 8) Frame's Method (ctd)\n", 73 | "Now we experiment with monadic and dyadic transpose.\n", 74 | "\n", 75 | "Monadic transpose reverses the axes of an array.\n", 76 | "\n", 77 | "In dyadic tranpose, the axes listed in the left argument are moved to the end of the list of axes. For an array of rank 2 (a matrix) the only possibilities are to leave the axes alone (and not change the matrix) or switch the axes, same as the monadic transpose.\n", 78 | "\n", 79 | "But if some axes in the left argument are boxed then those axes are run together, e.g. we get indicies i,i instead of i,j ." 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": null, 85 | "metadata": { 86 | "collapsed": false, 87 | "deletable": true, 88 | "editable": true 89 | }, 90 | "outputs": [], 91 | "source": [ 92 | " M; (|:M); (0|:M); (1|:M); ((<0 1)|:M)" 93 | ] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": { 98 | "deletable": true, 99 | "editable": true 100 | }, 101 | "source": [ 102 | "### (4 of 8) Frame's Method (ctd)\n", 103 | "Thus the principal diagonal of the matrix can be obtained with the \"pd\" function shown below.\n", 104 | "\n", 105 | "Then the trace is just the sum of the principal diagonal." 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": null, 111 | "metadata": { 112 | "collapsed": false, 113 | "deletable": true, 114 | "editable": true 115 | }, 116 | "outputs": [], 117 | "source": [ 118 | "pd =: (<0 1)&|:" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": null, 124 | "metadata": { 125 | "collapsed": false, 126 | "deletable": true, 127 | "editable": true 128 | }, 129 | "outputs": [], 130 | "source": [ 131 | "sum =: +/" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": null, 137 | "metadata": { 138 | "collapsed": false, 139 | "deletable": true, 140 | "editable": true 141 | }, 142 | "outputs": [], 143 | "source": [ 144 | "of =: @" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": null, 150 | "metadata": { 151 | "collapsed": false, 152 | "deletable": true, 153 | "editable": true 154 | }, 155 | "outputs": [], 156 | "source": [ 157 | "tr =: sum of pd" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": null, 163 | "metadata": { 164 | "collapsed": false, 165 | "deletable": true, 166 | "editable": true 167 | }, 168 | "outputs": [], 169 | "source": [ 170 | "tr M" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": { 176 | "deletable": true, 177 | "editable": true 178 | }, 179 | "source": [ 180 | "### (5 of 8) Frame's Method (ctd)\n", 181 | "The method of Frame is the following iteration.\n", 182 | "\n", 183 | "Let M be a given square matrix of size m by m\n", 184 | "\n", 185 | "Let F0 = I (the n by n identity matrix) and let C0 = 0.\n", 186 | "\n", 187 | "For k = 1 to m let\n", 188 | "\n", 189 | " ```Fk = M x (Fk-1 + Ck-1 x I) and Ck = -(tr Fk)/k```
\n", 190 | "\n", 191 | "Then the coefficients of the characteristic polynomial of M are Cm, ..., C1, 1. In particular, tr M = -C1 and det M = Cm(-1)^m Also, the adjoint of M is Fm-1 + Cm-1 x I and the inverse of M is (Fm-1 + Cm-1 x I)/Cm(-1)^m" 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": null, 197 | "metadata": { 198 | "collapsed": false, 199 | "deletable": true, 200 | "editable": true 201 | }, 202 | "outputs": [], 203 | "source": [ 204 | "frame =: verb define\n", 205 | "F =. I =. =i.m =. #M =. y\n", 206 | "C =. 0\n", 207 | "for_k. 1+i.m do.\n", 208 | "F =. M +/ . * F1 =. F + ({.C)*I\n", 209 | "C =. (-(tr F)%k),C\n", 210 | "end.\n", 211 | "((}:C),1);F1\n", 212 | ")" 213 | ] 214 | }, 215 | { 216 | "cell_type": "markdown", 217 | "metadata": { 218 | "deletable": true, 219 | "editable": true 220 | }, 221 | "source": [ 222 | "### (6 of 8) Frame's Method (ctd)\n", 223 | "Below is the method of Frame applied to the matrix M. The output is a boxed vector of the coefficients of the characteristic polynomial of M, i.e. of which the first entry is (-1)^m times the determinant of M, followed by a boxed matrix which is the adjoint of the matrix M.\n", 224 | "\n", 225 | "Note that we could easily modify the last line of the program to output the inverse instead of the adjoint: just replace \"F1\" by \"F1%({.C)*(-1)^m\"." 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": null, 231 | "metadata": { 232 | "collapsed": false, 233 | "deletable": true, 234 | "editable": true 235 | }, 236 | "outputs": [], 237 | "source": [ 238 | "frame M" 239 | ] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": { 244 | "deletable": true, 245 | "editable": true 246 | }, 247 | "source": [ 248 | "### (7 of 8) Frame's Method (ctd)\n", 249 | "It is useful to capture the ouput in variables as shown below. Then the coefficients and adjoint matrix can be used for subsequent calculations.\n", 250 | "\n", 251 | "For example, you can see below that M times M adjoint is the determinant times the identity matrix." 252 | ] 253 | }, 254 | { 255 | "cell_type": "code", 256 | "execution_count": null, 257 | "metadata": { 258 | "collapsed": false, 259 | "deletable": true, 260 | "editable": true 261 | }, 262 | "outputs": [], 263 | "source": [ 264 | "'C Mad' =: frame M" 265 | ] 266 | }, 267 | { 268 | "cell_type": "code", 269 | "execution_count": null, 270 | "metadata": { 271 | "collapsed": false, 272 | "deletable": true, 273 | "editable": true 274 | }, 275 | "outputs": [], 276 | "source": [ 277 | "C" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": null, 283 | "metadata": { 284 | "collapsed": false, 285 | "deletable": true, 286 | "editable": true 287 | }, 288 | "outputs": [], 289 | "source": [ 290 | "Mad" 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": null, 296 | "metadata": { 297 | "collapsed": false, 298 | "deletable": true, 299 | "editable": true 300 | }, 301 | "outputs": [], 302 | "source": [ 303 | "M +/ . * Mad" 304 | ] 305 | }, 306 | { 307 | "cell_type": "markdown", 308 | "metadata": { 309 | "deletable": true, 310 | "editable": true 311 | }, 312 | "source": [ 313 | "### (8 of 8) Frame's Method (ctd)\n", 314 | "Next, we can use the monadic polynomial function \"p.\" to find the roots of the characteristic polynomial, that is, the eigenvalues of the matrix M. Then we can verify that the eigenvalues are zeros of the function\n", 315 | "\n", 316 | " ```det(M - xI)```
" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": null, 322 | "metadata": { 323 | "collapsed": false, 324 | "deletable": true, 325 | "editable": true 326 | }, 327 | "outputs": [], 328 | "source": [ 329 | "p. C" 330 | ] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": null, 335 | "metadata": { 336 | "collapsed": false, 337 | "deletable": true, 338 | "editable": true 339 | }, 340 | "outputs": [], 341 | "source": [ 342 | "'E1 E2 E3' =: >{:p. C" 343 | ] 344 | }, 345 | { 346 | "cell_type": "code", 347 | "execution_count": null, 348 | "metadata": { 349 | "collapsed": false, 350 | "deletable": true, 351 | "editable": true 352 | }, 353 | "outputs": [], 354 | "source": [ 355 | "det =: -/ . *" 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "execution_count": null, 361 | "metadata": { 362 | "collapsed": false, 363 | "deletable": true, 364 | "editable": true 365 | }, 366 | "outputs": [], 367 | "source": [ 368 | "I =: =i.#M" 369 | ] 370 | }, 371 | { 372 | "cell_type": "code", 373 | "execution_count": null, 374 | "metadata": { 375 | "collapsed": false, 376 | "deletable": true, 377 | "editable": true 378 | }, 379 | "outputs": [], 380 | "source": [ 381 | "(det M - E1*I);(det M - E2*I);(det M - E3*I)" 382 | ] 383 | }, 384 | { 385 | "cell_type": "markdown", 386 | "metadata": { 387 | "deletable": true, 388 | "editable": true 389 | }, 390 | "source": [ 391 | "### End of Lab" 392 | ] 393 | }, 394 | { 395 | "cell_type": "code", 396 | "execution_count": null, 397 | "metadata": { 398 | "collapsed": false, 399 | "deletable": true, 400 | "editable": true 401 | }, 402 | "outputs": [], 403 | "source": [] 404 | } 405 | ], 406 | "metadata": { 407 | "kernelspec": { 408 | "display_name": "J", 409 | "language": "J", 410 | "name": "jkernel" 411 | }, 412 | "language_info": { 413 | "file_extension": "ijs", 414 | "mimetype": "text/x-J", 415 | "name": "J" 416 | } 417 | }, 418 | "nbformat": 4, 419 | "nbformat_minor": 2 420 | } 421 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/math/Binomial_Coefficients.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# J Labs\n", 11 | "\n", 12 | "### Binomial Coefficients" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": { 18 | "deletable": true, 19 | "editable": true 20 | }, 21 | "source": [ 22 | "### (1 of 6) TABLE OR MATRIX\n", 23 | "\n", 24 | "The expression k ! n produces the kth binomial coefficient of order n, and the function bc=: i. !/ i. may be used to produce a table or matrix of binomial coefficients. For example:" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": { 31 | "collapsed": false, 32 | "deletable": true, 33 | "editable": true 34 | }, 35 | "outputs": [], 36 | "source": [ 37 | "0!5" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": null, 43 | "metadata": { 44 | "collapsed": false, 45 | "deletable": true, 46 | "editable": true 47 | }, 48 | "outputs": [], 49 | "source": [ 50 | "1!5" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "metadata": { 57 | "collapsed": false, 58 | "deletable": true, 59 | "editable": true 60 | }, 61 | "outputs": [], 62 | "source": [ 63 | "2!5" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "metadata": { 70 | "collapsed": false, 71 | "deletable": true, 72 | "editable": true 73 | }, 74 | "outputs": [], 75 | "source": [ 76 | "bc=: i. !/ i." 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": { 83 | "collapsed": false, 84 | "deletable": true, 85 | "editable": true 86 | }, 87 | "outputs": [], 88 | "source": [ 89 | "bc 6" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": { 95 | "deletable": true, 96 | "editable": true 97 | }, 98 | "source": [ 99 | "### (2 of 6) TABLE OR MATRIX (ctd)\n", 100 | "\n", 101 | "Such a matrix can be used in a variety of interesting ways. For example, its inverse is the matrix of alternating binomials, and its matrix product with a vector of polynomial coefficients (with powers in ascending order) produces the coresponding \"expanded\" coefficients. For example:" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": { 108 | "collapsed": false, 109 | "deletable": true, 110 | "editable": true 111 | }, 112 | "outputs": [], 113 | "source": [ 114 | "bct=: bc 6" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": null, 120 | "metadata": { 121 | "collapsed": false, 122 | "deletable": true, 123 | "editable": true 124 | }, 125 | "outputs": [], 126 | "source": [ 127 | "bct" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "metadata": { 134 | "collapsed": false, 135 | "deletable": true, 136 | "editable": true 137 | }, 138 | "outputs": [], 139 | "source": [ 140 | "abct=: %. bct" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": null, 146 | "metadata": { 147 | "collapsed": false, 148 | "deletable": true, 149 | "editable": true 150 | }, 151 | "outputs": [], 152 | "source": [ 153 | "abct" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": null, 159 | "metadata": { 160 | "collapsed": false, 161 | "deletable": true, 162 | "editable": true 163 | }, 164 | "outputs": [], 165 | "source": [ 166 | "X=: +/ . * NB. The matrix product function" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": null, 172 | "metadata": { 173 | "collapsed": false, 174 | "deletable": true, 175 | "editable": true 176 | }, 177 | "outputs": [], 178 | "source": [ 179 | "bct X abct" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": null, 185 | "metadata": { 186 | "collapsed": false, 187 | "deletable": true, 188 | "editable": true 189 | }, 190 | "outputs": [], 191 | "source": [ 192 | "c=: 5 1 4 0 2 2" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": null, 198 | "metadata": { 199 | "collapsed": false, 200 | "deletable": true, 201 | "editable": true 202 | }, 203 | "outputs": [], 204 | "source": [ 205 | "d=: bct X c" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": null, 211 | "metadata": { 212 | "collapsed": false, 213 | "deletable": true, 214 | "editable": true 215 | }, 216 | "outputs": [], 217 | "source": [ 218 | "x=: 0 1 2 3 4 5 6 7" 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": null, 224 | "metadata": { 225 | "collapsed": false, 226 | "deletable": true, 227 | "editable": true 228 | }, 229 | "outputs": [], 230 | "source": [ 231 | "c p. x NB. The polynomial with coefficients c" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": null, 237 | "metadata": { 238 | "collapsed": false, 239 | "deletable": true, 240 | "editable": true 241 | }, 242 | "outputs": [], 243 | "source": [ 244 | "d p. x" 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "execution_count": null, 250 | "metadata": { 251 | "collapsed": false, 252 | "deletable": true, 253 | "editable": true 254 | }, 255 | "outputs": [], 256 | "source": [ 257 | "c p. x+1" 258 | ] 259 | }, 260 | { 261 | "cell_type": "markdown", 262 | "metadata": { 263 | "deletable": true, 264 | "editable": true 265 | }, 266 | "source": [ 267 | "### (3 of 6) TABLE OR MATRIX (ctd)\n", 268 | "\n", 269 | "The alternating binomial coefficients can be used to produce the inverse of expansion. For example:" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": { 276 | "collapsed": false, 277 | "deletable": true, 278 | "editable": true 279 | }, 280 | "outputs": [], 281 | "source": [ 282 | "abct X d" 283 | ] 284 | }, 285 | { 286 | "cell_type": "code", 287 | "execution_count": null, 288 | "metadata": { 289 | "collapsed": false, 290 | "deletable": true, 291 | "editable": true 292 | }, 293 | "outputs": [], 294 | "source": [ 295 | "c" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": null, 301 | "metadata": { 302 | "collapsed": false, 303 | "deletable": true, 304 | "editable": true 305 | }, 306 | "outputs": [], 307 | "source": [ 308 | "c=abct X d" 309 | ] 310 | }, 311 | { 312 | "cell_type": "markdown", 313 | "metadata": { 314 | "deletable": true, 315 | "editable": true 316 | }, 317 | "source": [ 318 | "### (4 of 6) MANUAL METHODS OF EXPANSION\n", 319 | "\n", 320 | "If the vector c is written as a column to the right of the matrix bct, the product bct X c is easily computed by hand. Moreover, such computation may be less prone to error than commonly used methods. Try the experiment of expanding the vector c by by this method and by any others you may know.\n", 321 | "\n", 322 | "Finally, it is easy to jot down the table bct of any order, because each row is obtained from the preceding row by adding it to a shift of itself.\n", 323 | "\n", 324 | "It may also be interesting to compute the sums of the columns of bct and abct (+/ bct and +/ abct), particularly since the result of the latter is commonly mis-stated." 325 | ] 326 | }, 327 | { 328 | "cell_type": "markdown", 329 | "metadata": { 330 | "deletable": true, 331 | "editable": true 332 | }, 333 | "source": [ 334 | "### (5 of 6) IDENTITIES\n", 335 | "\n", 336 | "It is clear that the product bct X bct contains sums over products of various binomial coefficients. If, therefore, one could spot and articulate the pattern of the elements of the result, it could be used to state a host of identities, provided that the pattern holds for larger tables.\n", 337 | "\n", 338 | "Try to state the pattern in the following results:" 339 | ] 340 | }, 341 | { 342 | "cell_type": "code", 343 | "execution_count": null, 344 | "metadata": { 345 | "collapsed": false, 346 | "deletable": true, 347 | "editable": true 348 | }, 349 | "outputs": [], 350 | "source": [ 351 | "bct X bct" 352 | ] 353 | }, 354 | { 355 | "cell_type": "code", 356 | "execution_count": null, 357 | "metadata": { 358 | "collapsed": false, 359 | "deletable": true, 360 | "editable": true 361 | }, 362 | "outputs": [], 363 | "source": [ 364 | "bct X bct X bct" 365 | ] 366 | }, 367 | { 368 | "cell_type": "code", 369 | "execution_count": null, 370 | "metadata": { 371 | "collapsed": false, 372 | "deletable": true, 373 | "editable": true 374 | }, 375 | "outputs": [], 376 | "source": [ 377 | "bct X bct X bct" 378 | ] 379 | }, 380 | { 381 | "cell_type": "code", 382 | "execution_count": null, 383 | "metadata": { 384 | "collapsed": false, 385 | "deletable": true, 386 | "editable": true 387 | }, 388 | "outputs": [], 389 | "source": [ 390 | "bct X bct X bct X bct" 391 | ] 392 | }, 393 | { 394 | "cell_type": "markdown", 395 | "metadata": { 396 | "deletable": true, 397 | "editable": true 398 | }, 399 | "source": [ 400 | "### (6 of 6) IDENTITIES (ctd)\n", 401 | "\n", 402 | "Using the fact that M % N denotes the element-by-element division of the matrix M by the matrix N, and the fact that 0%0 is defined to be 0, try to discern the pattern in the following results:" 403 | ] 404 | }, 405 | { 406 | "cell_type": "code", 407 | "execution_count": null, 408 | "metadata": { 409 | "collapsed": false, 410 | "deletable": true, 411 | "editable": true 412 | }, 413 | "outputs": [], 414 | "source": [ 415 | "(bct X bct) % bct" 416 | ] 417 | }, 418 | { 419 | "cell_type": "code", 420 | "execution_count": null, 421 | "metadata": { 422 | "collapsed": false, 423 | "deletable": true, 424 | "editable": true 425 | }, 426 | "outputs": [], 427 | "source": [ 428 | "(bct X bct X bct) % bct" 429 | ] 430 | }, 431 | { 432 | "cell_type": "code", 433 | "execution_count": null, 434 | "metadata": { 435 | "collapsed": false, 436 | "deletable": true, 437 | "editable": true 438 | }, 439 | "outputs": [], 440 | "source": [ 441 | "(bct X bct X bct) % bct" 442 | ] 443 | }, 444 | { 445 | "cell_type": "code", 446 | "execution_count": null, 447 | "metadata": { 448 | "collapsed": false, 449 | "deletable": true, 450 | "editable": true 451 | }, 452 | "outputs": [], 453 | "source": [ 454 | "(bct X bct X bct X bct) % bct" 455 | ] 456 | }, 457 | { 458 | "cell_type": "markdown", 459 | "metadata": { 460 | "deletable": true, 461 | "editable": true 462 | }, 463 | "source": [ 464 | "### End of Lab" 465 | ] 466 | }, 467 | { 468 | "cell_type": "code", 469 | "execution_count": null, 470 | "metadata": { 471 | "collapsed": false, 472 | "deletable": true, 473 | "editable": true 474 | }, 475 | "outputs": [], 476 | "source": [] 477 | } 478 | ], 479 | "metadata": { 480 | "kernelspec": { 481 | "display_name": "J", 482 | "language": "J", 483 | "name": "jkernel" 484 | }, 485 | "language_info": { 486 | "file_extension": "ijs", 487 | "mimetype": "text/x-J", 488 | "name": "J" 489 | } 490 | }, 491 | "nbformat": 4, 492 | "nbformat_minor": 2 493 | } 494 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/graphics/Plot_Package.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# J Labs\n", 8 | "\n", 9 | "### Plot Package" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "### (1 of 22) Plot Overview\n", 17 | "Plot is a plotting package for J providing business and scientific graphics.\n", 18 | "\n", 19 | "To load, enter:" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": null, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "load 'plot'" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "### (2 of 22) Plot Overview (ctd)\n", 36 | "This loads the package into locale plot, and defines two user functions, \"pd\" (Plot Driver) and \"plot\".\n", 37 | "\n", 38 | "```pd``` - low-level function that handles all calls to Plot, typically used for complex plots.\n", 39 | "\n", 40 | "```plot``` - cover function for pd that will handle most simple uses of Plot.\n", 41 | "\n", 42 | "The examples given below also require the utilities in scripts numeric and trig. Load these as:" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": null, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "load 'numeric trig'" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "### (3 of 22) Verb \"plot\"\n", 59 | "The form is:\n", 60 | "\n", 61 | " ```opt plot data```
\n", 62 | "\n", 63 | "The right argument is the data to be plotted. The optional left argument specifies various plot options.\n", 64 | "\n", 65 | "In general, 2D plots require x and y values given as a 2-element boxed list, and 3D plots require x, y and z values as a 3-element boxed list.\n", 66 | "\n", 67 | "However, if the right argument is open, it is treated as y values (2D plots) or z values (3D plots) . It should be a matrix of data. A vector is treated as a 1-row matrix. For 2D plots, each row of the matrix is treated as a separate data item." 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "### (4 of 22) Verb \"plot\" (ctd)\n", 75 | "The next section will plot a list of data. It is treated as y values, and the x values default to i.#y" 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": {}, 81 | "source": [ 82 | "### (5 of 22) Verb \"plot\" (ctd)" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": null, 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [ 91 | "plot 1 2 3 5" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "### (6 of 22) Verb \"plot\" (ctd)\n", 99 | "The following also plots a list of data, the sin of y where y ranges from 0 to 10 in 100 steps. The data is treated as y values, and the x values again default to i.#y\n", 100 | "\n", 101 | "This time, the default x values are inappropriate - they are shown as in the range 0 to 100, but are actually in the range 0 to 10:" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "plot sin steps 0 10 100" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "### (7 of 22) Verb \"plot\" (ctd)\n", 118 | "The next example provides the correct x values as the first element of a boxed list of x and y values:" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": null, 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [ 127 | "x=: steps 0 10 100" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "metadata": {}, 134 | "outputs": [], 135 | "source": [ 136 | "plot x;sin x" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "### (8 of 22) Plot\n", 144 | "The above example could have been entered more simply as:" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": null, 150 | "metadata": {}, 151 | "outputs": [], 152 | "source": [ 153 | "plot (];sin) steps 0 10 100" 154 | ] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "metadata": {}, 159 | "source": [ 160 | "### (9 of 22) Parametric Plot\n", 161 | "The next example provides applies verbs to generate both the x and y values, giving a parametric plot:" 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": null, 167 | "metadata": {}, 168 | "outputs": [], 169 | "source": [ 170 | "plot (sin;sin*cos) steps 0 10 100" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "### (10 of 22) Parametric Plot (ctd)\n", 178 | "It may be seen that all plots are parametric, but in the simpler cases, one of the verbs that generates the x or y values is the identity." 179 | ] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "### (11 of 22) Parametric Plot (ctd)\n", 186 | "The next example plots the sin curve, swapping the identity and sin verbs to rotate the plot:" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [ 195 | "plot (sin;]) steps 0 10 100" 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "metadata": {}, 201 | "source": [ 202 | "### (12 of 22) Parametric Plot (ctd)\n", 203 | "The above example could also have been entered as:" 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "execution_count": null, 209 | "metadata": {}, 210 | "outputs": [], 211 | "source": [ 212 | "plot |. (];sin) steps 0 10 100" 213 | ] 214 | }, 215 | { 216 | "cell_type": "markdown", 217 | "metadata": {}, 218 | "source": [ 219 | "### (13 of 22) Plot Options\n", 220 | "The left argument to plot specifies one or more options, delimited by semicolons. These are the options that may be given as arguments to pd, see below.\n", 221 | "\n", 222 | "For example, show the x and y axes, and do not show any labels:" 223 | ] 224 | }, 225 | { 226 | "cell_type": "code", 227 | "execution_count": null, 228 | "metadata": {}, 229 | "outputs": [], 230 | "source": [ 231 | "'axes 1 1;labels 0' plot (sin;sin*cos) steps 0 10 100" 232 | ] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "### (14 of 22) Plot Options (ctd)\n", 239 | "The next example plots a matrix of sin values. Each row is treated as a separate data item:" 240 | ] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "execution_count": null, 245 | "metadata": {}, 246 | "outputs": [], 247 | "source": [ 248 | "plot sin */~ steps 0 3 50" 249 | ] 250 | }, 251 | { 252 | "cell_type": "markdown", 253 | "metadata": {}, 254 | "source": [ 255 | "### (15 of 22) Surface Plots\n", 256 | "The \"surface\" option displays this as a surface plot:" 257 | ] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "execution_count": null, 262 | "metadata": {}, 263 | "outputs": [], 264 | "source": [ 265 | "'surface' plot sin */~ steps 0 3 50" 266 | ] 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "metadata": {}, 271 | "source": [ 272 | "### (16 of 22) Surface Plots (ctd)\n", 273 | "In the above example, \"surface\" is short for \"type surface\".\n", 274 | "\n", 275 | "If the first option is a type, the word \"type\" may be omitted.\n", 276 | "\n", 277 | "3D graphics options include viewpoint, viewbox sizing, and the vertical direction. For example:" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": null, 283 | "metadata": {}, 284 | "outputs": [], 285 | "source": [ 286 | "Z=: sin */~ steps 0 3 50" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": {}, 293 | "outputs": [], 294 | "source": [ 295 | "'surface;viewsize 1 1 0.2;viewpoint 1 0 0.7' plot Z" 296 | ] 297 | }, 298 | { 299 | "cell_type": "markdown", 300 | "metadata": {}, 301 | "source": [ 302 | "### (17 of 22) Surface Plots (ctd)\n", 303 | "Surface is the default type when x y and z values are provided in a 3-element boxed list.\n", 304 | "\n", 305 | "The following example shows the standard sombrero:" 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": null, 311 | "metadata": {}, 312 | "outputs": [], 313 | "source": [ 314 | "X=: Y=: steps _3 3 70" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": null, 320 | "metadata": {}, 321 | "outputs": [], 322 | "source": [ 323 | "Z=: (cos % 3&+) X (+/&:*:) Y" 324 | ] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "execution_count": null, 329 | "metadata": {}, 330 | "outputs": [], 331 | "source": [ 332 | "'boxed 0' plot X;Y;Z" 333 | ] 334 | }, 335 | { 336 | "cell_type": "markdown", 337 | "metadata": {}, 338 | "source": [ 339 | "### (18 of 22) Surface Plots (ctd)\n", 340 | "This is the same sombrero, after use as a cushion:" 341 | ] 342 | }, 343 | { 344 | "cell_type": "code", 345 | "execution_count": null, 346 | "metadata": {}, 347 | "outputs": [], 348 | "source": [ 349 | "'boxed 0;viewsize 1 1 0.05' plot X;Y;Z" 350 | ] 351 | }, 352 | { 353 | "cell_type": "markdown", 354 | "metadata": {}, 355 | "source": [ 356 | "### (19 of 22) Business Graphics\n", 357 | "Plots for business graphics include various bar charts, pie charts, and hi-lo close.\n", 358 | "\n", 359 | "For example, a stacked barchart:" 360 | ] 361 | }, 362 | { 363 | "cell_type": "code", 364 | "execution_count": null, 365 | "metadata": {}, 366 | "outputs": [], 367 | "source": [ 368 | "'sbar' plot >:?.>:i.3 5" 369 | ] 370 | }, 371 | { 372 | "cell_type": "markdown", 373 | "metadata": {}, 374 | "source": [ 375 | "### (20 of 22) Business Graphics (ctd)\n", 376 | "Plots for business graphics include various bar charts, pie charts, and hi-lo close.\n", 377 | "\n", 378 | "Floating barchart, with title:" 379 | ] 380 | }, 381 | { 382 | "cell_type": "code", 383 | "execution_count": null, 384 | "metadata": {}, 385 | "outputs": [], 386 | "source": [ 387 | "'fbar;title My Plot' plot >:?>:i.3 5" 388 | ] 389 | }, 390 | { 391 | "cell_type": "markdown", 392 | "metadata": {}, 393 | "source": [ 394 | "### (21 of 22) Verb \"pd\"\n", 395 | "\"pd\" is a monadic function whose argument is either a list of commands or options given as a character string delimited by semicolons, or data given as numeric data.\n", 396 | "\n", 397 | "For example:" 398 | ] 399 | }, 400 | { 401 | "cell_type": "code", 402 | "execution_count": null, 403 | "metadata": {}, 404 | "outputs": [], 405 | "source": [ 406 | "pd 'reset' NB. reset plot" 407 | ] 408 | }, 409 | { 410 | "cell_type": "code", 411 | "execution_count": null, 412 | "metadata": {}, 413 | "outputs": [], 414 | "source": [ 415 | "pd 'type line' NB. set line type" 416 | ] 417 | }, 418 | { 419 | "cell_type": "code", 420 | "execution_count": null, 421 | "metadata": {}, 422 | "outputs": [], 423 | "source": [ 424 | "pd *: i.10 NB. set plot data" 425 | ] 426 | }, 427 | { 428 | "cell_type": "code", 429 | "execution_count": null, 430 | "metadata": {}, 431 | "outputs": [], 432 | "source": [ 433 | "pd 'show' NB. show it" 434 | ] 435 | }, 436 | { 437 | "cell_type": "markdown", 438 | "metadata": {}, 439 | "source": [ 440 | "### (22 of 22) Plot Demo\n", 441 | "For several examples using pd, load the plot demo from menu item Studio|Demos|plot.\n", 442 | "\n", 443 | "In the demo, select menu item Options|View Definition to view and experiment with the definitions." 444 | ] 445 | }, 446 | { 447 | "cell_type": "markdown", 448 | "metadata": {}, 449 | "source": [ 450 | "### End of Lab" 451 | ] 452 | }, 453 | { 454 | "cell_type": "code", 455 | "execution_count": null, 456 | "metadata": {}, 457 | "outputs": [], 458 | "source": [] 459 | } 460 | ], 461 | "metadata": { 462 | "kernelspec": { 463 | "display_name": "J", 464 | "language": "J", 465 | "name": "jkernel" 466 | }, 467 | "language_info": { 468 | "file_extension": "ijs", 469 | "mimetype": "text/x-J", 470 | "name": "J" 471 | } 472 | }, 473 | "nbformat": 4, 474 | "nbformat_minor": 2 475 | } 476 | -------------------------------------------------------------------------------- /jkernel/jinter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env /usr/bin/python3 2 | ############################################################################### 3 | # File: jinter.py 4 | # Author: Martin Saurer, original 30.12.2017, rewrite 23.02.2020 5 | # Description: Call J from Python. 6 | # License: GPL Version 3 (see gpl3.txt) 7 | ############################################################################### 8 | # -*- coding: utf-8 -*- 9 | 10 | ############################################################################### 11 | # Import modules 12 | ############################################################################### 13 | 14 | # Standard Library Imports 15 | import os 16 | import sys 17 | import ctypes 18 | import warnings 19 | 20 | ############################################################################### 21 | # Utility functions 22 | ############################################################################### 23 | 24 | # Get exception info 25 | def get_exception_info(): 26 | typ,val,trb = sys.exc_info() 27 | fil = os.path.split(trb.tb_frame.f_code.co_filename)[1] 28 | lin = trb.tb_lineno 29 | est = ('Exception: ' + str(typ) + ': ' + str(val) + ' / in ' + str(fil) + 30 | ':' + str(lin)) 31 | return est 32 | # end def 33 | 34 | # Encode string to utf-8 bytes 35 | def string_encode(s): 36 | if isinstance(s,str): 37 | return s.encode('utf-8') 38 | else: 39 | return s 40 | # end if 41 | # end def 42 | 43 | # Decode utf-8 bytes to string 44 | def string_decode(s): 45 | if isinstance(s,str): 46 | return s 47 | else: 48 | return s.decode('utf-8','replace') 49 | # end if 50 | # end def 51 | 52 | # Conmvert byte-encoded integer to int 53 | def bytes_to_int(bytes,byteorder='little'): 54 | r = int.from_bytes(bytes,byteorder) 55 | return r 56 | # end def 57 | 58 | # Encode int to byte-encoded integer 59 | def int_to_bytes(value, 60 | length=ctypes.sizeof(ctypes.c_longlong), 61 | byteorder='little'): 62 | b = int(value).to_bytes(length,byteorder) 63 | return b 64 | # end def 65 | 66 | ############################################################################### 67 | # Internal setup 68 | ############################################################################### 69 | 70 | # We ignore warnings (for now ;-) 71 | #warnings.filterwarnings('ignore') 72 | 73 | ############################################################################### 74 | # J interpreter class 75 | ############################################################################### 76 | 77 | # J interpreter class 78 | class J(): 79 | 80 | # Constants 81 | MTYOFM = 1 # Formatted result array output 82 | MTYOER = 2 # Error output 83 | MTYOLOG = 3 # Output log 84 | MTYOSYS = 4 # System assertion failure 85 | MTYOEXIT = 5 # Exit 86 | MTYOFILE = 6 # Output 1!:2[2 87 | 88 | SMWIN = 0 # Windows front end 89 | SMJAVA = 2 # Java front end 90 | SMCON = 3 # Console (or shared library) 91 | 92 | # Constructor 93 | def __init__(self,JInsFol,JBinFol): 94 | 95 | # Members for input/output 96 | self.JInpRdy = False 97 | self.JOutRdy = False 98 | self.JIolRun = True 99 | self.JWForIn = True 100 | self.JCurDir = '' 101 | self.JProStr = '' 102 | self.JInpStr = '' 103 | self.JOutStr = '' 104 | 105 | # J Binaries Folder (absolute or relative (to JInsFol) path) 106 | self.JInsFol = JInsFol 107 | self.JBinFol = JBinFol 108 | 109 | # J user folder 110 | self.JUsrFol = '' 111 | 112 | # J Profile (absolute or relative (to JBinFol) path) 113 | self.JProFil = 'profile.ijs' 114 | 115 | # Declare J variable types for calling JGetM/JSetM 116 | self.JvrType = ctypes.c_longlong(0) 117 | self.JvrRank = ctypes.c_longlong(0) 118 | self.JvrShap = ctypes.c_longlong(0) 119 | self.JvrData = ctypes.c_longlong(0) 120 | 121 | # Build J Dynamic Library name 122 | if sys.platform.startswith('win' ): self.JDynLib = 'j.dll' 123 | elif sys.platform.startswith('darwin'): self.JDynLib = 'libj.dylib' 124 | elif sys.platform.startswith('linux' ): self.JDynLib = 'libj.so' 125 | else: self.JDynLib = '' 126 | 127 | # Build J path names 128 | if os.path.isabs(self.JBinFol): 129 | self.JBin = os.path.join(self.JBinFol) 130 | self.JLib = os.path.join(self.JBinFol, 131 | self.JDynLib) 132 | if os.path.isabs(self.JProFil): 133 | self.JPro = self.JProFil 134 | else: 135 | self.JPro = os.path.join(self.JBinFol, 136 | self.JProFil) 137 | # end if 138 | else: 139 | self.JBin = os.path.join(self.JInsFol, 140 | self.JBinFol) 141 | self.JLib = os.path.join(self.JInsFol, 142 | self.JBinFol, 143 | self.JDynLib) 144 | if os.path.isabs(self.JProFil): 145 | self.JPro = self.JProFil 146 | else: 147 | self.JPro = os.path.join(self.JInsFol, 148 | self.JBinFol, 149 | self.JProFil) 150 | # end if 151 | # end if 152 | 153 | # Declare J callback types 154 | if sys.platform.startswith('win'): 155 | 156 | self.JInputType = ctypes.WINFUNCTYPE(ctypes.c_char_p, 157 | ctypes.c_longlong, 158 | ctypes.c_char_p) 159 | 160 | self.JWdType = ctypes.WINFUNCTYPE(ctypes.c_longlong, 161 | ctypes.c_longlong, 162 | ctypes.c_longlong, 163 | ctypes.c_void_p, 164 | ctypes.c_void_p) 165 | 166 | self.JOutputType = ctypes.WINFUNCTYPE(None, 167 | ctypes.c_longlong, 168 | ctypes.c_longlong, 169 | ctypes.c_char_p) 170 | 171 | else: 172 | 173 | self.JInputType = ctypes.CFUNCTYPE (ctypes.c_char_p, 174 | ctypes.c_longlong, 175 | ctypes.c_char_p) 176 | 177 | self.JWdType = ctypes.CFUNCTYPE (ctypes.c_longlong, 178 | ctypes.c_longlong, 179 | ctypes.c_longlong, 180 | ctypes.c_void_p, 181 | ctypes.c_void_p) 182 | 183 | self.JOutputType = ctypes.CFUNCTYPE (None, 184 | ctypes.c_longlong, 185 | ctypes.c_longlong, 186 | ctypes.c_char_p) 187 | 188 | # end if 189 | 190 | # Declare J callback functions 191 | self.JInputFunc = self.JInputType(self.JInput) 192 | self.JWdFunc = self.JWdType(self.JWd) 193 | self.JOutputFunc = self.JOutputType(self.JOutput) 194 | self.JCallBacks = [ 195 | self.JOutputFunc, 196 | self.JWdFunc, 197 | self.JInputFunc, 198 | 0, 199 | ctypes.c_void_p(J.SMCON) 200 | ] 201 | self.JCBArTypes = (ctypes.c_void_p * len(self.JCallBacks)) 202 | self.JCBArArray = self.JCBArTypes() 203 | self.JCBArArray[0] = ctypes.cast(self.JCallBacks[0],ctypes.c_void_p) 204 | self.JCBArArray[1] = ctypes.cast(self.JCallBacks[1],ctypes.c_void_p) 205 | self.JCBArArray[2] = ctypes.cast(self.JCallBacks[2],ctypes.c_void_p) 206 | self.JCBArArray[3] = ctypes.c_void_p(self.JCallBacks[3]) 207 | self.JCBArArray[4] = self.JCallBacks[4] 208 | 209 | # Load J dynamic link library / shareable object 210 | if sys.platform.startswith('win'): 211 | self.JDll = ctypes.windll.LoadLibrary(self.JLib) 212 | else: 213 | self.JDll = ctypes.cdll.LoadLibrary(self.JLib) 214 | # end if 215 | 216 | # Declare result type of JInit (this is mandatory !!!) 217 | self.JDll.JInit.restype = ctypes.c_void_p 218 | 219 | # Initialize J engine 220 | self.JSession = ctypes.c_void_p(self.JDll.JInit()) 221 | 222 | # Register callback functions 223 | self.JDll.JSM(self.JSession,self.JCBArArray) 224 | 225 | # Setup J environment 226 | s = self.JDll.JDo(self.JSession, 227 | string_encode('ARGV_z_ =: \'\'')) 228 | s = self.JDll.JDo(self.JSession, 229 | string_encode('BINPATH_z_ =: \'' + self.JBin + '\'')) 230 | s = self.JDll.JDo(self.JSession, 231 | string_encode('0!:0 <\'' + self.JPro + '\'')) 232 | s = self.JDll.JDo(self.JSession, 233 | string_encode('NB. 9!:37 (0,16384,0,16000)')) 234 | s = self.JDll.JDo(self.JSession, 235 | string_encode('9!:7 (0{Boxes_j_)')) 236 | 237 | # end def __init__(self,JInsFol,JBinFol) 238 | 239 | ########################################################################### 240 | # I/O callback functions 241 | ########################################################################### 242 | 243 | # J input callback 244 | def JInput(self,j,p): 245 | return string_encode(input(p.decode('utf-8'))) 246 | # end def 247 | 248 | # J output callback 249 | def JOutput(self,j,t,s): 250 | if t == J.MTYOEXIT: 251 | sys.exit(0) 252 | # end if 253 | self.JOutStr += string_decode(s) 254 | self.JOutRdy = True 255 | # end def 256 | 257 | # J window driver callback 258 | # In fact, we use Jwd as an entry point for custom callbacks, using 259 | # J foreign function 11!:x 260 | # We read x (int) and the string in struct pa 261 | # We do not write anything to struct pz 262 | # Return is always 0 263 | # mode = x: ... 264 | # parm = : String Parameter to 11!:x '' 265 | def JWd(self,j,x,pa,pz): 266 | 267 | # Get mode 268 | mode = x 269 | 270 | # Get string parameter 271 | sptr = ctypes.pointer( 272 | ctypes.c_longlong(pa + 273 | (ctypes.sizeof(ctypes.c_longlong) * 274 | ctypes.sizeof(ctypes.c_longlong)))) 275 | parm = ctypes.string_at(sptr.contents.value) 276 | parm = string_decode(parm) 277 | 278 | # Relevant information is in "mode" and "parm", 279 | # but we don't use any of these for now 280 | if mode != 0: 281 | print('JWd: mode=' + str(mode) + ', parm=\"' + parm + '\"') 282 | # end if 283 | 284 | # Return 0 (always) 285 | return 0 286 | 287 | # end def 288 | 289 | ########################################################################### 290 | # Utility functions 291 | ########################################################################### 292 | 293 | # Do a J sentence 294 | def Exec(self,cmd): 295 | s = self.JDll.JDo(self.JSession,ctypes.c_char_p(string_encode(cmd))) 296 | return s 297 | # end def 298 | 299 | # Receive output 300 | def Recv(self): 301 | out = '' 302 | if self.JOutRdy: 303 | out = self.JOutStr 304 | self.JOutStr = '' 305 | self.JOutRdy = False 306 | # end if 307 | return out 308 | # end def 309 | 310 | # Get J string variable 311 | def GetStrVar(self,var): 312 | # Declare J variable types for calling JGetM/JSetM 313 | self.JvrType = ctypes.c_longlong(0) 314 | self.JvrRank = ctypes.c_longlong(0) 315 | self.JvrShap = ctypes.c_longlong(0) 316 | self.JvrData = ctypes.c_longlong(0) 317 | # Get variable 318 | sts = self.JDll.JGetM(self.JSession, 319 | string_encode(var), 320 | ctypes.byref(self.JvrType), 321 | ctypes.byref(self.JvrRank), 322 | ctypes.byref(self.JvrShap), 323 | ctypes.byref(self.JvrData)) 324 | if sts == 0: 325 | sln = bytes_to_int(ctypes.string_at(self.JvrShap.value, 326 | ctypes.sizeof(ctypes.c_longlong))) 327 | val = ctypes.string_at(self.JvrData.value,sln) 328 | val = string_decode(val) 329 | return val 330 | else: 331 | return '' 332 | # end if 333 | # end def 334 | 335 | # Set J string variable 336 | def SetStrVar(self,var,val): 337 | typ = ctypes.c_longlong(2) 338 | ran = ctypes.c_longlong(1) 339 | sln = ctypes.c_longlong(len(val)) 340 | sha = ctypes.c_char_p( 341 | ctypes.string_at( 342 | ctypes.addressof(sln),ctypes.sizeof(ctypes.c_longlong))) 343 | dat = ctypes.c_char_p(string_encode(val)) 344 | sts = self.JDll.JSetM(self.JSession, 345 | string_encode(var), 346 | ctypes.byref(typ), 347 | ctypes.byref(ran), 348 | ctypes.byref(sha), 349 | ctypes.byref(dat)) 350 | return sts 351 | # end def 352 | 353 | ############################################################################### 354 | # Main Entry Point 355 | ############################################################################### 356 | 357 | # For testing, here is an example of a Python driven Jconsole 358 | if __name__ == '__main__': 359 | 360 | # Create async J instance 361 | j = J('/home/martin/J901','bin') 362 | #j = J('C:\\Users\\martsa-adm\\J901','bin') 363 | 364 | # Run our I/O loop 365 | while True: 366 | 367 | # Get input 368 | cmd = input(' ') 369 | 370 | # Exec J sentence 371 | j.Exec(cmd) 372 | 373 | # Print output 374 | sys.stdout.write(j.Recv()) 375 | 376 | # end while 377 | 378 | # end if 379 | 380 | ############################################################################### 381 | # EOF 382 | ############################################################################### 383 | 384 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/core/A_Taste_of_J_(2).ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# J Labs\n", 11 | "\n", 12 | "### A Taste of J (2)" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": { 18 | "deletable": true, 19 | "editable": true 20 | }, 21 | "source": [ 22 | "### (1 of 18) First Steps\n", 23 | "Look at the following J sentences; can you figure them out? The sentences are shown indented 3 spaces; the result, if any, is shown aligned to the left margin.\n", 24 | "\n", 25 | "These simple sentences illustrate some of the core facilities of J, that will be described in this lab." 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": null, 31 | "metadata": { 32 | "collapsed": false, 33 | "deletable": true, 34 | "editable": true 35 | }, 36 | "outputs": [], 37 | "source": [ 38 | "tab=: /~" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": { 45 | "collapsed": false, 46 | "deletable": true, 47 | "editable": true 48 | }, 49 | "outputs": [], 50 | "source": [ 51 | "(];*.tab;!tab) _2+i.7" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": { 57 | "deletable": true, 58 | "editable": true 59 | }, 60 | "source": [ 61 | "### (2 of 18) First Steps (ctd)\n", 62 | "To start, note that \"verbs\" (i.e. functions) in J can apply to several data items at once. Indeed, the basic datatype is an array, and J verbs are designed to apply to arrays. For example, the following adds two lists of numbers:" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "metadata": { 69 | "collapsed": false, 70 | "deletable": true, 71 | "editable": true 72 | }, 73 | "outputs": [], 74 | "source": [ 75 | "2 3 5 + 10 20 30" 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": { 81 | "deletable": true, 82 | "editable": true 83 | }, 84 | "source": [ 85 | "### (3 of 18) Adverbs\n", 86 | "The \"adverb\" in J takes a verb argument and returns another verb, typically related. The behaviour is much like in English: \"run quickly\", is the verb \"run\", modified by the adverb \"quickly\".\n", 87 | "\n", 88 | "The J adverb / results in a verb that applies to each pair of elements, compare with above:" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": null, 94 | "metadata": { 95 | "collapsed": false, 96 | "deletable": true, 97 | "editable": true 98 | }, 99 | "outputs": [], 100 | "source": [ 101 | "2 3 5 +/ 10 20 30" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": { 107 | "deletable": true, 108 | "editable": true 109 | }, 110 | "source": [ 111 | "### (4 of 18) Adverbs (ctd)\n", 112 | "Thus, +/ forms an addition table, and similarly, \\*/ forms a multiplication table:" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": null, 118 | "metadata": { 119 | "collapsed": false, 120 | "deletable": true, 121 | "editable": true 122 | }, 123 | "outputs": [], 124 | "source": [ 125 | "2 3 5 */ 10 20 30" 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "metadata": { 131 | "deletable": true, 132 | "editable": true 133 | }, 134 | "source": [ 135 | "### (5 of 18) Adverbs (ctd)\n", 136 | "Try entering:\n", 137 | "\n", 138 | " ```2 3 5 %/ 10 20 30```
" 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "metadata": { 144 | "deletable": true, 145 | "editable": true 146 | }, 147 | "source": [ 148 | "### (6 of 18) Adverbs (ctd)\n", 149 | "The adverb ~ applies a verb with the same argument on the left as on the right, thus the following two expressions are equivalent:" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": null, 155 | "metadata": { 156 | "collapsed": false, 157 | "deletable": true, 158 | "editable": true 159 | }, 160 | "outputs": [], 161 | "source": [ 162 | "0 1 2 3 + 0 1 2 3" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": null, 168 | "metadata": { 169 | "collapsed": false, 170 | "deletable": true, 171 | "editable": true 172 | }, 173 | "outputs": [], 174 | "source": [ 175 | "+~ 0 1 2 3" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": { 181 | "deletable": true, 182 | "editable": true 183 | }, 184 | "source": [ 185 | "### (7 of 18) Adverbs (ctd)\n", 186 | "We can combine two adverbs. The following applies the +/ addition table with the same argument on left and right:" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": { 193 | "collapsed": false, 194 | "deletable": true, 195 | "editable": true 196 | }, 197 | "outputs": [], 198 | "source": [ 199 | "+/~ 0 1 2 3" 200 | ] 201 | }, 202 | { 203 | "cell_type": "markdown", 204 | "metadata": { 205 | "deletable": true, 206 | "editable": true 207 | }, 208 | "source": [ 209 | "### (8 of 18) Adverbs (ctd)\n", 210 | "Since /~ is to be used again, we give it a name \"tab\". This is not required, but is helpful in reading later expressions." 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": null, 216 | "metadata": { 217 | "collapsed": false, 218 | "deletable": true, 219 | "editable": true 220 | }, 221 | "outputs": [], 222 | "source": [ 223 | "tab=. /~" 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": null, 229 | "metadata": { 230 | "collapsed": false, 231 | "deletable": true, 232 | "editable": true 233 | }, 234 | "outputs": [], 235 | "source": [ 236 | "+ tab 0 1 2 3" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": { 243 | "collapsed": false, 244 | "deletable": true, 245 | "editable": true 246 | }, 247 | "outputs": [], 248 | "source": [ 249 | "* tab 0 1 2 3" 250 | ] 251 | }, 252 | { 253 | "cell_type": "markdown", 254 | "metadata": { 255 | "deletable": true, 256 | "editable": true 257 | }, 258 | "source": [ 259 | "### (9 of 18) Adverbs (ctd)\n", 260 | "Try entering:\n", 261 | "\n", 262 | " ```^ tab 0 1 2 3```
" 263 | ] 264 | }, 265 | { 266 | "cell_type": "markdown", 267 | "metadata": { 268 | "deletable": true, 269 | "editable": true 270 | }, 271 | "source": [ 272 | "### (10 of 18) Integer\n", 273 | "The verb i. (integer) generates the first n numbers.\n", 274 | "\n", 275 | "Try entering:\n", 276 | "\n", 277 | " ```i. 3 4```
\n", 278 | "\n", 279 | " ```i. 3 4 5```
" 280 | ] 281 | }, 282 | { 283 | "cell_type": "code", 284 | "execution_count": null, 285 | "metadata": { 286 | "collapsed": false, 287 | "deletable": true, 288 | "editable": true 289 | }, 290 | "outputs": [], 291 | "source": [ 292 | "i.7" 293 | ] 294 | }, 295 | { 296 | "cell_type": "markdown", 297 | "metadata": { 298 | "deletable": true, 299 | "editable": true 300 | }, 301 | "source": [ 302 | "### (11 of 18) Negative Numbers\n", 303 | "Negative numbers are shown with a leading underscore character, which is not the same as \"-\", the minus verb." 304 | ] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "execution_count": null, 309 | "metadata": { 310 | "collapsed": false, 311 | "deletable": true, 312 | "editable": true 313 | }, 314 | "outputs": [], 315 | "source": [ 316 | "_2+ i.7" 317 | ] 318 | }, 319 | { 320 | "cell_type": "markdown", 321 | "metadata": { 322 | "deletable": true, 323 | "editable": true 324 | }, 325 | "source": [ 326 | "### (12 of 18) Combining Verbs\n", 327 | "Now lets look at the expression in parentheses:\n", 328 | "\n", 329 | " ```];*.tab;!tab```
\n", 330 | "\n", 331 | "Ignoring the semicolons for the moment, the expression contains 3 verbs:\n", 332 | "\n", 333 | "] is the identity verb:" 334 | ] 335 | }, 336 | { 337 | "cell_type": "code", 338 | "execution_count": null, 339 | "metadata": { 340 | "collapsed": false, 341 | "deletable": true, 342 | "editable": true 343 | }, 344 | "outputs": [], 345 | "source": [ 346 | "] _2+i.7" 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "metadata": { 352 | "deletable": true, 353 | "editable": true 354 | }, 355 | "source": [ 356 | "### (13 of 18) Combining Verbs (ctd)\n", 357 | "```*.``` is the least common multiple verb, so ```*.tab``` is the corresponding table. For example, the LCM of 3 and 4 is 12:" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "metadata": { 364 | "collapsed": false, 365 | "deletable": true, 366 | "editable": true 367 | }, 368 | "outputs": [], 369 | "source": [ 370 | "3 *. 4" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": null, 376 | "metadata": { 377 | "collapsed": false, 378 | "deletable": true, 379 | "editable": true 380 | }, 381 | "outputs": [], 382 | "source": [ 383 | "*.tab _2+i.7" 384 | ] 385 | }, 386 | { 387 | "cell_type": "markdown", 388 | "metadata": { 389 | "deletable": true, 390 | "editable": true 391 | }, 392 | "source": [ 393 | "### (14 of 18) Combining Verbs (ctd)\n", 394 | "! is the combinations verb. m!n is the number of ways of taking m combinations of n objects; so !tab is the corresponding table. For example, 2!4 is 6.\n", 395 | "\n", 396 | "Note that if you look at the lower right part of the table, you can see a copy of the triangle of Pascal." 397 | ] 398 | }, 399 | { 400 | "cell_type": "code", 401 | "execution_count": null, 402 | "metadata": { 403 | "collapsed": false, 404 | "deletable": true, 405 | "editable": true 406 | }, 407 | "outputs": [], 408 | "source": [ 409 | "2!4" 410 | ] 411 | }, 412 | { 413 | "cell_type": "code", 414 | "execution_count": null, 415 | "metadata": { 416 | "collapsed": false, 417 | "deletable": true, 418 | "editable": true 419 | }, 420 | "outputs": [], 421 | "source": [ 422 | "!tab _2+i.7" 423 | ] 424 | }, 425 | { 426 | "cell_type": "markdown", 427 | "metadata": { 428 | "deletable": true, 429 | "editable": true 430 | }, 431 | "source": [ 432 | "### (15 of 18) Combining Verbs (ctd)\n", 433 | "The expression in parentheses:\n", 434 | "\n", 435 | " ```];*.tab;!tab```
\n", 436 | "\n", 437 | "is therefore seen to be of the form:\n", 438 | "\n", 439 | " ```f;g;h```
\n", 440 | "\n", 441 | "for verbs f g and h. It happens that ; is also a verb, so this expression is a list of 5 verbs!\n", 442 | "\n", 443 | "To understand this, consider a simpler list of 3 verbs commonly seen in mathematics. Suppose f and g are functions, then:\n", 444 | "\n", 445 | " ```(f + g) x```
\n", 446 | "\n", 447 | "is typically defined to be\n", 448 | "\n", 449 | " ```f(x) + g(x)```
\n", 450 | "\n", 451 | "In J, this concept is extended to any type of function. Given verbs f g and h, then:\n", 452 | "\n", 453 | " ```(f g h) x```
\n", 454 | "\n", 455 | "is defined as\n", 456 | "\n", 457 | " ```(f x) g (h x)```
\n", 458 | "\n", 459 | "Example:" 460 | ] 461 | }, 462 | { 463 | "cell_type": "code", 464 | "execution_count": null, 465 | "metadata": { 466 | "collapsed": false, 467 | "deletable": true, 468 | "editable": true 469 | }, 470 | "outputs": [], 471 | "source": [ 472 | "(] + %) 1 2 3 4 NB. % is the reciprocal" 473 | ] 474 | }, 475 | { 476 | "cell_type": "markdown", 477 | "metadata": { 478 | "deletable": true, 479 | "editable": true 480 | }, 481 | "source": [ 482 | "### (16 of 18) Combining Verbs (ctd)\n", 483 | "A list of 3 verbs together is called a fork, and defines a new verb.\n", 484 | "\n", 485 | "Here is another example. The verb ; links its arguments together, putting each in a box. The following is the fork: identity linked with reciprocal." 486 | ] 487 | }, 488 | { 489 | "cell_type": "code", 490 | "execution_count": null, 491 | "metadata": { 492 | "collapsed": false, 493 | "deletable": true, 494 | "editable": true 495 | }, 496 | "outputs": [], 497 | "source": [ 498 | "(] ; %) 1 2 3 4" 499 | ] 500 | }, 501 | { 502 | "cell_type": "markdown", 503 | "metadata": { 504 | "deletable": true, 505 | "editable": true 506 | }, 507 | "source": [ 508 | "### (17 of 18) Combining Verbs (ctd)\n", 509 | "J interprets a list of 5 verbs by creating a fork from the rightmost 3 verbs, then another fork from the new verb and the two remaining verbs.\n", 510 | "\n", 511 | "It may be seen that:\n", 512 | "\n", 513 | " ```(];*.tab;!tab)```
\n", 514 | "\n", 515 | "is a verb that returns the identity; the LCM table; and the combinations table; all linked together.\n", 516 | "\n", 517 | "Lets try it with a different argument:" 518 | ] 519 | }, 520 | { 521 | "cell_type": "code", 522 | "execution_count": null, 523 | "metadata": { 524 | "collapsed": false, 525 | "deletable": true, 526 | "editable": true 527 | }, 528 | "outputs": [], 529 | "source": [ 530 | "(];*.tab;!tab) 3+i.7" 531 | ] 532 | }, 533 | { 534 | "cell_type": "markdown", 535 | "metadata": { 536 | "deletable": true, 537 | "editable": true 538 | }, 539 | "source": [ 540 | "### (18 of 18) Table Utility\n", 541 | "Since verb tables are so useful for exploration, J has a standard utility adverb called \"table\" that creates a table bordered by its arguments.\n", 542 | "\n", 543 | "For example:" 544 | ] 545 | }, 546 | { 547 | "cell_type": "code", 548 | "execution_count": null, 549 | "metadata": { 550 | "collapsed": false, 551 | "deletable": true, 552 | "editable": true 553 | }, 554 | "outputs": [], 555 | "source": [ 556 | "!table 3+i.7 NB. right argument only" 557 | ] 558 | }, 559 | { 560 | "cell_type": "code", 561 | "execution_count": null, 562 | "metadata": { 563 | "collapsed": false, 564 | "deletable": true, 565 | "editable": true 566 | }, 567 | "outputs": [], 568 | "source": [ 569 | "0 1 2 3 !table 3+i.7 NB. left and right arguments" 570 | ] 571 | }, 572 | { 573 | "cell_type": "markdown", 574 | "metadata": { 575 | "deletable": true, 576 | "editable": true 577 | }, 578 | "source": [ 579 | "### End of Lab" 580 | ] 581 | }, 582 | { 583 | "cell_type": "code", 584 | "execution_count": null, 585 | "metadata": { 586 | "collapsed": false, 587 | "deletable": true, 588 | "editable": true 589 | }, 590 | "outputs": [], 591 | "source": [] 592 | } 593 | ], 594 | "metadata": { 595 | "kernelspec": { 596 | "display_name": "J", 597 | "language": "J", 598 | "name": "jkernel" 599 | }, 600 | "language_info": { 601 | "file_extension": "ijs", 602 | "mimetype": "text/x-J", 603 | "name": "J" 604 | } 605 | }, 606 | "nbformat": 4, 607 | "nbformat_minor": 2 608 | } 609 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/math/Rotations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# J Labs\n", 11 | "\n", 12 | "### Rotations" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": { 18 | "deletable": true, 19 | "editable": true 20 | }, 21 | "source": [ 22 | "### (1 of 7) ROTATIONS\n", 23 | "The function:\n", 24 | "\n", 25 | " ```length=: %:@:(+/@:*:)\"1```
\n", 26 | "\n", 27 | "yields the length of a vector to which it is applied, first squaring (*:) the elements, then summing (+/) the squares, and finally taking the square root (%:), thus:" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": { 34 | "collapsed": false, 35 | "deletable": true, 36 | "editable": true 37 | }, 38 | "outputs": [], 39 | "source": [ 40 | "length=: %:@:(+/@:*:)\"1" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "metadata": { 47 | "collapsed": false, 48 | "deletable": true, 49 | "editable": true 50 | }, 51 | "outputs": [], 52 | "source": [ 53 | "length 3 4" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": null, 59 | "metadata": { 60 | "collapsed": false, 61 | "deletable": true, 62 | "editable": true 63 | }, 64 | "outputs": [], 65 | "source": [ 66 | "length 3 4 12" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": { 72 | "deletable": true, 73 | "editable": true 74 | }, 75 | "source": [ 76 | "### (2 of 7) LENGTH\n", 77 | "The function:\n", 78 | "\n", 79 | " ```X=: +/ . \\*```
\n", 80 | "\n", 81 | "is the matrix product.\n", 82 | "\n", 83 | "If m is a matrix, and v is a vector, the result of m X v may differ from v in both length and direction.\n", 84 | "\n", 85 | "However, if m is a matrix whose row and column sums are of length 1, then the result of m X v has the same length as v The operation is called a rotation, and m is called a rotation matrix. For example:" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": null, 91 | "metadata": { 92 | "collapsed": false, 93 | "deletable": true, 94 | "editable": true 95 | }, 96 | "outputs": [], 97 | "source": [ 98 | "X=: +/ . *" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": null, 104 | "metadata": { 105 | "collapsed": false, 106 | "deletable": true, 107 | "editable": true 108 | }, 109 | "outputs": [], 110 | "source": [ 111 | "v=: 3 4" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": { 118 | "collapsed": false, 119 | "deletable": true, 120 | "editable": true 121 | }, 122 | "outputs": [], 123 | "source": [ 124 | "m=: > 1 2;2 1" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": null, 130 | "metadata": { 131 | "collapsed": false, 132 | "deletable": true, 133 | "editable": true 134 | }, 135 | "outputs": [], 136 | "source": [ 137 | "m" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": null, 143 | "metadata": { 144 | "collapsed": false, 145 | "deletable": true, 146 | "editable": true 147 | }, 148 | "outputs": [], 149 | "source": [ 150 | "m X v" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": null, 156 | "metadata": { 157 | "collapsed": false, 158 | "deletable": true, 159 | "editable": true 160 | }, 161 | "outputs": [], 162 | "source": [ 163 | "length m X v" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": null, 169 | "metadata": { 170 | "collapsed": false, 171 | "deletable": true, 172 | "editable": true 173 | }, 174 | "outputs": [], 175 | "source": [ 176 | "length v" 177 | ] 178 | }, 179 | { 180 | "cell_type": "code", 181 | "execution_count": null, 182 | "metadata": { 183 | "collapsed": false, 184 | "deletable": true, 185 | "editable": true 186 | }, 187 | "outputs": [], 188 | "source": [ 189 | "c=: % %: 2 NB. Reciprocal of square root of 2" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": null, 195 | "metadata": { 196 | "collapsed": false, 197 | "deletable": true, 198 | "editable": true 199 | }, 200 | "outputs": [], 201 | "source": [ 202 | "m=: > (c, c);((-c),c)" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": null, 208 | "metadata": { 209 | "collapsed": false, 210 | "deletable": true, 211 | "editable": true 212 | }, 213 | "outputs": [], 214 | "source": [ 215 | "m" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": null, 221 | "metadata": { 222 | "collapsed": false, 223 | "deletable": true, 224 | "editable": true 225 | }, 226 | "outputs": [], 227 | "source": [ 228 | "length m NB. Lengths of rows of m" 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": null, 234 | "metadata": { 235 | "collapsed": false, 236 | "deletable": true, 237 | "editable": true 238 | }, 239 | "outputs": [], 240 | "source": [ 241 | "|: m NB. Transpose of m" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": null, 247 | "metadata": { 248 | "collapsed": false, 249 | "deletable": true, 250 | "editable": true 251 | }, 252 | "outputs": [], 253 | "source": [ 254 | "length |: m NB. Lengths of columns of m" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": null, 260 | "metadata": { 261 | "collapsed": false, 262 | "deletable": true, 263 | "editable": true 264 | }, 265 | "outputs": [], 266 | "source": [ 267 | "m X v" 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": null, 273 | "metadata": { 274 | "collapsed": false, 275 | "deletable": true, 276 | "editable": true 277 | }, 278 | "outputs": [], 279 | "source": [ 280 | "length m X v" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": { 286 | "deletable": true, 287 | "editable": true 288 | }, 289 | "source": [ 290 | "### (3 of 7) ROTATION\n", 291 | "The function:\n", 292 | "\n", 293 | " ```r=: (sind , -@:cosd) ,. (cosd , sind)```
\n", 294 | "\n", 295 | "produces a rotation matrix. The angle of rotation it produces is determined by the argument of r. For example:" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": null, 301 | "metadata": { 302 | "collapsed": false, 303 | "deletable": true, 304 | "editable": true 305 | }, 306 | "outputs": [], 307 | "source": [ 308 | "load 'trig'" 309 | ] 310 | }, 311 | { 312 | "cell_type": "code", 313 | "execution_count": null, 314 | "metadata": { 315 | "collapsed": false, 316 | "deletable": true, 317 | "editable": true 318 | }, 319 | "outputs": [], 320 | "source": [ 321 | "r=: (cosd , -@:sind) ,. (sind , cosd)" 322 | ] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "execution_count": null, 327 | "metadata": { 328 | "collapsed": false, 329 | "deletable": true, 330 | "editable": true 331 | }, 332 | "outputs": [], 333 | "source": [ 334 | "m=: r 45" 335 | ] 336 | }, 337 | { 338 | "cell_type": "code", 339 | "execution_count": null, 340 | "metadata": { 341 | "collapsed": false, 342 | "deletable": true, 343 | "editable": true 344 | }, 345 | "outputs": [], 346 | "source": [ 347 | "m" 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": null, 353 | "metadata": { 354 | "collapsed": false, 355 | "deletable": true, 356 | "editable": true 357 | }, 358 | "outputs": [], 359 | "source": [ 360 | "m X v" 361 | ] 362 | }, 363 | { 364 | "cell_type": "code", 365 | "execution_count": null, 366 | "metadata": { 367 | "collapsed": false, 368 | "deletable": true, 369 | "editable": true 370 | }, 371 | "outputs": [], 372 | "source": [ 373 | "y=: (r 90) X v" 374 | ] 375 | }, 376 | { 377 | "cell_type": "code", 378 | "execution_count": null, 379 | "metadata": { 380 | "collapsed": false, 381 | "deletable": true, 382 | "editable": true 383 | }, 384 | "outputs": [], 385 | "source": [ 386 | "y" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": null, 392 | "metadata": { 393 | "collapsed": false, 394 | "deletable": true, 395 | "editable": true 396 | }, 397 | "outputs": [], 398 | "source": [ 399 | "y X v NB. 90-degree rotation produces a perpendicular vector" 400 | ] 401 | }, 402 | { 403 | "cell_type": "markdown", 404 | "metadata": { 405 | "deletable": true, 406 | "editable": true 407 | }, 408 | "source": [ 409 | "### (4 of 7) ROTATION MATRICES\n", 410 | "If m =. r a is a rotation matrix in 2-space, then the matrix 1 0 0,0 0,.m produces a corresponding rotation about the x axis in 3-space. For example:" 411 | ] 412 | }, 413 | { 414 | "cell_type": "code", 415 | "execution_count": null, 416 | "metadata": { 417 | "collapsed": false, 418 | "deletable": true, 419 | "editable": true 420 | }, 421 | "outputs": [], 422 | "source": [ 423 | "r 30" 424 | ] 425 | }, 426 | { 427 | "cell_type": "code", 428 | "execution_count": null, 429 | "metadata": { 430 | "collapsed": false, 431 | "deletable": true, 432 | "editable": true 433 | }, 434 | "outputs": [], 435 | "source": [ 436 | "rx30=: 1 0 0,0 0,.r 30" 437 | ] 438 | }, 439 | { 440 | "cell_type": "code", 441 | "execution_count": null, 442 | "metadata": { 443 | "collapsed": false, 444 | "deletable": true, 445 | "editable": true 446 | }, 447 | "outputs": [], 448 | "source": [ 449 | "rx30" 450 | ] 451 | }, 452 | { 453 | "cell_type": "code", 454 | "execution_count": null, 455 | "metadata": { 456 | "collapsed": false, 457 | "deletable": true, 458 | "editable": true 459 | }, 460 | "outputs": [], 461 | "source": [ 462 | "w=: 3 4 5" 463 | ] 464 | }, 465 | { 466 | "cell_type": "code", 467 | "execution_count": null, 468 | "metadata": { 469 | "collapsed": false, 470 | "deletable": true, 471 | "editable": true 472 | }, 473 | "outputs": [], 474 | "source": [ 475 | "rx30 X w" 476 | ] 477 | }, 478 | { 479 | "cell_type": "code", 480 | "execution_count": null, 481 | "metadata": { 482 | "collapsed": false, 483 | "deletable": true, 484 | "editable": true 485 | }, 486 | "outputs": [], 487 | "source": [ 488 | "length w" 489 | ] 490 | }, 491 | { 492 | "cell_type": "code", 493 | "execution_count": null, 494 | "metadata": { 495 | "collapsed": false, 496 | "deletable": true, 497 | "editable": true 498 | }, 499 | "outputs": [], 500 | "source": [ 501 | "length rx30 X w" 502 | ] 503 | }, 504 | { 505 | "cell_type": "markdown", 506 | "metadata": { 507 | "deletable": true, 508 | "editable": true 509 | }, 510 | "source": [ 511 | "### (5 of 7) ROTATION IN 3-SPACE\n", 512 | "If the rows and columns of a rotation about x are permuted to bring the 1 to the y or z position, the result is a rotation about the corresponding axis. For example:" 513 | ] 514 | }, 515 | { 516 | "cell_type": "code", 517 | "execution_count": null, 518 | "metadata": { 519 | "collapsed": false, 520 | "deletable": true, 521 | "editable": true 522 | }, 523 | "outputs": [], 524 | "source": [ 525 | "ry45=: 1 0 2 { 1 0 2 ({\"1) 1 0 0,0 0,.r 45" 526 | ] 527 | }, 528 | { 529 | "cell_type": "code", 530 | "execution_count": null, 531 | "metadata": { 532 | "collapsed": false, 533 | "deletable": true, 534 | "editable": true 535 | }, 536 | "outputs": [], 537 | "source": [ 538 | "rz60=: 1 2 0 { 1 2 0 ({\"1) 1 0 0,0 0,.r 60" 539 | ] 540 | }, 541 | { 542 | "cell_type": "code", 543 | "execution_count": null, 544 | "metadata": { 545 | "collapsed": false, 546 | "deletable": true, 547 | "editable": true 548 | }, 549 | "outputs": [], 550 | "source": [ 551 | "ry45" 552 | ] 553 | }, 554 | { 555 | "cell_type": "code", 556 | "execution_count": null, 557 | "metadata": { 558 | "collapsed": false, 559 | "deletable": true, 560 | "editable": true 561 | }, 562 | "outputs": [], 563 | "source": [ 564 | "ry45 X w" 565 | ] 566 | }, 567 | { 568 | "cell_type": "code", 569 | "execution_count": null, 570 | "metadata": { 571 | "collapsed": false, 572 | "deletable": true, 573 | "editable": true 574 | }, 575 | "outputs": [], 576 | "source": [ 577 | "rz60" 578 | ] 579 | }, 580 | { 581 | "cell_type": "code", 582 | "execution_count": null, 583 | "metadata": { 584 | "collapsed": false, 585 | "deletable": true, 586 | "editable": true 587 | }, 588 | "outputs": [], 589 | "source": [ 590 | "rz60 X w" 591 | ] 592 | }, 593 | { 594 | "cell_type": "markdown", 595 | "metadata": { 596 | "deletable": true, 597 | "editable": true 598 | }, 599 | "source": [ 600 | "### (6 of 7) ROTATION ABOUT y AND z\n", 601 | "The matrix product of two rotations is again a rotation, and a general rotation can therefore be produced as a product of rotations about each of the three axes. For example:" 602 | ] 603 | }, 604 | { 605 | "cell_type": "code", 606 | "execution_count": null, 607 | "metadata": { 608 | "collapsed": false, 609 | "deletable": true, 610 | "editable": true 611 | }, 612 | "outputs": [], 613 | "source": [ 614 | "rall=: rx30 X ry45 X rz60" 615 | ] 616 | }, 617 | { 618 | "cell_type": "code", 619 | "execution_count": null, 620 | "metadata": { 621 | "collapsed": false, 622 | "deletable": true, 623 | "editable": true 624 | }, 625 | "outputs": [], 626 | "source": [ 627 | "rall" 628 | ] 629 | }, 630 | { 631 | "cell_type": "code", 632 | "execution_count": null, 633 | "metadata": { 634 | "collapsed": false, 635 | "deletable": true, 636 | "editable": true 637 | }, 638 | "outputs": [], 639 | "source": [ 640 | "length rall" 641 | ] 642 | }, 643 | { 644 | "cell_type": "code", 645 | "execution_count": null, 646 | "metadata": { 647 | "collapsed": false, 648 | "deletable": true, 649 | "editable": true 650 | }, 651 | "outputs": [], 652 | "source": [ 653 | "rall X w" 654 | ] 655 | }, 656 | { 657 | "cell_type": "markdown", 658 | "metadata": { 659 | "deletable": true, 660 | "editable": true 661 | }, 662 | "source": [ 663 | "### (7 of 7) PRODUCT OF ROTATIONS\n", 664 | "We will now define a general rotation function GR whose left argument is a quoted list of axes, such as \"yxz\" or \"yz\" or \"x\"or \"xyxyx\", and whose right argument is a list of angles in degrees. Thus:" 665 | ] 666 | }, 667 | { 668 | "cell_type": "code", 669 | "execution_count": null, 670 | "metadata": { 671 | "collapsed": false, 672 | "deletable": true, 673 | "editable": true 674 | }, 675 | "outputs": [], 676 | "source": [ 677 | "GR=: 4 : 0\n", 678 | "res=: (i. =/ i.) 3 NB. Initialize res as identity matrix\n", 679 | "p=: >0 1 2;1 0 2;1 2 0 NB. Permutations for axes\n", 680 | "while. 0<# x do.\n", 681 | "cp=. ('xyz'i.{:x){p NB. Current permutation\n", 682 | "cr=. cp {\"1 cp { 1 0 0,0 0,.r {: y NB. Current rotation\n", 683 | "res =. cr X res\n", 684 | "x=. }: x\n", 685 | "y=. }: y\n", 686 | "end.\n", 687 | "res\n", 688 | ")" 689 | ] 690 | }, 691 | { 692 | "cell_type": "code", 693 | "execution_count": null, 694 | "metadata": { 695 | "collapsed": false, 696 | "deletable": true, 697 | "editable": true 698 | }, 699 | "outputs": [], 700 | "source": [ 701 | "'xyz' GR 30 45 60" 702 | ] 703 | }, 704 | { 705 | "cell_type": "code", 706 | "execution_count": null, 707 | "metadata": { 708 | "collapsed": false, 709 | "deletable": true, 710 | "editable": true 711 | }, 712 | "outputs": [], 713 | "source": [ 714 | "'yx' GR 45 60" 715 | ] 716 | }, 717 | { 718 | "cell_type": "code", 719 | "execution_count": null, 720 | "metadata": { 721 | "collapsed": false, 722 | "deletable": true, 723 | "editable": true 724 | }, 725 | "outputs": [], 726 | "source": [ 727 | "'y' GR 45" 728 | ] 729 | }, 730 | { 731 | "cell_type": "code", 732 | "execution_count": null, 733 | "metadata": { 734 | "collapsed": false, 735 | "deletable": true, 736 | "editable": true 737 | }, 738 | "outputs": [], 739 | "source": [ 740 | "'xyxyx' GR 1 2 3 4 5" 741 | ] 742 | }, 743 | { 744 | "cell_type": "markdown", 745 | "metadata": { 746 | "deletable": true, 747 | "editable": true 748 | }, 749 | "source": [ 750 | "### End of Lab" 751 | ] 752 | }, 753 | { 754 | "cell_type": "code", 755 | "execution_count": null, 756 | "metadata": { 757 | "collapsed": false, 758 | "deletable": true, 759 | "editable": true 760 | }, 761 | "outputs": [], 762 | "source": [] 763 | } 764 | ], 765 | "metadata": { 766 | "kernelspec": { 767 | "display_name": "J", 768 | "language": "J", 769 | "name": "jkernel" 770 | }, 771 | "language_info": { 772 | "file_extension": "ijs", 773 | "mimetype": "text/x-J", 774 | "name": "J" 775 | } 776 | }, 777 | "nbformat": 4, 778 | "nbformat_minor": 2 779 | } 780 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/math/Iteration_and_the_Power_Operator.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# J Labs\n", 11 | "\n", 12 | "### Iteration and the Power Operator" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": { 18 | "deletable": true, 19 | "editable": true 20 | }, 21 | "source": [ 22 | "### (1 of 10) ITERATION\n", 23 | "\n", 24 | "The repeated application of a function, such as doubling or halving, is called iteration. For example:" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": { 31 | "collapsed": false, 32 | "deletable": true, 33 | "editable": true 34 | }, 35 | "outputs": [], 36 | "source": [ 37 | "x=: 3" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": null, 43 | "metadata": { 44 | "collapsed": false, 45 | "deletable": true, 46 | "editable": true 47 | }, 48 | "outputs": [], 49 | "source": [ 50 | "+: x" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "metadata": { 57 | "collapsed": false, 58 | "deletable": true, 59 | "editable": true 60 | }, 61 | "outputs": [], 62 | "source": [ 63 | "+: +: x" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "metadata": { 70 | "collapsed": false, 71 | "deletable": true, 72 | "editable": true 73 | }, 74 | "outputs": [], 75 | "source": [ 76 | "+: +: +: x" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": { 83 | "collapsed": false, 84 | "deletable": true, 85 | "editable": true 86 | }, 87 | "outputs": [], 88 | "source": [ 89 | "-: x" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": null, 95 | "metadata": { 96 | "collapsed": false, 97 | "deletable": true, 98 | "editable": true 99 | }, 100 | "outputs": [], 101 | "source": [ 102 | "-: -: x" 103 | ] 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "metadata": { 108 | "deletable": true, 109 | "editable": true 110 | }, 111 | "source": [ 112 | "### (2 of 10) POWER OPERATOR\n", 113 | "\n", 114 | "The power operator ^: can be used to produce any specified number of iterations. For example:" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": null, 120 | "metadata": { 121 | "collapsed": false, 122 | "deletable": true, 123 | "editable": true 124 | }, 125 | "outputs": [], 126 | "source": [ 127 | "+:^:2 x" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "metadata": { 134 | "collapsed": false, 135 | "deletable": true, 136 | "editable": true 137 | }, 138 | "outputs": [], 139 | "source": [ 140 | "+:^:3 x" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": null, 146 | "metadata": { 147 | "collapsed": false, 148 | "deletable": true, 149 | "editable": true 150 | }, 151 | "outputs": [], 152 | "source": [ 153 | "+:^:0 1 2 3 4 x" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": null, 159 | "metadata": { 160 | "collapsed": false, 161 | "deletable": true, 162 | "editable": true 163 | }, 164 | "outputs": [], 165 | "source": [ 166 | "i=: 0 1 2 3 4" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": null, 172 | "metadata": { 173 | "collapsed": false, 174 | "deletable": true, 175 | "editable": true 176 | }, 177 | "outputs": [], 178 | "source": [ 179 | "+:^:i x" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": null, 185 | "metadata": { 186 | "collapsed": false, 187 | "deletable": true, 188 | "editable": true 189 | }, 190 | "outputs": [], 191 | "source": [ 192 | "v=: 3 4 5" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": null, 198 | "metadata": { 199 | "collapsed": false, 200 | "deletable": true, 201 | "editable": true 202 | }, 203 | "outputs": [], 204 | "source": [ 205 | "+: v" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": null, 211 | "metadata": { 212 | "collapsed": false, 213 | "deletable": true, 214 | "editable": true 215 | }, 216 | "outputs": [], 217 | "source": [ 218 | "+:^:i v" 219 | ] 220 | }, 221 | { 222 | "cell_type": "markdown", 223 | "metadata": { 224 | "deletable": true, 225 | "editable": true 226 | }, 227 | "source": [ 228 | "### (3 of 10) POWER OPERATOR (ctd)\n", 229 | "\n", 230 | "We will illustrate the use of the power operator on other functions, including the square (^&2), subtotals (+/\\), and permutations or anagrams (k&A.) .\n", 231 | "\n", 232 | "Further information on any of these expressions may be found by pressing the function key F1 to display the vocabulary, and then clicking the mouse on the desired item:" 233 | ] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": null, 238 | "metadata": { 239 | "collapsed": false, 240 | "deletable": true, 241 | "editable": true 242 | }, 243 | "outputs": [], 244 | "source": [ 245 | "^&2 ^: i i" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": null, 251 | "metadata": { 252 | "collapsed": false, 253 | "deletable": true, 254 | "editable": true 255 | }, 256 | "outputs": [], 257 | "source": [ 258 | "+/\\ ^: i i" 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "execution_count": null, 264 | "metadata": { 265 | "collapsed": false, 266 | "deletable": true, 267 | "editable": true 268 | }, 269 | "outputs": [], 270 | "source": [ 271 | "3&A.^: i i" 272 | ] 273 | }, 274 | { 275 | "cell_type": "code", 276 | "execution_count": null, 277 | "metadata": { 278 | "collapsed": false, 279 | "deletable": true, 280 | "editable": true 281 | }, 282 | "outputs": [], 283 | "source": [ 284 | "3&A.^: i 'ABCDE'" 285 | ] 286 | }, 287 | { 288 | "cell_type": "markdown", 289 | "metadata": { 290 | "deletable": true, 291 | "editable": true 292 | }, 293 | "source": [ 294 | "### (4 of 10) POWER OPERATOR (ctd)\n", 295 | "\n", 296 | "The larger powers in the table ```^&2 ^: i i``` appeared in \"scientific\" or exponential form. Such large numbers may be produced in \"extended precision\" as illustrated below:" 297 | ] 298 | }, 299 | { 300 | "cell_type": "code", 301 | "execution_count": null, 302 | "metadata": { 303 | "collapsed": false, 304 | "deletable": true, 305 | "editable": true 306 | }, 307 | "outputs": [], 308 | "source": [ 309 | "!! i" 310 | ] 311 | }, 312 | { 313 | "cell_type": "code", 314 | "execution_count": null, 315 | "metadata": { 316 | "collapsed": false, 317 | "deletable": true, 318 | "editable": true 319 | }, 320 | "outputs": [], 321 | "source": [ 322 | "!! x:i" 323 | ] 324 | }, 325 | { 326 | "cell_type": "code", 327 | "execution_count": null, 328 | "metadata": { 329 | "collapsed": false, 330 | "deletable": true, 331 | "editable": true 332 | }, 333 | "outputs": [], 334 | "source": [ 335 | "^&2 ^: i x:i" 336 | ] 337 | }, 338 | { 339 | "cell_type": "markdown", 340 | "metadata": { 341 | "deletable": true, 342 | "editable": true 343 | }, 344 | "source": [ 345 | "### (5 of 10) BINOMIAL COEFFICIENTS\n", 346 | "\n", 347 | "A table of binomial coefficients is often presented as a triangle (Pascals triangle) by suppressing the zeros that result from the number of ways that n elements can be chosen from a lesser number of items. Thus:\n", 348 | "\n", 349 | " ```1```
\n", 350 | " ```1 1```
\n", 351 | " ```1 2 1```
\n", 352 | " ```1 3 3 1```
\n", 353 | " ```1 4 6 4 1```
\n", 354 | "\n", 355 | "A row of these coefficients can be simply obtained from the preceding row, as illustrated below:" 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "execution_count": null, 361 | "metadata": { 362 | "collapsed": false, 363 | "deletable": true, 364 | "editable": true 365 | }, 366 | "outputs": [], 367 | "source": [ 368 | "r2=: 1 2 1" 369 | ] 370 | }, 371 | { 372 | "cell_type": "code", 373 | "execution_count": null, 374 | "metadata": { 375 | "collapsed": false, 376 | "deletable": true, 377 | "editable": true 378 | }, 379 | "outputs": [], 380 | "source": [ 381 | "0,r2" 382 | ] 383 | }, 384 | { 385 | "cell_type": "code", 386 | "execution_count": null, 387 | "metadata": { 388 | "collapsed": false, 389 | "deletable": true, 390 | "editable": true 391 | }, 392 | "outputs": [], 393 | "source": [ 394 | "r2,0" 395 | ] 396 | }, 397 | { 398 | "cell_type": "code", 399 | "execution_count": null, 400 | "metadata": { 401 | "collapsed": false, 402 | "deletable": true, 403 | "editable": true 404 | }, 405 | "outputs": [], 406 | "source": [ 407 | "(0,r2)+(r2,0)" 408 | ] 409 | }, 410 | { 411 | "cell_type": "markdown", 412 | "metadata": { 413 | "deletable": true, 414 | "editable": true 415 | }, 416 | "source": [ 417 | "### (6 of 10) BINOMIAL COEFFICIENTS (ctd)\n", 418 | "\n", 419 | "A function for this process may be defined and iterated as follows:" 420 | ] 421 | }, 422 | { 423 | "cell_type": "code", 424 | "execution_count": null, 425 | "metadata": { 426 | "collapsed": false, 427 | "deletable": true, 428 | "editable": true 429 | }, 430 | "outputs": [], 431 | "source": [ 432 | "next=: 0&, + ,&0" 433 | ] 434 | }, 435 | { 436 | "cell_type": "code", 437 | "execution_count": null, 438 | "metadata": { 439 | "collapsed": false, 440 | "deletable": true, 441 | "editable": true 442 | }, 443 | "outputs": [], 444 | "source": [ 445 | "next r2" 446 | ] 447 | }, 448 | { 449 | "cell_type": "code", 450 | "execution_count": null, 451 | "metadata": { 452 | "collapsed": false, 453 | "deletable": true, 454 | "editable": true 455 | }, 456 | "outputs": [], 457 | "source": [ 458 | "next 1" 459 | ] 460 | }, 461 | { 462 | "cell_type": "code", 463 | "execution_count": null, 464 | "metadata": { 465 | "collapsed": false, 466 | "deletable": true, 467 | "editable": true 468 | }, 469 | "outputs": [], 470 | "source": [ 471 | "next next 1" 472 | ] 473 | }, 474 | { 475 | "cell_type": "code", 476 | "execution_count": null, 477 | "metadata": { 478 | "collapsed": false, 479 | "deletable": true, 480 | "editable": true 481 | }, 482 | "outputs": [], 483 | "source": [ 484 | "bct=: next ^: i 1" 485 | ] 486 | }, 487 | { 488 | "cell_type": "code", 489 | "execution_count": null, 490 | "metadata": { 491 | "collapsed": false, 492 | "deletable": true, 493 | "editable": true 494 | }, 495 | "outputs": [], 496 | "source": [ 497 | "bct" 498 | ] 499 | }, 500 | { 501 | "cell_type": "markdown", 502 | "metadata": { 503 | "deletable": true, 504 | "editable": true 505 | }, 506 | "source": [ 507 | "### (7 of 10) BINOMIAL COEFFICIENTS (ctd)\n", 508 | "\n", 509 | "The operations of matrix algebra can be applied to this matrix of binomial coefficients in useful and interesting ways, as developed in a companion lab. For example, the inverse yields a table of alternating binomial coefficients:" 510 | ] 511 | }, 512 | { 513 | "cell_type": "code", 514 | "execution_count": null, 515 | "metadata": { 516 | "collapsed": false, 517 | "deletable": true, 518 | "editable": true 519 | }, 520 | "outputs": [], 521 | "source": [ 522 | "abct=: %. bct" 523 | ] 524 | }, 525 | { 526 | "cell_type": "code", 527 | "execution_count": null, 528 | "metadata": { 529 | "collapsed": false, 530 | "deletable": true, 531 | "editable": true 532 | }, 533 | "outputs": [], 534 | "source": [ 535 | "abct" 536 | ] 537 | }, 538 | { 539 | "cell_type": "code", 540 | "execution_count": null, 541 | "metadata": { 542 | "collapsed": false, 543 | "deletable": true, 544 | "editable": true 545 | }, 546 | "outputs": [], 547 | "source": [ 548 | "mp=: +/ . * NB. Matrix product" 549 | ] 550 | }, 551 | { 552 | "cell_type": "code", 553 | "execution_count": null, 554 | "metadata": { 555 | "collapsed": false, 556 | "deletable": true, 557 | "editable": true 558 | }, 559 | "outputs": [], 560 | "source": [ 561 | "bct mp abct" 562 | ] 563 | }, 564 | { 565 | "cell_type": "markdown", 566 | "metadata": { 567 | "deletable": true, 568 | "editable": true 569 | }, 570 | "source": [ 571 | "### (8 of 10) NEGATIVE POWERS\n", 572 | "\n", 573 | "Negative powers of a function yield powers of its inverse. For example:" 574 | ] 575 | }, 576 | { 577 | "cell_type": "code", 578 | "execution_count": null, 579 | "metadata": { 580 | "collapsed": false, 581 | "deletable": true, 582 | "editable": true 583 | }, 584 | "outputs": [], 585 | "source": [ 586 | "+: ^: _1 i" 587 | ] 588 | }, 589 | { 590 | "cell_type": "code", 591 | "execution_count": null, 592 | "metadata": { 593 | "collapsed": false, 594 | "deletable": true, 595 | "editable": true 596 | }, 597 | "outputs": [], 598 | "source": [ 599 | "+: ^: _2 i" 600 | ] 601 | }, 602 | { 603 | "cell_type": "code", 604 | "execution_count": null, 605 | "metadata": { 606 | "collapsed": false, 607 | "deletable": true, 608 | "editable": true 609 | }, 610 | "outputs": [], 611 | "source": [ 612 | "+/\\ ^: i i" 613 | ] 614 | }, 615 | { 616 | "cell_type": "code", 617 | "execution_count": null, 618 | "metadata": { 619 | "collapsed": false, 620 | "deletable": true, 621 | "editable": true 622 | }, 623 | "outputs": [], 624 | "source": [ 625 | "+/\\ ^: (-i) 0 1 6 21 56" 626 | ] 627 | }, 628 | { 629 | "cell_type": "markdown", 630 | "metadata": { 631 | "deletable": true, 632 | "editable": true 633 | }, 634 | "source": [ 635 | "### (9 of 10) LIMITS\n", 636 | "\n", 637 | "An iteration may approach a limiting value such that further applications of the function produce no discernible change. The cosine applied to 1 has such a property:" 638 | ] 639 | }, 640 | { 641 | "cell_type": "code", 642 | "execution_count": null, 643 | "metadata": { 644 | "collapsed": false, 645 | "deletable": true, 646 | "editable": true 647 | }, 648 | "outputs": [], 649 | "source": [ 650 | "Cos=: 2&o." 651 | ] 652 | }, 653 | { 654 | "cell_type": "code", 655 | "execution_count": null, 656 | "metadata": { 657 | "collapsed": false, 658 | "deletable": true, 659 | "editable": true 660 | }, 661 | "outputs": [], 662 | "source": [ 663 | "0 1r4p1 1p1 3r4p1 2p1 NB. Multiples of pi" 664 | ] 665 | }, 666 | { 667 | "cell_type": "code", 668 | "execution_count": null, 669 | "metadata": { 670 | "collapsed": false, 671 | "deletable": true, 672 | "editable": true 673 | }, 674 | "outputs": [], 675 | "source": [ 676 | "Cos 0 1r4p1 1p1 3r4p1 2p1" 677 | ] 678 | }, 679 | { 680 | "cell_type": "code", 681 | "execution_count": null, 682 | "metadata": { 683 | "collapsed": false, 684 | "deletable": true, 685 | "editable": true 686 | }, 687 | "outputs": [], 688 | "source": [ 689 | "i=: 0 1 2 3 4" 690 | ] 691 | }, 692 | { 693 | "cell_type": "code", 694 | "execution_count": null, 695 | "metadata": { 696 | "collapsed": false, 697 | "deletable": true, 698 | "editable": true 699 | }, 700 | "outputs": [], 701 | "source": [ 702 | "Cos^:i 1" 703 | ] 704 | }, 705 | { 706 | "cell_type": "code", 707 | "execution_count": null, 708 | "metadata": { 709 | "collapsed": false, 710 | "deletable": true, 711 | "editable": true 712 | }, 713 | "outputs": [], 714 | "source": [ 715 | "k=: i.4 5" 716 | ] 717 | }, 718 | { 719 | "cell_type": "code", 720 | "execution_count": null, 721 | "metadata": { 722 | "collapsed": false, 723 | "deletable": true, 724 | "editable": true 725 | }, 726 | "outputs": [], 727 | "source": [ 728 | "k" 729 | ] 730 | }, 731 | { 732 | "cell_type": "code", 733 | "execution_count": null, 734 | "metadata": { 735 | "collapsed": false, 736 | "deletable": true, 737 | "editable": true 738 | }, 739 | "outputs": [], 740 | "source": [ 741 | "Cos^: k 1" 742 | ] 743 | }, 744 | { 745 | "cell_type": "code", 746 | "execution_count": null, 747 | "metadata": { 748 | "collapsed": false, 749 | "deletable": true, 750 | "editable": true 751 | }, 752 | "outputs": [], 753 | "source": [ 754 | "y=: Cos^: _ (1)" 755 | ] 756 | }, 757 | { 758 | "cell_type": "code", 759 | "execution_count": null, 760 | "metadata": { 761 | "collapsed": false, 762 | "deletable": true, 763 | "editable": true 764 | }, 765 | "outputs": [], 766 | "source": [ 767 | "y" 768 | ] 769 | }, 770 | { 771 | "cell_type": "code", 772 | "execution_count": null, 773 | "metadata": { 774 | "collapsed": false, 775 | "deletable": true, 776 | "editable": true 777 | }, 778 | "outputs": [], 779 | "source": [ 780 | "Cos y" 781 | ] 782 | }, 783 | { 784 | "cell_type": "code", 785 | "execution_count": null, 786 | "metadata": { 787 | "collapsed": false, 788 | "deletable": true, 789 | "editable": true 790 | }, 791 | "outputs": [], 792 | "source": [ 793 | "y=Cos y" 794 | ] 795 | }, 796 | { 797 | "cell_type": "markdown", 798 | "metadata": { 799 | "deletable": true, 800 | "editable": true 801 | }, 802 | "source": [ 803 | "### (10 of 10) LIMITS (ctd)\n", 804 | "\n", 805 | "Since ```_``` denotes infinity, the expression Cos ^: ```_``` signifies an infinite number of iterations, but terminates automatically when two successive results agree. Consequently, the result y agrees with Cos y, and is therefore a solution of the equation expressed by the final line." 806 | ] 807 | }, 808 | { 809 | "cell_type": "markdown", 810 | "metadata": { 811 | "deletable": true, 812 | "editable": true 813 | }, 814 | "source": [ 815 | "### End of Lab" 816 | ] 817 | }, 818 | { 819 | "cell_type": "code", 820 | "execution_count": null, 821 | "metadata": { 822 | "collapsed": false, 823 | "deletable": true, 824 | "editable": true 825 | }, 826 | "outputs": [], 827 | "source": [] 828 | } 829 | ], 830 | "metadata": { 831 | "kernelspec": { 832 | "display_name": "J", 833 | "language": "J", 834 | "name": "jkernel" 835 | }, 836 | "language_info": { 837 | "file_extension": "ijs", 838 | "mimetype": "text/x-J", 839 | "name": "J" 840 | } 841 | }, 842 | "nbformat": 4, 843 | "nbformat_minor": 2 844 | } 845 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/math/Best_Fit.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# J Labs\n", 11 | "\n", 12 | "### Best Fit" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": { 18 | "deletable": true, 19 | "editable": true 20 | }, 21 | "source": [ 22 | "### (1 of 12) Best Fit to a Monomial\n", 23 | "This lab is based on an article [1] in the Computer Corner section of The College Mathematics Journal.\n", 24 | "\n", 25 | "The article deals with two methods of fitting a curve of the form y = f(x) = ax^k to a set of data points using least squares.\n", 26 | "\n", 27 | "The original article has numerical examples done with the Mathematica computer package.\n", 28 | "\n", 29 | "In this lab we show how to do the computations using the J programming language.\n", 30 | "\n", 31 | "[1] Helen Skala: \"Will the Real Best Fit Curve\n", 32 | " ```Please Stand Up?\"```
\n", 33 | " ```College Math. Journal```
\n", 34 | " ```Vol. 27, May 1996```
" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": { 40 | "deletable": true, 41 | "editable": true 42 | }, 43 | "source": [ 44 | "### (2 of 12) Two Methods\n", 45 | "Given a set of data points S = {(x```_```i,y```_```i) | i=1,...,n}, we wish to fit a curve y = f(x) = ax^k. What are the best values of a and k? We will select a and k to satisfy a least squares condition.\n", 46 | "\n", 47 | "Method 1: linear least squares on the logs of the data Because log y = log a + k log x, we can try to fit the logs of the data to a straight line with equation y = b + mx where b = log a and m = k. The least squares problem is:\n", 48 | "\n", 49 | " ```minimize sum_{i=1 to n}(b + k log x_i - log y_i)^2```
\n", 50 | "\n", 51 | "Method 2: nonlinear least squares on the original data\n", 52 | "\n", 53 | " ```minimize sum_{i=1 to n}(f(x_i) - y_i)^2```
\n", 54 | "\n", 55 | "where f(x) = ax^k" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": { 61 | "deletable": true, 62 | "editable": true 63 | }, 64 | "source": [ 65 | "### (3 of 12) Method 1:\n", 66 | "Let the given data be\n", 67 | "\n", 68 | " ```vx = 1, 2, 3, 4, 5, 10, 20```
\n", 69 | " ```vy = 6.1, 9.2, 14.1, 21.2, 30.3, 105.1, 405.2```
\n", 70 | "\n", 71 | "Compute the logs. We will use the same notation as the article and store the logs in variables xlg and ylg." 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": { 78 | "collapsed": false, 79 | "deletable": true, 80 | "editable": true 81 | }, 82 | "outputs": [], 83 | "source": [ 84 | "vx =: 1 2 3 4 5 10 20" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": null, 90 | "metadata": { 91 | "collapsed": false, 92 | "deletable": true, 93 | "editable": true 94 | }, 95 | "outputs": [], 96 | "source": [ 97 | "vy =: 6.1 9.2 14.1 21.2 30.3 105.1 405.2" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": null, 103 | "metadata": { 104 | "collapsed": false, 105 | "deletable": true, 106 | "editable": true 107 | }, 108 | "outputs": [], 109 | "source": [ 110 | "log =: ^. NB. Give the natural log function the name log" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": null, 116 | "metadata": { 117 | "collapsed": false, 118 | "deletable": true, 119 | "editable": true 120 | }, 121 | "outputs": [], 122 | "source": [ 123 | "[xlg =: log vx" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "metadata": { 130 | "collapsed": false, 131 | "deletable": true, 132 | "editable": true 133 | }, 134 | "outputs": [], 135 | "source": [ 136 | "[ylg =: log vy" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": { 142 | "deletable": true, 143 | "editable": true 144 | }, 145 | "source": [ 146 | "### (4 of 12) Method 1: (ctd)\n", 147 | "The formulas for linear least squares are well known. They are quoted in the article and then programmed in Mathematica.\n", 148 | "\n", 149 | "Here is the J version: [see below]\n", 150 | "\n", 151 | "Thus the best monomial fit is y = 3.74x^1.44 [see below]" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": null, 157 | "metadata": { 158 | "collapsed": false, 159 | "deletable": true, 160 | "editable": true 161 | }, 162 | "outputs": [], 163 | "source": [ 164 | "e =: ^ 1 NB. e = exp(1) is Euler's number" 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": null, 170 | "metadata": { 171 | "collapsed": false, 172 | "deletable": true, 173 | "editable": true 174 | }, 175 | "outputs": [], 176 | "source": [ 177 | "n =: #vx NB. n is the number of data points" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": null, 183 | "metadata": { 184 | "collapsed": false, 185 | "deletable": true, 186 | "editable": true 187 | }, 188 | "outputs": [], 189 | "source": [ 190 | "num =: (+/xlg*ylg)-(+/xlg)*(+/ylg)%n NB. +/ is summation" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": null, 196 | "metadata": { 197 | "collapsed": false, 198 | "deletable": true, 199 | "editable": true 200 | }, 201 | "outputs": [], 202 | "source": [ 203 | "den =: (+/xlg*xlg)-((+/xlg)^2)%n NB. % is division" 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "execution_count": null, 209 | "metadata": { 210 | "collapsed": false, 211 | "deletable": true, 212 | "editable": true 213 | }, 214 | "outputs": [], 215 | "source": [ 216 | "[k =: num%den" 217 | ] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "execution_count": null, 222 | "metadata": { 223 | "collapsed": false, 224 | "deletable": true, 225 | "editable": true 226 | }, 227 | "outputs": [], 228 | "source": [ 229 | "b =: ((+/ylg)-k*(+/xlg))%n" 230 | ] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "execution_count": null, 235 | "metadata": { 236 | "collapsed": false, 237 | "deletable": true, 238 | "editable": true 239 | }, 240 | "outputs": [], 241 | "source": [ 242 | "[a =: e^b" 243 | ] 244 | }, 245 | { 246 | "cell_type": "markdown", 247 | "metadata": { 248 | "deletable": true, 249 | "editable": true 250 | }, 251 | "source": [ 252 | "### (5 of 12) Method 1: (ctd)\n", 253 | "To check the quality of the fit, we can calculate the points predicted by the curve\n", 254 | "\n", 255 | " ```yp = ax^k```
\n", 256 | "\n", 257 | "and then sum of squares of the errors\n", 258 | "\n", 259 | " ```yp-vy```
\n", 260 | "\n", 261 | "The value, over 15,000, is quite large. [see below]\n", 262 | "\n", 263 | "At any time, you can interact with the lab. For example, to see the predicted values just type\n", 264 | "\n", 265 | " ```yp```
\n", 266 | "\n", 267 | "To see a list of the errors, type\n", 268 | "\n", 269 | " ```yp-vy```
" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": { 276 | "collapsed": false, 277 | "deletable": true, 278 | "editable": true 279 | }, 280 | "outputs": [], 281 | "source": [ 282 | "yp =: a*vx^k" 283 | ] 284 | }, 285 | { 286 | "cell_type": "code", 287 | "execution_count": null, 288 | "metadata": { 289 | "collapsed": false, 290 | "deletable": true, 291 | "editable": true 292 | }, 293 | "outputs": [], 294 | "source": [ 295 | "+/(yp-vy)^2" 296 | ] 297 | }, 298 | { 299 | "cell_type": "markdown", 300 | "metadata": { 301 | "deletable": true, 302 | "editable": true 303 | }, 304 | "source": [ 305 | "### (6 of 12) Shortcut for Method 1:\n", 306 | "J has a built-in linear least squares facility which we can use as an alternative to the formulas given above.\n", 307 | "\n", 308 | "Consider the matrix equation AX = B where A and B are given matrices and X is an unknown matrix. If A is a square nonsingular matrix then X = A^(-1)B. In J, the above computation of X from A and B would be written as\n", 309 | "\n", 310 | " ```X =: B %. A```
\n", 311 | "\n", 312 | "and the operation \"%.\" is called \"matrix divide\". More generally, if A has more rows than columns then B %. A is the least squares best approximation to a solution X of AX = B.\n", 313 | "\n", 314 | "With the use of matrix divide we can get a useful shortcut in method 1." 315 | ] 316 | }, 317 | { 318 | "cell_type": "markdown", 319 | "metadata": { 320 | "deletable": true, 321 | "editable": true 322 | }, 323 | "source": [ 324 | "### (7 of 12) Shortcut for Method 1: (ctd)\n", 325 | "In our case, we have n equations of the form\n", 326 | "\n", 327 | " ```(1)b + (log x_i)k = y_i```
\n", 328 | "\n", 329 | "in the two unknowns b and k. Thus to apply matrix divide:\n", 330 | "\n", 331 | " ```A = [1, log x_i], X = [b k], and B = [y_i]```
\n", 332 | "\n", 333 | "[The J code is shown below. Note that we get the same values for a and k that we had previously obtained.]" 334 | ] 335 | }, 336 | { 337 | "cell_type": "code", 338 | "execution_count": null, 339 | "metadata": { 340 | "collapsed": false, 341 | "deletable": true, 342 | "editable": true 343 | }, 344 | "outputs": [], 345 | "source": [ 346 | "A =: 1,.xlg" 347 | ] 348 | }, 349 | { 350 | "cell_type": "code", 351 | "execution_count": null, 352 | "metadata": { 353 | "collapsed": false, 354 | "deletable": true, 355 | "editable": true 356 | }, 357 | "outputs": [], 358 | "source": [ 359 | "'b k' =: ylg %. A" 360 | ] 361 | }, 362 | { 363 | "cell_type": "code", 364 | "execution_count": null, 365 | "metadata": { 366 | "collapsed": false, 367 | "deletable": true, 368 | "editable": true 369 | }, 370 | "outputs": [], 371 | "source": [ 372 | "[a =: e^b" 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "execution_count": null, 378 | "metadata": { 379 | "collapsed": false, 380 | "deletable": true, 381 | "editable": true 382 | }, 383 | "outputs": [], 384 | "source": [ 385 | "k" 386 | ] 387 | }, 388 | { 389 | "cell_type": "markdown", 390 | "metadata": { 391 | "deletable": true, 392 | "editable": true 393 | }, 394 | "source": [ 395 | "### (8 of 12) Method 2:\n", 396 | "For the nonlinear least squares version, we cannot rely on standard formulas; but we can minimize using calculus.\n", 397 | "\n", 398 | "We regard the sum of squares as a function of two variables, a and k. To minimize this function, we set the partial derivatives with respect to a and k equal to zero. This gives two equations for the two unknowns a and k.\n", 399 | "\n", 400 | "In the article, the first equation i.e. from the partial with respect to a, is solved algebraically for a in terms of k. The resulting expression is plugged into the second equation to give a single equation for k. This equation is then solved numerically using the Mathematica program FindRoot. Below is the J version for this approach." 401 | ] 402 | }, 403 | { 404 | "cell_type": "markdown", 405 | "metadata": { 406 | "deletable": true, 407 | "editable": true 408 | }, 409 | "source": [ 410 | "### (9 of 12) Method 2: (ctd)\n", 411 | "First we create a program FindRoot, an implementation of Newtons Method in J. Newtons Method applied to f involves iterating the function\n", 412 | "\n", 413 | " ```N(x) = x - f(x)/f'(x)```
\n", 414 | "\n", 415 | "starting with an initial approximation x0 to the root. Thus for some power p,\n", 416 | "\n", 417 | " ```N^p(x0)```
\n", 418 | "\n", 419 | "is an acceptable approximation to the root.\n", 420 | "\n", 421 | "In J, a function f is called a \"verb\". We define an \"adverb\" \"Nwtn\" that modifies f so that \"f Nwtn\" is the function N.\n", 422 | "\n", 423 | "We then iterate an infinite number of times. J will automatically stop the iteration when successive approximations agree to machine tolerance." 424 | ] 425 | }, 426 | { 427 | "cell_type": "code", 428 | "execution_count": null, 429 | "metadata": { 430 | "collapsed": false, 431 | "deletable": true, 432 | "editable": true 433 | }, 434 | "outputs": [], 435 | "source": [ 436 | "Nwtn =: adverb def 'y - (u y)%(u D.1 y)'" 437 | ] 438 | }, 439 | { 440 | "cell_type": "markdown", 441 | "metadata": { 442 | "deletable": true, 443 | "editable": true 444 | }, 445 | "source": [ 446 | "f Nwtn x does one iteration of Newtons method\n", 447 | "y represents the right argument x\n", 448 | "u represents the left argument f\n", 449 | "D.1 is first derivative" 450 | ] 451 | }, 452 | { 453 | "cell_type": "code", 454 | "execution_count": null, 455 | "metadata": { 456 | "collapsed": false, 457 | "deletable": true, 458 | "editable": true 459 | }, 460 | "outputs": [], 461 | "source": [ 462 | "FindRoot =: adverb def 'u Nwtn ^: _'" 463 | ] 464 | }, 465 | { 466 | "cell_type": "markdown", 467 | "metadata": { 468 | "deletable": true, 469 | "editable": true 470 | }, 471 | "source": [ 472 | "^: is power of a function (iteration)\n", 473 | "```_``` is the 'number' infinity" 474 | ] 475 | }, 476 | { 477 | "cell_type": "markdown", 478 | "metadata": { 479 | "deletable": true, 480 | "editable": true 481 | }, 482 | "source": [ 483 | "### (10 of 12) Method 2: (ctd)\n", 484 | "Next we define the function f according to the formula developed in the article. We want to solve f(k) = 0.\n", 485 | "\n", 486 | "We run the FindRoot procedure starting at 2, i.e. as was done with Mathematica in the article. The best fit curve is y = 1.36x^1.90 and the error criterion is 66.5 which is much better than the result of method 1. [See below]" 487 | ] 488 | }, 489 | { 490 | "cell_type": "code", 491 | "execution_count": null, 492 | "metadata": { 493 | "collapsed": false, 494 | "deletable": true, 495 | "editable": true 496 | }, 497 | "outputs": [], 498 | "source": [ 499 | "f =: verb define\n", 500 | "k =. y NB. y is the argument of f, renamed (local) to k\n", 501 | "c =. ((+/vy*vx^k)%(+/vx^(2*k)))*vx^k\n", 502 | "+/(c-vy)*c*xlg\n", 503 | ")" 504 | ] 505 | }, 506 | { 507 | "cell_type": "code", 508 | "execution_count": null, 509 | "metadata": { 510 | "collapsed": false, 511 | "deletable": true, 512 | "editable": true 513 | }, 514 | "outputs": [], 515 | "source": [ 516 | "[k =: f FindRoot 2" 517 | ] 518 | }, 519 | { 520 | "cell_type": "code", 521 | "execution_count": null, 522 | "metadata": { 523 | "collapsed": false, 524 | "deletable": true, 525 | "editable": true 526 | }, 527 | "outputs": [], 528 | "source": [ 529 | "[a =: (+/vy*vx^k)%(+/vx^2*k)" 530 | ] 531 | }, 532 | { 533 | "cell_type": "code", 534 | "execution_count": null, 535 | "metadata": { 536 | "collapsed": false, 537 | "deletable": true, 538 | "editable": true 539 | }, 540 | "outputs": [], 541 | "source": [ 542 | "yp =: a*vx^k" 543 | ] 544 | }, 545 | { 546 | "cell_type": "code", 547 | "execution_count": null, 548 | "metadata": { 549 | "collapsed": false, 550 | "deletable": true, 551 | "editable": true 552 | }, 553 | "outputs": [], 554 | "source": [ 555 | "+/(yp-vy)^2" 556 | ] 557 | }, 558 | { 559 | "cell_type": "markdown", 560 | "metadata": { 561 | "deletable": true, 562 | "editable": true 563 | }, 564 | "source": [ 565 | "### (11 of 12) Shortcut for Method 2:\n", 566 | "The article solved the nonlinear least squares problem by a mixture of algebraic work and numerical computer code. The purpose of the algebra was to reduce two equations in two unknowns to one equation in one unknown.\n", 567 | "\n", 568 | "It is possible to solve the problem directly on the computer by applying the Newton-Raphson method to the pair of equations. The only change necessary in the FindRoot program is to replace % (divide) by %. (matrix divide) in the Nwtn adverb. The details are shown below." 569 | ] 570 | }, 571 | { 572 | "cell_type": "code", 573 | "execution_count": null, 574 | "metadata": { 575 | "collapsed": false, 576 | "deletable": true, 577 | "editable": true 578 | }, 579 | "outputs": [], 580 | "source": [ 581 | "Nwtn =: adverb def 'y - (u y)%.(u D.1 y)'" 582 | ] 583 | }, 584 | { 585 | "cell_type": "markdown", 586 | "metadata": { 587 | "deletable": true, 588 | "editable": true 589 | }, 590 | "source": [ 591 | "f D.1 is a vector of partial of partial derivatives\n", 592 | "f D.1 D.1 is Hessian matrix of partial derivatives" 593 | ] 594 | }, 595 | { 596 | "cell_type": "code", 597 | "execution_count": null, 598 | "metadata": { 599 | "collapsed": false, 600 | "deletable": true, 601 | "editable": true 602 | }, 603 | "outputs": [], 604 | "source": [ 605 | "f =: verb define\n", 606 | "'a k' =. y\n", 607 | "yp =. a*vx^k\n", 608 | "+/(yp-vy)^2\n", 609 | ")" 610 | ] 611 | }, 612 | { 613 | "cell_type": "code", 614 | "execution_count": null, 615 | "metadata": { 616 | "collapsed": false, 617 | "deletable": true, 618 | "editable": true 619 | }, 620 | "outputs": [], 621 | "source": [ 622 | "['a k' =: f D.1 FindRoot 1 2" 623 | ] 624 | }, 625 | { 626 | "cell_type": "markdown", 627 | "metadata": { 628 | "deletable": true, 629 | "editable": true 630 | }, 631 | "source": [ 632 | "### (12 of 12) Some Limitations:\n", 633 | "We have presented FindRoot as an implementation of Newtons Method. Unfortunately, Newtons Method (especially the higher dimensional version) is very sensitive to the initial approximation. For example, the statement\n", 634 | "\n", 635 | " ```['a k' =: f D.1 FindRoot 3 2```
\n", 636 | "\n", 637 | "will not converge to finite values.\n", 638 | "\n", 639 | "We will not go into the general topic of algorithms for solving systems of nonlinear equations; but there is a simple modification of Newtons Method that helps us - we can reduce the step length of Newtons Method. This makes it slower but more stable.\n", 640 | "\n", 641 | "Let alpha be a parameter between zero and one. For alpha=1 we have the normal step length; for alpha=0.5 the step length is halved." 642 | ] 643 | }, 644 | { 645 | "cell_type": "code", 646 | "execution_count": null, 647 | "metadata": { 648 | "collapsed": false, 649 | "deletable": true, 650 | "editable": true 651 | }, 652 | "outputs": [], 653 | "source": [ 654 | "alpha =: 0.2" 655 | ] 656 | }, 657 | { 658 | "cell_type": "code", 659 | "execution_count": null, 660 | "metadata": { 661 | "collapsed": false, 662 | "deletable": true, 663 | "editable": true 664 | }, 665 | "outputs": [], 666 | "source": [ 667 | "Nwtn =: adverb def 'y - alpha*(u y)%.(u D.1 y)'" 668 | ] 669 | }, 670 | { 671 | "cell_type": "markdown", 672 | "metadata": { 673 | "deletable": true, 674 | "editable": true 675 | }, 676 | "source": [ 677 | "Search for the nonlinear solution starting\n", 678 | "at the 'linear' solution found in Method 1" 679 | ] 680 | }, 681 | { 682 | "cell_type": "code", 683 | "execution_count": null, 684 | "metadata": { 685 | "collapsed": false, 686 | "deletable": true, 687 | "editable": true 688 | }, 689 | "outputs": [], 690 | "source": [ 691 | "['a k' =: f D.1 FindRoot 3.7 1.4" 692 | ] 693 | }, 694 | { 695 | "cell_type": "markdown", 696 | "metadata": { 697 | "deletable": true, 698 | "editable": true 699 | }, 700 | "source": [ 701 | "### End of Lab" 702 | ] 703 | } 704 | ], 705 | "metadata": { 706 | "kernelspec": { 707 | "display_name": "J", 708 | "language": "J", 709 | "name": "jkernel" 710 | }, 711 | "language_info": { 712 | "file_extension": "ijs", 713 | "mimetype": "text/x-J", 714 | "name": "J" 715 | } 716 | }, 717 | "nbformat": 4, 718 | "nbformat_minor": 2 719 | } 720 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/general/The_Tower_of_Hanoi.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# J Labs\n", 11 | "\n", 12 | "### The Tower of Hanoi" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": { 18 | "deletable": true, 19 | "editable": true 20 | }, 21 | "source": [ 22 | "### (1 of 9) The Problem\n", 23 | "The Tower of Hanoi problem is to move a set of n\n", 24 | "different-sized disks from one peg to another,\n", 25 | "moving one disk at a time, using an intermediate\n", 26 | "peg if necessary. At all times no larger disk may\n", 27 | "sit on top of a smaller disk.\n", 28 | "\n", 29 | "For example, moving 3 disks from peg 0 to peg 1\n", 30 | "can be done as follows:\n", 31 | "\n", 32 | " ```move disk 0 from peg 0 to peg 1```
\n", 33 | " ```move disk 1 from peg 0 to peg 2```
\n", 34 | " ```move disk 0 from peg 1 to peg 2```
\n", 35 | " ```move disk 2 from peg 0 to peg 1```
\n", 36 | " ```move disk 0 from peg 2 to peg 0```
\n", 37 | " ```move disk 1 from peg 2 to peg 1```
\n", 38 | " ```move disk 0 from peg 0 to peg 1```
\n", 39 | "\n", 40 | "The description of the moves can be shortened if\n", 41 | "we observed that in moving a disk from peg A to\n", 42 | "peg B, it is always the top disk on peg A that\n", 43 | "is moved. Thus the 3-disk problem can be solved\n", 44 | "as follows:\n", 45 | "\n", 46 | " ```0 1```
\n", 47 | " ```0 2```
\n", 48 | " ```1 2```
\n", 49 | " ```0 1```
\n", 50 | " ```2 0```
\n", 51 | " ```2 1```
\n", 52 | " ```0 1```
\n", 53 | "\n", 54 | "Legend has it that a group of priests has been\n", 55 | "solving the 64-disk problem since the beginning\n", 56 | "of time, and when they finish, the world will\n", 57 | "come to an end." 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": { 63 | "deletable": true, 64 | "editable": true 65 | }, 66 | "source": [ 67 | "### (2 of 9) An Initial Solution\n", 68 | "There is a simple recursive solution to the n-disk\n", 69 | "problem: First, move disks 0 to n-2 from peg 0 to\n", 70 | "peg 2, then move disk n-1 from peg 0 to peg 1,\n", 71 | "then move disks 0 to n-2 from peg 2 to peg 1.\n", 72 | "If there is just one disk, the one disk can be\n", 73 | "moved from peg 0 to peg 1 straightaway.\n", 74 | "\n", 75 | "This can be implemented as a dyadic verb: the right\n", 76 | "argument is the number of disks; the left argument\n", 77 | "are 3 integers of the pegs (from, to, via)." 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": null, 83 | "metadata": { 84 | "collapsed": false, 85 | "deletable": true, 86 | "editable": true 87 | }, 88 | "outputs": [], 89 | "source": [ 90 | "H=: 4 : 0\n", 91 | " if. 1>:y do.\n", 92 | " (y,2)$x\n", 93 | " else.\n", 94 | " ((0 2 1{x) H y-1), (2{.x), ((2 1 0{x) H y-1)\n", 95 | " end.\n", 96 | ")" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": null, 102 | "metadata": { 103 | "collapsed": false, 104 | "deletable": true, 105 | "editable": true 106 | }, 107 | "outputs": [], 108 | "source": [ 109 | "0 1 2 H 3" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": { 115 | "deletable": true, 116 | "editable": true 117 | }, 118 | "source": [ 119 | "### (3 of 9) An Initial Solution (ctd)\n", 120 | "From the definition of H, it is easy to see that\n", 121 | "the n-disk problem requires <:2^n moves. If n=1,\n", 122 | "there is one move (1=<:2^1). If n=k-1 required\n", 123 | "<:2^k-1 moves, then n=k requires the following\n", 124 | "numbers of moves:\n", 125 | "\n", 126 | " ```<:2^k-1 ((0 2 1{x) H y-1)```
\n", 127 | " ```1 (2{.x)```
\n", 128 | " ```<:2^k-1 ((2 1 0{x) H y-1)```
\n", 129 | "\n", 130 | "for a total of <:2^k moves. A similar argument\n", 131 | "shows that the n-disk problem requires <:2^n calls\n", 132 | "of the verb H ." 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "metadata": { 139 | "collapsed": false, 140 | "deletable": true, 141 | "editable": true 142 | }, 143 | "outputs": [], 144 | "source": [ 145 | "0 1 2 #@H\"1 0 i.10" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": null, 151 | "metadata": { 152 | "collapsed": false, 153 | "deletable": true, 154 | "editable": true 155 | }, 156 | "outputs": [], 157 | "source": [ 158 | "<: 2 ^ i.10" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": { 164 | "deletable": true, 165 | "editable": true 166 | }, 167 | "source": [ 168 | "### (4 of 9) Singly Recursive Solutions\n", 169 | "The two recursive steps in H differ only in the\n", 170 | "labelling of the pegs. Therefore we can replace\n", 171 | "them with a single recursive call, and do two\n", 172 | "relabellings of the pegs to get the effect of two\n", 173 | "recursions. That is verb H1 below.\n", 174 | "\n", 175 | "Moreover, in verb H1 the left argument is unchanged\n", 176 | "in the recursion; that is, the left argument is\n", 177 | "always 0 1 2, and can be elided.\n", 178 | "\n", 179 | "We saw previously that on the n-disk problem the\n", 180 | "doubly recursive H required <:2^n calls. In the\n", 181 | "singly recursive H1 and H2, the n-disk problem\n", 182 | "requires n calls. Benchmarks on the 10-disk\n", 183 | "problem demonstrate the difference this makes." 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": null, 189 | "metadata": { 190 | "collapsed": false, 191 | "deletable": true, 192 | "editable": true 193 | }, 194 | "outputs": [], 195 | "source": [ 196 | "H1=: 4 : 0\n", 197 | " if. 1>:y do.\n", 198 | " (y,2)$0 1{x\n", 199 | " else.\n", 200 | " ({&0 2 1 , 0 1\"_ , {&2 1 0) x H1 y-1\n", 201 | " end.\n", 202 | ")" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": null, 208 | "metadata": { 209 | "collapsed": false, 210 | "deletable": true, 211 | "editable": true 212 | }, 213 | "outputs": [], 214 | "source": [ 215 | "H2=: 3 : 0\n", 216 | " if. 1>:y do.\n", 217 | " i.y,2\n", 218 | " else.\n", 219 | " ({&0 2 1 , 0 1\"_ , {&2 1 0) H2 y-1\n", 220 | " end.\n", 221 | ")" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": null, 227 | "metadata": { 228 | "collapsed": false, 229 | "deletable": true, 230 | "editable": true 231 | }, 232 | "outputs": [], 233 | "source": [ 234 | "0 1 2 (H -: H1)\"1 0 i.10" 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": null, 240 | "metadata": { 241 | "collapsed": false, 242 | "deletable": true, 243 | "editable": true 244 | }, 245 | "outputs": [], 246 | "source": [ 247 | "(0 1 2&H -: H2)\"0 i.10" 248 | ] 249 | }, 250 | { 251 | "cell_type": "code", 252 | "execution_count": null, 253 | "metadata": { 254 | "collapsed": false, 255 | "deletable": true, 256 | "editable": true 257 | }, 258 | "outputs": [], 259 | "source": [ 260 | "ts=: 6!:2 , 7!:2@] NB. time and space" 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": null, 266 | "metadata": { 267 | "collapsed": false, 268 | "deletable": true, 269 | "editable": true 270 | }, 271 | "outputs": [], 272 | "source": [ 273 | "ts '0 1 2 H 10'" 274 | ] 275 | }, 276 | { 277 | "cell_type": "code", 278 | "execution_count": null, 279 | "metadata": { 280 | "collapsed": false, 281 | "deletable": true, 282 | "editable": true 283 | }, 284 | "outputs": [], 285 | "source": [ 286 | "ts '0 1 2 H1 10'" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": { 293 | "collapsed": false, 294 | "deletable": true, 295 | "editable": true 296 | }, 297 | "outputs": [], 298 | "source": [ 299 | "ts 'H2 10'" 300 | ] 301 | }, 302 | { 303 | "cell_type": "markdown", 304 | "metadata": { 305 | "deletable": true, 306 | "editable": true 307 | }, 308 | "source": [ 309 | "### (5 of 9) Non-Recursive Solutions\n", 310 | "We now proceed to derive non-recursive solutions\n", 311 | "to the problem.\n", 312 | "\n", 313 | "The results of verbs H, H1, and H2 are rows of the\n", 314 | "6-row matrix A (the 6 different ways of moving from\n", 315 | "peg i to peg j where i and j can be 0, 1, or 2).\n", 316 | "Thus a more efficient representation for the\n", 317 | "solutions is to encode the moves as row indices\n", 318 | "of A, the integers from 0 to 5." 319 | ] 320 | }, 321 | { 322 | "cell_type": "code", 323 | "execution_count": null, 324 | "metadata": { 325 | "collapsed": false, 326 | "deletable": true, 327 | "editable": true 328 | }, 329 | "outputs": [], 330 | "source": [ 331 | "A=: 6 2 $ 0 1 0 2 1 0 1 2 2 0 2 1" 332 | ] 333 | }, 334 | { 335 | "cell_type": "code", 336 | "execution_count": null, 337 | "metadata": { 338 | "collapsed": false, 339 | "deletable": true, 340 | "editable": true 341 | }, 342 | "outputs": [], 343 | "source": [ 344 | "A" 345 | ] 346 | }, 347 | { 348 | "cell_type": "code", 349 | "execution_count": null, 350 | "metadata": { 351 | "collapsed": false, 352 | "deletable": true, 353 | "editable": true 354 | }, 355 | "outputs": [], 356 | "source": [ 357 | "A i. H2 1" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "metadata": { 364 | "collapsed": false, 365 | "deletable": true, 366 | "editable": true 367 | }, 368 | "outputs": [], 369 | "source": [ 370 | "A i. H2 2" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": null, 376 | "metadata": { 377 | "collapsed": false, 378 | "deletable": true, 379 | "editable": true 380 | }, 381 | "outputs": [], 382 | "source": [ 383 | "A i. H2 3" 384 | ] 385 | }, 386 | { 387 | "cell_type": "code", 388 | "execution_count": null, 389 | "metadata": { 390 | "collapsed": false, 391 | "deletable": true, 392 | "editable": true 393 | }, 394 | "outputs": [], 395 | "source": [ 396 | "A i. H2 4" 397 | ] 398 | }, 399 | { 400 | "cell_type": "code", 401 | "execution_count": null, 402 | "metadata": { 403 | "collapsed": false, 404 | "deletable": true, 405 | "editable": true 406 | }, 407 | "outputs": [], 408 | "source": [ 409 | "A i. H2 5" 410 | ] 411 | }, 412 | { 413 | "cell_type": "markdown", 414 | "metadata": { 415 | "deletable": true, 416 | "editable": true 417 | }, 418 | "source": [ 419 | "### (6 of 9) Non-Recursive Solutions (ctd)\n", 420 | "Judicious alignment of the indices reveals a pattern:\n", 421 | "\n", 422 | " ```1: 0```
\n", 423 | " ```2: 1 0 5```
\n", 424 | "\n", 425 | " ```2: 1 0 5```
\n", 426 | " ```3: 0 1 3 0 4 5 0```
\n", 427 | "\n", 428 | " ```3: 0 1 3 0 4 5 0```
\n", 429 | " ```4: 1 0 5 1 2 3 1 0 5 4 2 5 1 0 5```
\n", 430 | "\n", 431 | " ```4: 1 0 5 1 2 3 1 0 5 4 2 5 1 0 5```
\n", 432 | " ```5: 0 1 3 0 4 5 0 1 3 2 4 3 0 1 3 0 4 5 0 4 3 2 4 5 0 1 3 0 4 5 0```
\n", 433 | "\n", 434 | "To get from A i. H2 n-1 to A i. H2 n , merge\n", 435 | "(intersperse) the result for n with 1 5 2 if n is\n", 436 | "even and with 0 3 4 if n is odd. Thus:" 437 | ] 438 | }, 439 | { 440 | "cell_type": "code", 441 | "execution_count": null, 442 | "metadata": { 443 | "collapsed": false, 444 | "deletable": true, 445 | "editable": true 446 | }, 447 | "outputs": [], 448 | "source": [ 449 | "H3=: 3 : 0\n", 450 | " if. 1>:y do.\n", 451 | " y$0\n", 452 | " else.\n", 453 | " }: , ((2^y-1)$(2|y){1 5 2,:0 3 4) ,. 0,~H3 y-1\n", 454 | " end.\n", 455 | ")" 456 | ] 457 | }, 458 | { 459 | "cell_type": "code", 460 | "execution_count": null, 461 | "metadata": { 462 | "collapsed": false, 463 | "deletable": true, 464 | "editable": true 465 | }, 466 | "outputs": [], 467 | "source": [ 468 | "H3 3" 469 | ] 470 | }, 471 | { 472 | "cell_type": "code", 473 | "execution_count": null, 474 | "metadata": { 475 | "collapsed": false, 476 | "deletable": true, 477 | "editable": true 478 | }, 479 | "outputs": [], 480 | "source": [ 481 | "(A i. H2 3) -: H3 3" 482 | ] 483 | }, 484 | { 485 | "cell_type": "code", 486 | "execution_count": null, 487 | "metadata": { 488 | "collapsed": false, 489 | "deletable": true, 490 | "editable": true 491 | }, 492 | "outputs": [], 493 | "source": [ 494 | "(A&i.@H2 -: H3)\"0 i.10" 495 | ] 496 | }, 497 | { 498 | "cell_type": "markdown", 499 | "metadata": { 500 | "deletable": true, 501 | "editable": true 502 | }, 503 | "source": [ 504 | "### (7 of 9) Non-Recursive Solutions (ctd)\n", 505 | "H3 n works by appending an atom to the result of\n", 506 | "H3 n-1 ; then stitching a list, repetitions of\n", 507 | "1 5 2 or 0 3 4; then ravelling; then dropping the\n", 508 | "last (previously appended) atom.\n", 509 | "\n", 510 | "The list of numbers to be stitched (repetitions of\n", 511 | "0 3 4 or 1 5 2) depends only on n, and on H3 n-1\n", 512 | "not at all. This suggests a different method of\n", 513 | "directing the computation: Compute the lists xi\n", 514 | "of numbers to be stitched for 1, 2, 3, ..., up to n,\n", 515 | "and then apply an appropriate verb f between them:\n", 516 | "\n", 517 | " ```xn f ... f x3 f x2 f x1```
\n", 518 | " ```> f&.> / xn ; ... ; x3 ; x2 ; x1```
\n", 519 | "\n", 520 | "Moreover, we can avoid incorporating into f the\n", 521 | "appending and dropping of atoms, if we start out\n", 522 | "with an \"extra\" atom and drop it only at the end:\n", 523 | "\n", 524 | " ```> f&.> / xn ; ... ; x3 ; x2 ; x1```
\n", 525 | " ```}: > g&.> / xn ; ... ; x3 ; x2 ; x1 ; atom```
\n", 526 | "\n", 527 | "In H4 below, the verb g is ,@,. (ravel stitch)." 528 | ] 529 | }, 530 | { 531 | "cell_type": "code", 532 | "execution_count": null, 533 | "metadata": { 534 | "collapsed": false, 535 | "deletable": true, 536 | "editable": true 537 | }, 538 | "outputs": [], 539 | "source": [ 540 | "H4 =: }: @ > @ (,@,.&.>/) @ (< ,~ 2&^@i. $&.>&|. $&(0 3 4;1 5 2))" 541 | ] 542 | }, 543 | { 544 | "cell_type": "code", 545 | "execution_count": null, 546 | "metadata": { 547 | "collapsed": false, 548 | "deletable": true, 549 | "editable": true 550 | }, 551 | "outputs": [], 552 | "source": [ 553 | "(H3 -: H4)\"0 i.10" 554 | ] 555 | }, 556 | { 557 | "cell_type": "code", 558 | "execution_count": null, 559 | "metadata": { 560 | "collapsed": false, 561 | "deletable": true, 562 | "editable": true 563 | }, 564 | "outputs": [], 565 | "source": [ 566 | "arg=: < ,~ 2&^@i. $&.>&|. $&(0 3 4;1 5 2)" 567 | ] 568 | }, 569 | { 570 | "cell_type": "code", 571 | "execution_count": null, 572 | "metadata": { 573 | "collapsed": false, 574 | "deletable": true, 575 | "editable": true 576 | }, 577 | "outputs": [], 578 | "source": [ 579 | "arg 1" 580 | ] 581 | }, 582 | { 583 | "cell_type": "code", 584 | "execution_count": null, 585 | "metadata": { 586 | "collapsed": false, 587 | "deletable": true, 588 | "editable": true 589 | }, 590 | "outputs": [], 591 | "source": [ 592 | "arg 2" 593 | ] 594 | }, 595 | { 596 | "cell_type": "code", 597 | "execution_count": null, 598 | "metadata": { 599 | "collapsed": false, 600 | "deletable": true, 601 | "editable": true 602 | }, 603 | "outputs": [], 604 | "source": [ 605 | "arg 3" 606 | ] 607 | }, 608 | { 609 | "cell_type": "code", 610 | "execution_count": null, 611 | "metadata": { 612 | "collapsed": false, 613 | "deletable": true, 614 | "editable": true 615 | }, 616 | "outputs": [], 617 | "source": [ 618 | "arg 4" 619 | ] 620 | }, 621 | { 622 | "cell_type": "code", 623 | "execution_count": null, 624 | "metadata": { 625 | "collapsed": false, 626 | "deletable": true, 627 | "editable": true 628 | }, 629 | "outputs": [], 630 | "source": [ 631 | "arg 5" 632 | ] 633 | }, 634 | { 635 | "cell_type": "markdown", 636 | "metadata": { 637 | "deletable": true, 638 | "editable": true 639 | }, 640 | "source": [ 641 | "### (8 of 9) Non-Recursive Solutions (ctd)\n", 642 | "There is another possibility. The pattern in H4 is:\n", 643 | "\n", 644 | " ```}: > g&.> / xn ; ... ; x3 ; x2 ; x1 ; atom```
\n", 645 | "\n", 646 | "In an intermediate stage, when g is being applied,\n", 647 | "\n", 648 | " ```xi g yi```
\n", 649 | "\n", 650 | "g \"knows\" from yi alone what xi has to be:\n", 651 | "the length of yi determines the length of xi,\n", 652 | "and the leading atom of yi (0 or 1) determines\n", 653 | "whether 1 5 2 or 0 3 4 should be ravel-stitched.\n", 654 | "This suggests another solution: a monad is applied\n", 655 | "n times to the atom 1." 656 | ] 657 | }, 658 | { 659 | "cell_type": "code", 660 | "execution_count": null, 661 | "metadata": { 662 | "collapsed": false, 663 | "deletable": true, 664 | "editable": true 665 | }, 666 | "outputs": [], 667 | "source": [ 668 | "H5=: [: }: (,@,.~ # $ {. { (1 5 2,:0 3 4)\"_)^:(]`1:)" 669 | ] 670 | }, 671 | { 672 | "cell_type": "code", 673 | "execution_count": null, 674 | "metadata": { 675 | "collapsed": false, 676 | "deletable": true, 677 | "editable": true 678 | }, 679 | "outputs": [], 680 | "source": [ 681 | "(H4 -: H5)\"0 i.10" 682 | ] 683 | }, 684 | { 685 | "cell_type": "code", 686 | "execution_count": null, 687 | "metadata": { 688 | "collapsed": false, 689 | "deletable": true, 690 | "editable": true 691 | }, 692 | "outputs": [], 693 | "source": [ 694 | "rsa=: ,@,.~ # $ {. { (1 5 2,:0 3 4)\"_" 695 | ] 696 | }, 697 | { 698 | "cell_type": "code", 699 | "execution_count": null, 700 | "metadata": { 701 | "collapsed": false, 702 | "deletable": true, 703 | "editable": true 704 | }, 705 | "outputs": [], 706 | "source": [ 707 | "rsa 1" 708 | ] 709 | }, 710 | { 711 | "cell_type": "code", 712 | "execution_count": null, 713 | "metadata": { 714 | "collapsed": false, 715 | "deletable": true, 716 | "editable": true 717 | }, 718 | "outputs": [], 719 | "source": [ 720 | "rsa rsa 1" 721 | ] 722 | }, 723 | { 724 | "cell_type": "code", 725 | "execution_count": null, 726 | "metadata": { 727 | "collapsed": false, 728 | "deletable": true, 729 | "editable": true 730 | }, 731 | "outputs": [], 732 | "source": [ 733 | "rsa rsa rsa 1" 734 | ] 735 | }, 736 | { 737 | "cell_type": "code", 738 | "execution_count": null, 739 | "metadata": { 740 | "collapsed": false, 741 | "deletable": true, 742 | "editable": true 743 | }, 744 | "outputs": [], 745 | "source": [ 746 | "rsa^:(3) 1" 747 | ] 748 | }, 749 | { 750 | "cell_type": "code", 751 | "execution_count": null, 752 | "metadata": { 753 | "collapsed": false, 754 | "deletable": true, 755 | "editable": true 756 | }, 757 | "outputs": [], 758 | "source": [ 759 | "H5 3" 760 | ] 761 | }, 762 | { 763 | "cell_type": "markdown", 764 | "metadata": { 765 | "deletable": true, 766 | "editable": true 767 | }, 768 | "source": [ 769 | "### (9 of 9) Conclusion\n", 770 | "The Tower of Hanoi problem can be solved in a\n", 771 | "variety of ways, with a wide variation in efficiency.\n", 772 | "\n", 773 | " ```H double recursion```
\n", 774 | " ```H1 single recursion```
\n", 775 | " ```H2 single recursion monad```
\n", 776 | " ```H3 single recursion, atomic representation```
\n", 777 | " ```H4 non-recursive, insert```
\n", 778 | " ```H5 non-recursive, power```
" 779 | ] 780 | }, 781 | { 782 | "cell_type": "code", 783 | "execution_count": null, 784 | "metadata": { 785 | "collapsed": false, 786 | "deletable": true, 787 | "editable": true 788 | }, 789 | "outputs": [], 790 | "source": [ 791 | "0j8 0 \": ts;._1 '/0 1 2 H 10/0 1 2 H1 10/H2 10/H3 10/H4 10/H5 10'" 792 | ] 793 | }, 794 | { 795 | "cell_type": "markdown", 796 | "metadata": { 797 | "deletable": true, 798 | "editable": true 799 | }, 800 | "source": [ 801 | "### End of Lab" 802 | ] 803 | }, 804 | { 805 | "cell_type": "code", 806 | "execution_count": null, 807 | "metadata": { 808 | "collapsed": false, 809 | "deletable": true, 810 | "editable": true 811 | }, 812 | "outputs": [], 813 | "source": [] 814 | } 815 | ], 816 | "metadata": { 817 | "kernelspec": { 818 | "display_name": "J", 819 | "language": "J", 820 | "name": "jkernel" 821 | }, 822 | "language_info": { 823 | "file_extension": "ijs", 824 | "mimetype": "text/x-J", 825 | "name": "J" 826 | } 827 | }, 828 | "nbformat": 4, 829 | "nbformat_minor": 2 830 | } 831 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/general/Huffman_Coding.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# J Labs\n", 11 | "\n", 12 | "### Huffman Coding" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": { 18 | "deletable": true, 19 | "editable": true 20 | }, 21 | "source": [ 22 | "### (1 of 8) Introduction\n", 23 | "\n", 24 | "Huffman coding assigns codes to words in a text based on the\n", 25 | "frequency (probability, weight) of occurrence of the words,\n", 26 | "to reduce the space needed to represent the text. It exploits\n", 27 | "the disparity in word frequencies by assigning short codes\n", 28 | "to the more frequently occurring words, and conversely longer\n", 29 | "codes to the less frequently occurring words.\n", 30 | "\n", 31 | "A simplified version is presented here where the \"words\" are\n", 32 | "letters and codes are binary (lists of 0s and 1s)." 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": { 38 | "deletable": true, 39 | "editable": true 40 | }, 41 | "source": [ 42 | "### (2 of 8) Encoding\n", 43 | "\n", 44 | "The assigning of codes is done by constructing a binary tree\n", 45 | "with minimum weighted path lengths with the words at the\n", 46 | "leaves. The paths are the codes.\n", 47 | "\n", 48 | "The method is due to David A. Huffman (Kenneth E. Iverson, A\n", 49 | "Programming Language, Wiley, 1962, Section 3.4, Example 3.2;\n", 50 | "Donald Knuth, The Art of Computer Programming, Volume 1,\n", 51 | "Addison-Wesley, 1973, Section 2.3.4.5). The main logic is\n", 52 | "embodied in the recursive verb hc below. The arguments are a\n", 53 | "list of weights and a list of the corresponding subtrees.\n", 54 | "hc takes the two subtrees with the smallest weights and makes\n", 55 | "a new subtree from them, whose weight is the sum of the two\n", 56 | "weights. Initially the weights are the original frequencies\n", 57 | "and the subtrees are the original words. The recursion stops\n", 58 | "when there is just one subtree (and one weight)." 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "metadata": { 65 | "collapsed": false, 66 | "deletable": true, 67 | "editable": true 68 | }, 69 | "outputs": [], 70 | "source": [ 71 | "hc=: 4 : 0\n", 72 | " if. 1=#x do. y\n", 73 | " else. ((i{x),+/j{x) hc (i{y),: L.y NB. words are boxed not more than once\n", 91 | " w=. ,&.> y NB. standardized words\n", 92 | " assert. w -: ~.w NB. words are unique\n", 93 | " t=. 0 {:: x hc w NB. minimal weight binary tree\n", 94 | " ((< S: 0 t) i. w) { <@(1&=)@; S: 1 {:: t\n", 95 | ")" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": { 101 | "deletable": true, 102 | "editable": true 103 | }, 104 | "source": [ 105 | "### (3 of 8) Encoding (ctd)\n", 106 | "\n", 107 | "We use a small example to illustrate the workings of the\n", 108 | "Huffman encoding algorithm. The letters are a b c d e f\n", 109 | "and the corresponding frequencies are 3 1 4 1 5 9.\n", 110 | "\n", 111 | "hc constructs the minimum weighted binary tree t with\n", 112 | "the words at the leaves.\n", 113 | "\n", 114 | "< S: 0 t gives the words in left first traversal.\n", 115 | "\n", 116 | "{:: t gives the paths to the words.\n", 117 | "\n", 118 | "<@(1&=)@; S: 1 {:: t makes a list of the paths in left\n", 119 | "first order. (The 1&= makes the numbers boolean.)\n", 120 | "\n", 121 | "A final index gives the Huffman codes." 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": null, 127 | "metadata": { 128 | "collapsed": false, 129 | "deletable": true, 130 | "editable": true 131 | }, 132 | "outputs": [], 133 | "source": [ 134 | "A=: 'abcdef' NB. letters" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": null, 140 | "metadata": { 141 | "collapsed": false, 142 | "deletable": true, 143 | "editable": true 144 | }, 145 | "outputs": [], 146 | "source": [ 147 | "F=: 3 1 4 1 5 9 NB. corresponding frequencies" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": null, 153 | "metadata": { 154 | "collapsed": false, 155 | "deletable": true, 156 | "editable": true 157 | }, 158 | "outputs": [], 159 | "source": [ 160 | "] t=: 0 {:: F hc ,&.>A NB. minimum weighted binary tree" 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": null, 166 | "metadata": { 167 | "collapsed": false, 168 | "deletable": true, 169 | "editable": true 170 | }, 171 | "outputs": [], 172 | "source": [ 173 | "] a=: < S: 0 t NB. the words in left first traversal" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": null, 179 | "metadata": { 180 | "collapsed": false, 181 | "deletable": true, 182 | "editable": true 183 | }, 184 | "outputs": [], 185 | "source": [ 186 | "{:: t NB. paths to the words" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": null, 192 | "metadata": { 193 | "collapsed": false, 194 | "deletable": true, 195 | "editable": true 196 | }, 197 | "outputs": [], 198 | "source": [ 199 | "] p=: <@(1&=)@; S: 1 {:: t NB. paths in standard form" 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": null, 205 | "metadata": { 206 | "collapsed": false, 207 | "deletable": true, 208 | "editable": true 209 | }, 210 | "outputs": [], 211 | "source": [ 212 | "((;a) i. A) { p NB. Huffman codes for a b c d e f" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": null, 218 | "metadata": { 219 | "collapsed": false, 220 | "deletable": true, 221 | "editable": true 222 | }, 223 | "outputs": [], 224 | "source": [ 225 | "] H=: F hcodes A NB. Huffman codes for a b c d e f" 226 | ] 227 | }, 228 | { 229 | "cell_type": "markdown", 230 | "metadata": { 231 | "deletable": true, 232 | "editable": true 233 | }, 234 | "source": [ 235 | "### (4 of 8) Encoding (ctd)\n", 236 | "\n", 237 | "To encode a given text, find the location of each letter in\n", 238 | "the alphabet A and then index into the list of Huffman\n", 239 | "codes H. The raze of these codes is the Huffman encoding." 240 | ] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "execution_count": null, 245 | "metadata": { 246 | "collapsed": false, 247 | "deletable": true, 248 | "editable": true 249 | }, 250 | "outputs": [], 251 | "source": [ 252 | "hencode=: 4 : '(>{.x) ;@:{~ (>{:x) i. y'" 253 | ] 254 | }, 255 | { 256 | "cell_type": "code", 257 | "execution_count": null, 258 | "metadata": { 259 | "collapsed": false, 260 | "deletable": true, 261 | "editable": true 262 | }, 263 | "outputs": [], 264 | "source": [ 265 | "(A i. 'cab') { H" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": null, 271 | "metadata": { 272 | "collapsed": false, 273 | "deletable": true, 274 | "editable": true 275 | }, 276 | "outputs": [], 277 | "source": [ 278 | "; (A i. 'cab') { H" 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": null, 284 | "metadata": { 285 | "collapsed": false, 286 | "deletable": true, 287 | "editable": true 288 | }, 289 | "outputs": [], 290 | "source": [ 291 | "HA=: H;A" 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": null, 297 | "metadata": { 298 | "collapsed": false, 299 | "deletable": true, 300 | "editable": true 301 | }, 302 | "outputs": [], 303 | "source": [ 304 | "HA hencode 'cab'" 305 | ] 306 | }, 307 | { 308 | "cell_type": "markdown", 309 | "metadata": { 310 | "deletable": true, 311 | "editable": true 312 | }, 313 | "source": [ 314 | "### (5 of 8) Decoding\n", 315 | "\n", 316 | "The dyad ;: (sequential machine) facilitates conversion from\n", 317 | "Huffman codes back into the original text. The verb hst\n", 318 | "computes S and B required to effect the decoding.\n", 319 | "\n", 320 | "S is the state transition and output table (\"state table\"\n", 321 | "for short), a key item in the left argument for ;: .\n", 322 | "\n", 323 | "B is the list such that ```_```2]\\B are the letters that correspond\n", 324 | "to the entries in S. B has '```_```' for entries in S that do not\n", 325 | "correspond to any letter." 326 | ] 327 | }, 328 | { 329 | "cell_type": "markdown", 330 | "metadata": { 331 | "deletable": true, 332 | "editable": true 333 | }, 334 | "source": [ 335 | "### (6 of 8) Decoding (ctd)\n", 336 | "\n", 337 | "Each entry of the state table S is a pair of numbers of the\n", 338 | "new state and output code. The table has outer shape s,2,\n", 339 | "where s is the number of possible states and 2 is the number\n", 340 | "of possible values in Huffman codes (0 and 1).\n", 341 | "\n", 342 | "The table is constructed by considering all possible prefixes\n", 343 | "of the Huffman codes, sorted by length and value. This is\n", 344 | "the quantity p in the verb hst. (The sorting is for esthetic\n", 345 | "purposes and is not required for the correct functioning of\n", 346 | "the decoding.) 0 and 1 are then separately appended to each\n", 347 | "prefix, q in the verb hst. These correspond to the entries\n", 348 | "in S.\n", 349 | "\n", 350 | "If an entry of q is an actual Huffman code, the output code\n", 351 | "is 3 (terminate the current code word) and the new state is 0\n", 352 | "(scan for a new code word); if it does not, then the output\n", 353 | "code is 0 (continue building the current code word) and the\n", 354 | "new state is the row in q that corresponds to the abuilding\n", 355 | "code word.\n", 356 | "\n", 357 | "The last phrase below shows the correspondence between q S B;\n", 358 | "respectively, the code words, the state table (with the new\n", 359 | "state and output codes), and the original letters." 360 | ] 361 | }, 362 | { 363 | "cell_type": "code", 364 | "execution_count": null, 365 | "metadata": { 366 | "collapsed": false, 367 | "deletable": true, 368 | "editable": true 369 | }, 370 | "outputs": [], 371 | "source": [ 372 | "type =: 3!:0" 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "execution_count": null, 378 | "metadata": { 379 | "collapsed": false, 380 | "deletable": true, 381 | "editable": true 382 | }, 383 | "outputs": [], 384 | "source": [ 385 | "nullc=: '_' NB. illegal character (use {:a. in practice)" 386 | ] 387 | }, 388 | { 389 | "cell_type": "code", 390 | "execution_count": null, 391 | "metadata": { 392 | "collapsed": false, 393 | "deletable": true, 394 | "editable": true 395 | }, 396 | "outputs": [], 397 | "source": [ 398 | "hst=: 3 : 0 NB. Huffman decode state transition table\n", 399 | " 'H A'=. y\n", 400 | " assert. H-:&#A\n", 401 | " assert. (1=#$A)*. 2=type A NB. letters\n", 402 | " assert. (1=#$H)*.32=type H NB. corresponding Huffman codes\n", 403 | " assert. (1=#@$&>H)*.1=type&>H NB. H-codes are boolean lists\n", 404 | " assert. H -: ~.H NB. H-codes must be unique\n", 405 | " assert. -. a: e. H NB. H-codes must be non-empty\n", 406 | " p=. ~. a: , ; <\\@}:&.>H NB. all possible prefixes\n", 407 | " p=. p /: (#&.>p),.p NB. sorted by length and value\n", 408 | " q=. p ,&.>/ 0;1 NB. code words corresponding to S\n", 409 | " assert. H e. ,q NB. should contain all the H-codes\n", 410 | " B=. (H i.,q){A,nullc NB. plain letter for each state\n", 411 | " b=. q e. H NB. 1 iff an actual Huffman code\n", 412 | " e=. 1, }. 3 * b NB. output codes\n", 413 | " s=. (-.b) * p i. q NB. state transitions\n", 414 | " assert. -. (,&.>0 1) e. H NB. nonce error if (,0) or (,1) are H-codes\n", 415 | " S=. s,\"0 e\n", 416 | " S;B\n", 417 | ")" 418 | ] 419 | }, 420 | { 421 | "cell_type": "code", 422 | "execution_count": null, 423 | "metadata": { 424 | "collapsed": false, 425 | "deletable": true, 426 | "editable": true 427 | }, 428 | "outputs": [], 429 | "source": [ 430 | "'S B'=: SB=: hst HA" 431 | ] 432 | }, 433 | { 434 | "cell_type": "code", 435 | "execution_count": null, 436 | "metadata": { 437 | "collapsed": false, 438 | "deletable": true, 439 | "editable": true 440 | }, 441 | "outputs": [], 442 | "source": [ 443 | "$S" 444 | ] 445 | }, 446 | { 447 | "cell_type": "code", 448 | "execution_count": null, 449 | "metadata": { 450 | "collapsed": false, 451 | "deletable": true, 452 | "editable": true 453 | }, 454 | "outputs": [], 455 | "source": [ 456 | "#B" 457 | ] 458 | }, 459 | { 460 | "cell_type": "code", 461 | "execution_count": null, 462 | "metadata": { 463 | "collapsed": false, 464 | "deletable": true, 465 | "editable": true 466 | }, 467 | "outputs": [], 468 | "source": [ 469 | "(#B) = */ 2{.$S" 470 | ] 471 | }, 472 | { 473 | "cell_type": "code", 474 | "execution_count": null, 475 | "metadata": { 476 | "collapsed": false, 477 | "deletable": true, 478 | "editable": true 479 | }, 480 | "outputs": [], 481 | "source": [ 482 | "p=: ~. a: , ; <\\@}:&.>H NB. all possible prefixes" 483 | ] 484 | }, 485 | { 486 | "cell_type": "code", 487 | "execution_count": null, 488 | "metadata": { 489 | "collapsed": false, 490 | "deletable": true, 491 | "editable": true 492 | }, 493 | "outputs": [], 494 | "source": [ 495 | "p=: p /: (#&.>p),.p NB. sorted by length and value" 496 | ] 497 | }, 498 | { 499 | "cell_type": "code", 500 | "execution_count": null, 501 | "metadata": { 502 | "collapsed": false, 503 | "deletable": true, 504 | "editable": true 505 | }, 506 | "outputs": [], 507 | "source": [ 508 | "q=: p ,&.>/ 0;1 NB. code words corresponding to S" 509 | ] 510 | }, 511 | { 512 | "cell_type": "markdown", 513 | "metadata": { 514 | "deletable": true, 515 | "editable": true 516 | }, 517 | "source": [ 518 | "code words, new state and output codes, original letters" 519 | ] 520 | }, 521 | { 522 | "cell_type": "code", 523 | "execution_count": null, 524 | "metadata": { 525 | "collapsed": false, 526 | "deletable": true, 527 | "editable": true 528 | }, 529 | "outputs": [], 530 | "source": [ 531 | "(\":q),.' ',.(\":<\"1 S),.' ',.\": <\"0 ] _2 ]\\B" 532 | ] 533 | }, 534 | { 535 | "cell_type": "markdown", 536 | "metadata": { 537 | "deletable": true, 538 | "editable": true 539 | }, 540 | "source": [ 541 | "### (7 of 8) Decoding (ctd)\n", 542 | "\n", 543 | "Having the state table and corresponding letters in hand,\n", 544 | "it is a simple matter to recover the original text: run the\n", 545 | "sequential machine using function code 3 -- return as result\n", 546 | "the state table indices at the time of output -- and use\n", 547 | "the indices to index into B." 548 | ] 549 | }, 550 | { 551 | "cell_type": "code", 552 | "execution_count": null, 553 | "metadata": { 554 | "collapsed": false, 555 | "deletable": true, 556 | "editable": true 557 | }, 558 | "outputs": [], 559 | "source": [ 560 | "hdecode=: 4 : '(>{:x) {~ (3;{.x);:y'" 561 | ] 562 | }, 563 | { 564 | "cell_type": "code", 565 | "execution_count": null, 566 | "metadata": { 567 | "collapsed": false, 568 | "deletable": true, 569 | "editable": true 570 | }, 571 | "outputs": [], 572 | "source": [ 573 | "SB hdecode HA hencode 'cabbed'" 574 | ] 575 | }, 576 | { 577 | "cell_type": "markdown", 578 | "metadata": { 579 | "deletable": true, 580 | "editable": true 581 | }, 582 | "source": [ 583 | "### (8 of 8) Example\n", 584 | "\n", 585 | "Here we use a more extended example. A is a list of the\n", 586 | "space and the letters of the alphabet. F is a list of the\n", 587 | "corresponding frequencies based on the book of Isaiah in\n", 588 | "the NIV bible.\n", 589 | "\n", 590 | "For example, the space occurs 34511 times, the letter a\n", 591 | "occurs 10413 times, b 2041 times, etc. The letter z\n", 592 | "occurs 161 times, much less frequently than the letter a.\n", 593 | "\n", 594 | "H is a list of the Huffman codes for the letters A whose\n", 595 | "frequencies are F. Thus:\n", 596 | "\n", 597 | " ```letter freq hcode```
\n", 598 | "\n", 599 | " ```space 34511 0 0```
\n", 600 | " ```a 10413 1 0 0 1```
\n", 601 | " ```b 2041 0 1 1 0 0 0```
\n", 602 | " ```z 161 1 1 0 0 1 0 1 0 0 1```
\n", 603 | "\n", 604 | "The benchmarks show that hencode and hdecode are quite\n", 605 | "efficient." 606 | ] 607 | }, 608 | { 609 | "cell_type": "code", 610 | "execution_count": null, 611 | "metadata": { 612 | "collapsed": false, 613 | "deletable": true, 614 | "editable": true 615 | }, 616 | "outputs": [], 617 | "source": [ 618 | "A=: ' ',(97+i.26){a." 619 | ] 620 | }, 621 | { 622 | "cell_type": "code", 623 | "execution_count": null, 624 | "metadata": { 625 | "collapsed": false, 626 | "deletable": true, 627 | "editable": true 628 | }, 629 | "outputs": [], 630 | "source": [ 631 | "F=: 34511 10413 2041 2339 6059 17277 3241 2668 9437 9454 292 1199 7690 3306 8723 11885 2110 39 8739 8780 11621 3883 1351 3953 53 3564 161" 632 | ] 633 | }, 634 | { 635 | "cell_type": "code", 636 | "execution_count": null, 637 | "metadata": { 638 | "collapsed": false, 639 | "deletable": true, 640 | "editable": true 641 | }, 642 | "outputs": [], 643 | "source": [ 644 | "(#A) = #F" 645 | ] 646 | }, 647 | { 648 | "cell_type": "code", 649 | "execution_count": null, 650 | "metadata": { 651 | "collapsed": false, 652 | "deletable": true, 653 | "editable": true 654 | }, 655 | "outputs": [], 656 | "source": [ 657 | "H=: F hcodes A" 658 | ] 659 | }, 660 | { 661 | "cell_type": "code", 662 | "execution_count": null, 663 | "metadata": { 664 | "collapsed": false, 665 | "deletable": true, 666 | "editable": true 667 | }, 668 | "outputs": [], 669 | "source": [ 670 | "H {~ A i. ' abz'" 671 | ] 672 | }, 673 | { 674 | "cell_type": "code", 675 | "execution_count": null, 676 | "metadata": { 677 | "collapsed": false, 678 | "deletable": true, 679 | "editable": true 680 | }, 681 | "outputs": [], 682 | "source": [ 683 | "HA=: H;A" 684 | ] 685 | }, 686 | { 687 | "cell_type": "code", 688 | "execution_count": null, 689 | "metadata": { 690 | "collapsed": false, 691 | "deletable": true, 692 | "editable": true 693 | }, 694 | "outputs": [], 695 | "source": [ 696 | "t=: 'the quick brown fox jumps over the lazy dog '" 697 | ] 698 | }, 699 | { 700 | "cell_type": "code", 701 | "execution_count": null, 702 | "metadata": { 703 | "collapsed": false, 704 | "deletable": true, 705 | "editable": true 706 | }, 707 | "outputs": [], 708 | "source": [ 709 | "HA hencode t" 710 | ] 711 | }, 712 | { 713 | "cell_type": "code", 714 | "execution_count": null, 715 | "metadata": { 716 | "collapsed": false, 717 | "deletable": true, 718 | "editable": true 719 | }, 720 | "outputs": [], 721 | "source": [ 722 | "SB=: hst HA" 723 | ] 724 | }, 725 | { 726 | "cell_type": "code", 727 | "execution_count": null, 728 | "metadata": { 729 | "collapsed": false, 730 | "deletable": true, 731 | "editable": true 732 | }, 733 | "outputs": [], 734 | "source": [ 735 | "SB hdecode HA hencode t" 736 | ] 737 | }, 738 | { 739 | "cell_type": "code", 740 | "execution_count": null, 741 | "metadata": { 742 | "collapsed": false, 743 | "deletable": true, 744 | "editable": true 745 | }, 746 | "outputs": [], 747 | "source": [ 748 | "x=: 1e6 $ t" 749 | ] 750 | }, 751 | { 752 | "cell_type": "code", 753 | "execution_count": null, 754 | "metadata": { 755 | "collapsed": false, 756 | "deletable": true, 757 | "editable": true 758 | }, 759 | "outputs": [], 760 | "source": [ 761 | "# y=: HA hencode x" 762 | ] 763 | }, 764 | { 765 | "cell_type": "code", 766 | "execution_count": null, 767 | "metadata": { 768 | "collapsed": false, 769 | "deletable": true, 770 | "editable": true 771 | }, 772 | "outputs": [], 773 | "source": [ 774 | "x -: SB hdecode y" 775 | ] 776 | }, 777 | { 778 | "cell_type": "code", 779 | "execution_count": null, 780 | "metadata": { 781 | "collapsed": false, 782 | "deletable": true, 783 | "editable": true 784 | }, 785 | "outputs": [], 786 | "source": [ 787 | "ts=: 6!:2 , 7!:2@]" 788 | ] 789 | }, 790 | { 791 | "cell_type": "code", 792 | "execution_count": null, 793 | "metadata": { 794 | "collapsed": false, 795 | "deletable": true, 796 | "editable": true 797 | }, 798 | "outputs": [], 799 | "source": [ 800 | "ts 'HA hencode x'" 801 | ] 802 | }, 803 | { 804 | "cell_type": "code", 805 | "execution_count": null, 806 | "metadata": { 807 | "collapsed": false, 808 | "deletable": true, 809 | "editable": true 810 | }, 811 | "outputs": [], 812 | "source": [ 813 | "ts 'SB hdecode y'" 814 | ] 815 | }, 816 | { 817 | "cell_type": "markdown", 818 | "metadata": { 819 | "deletable": true, 820 | "editable": true 821 | }, 822 | "source": [ 823 | "### End of Lab" 824 | ] 825 | }, 826 | { 827 | "cell_type": "code", 828 | "execution_count": null, 829 | "metadata": { 830 | "collapsed": false, 831 | "deletable": true, 832 | "editable": true 833 | }, 834 | "outputs": [], 835 | "source": [] 836 | } 837 | ], 838 | "metadata": { 839 | "kernelspec": { 840 | "display_name": "J", 841 | "language": "J", 842 | "name": "jkernel" 843 | }, 844 | "language_info": { 845 | "file_extension": "ijs", 846 | "mimetype": "text/x-J", 847 | "name": "J" 848 | } 849 | }, 850 | "nbformat": 4, 851 | "nbformat_minor": 2 852 | } 853 | -------------------------------------------------------------------------------- /Jupyter_Notebook_J_Labs/math/Catalan_Numbers.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "deletable": true, 7 | "editable": true 8 | }, 9 | "source": [ 10 | "# J Labs\n", 11 | "\n", 12 | "### Catalan Numbers" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": { 18 | "deletable": true, 19 | "editable": true 20 | }, 21 | "source": [ 22 | "### (1 of 24) Introduction\n", 23 | "Catalan numbers appear in several areas of mathematics. For example, the nth Catalan number is the number of planar binary trees with n nodes, and is the number of ways of cutting up a polygon with n+2 sides into triangles by drawing non-intersecting diagonals.\n", 24 | "\n", 25 | "Catalan numbers 0-8 are: 1 1 2 5 14 42 132 429 1430\n", 26 | "\n", 27 | "The question we will look at here is how to calculate the nth Catalan number, for n taking values of 5, 10, 1000, 10000 and up." 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": { 33 | "deletable": true, 34 | "editable": true 35 | }, 36 | "source": [ 37 | "### (2 of 24) Basic Formula\n", 38 | "The formula in conventional math notation is:\n", 39 | "\n", 40 | "$$\n", 41 | "\\frac{2n!}{n!(n+1)!} \\\\\n", 42 | "$$\n", 43 | "\n", 44 | "A direct translation of the formula into J is given below, evaluated for n=5. Note that the factorial function is written !n" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": { 51 | "collapsed": false, 52 | "deletable": true, 53 | "editable": true 54 | }, 55 | "outputs": [], 56 | "source": [ 57 | "n=: 5" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": { 64 | "collapsed": false, 65 | "deletable": true, 66 | "editable": true 67 | }, 68 | "outputs": [], 69 | "source": [ 70 | "(!2*n) % (!n) * (!n+1)" 71 | ] 72 | }, 73 | { 74 | "cell_type": "markdown", 75 | "metadata": { 76 | "deletable": true, 77 | "editable": true 78 | }, 79 | "source": [ 80 | "### (3 of 24) Basic Formula (ctd)\n", 81 | "For a more efficient solution, rewrite the formula as:\n", 82 | "\n", 83 | "$$\n", 84 | "\\frac{2n!}{n!n!} \\frac{1}{(n+1)}\\\\\n", 85 | "$$\n", 86 | "\n", 87 | "and note that the first expression is the number of ways of choosing n things from 2n, which in J is the binomial coefficent: n!2*n" 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "metadata": { 93 | "deletable": true, 94 | "editable": true 95 | }, 96 | "source": [ 97 | "### (4 of 24) Basic Formula (ctd)\n", 98 | "A direct translation of this formula into J is:" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": null, 104 | "metadata": { 105 | "collapsed": false, 106 | "deletable": true, 107 | "editable": true 108 | }, 109 | "outputs": [], 110 | "source": [ 111 | "(n ! 2*n) % n+1" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "metadata": { 117 | "deletable": true, 118 | "editable": true 119 | }, 120 | "source": [ 121 | "### (5 of 24) Basic Formula (ctd)\n", 122 | "This can be simplified using +: (double) and >: (increment) as follows:" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": null, 128 | "metadata": { 129 | "collapsed": false, 130 | "deletable": true, 131 | "editable": true 132 | }, 133 | "outputs": [], 134 | "source": [ 135 | "(n ! +: n) % >: n" 136 | ] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": { 141 | "deletable": true, 142 | "editable": true 143 | }, 144 | "source": [ 145 | "### (6 of 24) Basic Formula (ctd)\n", 146 | "Try this with other values for n:" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": null, 152 | "metadata": { 153 | "collapsed": false, 154 | "deletable": true, 155 | "editable": true 156 | }, 157 | "outputs": [], 158 | "source": [ 159 | "n=: i.8" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": null, 165 | "metadata": { 166 | "collapsed": false, 167 | "deletable": true, 168 | "editable": true 169 | }, 170 | "outputs": [], 171 | "source": [ 172 | "(n ! +: n) % >: n" 173 | ] 174 | }, 175 | { 176 | "cell_type": "markdown", 177 | "metadata": { 178 | "deletable": true, 179 | "editable": true 180 | }, 181 | "source": [ 182 | "### (7 of 24) First Solution\n", 183 | "We can now define our first Catalan verb, by removing references to the argument n in the expression:\n", 184 | "\n", 185 | " ```(n ! +: n) % >: n```
\n", 186 | "\n", 187 | "and assigning the result to cat1." 188 | ] 189 | }, 190 | { 191 | "cell_type": "code", 192 | "execution_count": null, 193 | "metadata": { 194 | "collapsed": false, 195 | "deletable": true, 196 | "editable": true 197 | }, 198 | "outputs": [], 199 | "source": [ 200 | "cat1=: (! +:) % >:" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": null, 206 | "metadata": { 207 | "collapsed": false, 208 | "deletable": true, 209 | "editable": true 210 | }, 211 | "outputs": [], 212 | "source": [ 213 | "cat1 i.8" 214 | ] 215 | }, 216 | { 217 | "cell_type": "markdown", 218 | "metadata": { 219 | "deletable": true, 220 | "editable": true 221 | }, 222 | "source": [ 223 | "### (8 of 24) First Solution (ctd)\n", 224 | "To display a table of numbers, join n with cat1 n, as below:" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": null, 230 | "metadata": { 231 | "collapsed": false, 232 | "deletable": true, 233 | "editable": true 234 | }, 235 | "outputs": [], 236 | "source": [ 237 | "n=: i.8" 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": null, 243 | "metadata": { 244 | "collapsed": false, 245 | "deletable": true, 246 | "editable": true 247 | }, 248 | "outputs": [], 249 | "source": [ 250 | "n ,. cat1 n" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": null, 256 | "metadata": { 257 | "collapsed": false, 258 | "deletable": true, 259 | "editable": true 260 | }, 261 | "outputs": [], 262 | "source": [ 263 | "(,. cat1) i.8" 264 | ] 265 | }, 266 | { 267 | "cell_type": "markdown", 268 | "metadata": { 269 | "deletable": true, 270 | "editable": true 271 | }, 272 | "source": [ 273 | "### (9 of 24) First Solution (ctd)\n", 274 | "Lets now try this with n=100. This results in a big number that exceeds the standard integer representation.\n", 275 | "\n", 276 | "To calculate it accurately, use x: to convert the argument to an extended integer." 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": null, 282 | "metadata": { 283 | "collapsed": false, 284 | "deletable": true, 285 | "editable": true 286 | }, 287 | "outputs": [], 288 | "source": [ 289 | "cat1 100" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": null, 295 | "metadata": { 296 | "collapsed": false, 297 | "deletable": true, 298 | "editable": true 299 | }, 300 | "outputs": [], 301 | "source": [ 302 | "cat1 x: 100" 303 | ] 304 | }, 305 | { 306 | "cell_type": "markdown", 307 | "metadata": { 308 | "deletable": true, 309 | "editable": true 310 | }, 311 | "source": [ 312 | "### (10 of 24) Second Solution\n", 313 | "This suggests a new verb cat2, which applies x: followed by cat1." 314 | ] 315 | }, 316 | { 317 | "cell_type": "code", 318 | "execution_count": null, 319 | "metadata": { 320 | "collapsed": false, 321 | "deletable": true, 322 | "editable": true 323 | }, 324 | "outputs": [], 325 | "source": [ 326 | "cat2=: cat1 @ x:" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": null, 332 | "metadata": { 333 | "collapsed": false, 334 | "deletable": true, 335 | "editable": true 336 | }, 337 | "outputs": [], 338 | "source": [ 339 | "cat2 100" 340 | ] 341 | }, 342 | { 343 | "cell_type": "code", 344 | "execution_count": null, 345 | "metadata": { 346 | "collapsed": false, 347 | "deletable": true, 348 | "editable": true 349 | }, 350 | "outputs": [], 351 | "source": [ 352 | "(,. cat2) 100+i.10" 353 | ] 354 | }, 355 | { 356 | "cell_type": "markdown", 357 | "metadata": { 358 | "deletable": true, 359 | "editable": true 360 | }, 361 | "source": [ 362 | "### (11 of 24) Second Solution (ctd)\n", 363 | "The 1,000th catalan number has 598 digits:" 364 | ] 365 | }, 366 | { 367 | "cell_type": "code", 368 | "execution_count": null, 369 | "metadata": { 370 | "collapsed": false, 371 | "deletable": true, 372 | "editable": true 373 | }, 374 | "outputs": [], 375 | "source": [ 376 | "cat2 1000" 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "execution_count": null, 382 | "metadata": { 383 | "collapsed": false, 384 | "deletable": true, 385 | "editable": true 386 | }, 387 | "outputs": [], 388 | "source": [ 389 | "$\":cat2 1000" 390 | ] 391 | }, 392 | { 393 | "cell_type": "markdown", 394 | "metadata": { 395 | "deletable": true, 396 | "editable": true 397 | }, 398 | "source": [ 399 | "### (12 of 24) Second Solution (ctd)\n", 400 | "This can be formatted using the xfmt (extended format) utility:" 401 | ] 402 | }, 403 | { 404 | "cell_type": "code", 405 | "execution_count": null, 406 | "metadata": { 407 | "collapsed": false, 408 | "deletable": true, 409 | "editable": true 410 | }, 411 | "outputs": [], 412 | "source": [ 413 | "load 'general/misc/format'" 414 | ] 415 | }, 416 | { 417 | "cell_type": "code", 418 | "execution_count": null, 419 | "metadata": { 420 | "collapsed": false, 421 | "deletable": true, 422 | "editable": true 423 | }, 424 | "outputs": [], 425 | "source": [ 426 | "xfmt cat2 1000" 427 | ] 428 | }, 429 | { 430 | "cell_type": "markdown", 431 | "metadata": { 432 | "deletable": true, 433 | "editable": true 434 | }, 435 | "source": [ 436 | "### (13 of 24) Second Solution (ctd)\n", 437 | "Can cat2 be used to generate the 10,000th Catalan number?\n", 438 | "\n", 439 | "Yes - with a fast PC and enough memory. On the authors PC, this calculation takes just under a second and results in a number with 6,015 digits. However, it is near the limit of what can be achieved using this simple formula. If you try this, you might find that your PC runs out of memory, and starts paging memory to hard disk. This slows the calculation down enormously, and should be avoided." 440 | ] 441 | }, 442 | { 443 | "cell_type": "markdown", 444 | "metadata": { 445 | "deletable": true, 446 | "editable": true 447 | }, 448 | "source": [ 449 | "### (14 of 24) Third Solution\n", 450 | "It turns out that you can calculate !n by calculating the exponents in !n of each prime up to n, and this leads to a more efficient technique for computing the Catalan numbers where n is very large.\n", 451 | "\n", 452 | "The idea is that for each prime p up to n, you calculate a list, lp, of the prime powers of p up to n, and then the exponent of p in !n is given by:\n", 453 | "\n", 454 | " ```+/ <. n % lp```
\n", 455 | "\n", 456 | "To keep numbers small, We will illustrate this for the calculation of !100." 457 | ] 458 | }, 459 | { 460 | "cell_type": "markdown", 461 | "metadata": { 462 | "deletable": true, 463 | "editable": true 464 | }, 465 | "source": [ 466 | "### (15 of 24) Third Solution (ctd)\n", 467 | "For any prime p, the maximum power of p less than or equal to n is:\n", 468 | "\n", 469 | " ```<. p ^. n```
\n", 470 | "\n", 471 | "For example, the maximum power of 3 less than or equal to 100 is 4, and the corresponding maximum power of 7 is 2:" 472 | ] 473 | }, 474 | { 475 | "cell_type": "code", 476 | "execution_count": null, 477 | "metadata": { 478 | "collapsed": false, 479 | "deletable": true, 480 | "editable": true 481 | }, 482 | "outputs": [], 483 | "source": [ 484 | "<. 3 ^. 100" 485 | ] 486 | }, 487 | { 488 | "cell_type": "code", 489 | "execution_count": null, 490 | "metadata": { 491 | "collapsed": false, 492 | "deletable": true, 493 | "editable": true 494 | }, 495 | "outputs": [], 496 | "source": [ 497 | "3 ^ 1 2 3 4 5" 498 | ] 499 | }, 500 | { 501 | "cell_type": "code", 502 | "execution_count": null, 503 | "metadata": { 504 | "collapsed": false, 505 | "deletable": true, 506 | "editable": true 507 | }, 508 | "outputs": [], 509 | "source": [ 510 | "<. 7 ^. 100" 511 | ] 512 | }, 513 | { 514 | "cell_type": "code", 515 | "execution_count": null, 516 | "metadata": { 517 | "collapsed": false, 518 | "deletable": true, 519 | "editable": true 520 | }, 521 | "outputs": [], 522 | "source": [ 523 | "7 ^ 1 2 3" 524 | ] 525 | }, 526 | { 527 | "cell_type": "markdown", 528 | "metadata": { 529 | "deletable": true, 530 | "editable": true 531 | }, 532 | "source": [ 533 | "### (16 of 24) Third Solution (ctd)\n", 534 | "The exponent of p in !n is then:\n", 535 | "\n", 536 | " ```+/ <. n % p ^ >: i. <. p ^. n```
\n", 537 | "\n", 538 | "For example:" 539 | ] 540 | }, 541 | { 542 | "cell_type": "code", 543 | "execution_count": null, 544 | "metadata": { 545 | "collapsed": false, 546 | "deletable": true, 547 | "editable": true 548 | }, 549 | "outputs": [], 550 | "source": [ 551 | "+/ <. 100 % 3 ^ >: i. <. 3 ^. 100" 552 | ] 553 | }, 554 | { 555 | "cell_type": "markdown", 556 | "metadata": { 557 | "deletable": true, 558 | "editable": true 559 | }, 560 | "source": [ 561 | "### (17 of 24) Third Solution (ctd)\n", 562 | "As confirmation, note that 3^48 evenly divides !100, but 3^49 does not:" 563 | ] 564 | }, 565 | { 566 | "cell_type": "code", 567 | "execution_count": null, 568 | "metadata": { 569 | "collapsed": false, 570 | "deletable": true, 571 | "editable": true 572 | }, 573 | "outputs": [], 574 | "source": [ 575 | "a=: !100x" 576 | ] 577 | }, 578 | { 579 | "cell_type": "code", 580 | "execution_count": null, 581 | "metadata": { 582 | "collapsed": false, 583 | "deletable": true, 584 | "editable": true 585 | }, 586 | "outputs": [], 587 | "source": [ 588 | "b=: 3^48x" 589 | ] 590 | }, 591 | { 592 | "cell_type": "code", 593 | "execution_count": null, 594 | "metadata": { 595 | "collapsed": false, 596 | "deletable": true, 597 | "editable": true 598 | }, 599 | "outputs": [], 600 | "source": [ 601 | "a -: b * a <.@% b" 602 | ] 603 | }, 604 | { 605 | "cell_type": "code", 606 | "execution_count": null, 607 | "metadata": { 608 | "collapsed": false, 609 | "deletable": true, 610 | "editable": true 611 | }, 612 | "outputs": [], 613 | "source": [ 614 | "b=: 3^49x" 615 | ] 616 | }, 617 | { 618 | "cell_type": "code", 619 | "execution_count": null, 620 | "metadata": { 621 | "collapsed": false, 622 | "deletable": true, 623 | "editable": true 624 | }, 625 | "outputs": [], 626 | "source": [ 627 | "a -: b * a <.@% b" 628 | ] 629 | }, 630 | { 631 | "cell_type": "markdown", 632 | "metadata": { 633 | "deletable": true, 634 | "editable": true 635 | }, 636 | "source": [ 637 | "### (18 of 24) Third Solution (ctd)\n", 638 | "The formula for each prime used (as above) is:\n", 639 | "\n", 640 | " ```+/ <. n % p ^ >: i. <. p ^. n```
\n", 641 | "\n", 642 | "Since n may be an extended integer, we rewrite this to avoid floating point results as:\n", 643 | "\n", 644 | " ```+/ n <.@% p ^ >: i. p <.@^. n```
\n", 645 | "\n", 646 | "and define a corresponding verb pexp:" 647 | ] 648 | }, 649 | { 650 | "cell_type": "code", 651 | "execution_count": null, 652 | "metadata": { 653 | "collapsed": false, 654 | "deletable": true, 655 | "editable": true 656 | }, 657 | "outputs": [], 658 | "source": [ 659 | "pexp=: [: +/ ] <.@% [ ^ >: @ i. @ (<.@^.)" 660 | ] 661 | }, 662 | { 663 | "cell_type": "code", 664 | "execution_count": null, 665 | "metadata": { 666 | "collapsed": false, 667 | "deletable": true, 668 | "editable": true 669 | }, 670 | "outputs": [], 671 | "source": [ 672 | "3 pexp 100" 673 | ] 674 | }, 675 | { 676 | "cell_type": "code", 677 | "execution_count": null, 678 | "metadata": { 679 | "collapsed": false, 680 | "deletable": true, 681 | "editable": true 682 | }, 683 | "outputs": [], 684 | "source": [ 685 | "7 pexp 100" 686 | ] 687 | }, 688 | { 689 | "cell_type": "markdown", 690 | "metadata": { 691 | "deletable": true, 692 | "editable": true 693 | }, 694 | "source": [ 695 | "### (19 of 24) Third Solution (ctd)\n", 696 | "The list of primes less than or equal to n can be found using the inverse of p: the prime-producing verb.\n", 697 | "\n", 698 | "Define a verb, ple, to produce this list." 699 | ] 700 | }, 701 | { 702 | "cell_type": "code", 703 | "execution_count": null, 704 | "metadata": { 705 | "collapsed": false, 706 | "deletable": true, 707 | "editable": true 708 | }, 709 | "outputs": [], 710 | "source": [ 711 | "p: 7 NB. 7th prime" 712 | ] 713 | }, 714 | { 715 | "cell_type": "code", 716 | "execution_count": null, 717 | "metadata": { 718 | "collapsed": false, 719 | "deletable": true, 720 | "editable": true 721 | }, 722 | "outputs": [], 723 | "source": [ 724 | "p: inverse 19 NB. which prime is 19?" 725 | ] 726 | }, 727 | { 728 | "cell_type": "code", 729 | "execution_count": null, 730 | "metadata": { 731 | "collapsed": false, 732 | "deletable": true, 733 | "editable": true 734 | }, 735 | "outputs": [], 736 | "source": [ 737 | "p: i. p: inverse 19 NB. primes 0-6 (=i.7)" 738 | ] 739 | }, 740 | { 741 | "cell_type": "code", 742 | "execution_count": null, 743 | "metadata": { 744 | "collapsed": false, 745 | "deletable": true, 746 | "editable": true 747 | }, 748 | "outputs": [], 749 | "source": [ 750 | "p: i. p: inverse 20 NB. primes 0-7 (=i.8)" 751 | ] 752 | }, 753 | { 754 | "cell_type": "code", 755 | "execution_count": null, 756 | "metadata": { 757 | "collapsed": false, 758 | "deletable": true, 759 | "editable": true 760 | }, 761 | "outputs": [], 762 | "source": [ 763 | "ple=: p: @ i. @ (p: inverse) @ >:" 764 | ] 765 | }, 766 | { 767 | "cell_type": "code", 768 | "execution_count": null, 769 | "metadata": { 770 | "collapsed": false, 771 | "deletable": true, 772 | "editable": true 773 | }, 774 | "outputs": [], 775 | "source": [ 776 | "ple 19" 777 | ] 778 | }, 779 | { 780 | "cell_type": "markdown", 781 | "metadata": { 782 | "deletable": true, 783 | "editable": true 784 | }, 785 | "source": [ 786 | "### (20 of 24) Third Solution (ctd)\n", 787 | "The exponents of each prime p in !n are then given by:\n", 788 | "\n", 789 | " ```(ple n) pexp\"0 n```
\n", 790 | "\n", 791 | "Rank 0 is used to evaluate pexp on each prime in the left argument, rather than the list of primes as a whole." 792 | ] 793 | }, 794 | { 795 | "cell_type": "code", 796 | "execution_count": null, 797 | "metadata": { 798 | "collapsed": false, 799 | "deletable": true, 800 | "editable": true 801 | }, 802 | "outputs": [], 803 | "source": [ 804 | "n=: 100" 805 | ] 806 | }, 807 | { 808 | "cell_type": "code", 809 | "execution_count": null, 810 | "metadata": { 811 | "collapsed": false, 812 | "deletable": true, 813 | "editable": true 814 | }, 815 | "outputs": [], 816 | "source": [ 817 | "ple n" 818 | ] 819 | }, 820 | { 821 | "cell_type": "code", 822 | "execution_count": null, 823 | "metadata": { 824 | "collapsed": false, 825 | "deletable": true, 826 | "editable": true 827 | }, 828 | "outputs": [], 829 | "source": [ 830 | "(ple n) pexp\"0 n" 831 | ] 832 | }, 833 | { 834 | "cell_type": "markdown", 835 | "metadata": { 836 | "deletable": true, 837 | "editable": true 838 | }, 839 | "source": [ 840 | "### (21 of 24) Third Solution (ctd)\n", 841 | "The calculation of:\n", 842 | "\n", 843 | "$$\n", 844 | "\\frac{2n!}{n!(n+1)!} \\\\\n", 845 | "$$\n", 846 | "\n", 847 | "can now be done by calculating the exponents of the numerator less the exponents of the denominator, for each prime up to 2n, then taking the product of the prime powers." 848 | ] 849 | }, 850 | { 851 | "cell_type": "markdown", 852 | "metadata": { 853 | "deletable": true, 854 | "editable": true 855 | }, 856 | "source": [ 857 | "### (22 of 24) Third Solution (ctd)\n", 858 | "Therefore we define cat3 as below, and check it matches cat2:" 859 | ] 860 | }, 861 | { 862 | "cell_type": "code", 863 | "execution_count": null, 864 | "metadata": { 865 | "collapsed": false, 866 | "deletable": true, 867 | "editable": true 868 | }, 869 | "outputs": [], 870 | "source": [ 871 | "cat3=: 3 : 0\n", 872 | "p=. ple +: y\n", 873 | "e1=. p pexp\"0 +: y\n", 874 | "e2=. p pexp\"0 y\n", 875 | "e3=. p pexp\"0 >: y\n", 876 | "*/ p ^ x: e1-e2+e3\n", 877 | ")" 878 | ] 879 | }, 880 | { 881 | "cell_type": "code", 882 | "execution_count": null, 883 | "metadata": { 884 | "collapsed": false, 885 | "deletable": true, 886 | "editable": true 887 | }, 888 | "outputs": [], 889 | "source": [ 890 | "(cat2 1000) -: cat3 1000" 891 | ] 892 | }, 893 | { 894 | "cell_type": "markdown", 895 | "metadata": { 896 | "deletable": true, 897 | "editable": true 898 | }, 899 | "source": [ 900 | "### (23 of 24) Third Solution (ctd)\n", 901 | "cat3 can be used to calculate the 10,000th Catalan number.\n", 902 | "\n", 903 | "You can try larger numbers, but be warned this may take a long time, or run out of memory. On the PC of the author, cat3 100,000 takes just under 1 second and returns a result with 60,199 digits.\n", 904 | "\n", 905 | "The next section calculates cat3 10000." 906 | ] 907 | }, 908 | { 909 | "cell_type": "markdown", 910 | "metadata": { 911 | "deletable": true, 912 | "editable": true 913 | }, 914 | "source": [ 915 | "### (24 of 24) Third Solution (ctd)\n", 916 | "To see the answer in full, enter:\n", 917 | "\n", 918 | " ```xfmt a```
" 919 | ] 920 | }, 921 | { 922 | "cell_type": "code", 923 | "execution_count": null, 924 | "metadata": { 925 | "collapsed": false, 926 | "deletable": true, 927 | "editable": true 928 | }, 929 | "outputs": [], 930 | "source": [ 931 | "a=: cat3 10000" 932 | ] 933 | }, 934 | { 935 | "cell_type": "code", 936 | "execution_count": null, 937 | "metadata": { 938 | "collapsed": false, 939 | "deletable": true, 940 | "editable": true 941 | }, 942 | "outputs": [], 943 | "source": [ 944 | "$\":a" 945 | ] 946 | }, 947 | { 948 | "cell_type": "markdown", 949 | "metadata": { 950 | "deletable": true, 951 | "editable": true 952 | }, 953 | "source": [ 954 | "### End of Lab" 955 | ] 956 | }, 957 | { 958 | "cell_type": "code", 959 | "execution_count": null, 960 | "metadata": { 961 | "collapsed": false, 962 | "deletable": true, 963 | "editable": true 964 | }, 965 | "outputs": [], 966 | "source": [] 967 | } 968 | ], 969 | "metadata": { 970 | "kernelspec": { 971 | "display_name": "J", 972 | "language": "J", 973 | "name": "jkernel" 974 | }, 975 | "language_info": { 976 | "file_extension": "ijs", 977 | "mimetype": "text/x-J", 978 | "name": "J" 979 | } 980 | }, 981 | "nbformat": 4, 982 | "nbformat_minor": 2 983 | } 984 | --------------------------------------------------------------------------------