├── run_docker.sh ├── README.md ├── LICENSE ├── Dockerfile └── notebooks ├── example_Running Code.ipynb ├── example_Lecture-0-Scientific-Computing-with-Python.ipynb └── example_Lecture-5-Sympy.ipynb /run_docker.sh: -------------------------------------------------------------------------------- 1 | docker run -v $(pwd)/notebooks:/pandas/notebooks \ 2 | -p 8888:8888 \ 3 | -ti include/pandas 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | Docker image to run Pandas on iPython3. Yes Python3! 4 | 5 | ## Building the image 6 | 7 | git clone https://github.com/include/pandas.git 8 | cd pandas 9 | docker build -t include/pandas . 10 | 11 | ## Running the container 12 | 13 | ./run_docker.sh 14 | 15 | ### or manually something like: 16 | 17 | cd pandas 18 | 19 | docker run -v `pwd`/notebooks:/pandas/notebooks -p 8888:8888 -it include/pandas 20 | 21 | ## Working with iPython/Pandas 22 | 23 | 1. Point your browser to http://YOUR_IP_ADDRESS:8888 and start playing! 24 | 25 | 2. All your notebooks will not get lost after stopping Docker. They all live in 26 | your pandas/notebooks directory. 27 | 28 | 3. have fun 29 | 30 | ## Contrib 31 | 32 | * https://github.com/ipython/ipython/wiki/A-gallery-of-interesting-IPython-Notebooks 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Francisco Cabrita 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of pandas nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | MAINTAINER include 3 | 4 | ENV DEBIAN_FRONTEND noninteractive 5 | ENV LANGUAGE en_US.UTF-8 6 | ENV LANG en_US.UTF-8 7 | ENV LC_ALL en_US.UTF-8 8 | ENV IPYTHONDIR /pandas 9 | 10 | RUN apt-get update && apt-get upgrade -y && apt-get install -y language-pack-en 11 | 12 | RUN locale-gen en_US.UTF-8 && dpkg-reconfigure locales 13 | 14 | RUN apt-get install -y \ 15 | build-essential \ 16 | gcc \ 17 | make \ 18 | wget \ 19 | curl \ 20 | tmux \ 21 | git \ 22 | libxml2-dev \ 23 | libsqlite3-dev \ 24 | sqlite3 \ 25 | bzip2 \ 26 | libbz2-dev \ 27 | libfreetype6 \ 28 | libfreetype6-dev \ 29 | libpng-dev \ 30 | libzmq3-dev \ 31 | python3-software-properties \ 32 | python3-pip \ 33 | python3-requests \ 34 | python3-simplejson \ 35 | python3-imaging \ 36 | python3-zmq \ 37 | python3-numpy \ 38 | python3-pandas \ 39 | python3-scipy \ 40 | python3-jinja2 \ 41 | python3-tornado \ 42 | python3-matplotlib \ 43 | ipython3-notebook && \ 44 | apt-get clean && \ 45 | rm -rf /var/lib/apt/lists/* 46 | 47 | RUN pip3 install \ 48 | bokeh \ 49 | seaborn 50 | 51 | RUN ipython3 profile create default 52 | 53 | #RUN rm ~/.ipython/profile_default/ipython_notebook_config.py 54 | #RUN ln -s /notebooks/ipython_notebook_config.py ~/.ipython/profile_default/ipython_notebook_config.py 55 | 56 | WORKDIR /pandas 57 | 58 | EXPOSE 8888 59 | 60 | CMD ipython3 notebook \ 61 | --pylab=inline \ 62 | --ip=* \ 63 | --MappingKernelManager.time_to_dead=10 \ 64 | --MappingKernelManager.first_beat=3 \ 65 | --notebook-dir=/pandas/notebooks 66 | -------------------------------------------------------------------------------- /notebooks/example_Running Code.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Running Code" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "First and foremost, the IPython Notebook is an interactive environment for writing and running code. IPython is capable of running code in a wide range of languages. However, this notebook, and the default kernel in IPython 2.0, runs Python code." 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "## Code cells allow you to enter and run Python code" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "Run a code cell using `Shift-Enter` or pressing the button in the toolbar above:" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": null, 34 | "metadata": { 35 | "collapsed": false 36 | }, 37 | "outputs": [], 38 | "source": [ 39 | "a = 10" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": null, 45 | "metadata": { 46 | "collapsed": false 47 | }, 48 | "outputs": [], 49 | "source": [ 50 | "print(a)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "There are two other keyboard shortcuts for running code:\n", 58 | "\n", 59 | "* `Alt-Enter` runs the current cell and inserts a new one below.\n", 60 | "* `Ctrl-Enter` run the current cell and enters command mode." 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "## Managing the IPython Kernel" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "Code is run in a separate process called the IPython Kernel. The Kernel can be interrupted or restarted. Try running the following cell and then hit the button in the toolbar above." 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": { 81 | "collapsed": false 82 | }, 83 | "outputs": [], 84 | "source": [ 85 | "import time\n", 86 | "time.sleep(10)" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "If the Kernel dies you will be prompted to restart it. Here we call the low-level system libc.time routine with the wrong argument via\n", 94 | "ctypes to segfault the Python interpreter:" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": null, 100 | "metadata": { 101 | "collapsed": false 102 | }, 103 | "outputs": [], 104 | "source": [ 105 | "import sys\n", 106 | "from ctypes import CDLL\n", 107 | "# This will crash a Linux or Mac system\n", 108 | "# equivalent calls can be made on Windows\n", 109 | "dll = 'dylib' if sys.platform == 'darwin' else 'so.6'\n", 110 | "libc = CDLL(\"libc.%s\" % dll) \n", 111 | "libc.time(-1) # BOOM!!" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "metadata": {}, 117 | "source": [ 118 | "## Cell menu" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "metadata": {}, 124 | "source": [ 125 | "The \"Cell\" menu has a number of menu items for running code in different ways. These includes:\n", 126 | "\n", 127 | "* Run and Select Below\n", 128 | "* Run and Insert Below\n", 129 | "* Run All\n", 130 | "* Run All Above\n", 131 | "* Run All Below" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "## Restarting the kernels" 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "metadata": {}, 144 | "source": [ 145 | "The kernel maintains the state of a notebook's computations. You can reset this state by restarting the kernel. This is done by clicking on the in the toolbar above." 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "## sys.stdout and sys.stderr" 153 | ] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "metadata": {}, 158 | "source": [ 159 | "The stdout and stderr streams are displayed as text in the output area." 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": null, 165 | "metadata": { 166 | "collapsed": false 167 | }, 168 | "outputs": [], 169 | "source": [ 170 | "print(\"hi, stdout\")" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": null, 176 | "metadata": { 177 | "collapsed": false 178 | }, 179 | "outputs": [], 180 | "source": [ 181 | "from __future__ import print_function\n", 182 | "print('hi, stderr', file=sys.stderr)" 183 | ] 184 | }, 185 | { 186 | "cell_type": "markdown", 187 | "metadata": {}, 188 | "source": [ 189 | "## Output is asynchronous" 190 | ] 191 | }, 192 | { 193 | "cell_type": "markdown", 194 | "metadata": {}, 195 | "source": [ 196 | "All output is displayed asynchronously as it is generated in the Kernel. If you execute the next cell, you will see the output one piece at a time, not all at the end." 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": null, 202 | "metadata": { 203 | "collapsed": false 204 | }, 205 | "outputs": [], 206 | "source": [ 207 | "import time, sys\n", 208 | "for i in range(8):\n", 209 | " print(i)\n", 210 | " time.sleep(0.5)" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "metadata": {}, 216 | "source": [ 217 | "## Large outputs" 218 | ] 219 | }, 220 | { 221 | "cell_type": "markdown", 222 | "metadata": {}, 223 | "source": [ 224 | "To better handle large outputs, the output area can be collapsed. Run the following cell and then single- or double- click on the active area to the left of the output:" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": null, 230 | "metadata": { 231 | "collapsed": false 232 | }, 233 | "outputs": [], 234 | "source": [ 235 | "for i in range(50):\n", 236 | " print(i)" 237 | ] 238 | }, 239 | { 240 | "cell_type": "markdown", 241 | "metadata": {}, 242 | "source": [ 243 | "Beyond a certain point, output will scroll automatically:" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": null, 249 | "metadata": { 250 | "collapsed": false 251 | }, 252 | "outputs": [], 253 | "source": [ 254 | "for i in range(500):\n", 255 | " print(2**i - 1)" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": null, 261 | "metadata": { 262 | "collapsed": false 263 | }, 264 | "outputs": [], 265 | "source": [] 266 | } 267 | ], 268 | "metadata": { 269 | "kernelspec": { 270 | "display_name": "Python 3", 271 | "language": "python", 272 | "name": "python3" 273 | }, 274 | "language_info": { 275 | "codemirror_mode": { 276 | "name": "ipython", 277 | "version": 3 278 | }, 279 | "file_extension": ".py", 280 | "mimetype": "text/x-python", 281 | "name": "python", 282 | "nbconvert_exporter": "python", 283 | "pygments_lexer": "ipython3", 284 | "version": "3.4.3" 285 | } 286 | }, 287 | "nbformat": 4, 288 | "nbformat_minor": 0 289 | } 290 | -------------------------------------------------------------------------------- /notebooks/example_Lecture-0-Scientific-Computing-with-Python.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "" 4 | }, 5 | "nbformat": 3, 6 | "nbformat_minor": 0, 7 | "worksheets": [ 8 | { 9 | "cells": [ 10 | { 11 | "cell_type": "heading", 12 | "level": 1, 13 | "metadata": {}, 14 | "source": [ 15 | "Introduction to scientific computing with Python" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "J.R. Johansson (robert@riken.jp) http://dml.riken.jp/~rob/\n", 23 | "\n", 24 | "The latest version of this [IPython notebook](http://ipython.org/notebook.html) lecture is available at [http://github.com/jrjohansson/scientific-python-lectures](http://github.com/jrjohansson/scientific-python-lectures).\n", 25 | "\n", 26 | "The other notebooks in this lecture series are indexed at [http://jrjohansson.github.com](http://jrjohansson.github.com)." 27 | ] 28 | }, 29 | { 30 | "cell_type": "heading", 31 | "level": 2, 32 | "metadata": {}, 33 | "source": [ 34 | "The role of computing in science" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "Science has traditionally been divided into experimental and theoretical disciplines, but during the last several decades computing has emerged as a very important part of science. Scientific computing is often closely related to theory, but it also has many characteristics in common with experimental work. It is therefore often viewed as a new third branch of science. In most fields of science, computational work is an important complement to both experiments and theory, and nowadays a vast majority of both experimental and theoretical papers involve some numerical calculations, simulations or computer modeling.\n", 42 | "
\n", 43 | "\n", 44 | "
\n", 45 | "\n", 46 | "In experimental and theoretical sciences there are well established codes of conducts for how results and methods are published and made available to other scientists. For example, in theoretical sciences, derivations, proofs and other results are published in full detail, or made available upon request. Likewise, in experimental sciences, the methods used and the results are published, and all experimental data should be available upon request. It is considered unscientific to withhold crucial details in a theoretical proof or experimental method, that would hinder other scientists from replicating and reproducing the results.\n", 47 | "\n", 48 | "In computational sciences there are not yet any well established guidelines for how source code and generated data should be handled. For example, it is relatively rare that source code used in simulations for published papers are provided to readers, in contrast to the open nature of experimental and theoretical work. And it is not uncommon that source code for simulation software is withheld and considered a competitive advantage (or unnecessary to publish). \n", 49 | "\n", 50 | "However, this issue has recently started to attract increasing attention, and a number of editorials in high-profile journals have called for increased openness in computational sciences. Some prestigious journals, including Science, have even started to demand of authors to provide the source code for simulation software used in publications to readers upon request. \n", 51 | "\n", 52 | "Discussions are also ongoing on how to facilitate distribution of scientific software, for example as supplementary materials to scientific papers." 53 | ] 54 | }, 55 | { 56 | "cell_type": "heading", 57 | "level": 3, 58 | "metadata": {}, 59 | "source": [ 60 | "References" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | " * [Reproducible Research in Computational Science](http://dx.doi.org/10.1126/science.1213847), Roger D. Peng, Science 334, 1226 (2011).\n", 68 | "\n", 69 | " * [Shining Light into Black Boxes](http://dx.doi.org/10.1126/science.1218263), A. Morin et al., Science 336, 159-160 (2012).\n", 70 | " \n", 71 | " * [The case for open computer programs](http://dx.doi.org/doi:10.1038/nature10836), D.C. Ince, Nature 482, 485 (2012)." 72 | ] 73 | }, 74 | { 75 | "cell_type": "heading", 76 | "level": 2, 77 | "metadata": {}, 78 | "source": [ 79 | "Requirements on scientific computing" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "**Replication** and **reproducibility** are two of the cornerstones in the scientific method. With respect to numerical work, complying with these concepts have the following practical implications:\n", 87 | "\n", 88 | "* Replication: An author of a scientific paper that involves numerical calculations should be able to rerun the simulations and replicate the results upon request. Other scientist should also be able to perform the same calculations and obtain the same results, given the information about the methods used in a publication.\n", 89 | "\n", 90 | "* Reproducibility: The results obtained from numerical simulations should be reproducible with an independent implementation of the method, or using a different method altogether. \n", 91 | "\n", 92 | "\n", 93 | "In summary: A sound scientific result should be reproducible, and a sound scientific study should be replicable.\n", 94 | "\n", 95 | "\n", 96 | "To achieve these goals, we need to:\n", 97 | "\n", 98 | "* Keep and take note of *exactly* which source code and version that was used to produce data and figures in published papers.\n", 99 | "\n", 100 | "* Record information of which version of external software that was used. Keep access to the environment that was used.\n", 101 | "\n", 102 | "* Make sure that old codes and notes are backed up and kept for future reference. \n", 103 | "\n", 104 | "* Be ready to give additional information about the methods used, and perhaps also the simulation codes, to an interested reader who requests it (even years after the paper was published!).\n", 105 | "\n", 106 | "* Ideally codes should be published online, to make it easier for other scientists interested in the codes to access it." 107 | ] 108 | }, 109 | { 110 | "cell_type": "heading", 111 | "level": 3, 112 | "metadata": {}, 113 | "source": [ 114 | "Tools for managing source code" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "Ensuring replicability and reprodicibility of scientific simulations is a *complicated problem*, but there are good tools to help with this:\n", 122 | "\n", 123 | "* Revision Control System (RCS) software. \n", 124 | " * Good choices include:\n", 125 | " * git - http://git-scm.com\n", 126 | " * mercurial - http://mercurial.selenic.com. Also known as `hg`.\n", 127 | " * subversion - http://subversion.apache.org. Also known as `svn`.\n", 128 | "\n", 129 | "* Online repositories for source code. Available as both private and public repositories. \n", 130 | " * Some good alternatives are\n", 131 | " * Github - http://www.github.com\n", 132 | " * Bitbucket - http://www.bitbucket.com\n", 133 | " * Privately hosted repositories on the university's or department's servers.\n", 134 | "\n", 135 | "#### Note\n", 136 | "\t\n", 137 | "Repositories are also excellent for version controlling manuscripts, figures, thesis files, data files, lab logs, etc. Basically for any digital content that must be preserved and is frequently updated. Again, both public and private repositories are readily available. They are also excellent collaboration tools!" 138 | ] 139 | }, 140 | { 141 | "cell_type": "heading", 142 | "level": 2, 143 | "metadata": {}, 144 | "source": [ 145 | "What is Python?" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "[Python](http://www.python.org/) is a modern, general-purpose, object-oriented, high-level programming language.\n", 153 | "\n", 154 | "General characteristics of Python:\n", 155 | "\n", 156 | "* **clean and simple language:** Easy-to-read and intuitive code, easy-to-learn minimalistic syntax, maintainability scales well with size of projects.\n", 157 | "* **expressive language:** Fewer lines of code, fewer bugs, easier to maintain.\n", 158 | "\n", 159 | "Technical details:\n", 160 | "\n", 161 | "* **dynamically typed:** No need to define the type of variables, function arguments or return types.\n", 162 | "* **automatic memory management:** No need to explicitly allocate and deallocate memory for variables and data arrays. No memory leak bugs. \n", 163 | "* **interpreted:** No need to compile the code. The Python interpreter reads and executes the python code directly.\n", 164 | "\n", 165 | "Advantages:\n", 166 | "\n", 167 | "* The main advantage is ease of programming, minimizing the time required to develop, debug and maintain the code.\n", 168 | "* Well designed language that encourage many good programming practices:\n", 169 | " * Modular and object-oriented programming, good system for packaging and re-use of code. This often results in more transparent, maintainable and bug-free code.\n", 170 | " * Documentation tightly integrated with the code.\n", 171 | "* A large standard library, and a large collection of add-on packages.\n", 172 | "\n", 173 | "Disadvantages:\n", 174 | "\n", 175 | "* Since Python is an interpreted and dynamically typed programming language, the execution of python code can be slow compared to compiled statically typed programming languages, such as C and Fortran. \n", 176 | "* Somewhat decentralized, with different environment, packages and documentation spread out at different places. Can make it harder to get started." 177 | ] 178 | }, 179 | { 180 | "cell_type": "heading", 181 | "level": 2, 182 | "metadata": {}, 183 | "source": [ 184 | "What makes python suitable for scientific computing?" 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "\n", 192 | "\n", 193 | "* Python has a strong position in scientific computing: \n", 194 | " * Large community of users, easy to find help and documentation.\n", 195 | "\n", 196 | "* Extensive ecosystem of scientific libraries and environments\n", 197 | " * numpy: http://numpy.scipy.org - Numerical Python\n", 198 | " * scipy: http://www.scipy.org - Scientific Python\n", 199 | " * matplotlib: http://www.matplotlib.org - graphics library\n", 200 | "\n", 201 | "* Great performance due to close integration with time-tested and highly optimized codes written in C and Fortran:\n", 202 | " * blas, altas blas, lapack, arpack, Intel MKL, ...\n", 203 | "\n", 204 | "* Good support for \n", 205 | " * Parallel processing with processes and threads\n", 206 | " * Interprocess communication (MPI)\n", 207 | " * GPU computing (OpenCL and CUDA)\n", 208 | "\n", 209 | "* Readily available and suitable for use on high-performance computing clusters. \n", 210 | "\n", 211 | "* No license costs, no unnecessary use of research budget.\n" 212 | ] 213 | }, 214 | { 215 | "cell_type": "heading", 216 | "level": 3, 217 | "metadata": {}, 218 | "source": [ 219 | "The scientific python software stack" 220 | ] 221 | }, 222 | { 223 | "cell_type": "markdown", 224 | "metadata": {}, 225 | "source": [ 226 | "\n", 227 | "" 228 | ] 229 | }, 230 | { 231 | "cell_type": "heading", 232 | "level": 3, 233 | "metadata": {}, 234 | "source": [ 235 | "Python environments" 236 | ] 237 | }, 238 | { 239 | "cell_type": "markdown", 240 | "metadata": {}, 241 | "source": [ 242 | "Python is not only a programming language, but often also refers to the standard implementation of the interpreter (technically referred to as [CPython](http://en.wikipedia.org/wiki/CPython)) that actually runs the python code on a computer.\n", 243 | "\n", 244 | "There are also many different environments through which the python interpreter can be used. Each environment have different advantages and is suitable for different workflows. One strength of python is that it versatile and can be used in complementary ways, but it can be confusing for beginners so we will start with a brief survey of python environments that are useful for scientific computing." 245 | ] 246 | }, 247 | { 248 | "cell_type": "heading", 249 | "level": 3, 250 | "metadata": {}, 251 | "source": [ 252 | "Python interpreter" 253 | ] 254 | }, 255 | { 256 | "cell_type": "markdown", 257 | "metadata": {}, 258 | "source": [ 259 | "The standard way to use the Python programming language is to use the Python interpreter to run python code. The python interpreter is a program that read and execute the python code in files passed to it as arguments. At the command prompt, the command ``python`` is used to invoke the Python interpreter.\n", 260 | "\n", 261 | "For example, to run a file ``my-program.py`` that contains python code from the command prompt, use::\n", 262 | "\n", 263 | " $ python my-program.py\n", 264 | "\n", 265 | "We can also start the interpreter by simply typing ``python`` at the command line, and interactively type python code into the interpreter. \n", 266 | "\n", 267 | "\n", 268 | "\n", 269 | "\n", 270 | "\n", 271 | "This is often how we want to work when developing scientific applications, or when doing small calculations. But the standard python interpreter is not very convenient for this kind of work, due to a number of limitations." 272 | ] 273 | }, 274 | { 275 | "cell_type": "heading", 276 | "level": 3, 277 | "metadata": {}, 278 | "source": [ 279 | "IPython" 280 | ] 281 | }, 282 | { 283 | "cell_type": "markdown", 284 | "metadata": {}, 285 | "source": [ 286 | "IPython is an interactive shell that addresses the limitation of the standard python interpreter, and it is a work-horse for scientific use of python. It provides an interactive prompt to the python interpreter with a greatly improved user-friendliness.\n", 287 | "\n", 288 | "\n", 289 | "\n", 290 | "\n", 291 | "Some of the many useful features of IPython includes:\n", 292 | "\n", 293 | "* Command history, which can be browsed with the up and down arrows on the keyboard.\n", 294 | "* Tab auto-completion.\n", 295 | "* In-line editing of code.\n", 296 | "* Object introspection, and automatic extract of documentation strings from python objects like classes and functions.\n", 297 | "* Good interaction with operating system shell.\n", 298 | "* Support for multiple parallel back-end processes, that can run on computing clusters or cloud services like Amazon EE2.\n" 299 | ] 300 | }, 301 | { 302 | "cell_type": "heading", 303 | "level": 3, 304 | "metadata": {}, 305 | "source": [ 306 | "IPython notebook" 307 | ] 308 | }, 309 | { 310 | "cell_type": "markdown", 311 | "metadata": {}, 312 | "source": [ 313 | "[IPython notebook](http://ipython.org/notebook.html) is an HTML-based notebook environment for Python, similar to Mathematica or Maple. It is based on the IPython shell, but provides a cell-based environment with great interactivity, where calculations can be organized documented in a structured way.\n", 314 | "\n", 315 | "\n", 316 | "\n", 317 | "\n", 318 | "Although using the a web browser as graphical interface, IPython notebooks are usually run locally, from the same computer that run the browser. To start a new IPython notebook session, run the following command:\n", 319 | "\n", 320 | " $ ipython notebook\n", 321 | "\n", 322 | "from a directory where you want the notebooks to be stored. This will open a new browser window (or a new tab in an existing window) with an index page where existing notebooks are shown and from which new notebooks can be created." 323 | ] 324 | }, 325 | { 326 | "cell_type": "heading", 327 | "level": 3, 328 | "metadata": {}, 329 | "source": [ 330 | "Spyder" 331 | ] 332 | }, 333 | { 334 | "cell_type": "markdown", 335 | "metadata": {}, 336 | "source": [ 337 | "[Spyder](http://code.google.com/p/spyderlib/) is a MATLAB-like IDE for scientific computing with python. It has the many advantages of a traditional IDE environment, for example that everything from code editing, execution and debugging is carried out in a single environment, and work on different calculations can be organized as projects in the IDE environment.\n", 338 | "\n", 339 | "\n", 340 | "\n", 341 | "\n", 342 | "Some advantages of Spyder:\n", 343 | "\n", 344 | "* Powerful code editor, with syntax high-lighting, dynamic code introspection and integration with the python debugger.\n", 345 | "* Variable explorer, IPython command prompt.\n", 346 | "* Integrated documentation and help." 347 | ] 348 | }, 349 | { 350 | "cell_type": "heading", 351 | "level": 2, 352 | "metadata": {}, 353 | "source": [ 354 | "Versions of Python" 355 | ] 356 | }, 357 | { 358 | "cell_type": "markdown", 359 | "metadata": {}, 360 | "source": [ 361 | "There are currently two versions of python: Python 2 and Python 3. Python 3 will eventually supercede Python 2, but it is not backward-compatible with Python 2. A lot of existing python code and packages has been written for Python 2, and it is still the most wide-spread version. For these lectures either version will be fine, but it is probably easier to stick with Python 2 for now, because it is more readily available via prebuilt packages and binary installers.\n", 362 | "\n", 363 | "To see which version of Python you have, run\n", 364 | " \n", 365 | " $ python --version\n", 366 | " Python 2.7.3\n", 367 | " $ python3.2 --version\n", 368 | " Python 3.2.3\n", 369 | "\n", 370 | "Several versions of Python can be installed in parallel, as shown above.\n" 371 | ] 372 | }, 373 | { 374 | "cell_type": "heading", 375 | "level": 2, 376 | "metadata": {}, 377 | "source": [ 378 | "Installation" 379 | ] 380 | }, 381 | { 382 | "cell_type": "heading", 383 | "level": 3, 384 | "metadata": {}, 385 | "source": [ 386 | "Linux" 387 | ] 388 | }, 389 | { 390 | "cell_type": "markdown", 391 | "metadata": {}, 392 | "source": [ 393 | "In Ubuntu Linux, to installing python and all the requirements run:\n", 394 | "\n", 395 | " $ sudo apt-get install python ipython ipython-notebook\n", 396 | " $ sudo apt-get install python-numpy python-scipy python-matplotlib python-sympy\n", 397 | " $ sudo apt-get install spyder" 398 | ] 399 | }, 400 | { 401 | "cell_type": "heading", 402 | "level": 3, 403 | "metadata": {}, 404 | "source": [ 405 | "MacOS X" 406 | ] 407 | }, 408 | { 409 | "cell_type": "markdown", 410 | "metadata": {}, 411 | "source": [ 412 | "*Macports*\n", 413 | "\n", 414 | "Python is included by default in Mac OS X, but for our purposes it will be useful to install a new python environment using [Macports](http://www.macports.org/), because it makes it much easier to install all the required additional packages. Using Macports, we can install what we need with:\n", 415 | "\n", 416 | " $ sudo port install py27-ipython +pyside+notebook+parallel+scientific\n", 417 | " $ sudo port install py27-scipy py27-matplotlib py27-sympy\n", 418 | " $ sudo port install py27-spyder\n", 419 | "\n", 420 | "These will associate the commands `python` and `ipython` with the versions installed via macports (instead of the one that is shipped with Mac OS X), run the following commands:\n", 421 | "\n", 422 | " $ sudo port select python python27\n", 423 | " $ sudo port select ipython ipython27\n", 424 | "\n", 425 | "*Fink*\n", 426 | "\n", 427 | "Or, alternatively, you can use the [Fink](http://www.finkproject.org/) package manager. After installing Fink, use the following command to install python and the packages that we need:\n", 428 | "\n", 429 | " $ sudo fink install python27 ipython-py27 numpy-py27 matplotlib-py27 scipy-py27 sympy-py27\n", 430 | " $ sudo fink install spyder-mac-py27" 431 | ] 432 | }, 433 | { 434 | "cell_type": "heading", 435 | "level": 3, 436 | "metadata": {}, 437 | "source": [ 438 | "Windows" 439 | ] 440 | }, 441 | { 442 | "cell_type": "markdown", 443 | "metadata": {}, 444 | "source": [ 445 | "Windows lacks a good packaging system, so the easiest way to setup a Python environment is to install a pre-packaged distribution. Some good alternatives are:\n", 446 | "\n", 447 | " * [Enthought Python Distribution](http://www.enthought.com/products/epd.php). EPD is a commercial product but is available free for academic use.\n", 448 | " * [Anaconda CE](http://continuum.io/downloads.html). Anaconda Pro is a commercial product, but Anaconda Community Edition is free.\n", 449 | " * [Python(x,y)](http://code.google.com/p/pythonxy/). Fully open source.\n", 450 | "\n", 451 | "\n", 452 | "\n", 453 | "#### Note\n", 454 | "\n", 455 | "EPD and Anaconda CE are also available for Linux and Max OS X." 456 | ] 457 | }, 458 | { 459 | "cell_type": "heading", 460 | "level": 2, 461 | "metadata": {}, 462 | "source": [ 463 | "Further reading" 464 | ] 465 | }, 466 | { 467 | "cell_type": "markdown", 468 | "metadata": {}, 469 | "source": [ 470 | " * [Python](http://www.python.org). The official Python web site.\n", 471 | " * [Python tutorials](http://docs.python.org/2/tutorial). The official Python tutorials.\n", 472 | " * [Think Python](http://www.greenteapress.com/thinkpython). A free book on Python." 473 | ] 474 | }, 475 | { 476 | "cell_type": "heading", 477 | "level": 2, 478 | "metadata": {}, 479 | "source": [ 480 | "Python and module versions" 481 | ] 482 | }, 483 | { 484 | "cell_type": "markdown", 485 | "metadata": {}, 486 | "source": [ 487 | "Since there are several different versions of Python and each Python package has its own release cycle and version number (for example scipy, numpy, matplotlib, etc., which we installed above and will discuss in detail in the following lectures), it is important for the reproducibility of an IPython notebook to record the versions of all these different software packages. If this is done properly it will be easy to reproduce the environment that was used to run a notebook, but if not it can be hard to know what was used to produce the results in a notebook.\n", 488 | "\n", 489 | "To encourage the practice of recording Python and module versions in notebooks, I've created a simple IPython extension that produces a table with versions numbers of selected software components. I believe that it is a good practice to include this kind of table in every notebook you create. \n", 490 | "\n", 491 | "To install this IPython extension, run:" 492 | ] 493 | }, 494 | { 495 | "cell_type": "code", 496 | "collapsed": false, 497 | "input": [ 498 | "# you only need to do this once\n", 499 | "%install_ext http://raw.github.com/jrjohansson/version_information/master/version_information.py" 500 | ], 501 | "language": "python", 502 | "metadata": {}, 503 | "outputs": [ 504 | { 505 | "output_type": "stream", 506 | "stream": "stdout", 507 | "text": [ 508 | "Installed version_information.py. To use it, type:\n", 509 | " %load_ext version_information\n" 510 | ] 511 | } 512 | ], 513 | "prompt_number": 1 514 | }, 515 | { 516 | "cell_type": "markdown", 517 | "metadata": {}, 518 | "source": [ 519 | "Now, to load the extension and produce the version table" 520 | ] 521 | }, 522 | { 523 | "cell_type": "code", 524 | "collapsed": false, 525 | "input": [ 526 | "%load_ext version_information\n", 527 | "\n", 528 | "%version_information numpy, scipy, matplotlib, sympy" 529 | ], 530 | "language": "python", 531 | "metadata": {}, 532 | "outputs": [ 533 | { 534 | "html": [ 535 | "
SoftwareVersion
Python2.7.5 (default, May 19 2013, 13:26:46) [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))]
IPython0.13.2
OSposix [darwin]
numpy1.7.1
scipy0.12.0
matplotlib1.2.1
sympy0.7.2
Thu Aug 08 11:18:41 2013 JST
" 536 | ], 537 | "json": [ 538 | "{ \"Software versions\" : [{ \"module\" : \"Python\", \"version\" : \"2.7.5 (default, May 19 2013, 13:26:46) [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))]\" }, { \"module\" : \"IPython\", \"version\" : \"0.13.2\" }, { \"module\" : \"OS\", \"version\" : \"posix [darwin]\" }, { \"module\" : \"numpy\", \"version\" : \"1.7.1\" }, { \"module\" : \"scipy\", \"version\" : \"0.12.0\" }, { \"module\" : \"matplotlib\", \"version\" : \"1.2.1\" }, { \"module\" : \"sympy\", \"version\" : \"0.7.2\" } ] }" 539 | ], 540 | "latex": [ 541 | "\\begin{tabular}{|l|l|}\\hline\n", 542 | "{\\bf Software} & {\\bf Version} \\\\ \\hline\\hline\n", 543 | "Python & 2.7.5 (default, May 19 2013, 13:26:46) [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] \\\\ \\hline\n", 544 | "IPython & 0.13.2 \\\\ \\hline\n", 545 | "OS & posix [darwin] \\\\ \\hline\n", 546 | "numpy & 1.7.1 \\\\ \\hline\n", 547 | "scipy & 0.12.0 \\\\ \\hline\n", 548 | "matplotlib & 1.2.1 \\\\ \\hline\n", 549 | "sympy & 0.7.2 \\\\ \\hline\n", 550 | "\\hline \\multicolumn{2}{|l|}{Thu Aug 08 11:18:41 2013 JST} \\\\ \\hline\n", 551 | "\\end{tabular}\n" 552 | ], 553 | "metadata": {}, 554 | "output_type": "pyout", 555 | "prompt_number": 2, 556 | "text": [ 557 | "Software versions\n", 558 | "Python 2.7.5 (default, May 19 2013, 13:26:46) [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))]\n", 559 | "IPython 0.13.2\n", 560 | "OS posix [darwin]\n", 561 | "numpy 1.7.1\n", 562 | "scipy 0.12.0\n", 563 | "matplotlib 1.2.1\n", 564 | "sympy 0.7.2\n", 565 | "\n", 566 | "Thu Aug 08 11:18:41 2013 JST" 567 | ] 568 | } 569 | ], 570 | "prompt_number": 2 571 | } 572 | ], 573 | "metadata": {} 574 | } 575 | ] 576 | } -------------------------------------------------------------------------------- /notebooks/example_Lecture-5-Sympy.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "" 4 | }, 5 | "nbformat": 3, 6 | "nbformat_minor": 0, 7 | "worksheets": [ 8 | { 9 | "cells": [ 10 | { 11 | "cell_type": "heading", 12 | "level": 1, 13 | "metadata": {}, 14 | "source": [ 15 | "Sympy - Symbolic algebra in Python" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "J.R. Johansson (robert@riken.jp) http://dml.riken.jp/~rob/\n", 23 | "\n", 24 | "The latest version of this [IPython notebook](http://ipython.org/notebook.html) lecture is available at [http://github.com/jrjohansson/scientific-python-lectures](http://github.com/jrjohansson/scientific-python-lectures).\n", 25 | "\n", 26 | "The other notebooks in this lecture series are indexed at [http://jrjohansson.github.com](http://jrjohansson.github.com)." 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "collapsed": false, 32 | "input": [ 33 | "%pylab inline" 34 | ], 35 | "language": "python", 36 | "metadata": {}, 37 | "outputs": [ 38 | { 39 | "output_type": "stream", 40 | "stream": "stdout", 41 | "text": [ 42 | "\n", 43 | "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.kernel.zmq.pylab.backend_inline].\n", 44 | "For more information, type 'help(pylab)'.\n" 45 | ] 46 | } 47 | ], 48 | "prompt_number": 1 49 | }, 50 | { 51 | "cell_type": "heading", 52 | "level": 2, 53 | "metadata": {}, 54 | "source": [ 55 | "Introduction" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "There are two notable Computer Algebra Systems (CAS) for Python:\n", 63 | "\n", 64 | "* [SymPy](http://sympy.org/en/index.html) - A python module that can be used in any Python program, or in an IPython session, that provides powerful CAS features. \n", 65 | "* [Sage](http://www.sagemath.org/) - Sage is a full-featured and very powerful CAS enviroment that aims to provide an open source system that competes with Mathematica and Maple. Sage is not a regular Python module, but rather a CAS environment that uses Python as its programming language.\n", 66 | "\n", 67 | "Sage is in some aspects more powerful than SymPy, but both offer very comprehensive CAS functionality. The advantage of SymPy is that it is a regular Python module and integrates well with the IPython notebook. \n", 68 | "\n", 69 | "In this lecture we will therefore look at how to use SymPy with IPython notebooks. If you are interested in an open source CAS environment I also recommend to read more about Sage.\n", 70 | "\n", 71 | "To get started using SymPy in a Python program or notebook, import the module `sympy`:" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "collapsed": false, 77 | "input": [ 78 | "from sympy import *" 79 | ], 80 | "language": "python", 81 | "metadata": {}, 82 | "outputs": [], 83 | "prompt_number": 2 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "To get nice-looking $\\LaTeX$ formatted output run:" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "collapsed": false, 95 | "input": [ 96 | "init_printing()\n", 97 | "\n", 98 | "# or with older versions of sympy/ipython, load the IPython extension\n", 99 | "#%load_ext sympy.interactive.ipythonprinting\n", 100 | "# or\n", 101 | "#%load_ext sympyprinting" 102 | ], 103 | "language": "python", 104 | "metadata": {}, 105 | "outputs": [], 106 | "prompt_number": 3 107 | }, 108 | { 109 | "cell_type": "heading", 110 | "level": 2, 111 | "metadata": {}, 112 | "source": [ 113 | "Symbolic variables" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "In SymPy we need to create symbols for the variables we want to work with. We can create a new symbol using the `Symbol` class:" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "collapsed": false, 126 | "input": [ 127 | "x = Symbol('x')" 128 | ], 129 | "language": "python", 130 | "metadata": {}, 131 | "outputs": [], 132 | "prompt_number": 4 133 | }, 134 | { 135 | "cell_type": "code", 136 | "collapsed": false, 137 | "input": [ 138 | "(pi + x)**2" 139 | ], 140 | "language": "python", 141 | "metadata": {}, 142 | "outputs": [ 143 | { 144 | "latex": [ 145 | "$$\\left(x + \\pi\\right)^{2}$$" 146 | ], 147 | "metadata": {}, 148 | "output_type": "pyout", 149 | "prompt_number": 5, 150 | "text": [ 151 | " 2\n", 152 | "(x + \u03c0) " 153 | ] 154 | } 155 | ], 156 | "prompt_number": 5 157 | }, 158 | { 159 | "cell_type": "code", 160 | "collapsed": false, 161 | "input": [ 162 | "# alternative way of defining symbols\n", 163 | "a, b, c = symbols(\"a, b, c\")" 164 | ], 165 | "language": "python", 166 | "metadata": {}, 167 | "outputs": [], 168 | "prompt_number": 6 169 | }, 170 | { 171 | "cell_type": "code", 172 | "collapsed": false, 173 | "input": [ 174 | "type(a)" 175 | ], 176 | "language": "python", 177 | "metadata": {}, 178 | "outputs": [ 179 | { 180 | "metadata": {}, 181 | "output_type": "pyout", 182 | "prompt_number": 7, 183 | "text": [ 184 | "sympy.core.symbol.Symbol" 185 | ] 186 | } 187 | ], 188 | "prompt_number": 7 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "We can add assumptions to symbols when we create them:" 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "collapsed": false, 200 | "input": [ 201 | "x = Symbol('x', real=True)" 202 | ], 203 | "language": "python", 204 | "metadata": {}, 205 | "outputs": [], 206 | "prompt_number": 8 207 | }, 208 | { 209 | "cell_type": "code", 210 | "collapsed": false, 211 | "input": [ 212 | "x.is_imaginary" 213 | ], 214 | "language": "python", 215 | "metadata": {}, 216 | "outputs": [ 217 | { 218 | "latex": [ 219 | "$$False$$" 220 | ], 221 | "metadata": {}, 222 | "output_type": "pyout", 223 | "prompt_number": 9, 224 | "text": [ 225 | "False" 226 | ] 227 | } 228 | ], 229 | "prompt_number": 9 230 | }, 231 | { 232 | "cell_type": "code", 233 | "collapsed": false, 234 | "input": [ 235 | "x = Symbol('x', positive=True)" 236 | ], 237 | "language": "python", 238 | "metadata": {}, 239 | "outputs": [], 240 | "prompt_number": 10 241 | }, 242 | { 243 | "cell_type": "code", 244 | "collapsed": false, 245 | "input": [ 246 | "x > 0" 247 | ], 248 | "language": "python", 249 | "metadata": {}, 250 | "outputs": [ 251 | { 252 | "latex": [ 253 | "$$True$$" 254 | ], 255 | "metadata": {}, 256 | "output_type": "pyout", 257 | "prompt_number": 11, 258 | "text": [ 259 | "True" 260 | ] 261 | } 262 | ], 263 | "prompt_number": 11 264 | }, 265 | { 266 | "cell_type": "heading", 267 | "level": 3, 268 | "metadata": {}, 269 | "source": [ 270 | "Complex numbers" 271 | ] 272 | }, 273 | { 274 | "cell_type": "markdown", 275 | "metadata": {}, 276 | "source": [ 277 | "The imaginary unit is denoted `I` in Sympy. " 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "collapsed": false, 283 | "input": [ 284 | "1+1*I" 285 | ], 286 | "language": "python", 287 | "metadata": {}, 288 | "outputs": [ 289 | { 290 | "latex": [ 291 | "$$1 + i$$" 292 | ], 293 | "metadata": {}, 294 | "output_type": "pyout", 295 | "prompt_number": 12, 296 | "text": [ 297 | "1 + \u2148" 298 | ] 299 | } 300 | ], 301 | "prompt_number": 12 302 | }, 303 | { 304 | "cell_type": "code", 305 | "collapsed": false, 306 | "input": [ 307 | "I**2" 308 | ], 309 | "language": "python", 310 | "metadata": {}, 311 | "outputs": [ 312 | { 313 | "latex": [ 314 | "$$-1$$" 315 | ], 316 | "metadata": {}, 317 | "output_type": "pyout", 318 | "prompt_number": 13, 319 | "text": [ 320 | "-1" 321 | ] 322 | } 323 | ], 324 | "prompt_number": 13 325 | }, 326 | { 327 | "cell_type": "code", 328 | "collapsed": false, 329 | "input": [ 330 | "(x * I + 1)**2" 331 | ], 332 | "language": "python", 333 | "metadata": {}, 334 | "outputs": [ 335 | { 336 | "latex": [ 337 | "$$\\left(i x + 1\\right)^{2}$$" 338 | ], 339 | "metadata": {}, 340 | "output_type": "pyout", 341 | "prompt_number": 14, 342 | "text": [ 343 | " 2\n", 344 | "(\u2148\u22c5x + 1) " 345 | ] 346 | } 347 | ], 348 | "prompt_number": 14 349 | }, 350 | { 351 | "cell_type": "heading", 352 | "level": 3, 353 | "metadata": {}, 354 | "source": [ 355 | "Rational numbers" 356 | ] 357 | }, 358 | { 359 | "cell_type": "markdown", 360 | "metadata": {}, 361 | "source": [ 362 | "There are three different numerical types in SymPy: `Real`, `Rational`, `Integer`: " 363 | ] 364 | }, 365 | { 366 | "cell_type": "code", 367 | "collapsed": false, 368 | "input": [ 369 | "r1 = Rational(4,5)\n", 370 | "r2 = Rational(5,4)" 371 | ], 372 | "language": "python", 373 | "metadata": {}, 374 | "outputs": [], 375 | "prompt_number": 15 376 | }, 377 | { 378 | "cell_type": "code", 379 | "collapsed": false, 380 | "input": [ 381 | "r1" 382 | ], 383 | "language": "python", 384 | "metadata": {}, 385 | "outputs": [ 386 | { 387 | "latex": [ 388 | "$$\\frac{4}{5}$$" 389 | ], 390 | "metadata": {}, 391 | "output_type": "pyout", 392 | "prompt_number": 16, 393 | "text": [ 394 | "4/5" 395 | ] 396 | } 397 | ], 398 | "prompt_number": 16 399 | }, 400 | { 401 | "cell_type": "code", 402 | "collapsed": false, 403 | "input": [ 404 | "r1+r2" 405 | ], 406 | "language": "python", 407 | "metadata": {}, 408 | "outputs": [ 409 | { 410 | "latex": [ 411 | "$$\\frac{41}{20}$$" 412 | ], 413 | "metadata": {}, 414 | "output_type": "pyout", 415 | "prompt_number": 17, 416 | "text": [ 417 | "41\n", 418 | "\u2500\u2500\n", 419 | "20" 420 | ] 421 | } 422 | ], 423 | "prompt_number": 17 424 | }, 425 | { 426 | "cell_type": "code", 427 | "collapsed": false, 428 | "input": [ 429 | "r1/r2" 430 | ], 431 | "language": "python", 432 | "metadata": {}, 433 | "outputs": [ 434 | { 435 | "latex": [ 436 | "$$\\frac{16}{25}$$" 437 | ], 438 | "metadata": {}, 439 | "output_type": "pyout", 440 | "prompt_number": 18, 441 | "text": [ 442 | "16\n", 443 | "\u2500\u2500\n", 444 | "25" 445 | ] 446 | } 447 | ], 448 | "prompt_number": 18 449 | }, 450 | { 451 | "cell_type": "heading", 452 | "level": 2, 453 | "metadata": {}, 454 | "source": [ 455 | "Numerical evaluation" 456 | ] 457 | }, 458 | { 459 | "cell_type": "markdown", 460 | "metadata": {}, 461 | "source": [ 462 | "SymPy uses a library for artitrary precision as numerical backend, and has predefined SymPy expressions for a number of mathematical constants, such as: `pi`, `e`, `oo` for infinity.\n", 463 | "\n", 464 | "To evaluate an expression numerically we can use the `evalf` function (or `N`). It takes an argument `n` which specifies the number of significant digits." 465 | ] 466 | }, 467 | { 468 | "cell_type": "code", 469 | "collapsed": false, 470 | "input": [ 471 | "pi.evalf(n=50)" 472 | ], 473 | "language": "python", 474 | "metadata": {}, 475 | "outputs": [ 476 | { 477 | "latex": [ 478 | "$$3.1415926535897932384626433832795028841971693993751$$" 479 | ], 480 | "metadata": {}, 481 | "output_type": "pyout", 482 | "prompt_number": 19, 483 | "text": [ 484 | "3.1415926535897932384626433832795028841971693993751" 485 | ] 486 | } 487 | ], 488 | "prompt_number": 19 489 | }, 490 | { 491 | "cell_type": "code", 492 | "collapsed": false, 493 | "input": [ 494 | "y = (x + pi)**2" 495 | ], 496 | "language": "python", 497 | "metadata": {}, 498 | "outputs": [], 499 | "prompt_number": 20 500 | }, 501 | { 502 | "cell_type": "code", 503 | "collapsed": false, 504 | "input": [ 505 | "N(y, 5) # same as evalf" 506 | ], 507 | "language": "python", 508 | "metadata": {}, 509 | "outputs": [ 510 | { 511 | "latex": [ 512 | "$$\\left(x + 3.1416\\right)^{2}$$" 513 | ], 514 | "metadata": {}, 515 | "output_type": "pyout", 516 | "prompt_number": 21, 517 | "text": [ 518 | " 2\n", 519 | "(x + 3.1416) " 520 | ] 521 | } 522 | ], 523 | "prompt_number": 21 524 | }, 525 | { 526 | "cell_type": "markdown", 527 | "metadata": {}, 528 | "source": [ 529 | "When we numerically evaluate algebraic expressions we often want to substitute a symbol with a numerical value. In SymPy we do that using the `subs` function:" 530 | ] 531 | }, 532 | { 533 | "cell_type": "code", 534 | "collapsed": false, 535 | "input": [ 536 | "y.subs(x, 1.5)" 537 | ], 538 | "language": "python", 539 | "metadata": {}, 540 | "outputs": [ 541 | { 542 | "latex": [ 543 | "$$\\left(1.5 + \\pi\\right)^{2}$$" 544 | ], 545 | "metadata": {}, 546 | "output_type": "pyout", 547 | "prompt_number": 22, 548 | "text": [ 549 | " 2\n", 550 | "(1.5 + \u03c0) " 551 | ] 552 | } 553 | ], 554 | "prompt_number": 22 555 | }, 556 | { 557 | "cell_type": "code", 558 | "collapsed": false, 559 | "input": [ 560 | "N(y.subs(x, 1.5))" 561 | ], 562 | "language": "python", 563 | "metadata": {}, 564 | "outputs": [ 565 | { 566 | "latex": [ 567 | "$$21.5443823618587$$" 568 | ], 569 | "metadata": {}, 570 | "output_type": "pyout", 571 | "prompt_number": 23, 572 | "text": [ 573 | "21.5443823618587" 574 | ] 575 | } 576 | ], 577 | "prompt_number": 23 578 | }, 579 | { 580 | "cell_type": "markdown", 581 | "metadata": {}, 582 | "source": [ 583 | "The `subs` function can of course also be used to substitute Symbols and expressions:" 584 | ] 585 | }, 586 | { 587 | "cell_type": "code", 588 | "collapsed": false, 589 | "input": [ 590 | "y.subs(x, a+pi)" 591 | ], 592 | "language": "python", 593 | "metadata": {}, 594 | "outputs": [ 595 | { 596 | "latex": [ 597 | "$$\\left(a + 2 \\pi\\right)^{2}$$" 598 | ], 599 | "metadata": {}, 600 | "output_type": "pyout", 601 | "prompt_number": 24, 602 | "text": [ 603 | " 2\n", 604 | "(a + 2\u22c5\u03c0) " 605 | ] 606 | } 607 | ], 608 | "prompt_number": 24 609 | }, 610 | { 611 | "cell_type": "markdown", 612 | "metadata": {}, 613 | "source": [ 614 | "We can also combine numerical evolution of expressions with NumPy arrays:" 615 | ] 616 | }, 617 | { 618 | "cell_type": "code", 619 | "collapsed": false, 620 | "input": [ 621 | "import numpy" 622 | ], 623 | "language": "python", 624 | "metadata": {}, 625 | "outputs": [], 626 | "prompt_number": 25 627 | }, 628 | { 629 | "cell_type": "code", 630 | "collapsed": false, 631 | "input": [ 632 | "x_vec = numpy.arange(0, 10, 0.1)" 633 | ], 634 | "language": "python", 635 | "metadata": {}, 636 | "outputs": [], 637 | "prompt_number": 26 638 | }, 639 | { 640 | "cell_type": "code", 641 | "collapsed": false, 642 | "input": [ 643 | "y_vec = numpy.array([N(((x + pi)**2).subs(x, xx)) for xx in x_vec])" 644 | ], 645 | "language": "python", 646 | "metadata": {}, 647 | "outputs": [], 648 | "prompt_number": 27 649 | }, 650 | { 651 | "cell_type": "code", 652 | "collapsed": false, 653 | "input": [ 654 | "fig, ax = subplots()\n", 655 | "ax.plot(x_vec, y_vec);" 656 | ], 657 | "language": "python", 658 | "metadata": {}, 659 | "outputs": [ 660 | { 661 | "metadata": {}, 662 | "output_type": "display_data", 663 | "png": "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\naFlJKJFyhJ8AAAAASUVORK5CYII=\n", 664 | "text": [ 665 | "" 666 | ] 667 | } 668 | ], 669 | "prompt_number": 28 670 | }, 671 | { 672 | "cell_type": "markdown", 673 | "metadata": {}, 674 | "source": [ 675 | "However, this kind of numerical evolution can be very slow, and there is a much more efficient way to do it: Use the function `lambdify` to \"compile\" a Sympy expression into a function that is much more efficient to evaluate numerically:" 676 | ] 677 | }, 678 | { 679 | "cell_type": "code", 680 | "collapsed": false, 681 | "input": [ 682 | "f = lambdify([x], (x + pi)**2, 'numpy') # the first argument is a list of variables that\n", 683 | " # f will be a function of: in this case only x -> f(x)" 684 | ], 685 | "language": "python", 686 | "metadata": {}, 687 | "outputs": [], 688 | "prompt_number": 29 689 | }, 690 | { 691 | "cell_type": "code", 692 | "collapsed": false, 693 | "input": [ 694 | "y_vec = f(x_vec) # now we can directly pass a numpy array and f(x) is efficiently evaluated" 695 | ], 696 | "language": "python", 697 | "metadata": {}, 698 | "outputs": [], 699 | "prompt_number": 30 700 | }, 701 | { 702 | "cell_type": "markdown", 703 | "metadata": {}, 704 | "source": [ 705 | "The speedup when using \"lambdified\" functions instead of direct numerical evaluation can be significant, often several orders of magnitude. Even in this simple example we get a significant speed up:" 706 | ] 707 | }, 708 | { 709 | "cell_type": "code", 710 | "collapsed": false, 711 | "input": [ 712 | "%%timeit\n", 713 | "\n", 714 | "y_vec = numpy.array([N(((x + pi)**2).subs(x, xx)) for xx in x_vec])" 715 | ], 716 | "language": "python", 717 | "metadata": {}, 718 | "outputs": [ 719 | { 720 | "output_type": "stream", 721 | "stream": "stdout", 722 | "text": [ 723 | "10 loops, best of 3: 20.4 ms per loop\n" 724 | ] 725 | } 726 | ], 727 | "prompt_number": 31 728 | }, 729 | { 730 | "cell_type": "code", 731 | "collapsed": false, 732 | "input": [ 733 | "%%timeit\n", 734 | "\n", 735 | "y_vec = f(x_vec)" 736 | ], 737 | "language": "python", 738 | "metadata": {}, 739 | "outputs": [ 740 | { 741 | "output_type": "stream", 742 | "stream": "stdout", 743 | "text": [ 744 | "100000 loops, best of 3: 3.67 \u00b5s per loop\n" 745 | ] 746 | } 747 | ], 748 | "prompt_number": 32 749 | }, 750 | { 751 | "cell_type": "heading", 752 | "level": 2, 753 | "metadata": {}, 754 | "source": [ 755 | "Algebraic manipulations" 756 | ] 757 | }, 758 | { 759 | "cell_type": "markdown", 760 | "metadata": {}, 761 | "source": [ 762 | "One of the main uses of an CAS is to perform algebraic manipulations of expressions. For example, we might want to expand a product, factor an expression, or simply an expression. The functions for doing these basic operations in SymPy are demonstrated in this section." 763 | ] 764 | }, 765 | { 766 | "cell_type": "heading", 767 | "level": 3, 768 | "metadata": {}, 769 | "source": [ 770 | "Expand and factor" 771 | ] 772 | }, 773 | { 774 | "cell_type": "markdown", 775 | "metadata": {}, 776 | "source": [ 777 | "The first steps in an algebraic manipulation " 778 | ] 779 | }, 780 | { 781 | "cell_type": "code", 782 | "collapsed": false, 783 | "input": [ 784 | "(x+1)*(x+2)*(x+3)" 785 | ], 786 | "language": "python", 787 | "metadata": {}, 788 | "outputs": [ 789 | { 790 | "latex": [ 791 | "$$\\left(x + 1\\right) \\left(x + 2\\right) \\left(x + 3\\right)$$" 792 | ], 793 | "metadata": {}, 794 | "output_type": "pyout", 795 | "prompt_number": 33, 796 | "text": [ 797 | "(x + 1)\u22c5(x + 2)\u22c5(x + 3)" 798 | ] 799 | } 800 | ], 801 | "prompt_number": 33 802 | }, 803 | { 804 | "cell_type": "code", 805 | "collapsed": false, 806 | "input": [ 807 | "expand((x+1)*(x+2)*(x+3))" 808 | ], 809 | "language": "python", 810 | "metadata": {}, 811 | "outputs": [ 812 | { 813 | "latex": [ 814 | "$$x^{3} + 6 x^{2} + 11 x + 6$$" 815 | ], 816 | "metadata": {}, 817 | "output_type": "pyout", 818 | "prompt_number": 34, 819 | "text": [ 820 | " 3 2 \n", 821 | "x + 6\u22c5x + 11\u22c5x + 6" 822 | ] 823 | } 824 | ], 825 | "prompt_number": 34 826 | }, 827 | { 828 | "cell_type": "markdown", 829 | "metadata": {}, 830 | "source": [ 831 | "The `expand` function takes a number of keywords arguments which we can tell the functions what kind of expansions we want to have performed. For example, to expand trigonometric expressions, use the `trig=True` keyword argument:" 832 | ] 833 | }, 834 | { 835 | "cell_type": "code", 836 | "collapsed": false, 837 | "input": [ 838 | "sin(a+b)" 839 | ], 840 | "language": "python", 841 | "metadata": {}, 842 | "outputs": [ 843 | { 844 | "latex": [ 845 | "$$\\sin{\\left (a + b \\right )}$$" 846 | ], 847 | "metadata": {}, 848 | "output_type": "pyout", 849 | "prompt_number": 35, 850 | "text": [ 851 | "sin(a + b)" 852 | ] 853 | } 854 | ], 855 | "prompt_number": 35 856 | }, 857 | { 858 | "cell_type": "code", 859 | "collapsed": false, 860 | "input": [ 861 | "expand(sin(a+b), trig=True)" 862 | ], 863 | "language": "python", 864 | "metadata": {}, 865 | "outputs": [ 866 | { 867 | "latex": [ 868 | "$$\\sin{\\left (a \\right )} \\cos{\\left (b \\right )} + \\sin{\\left (b \\right )} \\cos{\\left (a \\right )}$$" 869 | ], 870 | "metadata": {}, 871 | "output_type": "pyout", 872 | "prompt_number": 36, 873 | "text": [ 874 | "sin(a)\u22c5cos(b) + sin(b)\u22c5cos(a)" 875 | ] 876 | } 877 | ], 878 | "prompt_number": 36 879 | }, 880 | { 881 | "cell_type": "markdown", 882 | "metadata": {}, 883 | "source": [ 884 | "See `help(expand)` for a detailed explanation of the various types of expansions the `expand` functions can perform." 885 | ] 886 | }, 887 | { 888 | "cell_type": "markdown", 889 | "metadata": {}, 890 | "source": [ 891 | "The opposite a product expansion is of course factoring. The factor an expression in SymPy use the `factor` function: " 892 | ] 893 | }, 894 | { 895 | "cell_type": "code", 896 | "collapsed": false, 897 | "input": [ 898 | "factor(x**3 + 6 * x**2 + 11*x + 6)" 899 | ], 900 | "language": "python", 901 | "metadata": {}, 902 | "outputs": [ 903 | { 904 | "latex": [ 905 | "$$\\left(x + 1\\right) \\left(x + 2\\right) \\left(x + 3\\right)$$" 906 | ], 907 | "metadata": {}, 908 | "output_type": "pyout", 909 | "prompt_number": 37, 910 | "text": [ 911 | "(x + 1)\u22c5(x + 2)\u22c5(x + 3)" 912 | ] 913 | } 914 | ], 915 | "prompt_number": 37 916 | }, 917 | { 918 | "cell_type": "heading", 919 | "level": 3, 920 | "metadata": {}, 921 | "source": [ 922 | "Simplify" 923 | ] 924 | }, 925 | { 926 | "cell_type": "markdown", 927 | "metadata": {}, 928 | "source": [ 929 | "The `simplify` tries to simplify an expression into a nice looking expression, using various techniques. More specific alternatives to the `simplify` functions also exists: `trigsimp`, `powsimp`, `logcombine`, etc. \n", 930 | "\n", 931 | "The basic usages of these functions are as follows:" 932 | ] 933 | }, 934 | { 935 | "cell_type": "code", 936 | "collapsed": false, 937 | "input": [ 938 | "# simplify expands a product\n", 939 | "simplify((x+1)*(x+2)*(x+3))" 940 | ], 941 | "language": "python", 942 | "metadata": {}, 943 | "outputs": [ 944 | { 945 | "latex": [ 946 | "$$\\left(x + 1\\right) \\left(x + 2\\right) \\left(x + 3\\right)$$" 947 | ], 948 | "metadata": {}, 949 | "output_type": "pyout", 950 | "prompt_number": 38, 951 | "text": [ 952 | "(x + 1)\u22c5(x + 2)\u22c5(x + 3)" 953 | ] 954 | } 955 | ], 956 | "prompt_number": 38 957 | }, 958 | { 959 | "cell_type": "code", 960 | "collapsed": false, 961 | "input": [ 962 | "# simplify uses trigonometric identities\n", 963 | "simplify(sin(a)**2 + cos(a)**2)" 964 | ], 965 | "language": "python", 966 | "metadata": {}, 967 | "outputs": [ 968 | { 969 | "latex": [ 970 | "$$1$$" 971 | ], 972 | "metadata": {}, 973 | "output_type": "pyout", 974 | "prompt_number": 39, 975 | "text": [ 976 | "1" 977 | ] 978 | } 979 | ], 980 | "prompt_number": 39 981 | }, 982 | { 983 | "cell_type": "code", 984 | "collapsed": false, 985 | "input": [ 986 | "simplify(cos(x)/sin(x))" 987 | ], 988 | "language": "python", 989 | "metadata": {}, 990 | "outputs": [ 991 | { 992 | "latex": [ 993 | "$$\\frac{1}{\\tan{\\left (x \\right )}}$$" 994 | ], 995 | "metadata": {}, 996 | "output_type": "pyout", 997 | "prompt_number": 40, 998 | "text": [ 999 | " 1 \n", 1000 | "\u2500\u2500\u2500\u2500\u2500\u2500\n", 1001 | "tan(x)" 1002 | ] 1003 | } 1004 | ], 1005 | "prompt_number": 40 1006 | }, 1007 | { 1008 | "cell_type": "heading", 1009 | "level": 3, 1010 | "metadata": {}, 1011 | "source": [ 1012 | "apart and together" 1013 | ] 1014 | }, 1015 | { 1016 | "cell_type": "markdown", 1017 | "metadata": {}, 1018 | "source": [ 1019 | "To manipulate symbolic expressions of fractions, we can use the `apart` and `together` functions:" 1020 | ] 1021 | }, 1022 | { 1023 | "cell_type": "code", 1024 | "collapsed": false, 1025 | "input": [ 1026 | "f1 = 1/((a+1)*(a+2))" 1027 | ], 1028 | "language": "python", 1029 | "metadata": {}, 1030 | "outputs": [], 1031 | "prompt_number": 41 1032 | }, 1033 | { 1034 | "cell_type": "code", 1035 | "collapsed": false, 1036 | "input": [ 1037 | "f1" 1038 | ], 1039 | "language": "python", 1040 | "metadata": {}, 1041 | "outputs": [ 1042 | { 1043 | "latex": [ 1044 | "$$\\frac{1}{\\left(a + 1\\right) \\left(a + 2\\right)}$$" 1045 | ], 1046 | "metadata": {}, 1047 | "output_type": "pyout", 1048 | "prompt_number": 42, 1049 | "text": [ 1050 | " 1 \n", 1051 | "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", 1052 | "(a + 1)\u22c5(a + 2)" 1053 | ] 1054 | } 1055 | ], 1056 | "prompt_number": 42 1057 | }, 1058 | { 1059 | "cell_type": "code", 1060 | "collapsed": false, 1061 | "input": [ 1062 | "apart(f1)" 1063 | ], 1064 | "language": "python", 1065 | "metadata": {}, 1066 | "outputs": [ 1067 | { 1068 | "latex": [ 1069 | "$$- \\frac{1}{a + 2} + \\frac{1}{a + 1}$$" 1070 | ], 1071 | "metadata": {}, 1072 | "output_type": "pyout", 1073 | "prompt_number": 43, 1074 | "text": [ 1075 | " 1 1 \n", 1076 | "- \u2500\u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500\u2500\n", 1077 | " a + 2 a + 1" 1078 | ] 1079 | } 1080 | ], 1081 | "prompt_number": 43 1082 | }, 1083 | { 1084 | "cell_type": "code", 1085 | "collapsed": false, 1086 | "input": [ 1087 | "f2 = 1/(a+2) + 1/(a+3)" 1088 | ], 1089 | "language": "python", 1090 | "metadata": {}, 1091 | "outputs": [], 1092 | "prompt_number": 44 1093 | }, 1094 | { 1095 | "cell_type": "code", 1096 | "collapsed": false, 1097 | "input": [ 1098 | "f2" 1099 | ], 1100 | "language": "python", 1101 | "metadata": {}, 1102 | "outputs": [ 1103 | { 1104 | "latex": [ 1105 | "$$\\frac{1}{a + 3} + \\frac{1}{a + 2}$$" 1106 | ], 1107 | "metadata": {}, 1108 | "output_type": "pyout", 1109 | "prompt_number": 45, 1110 | "text": [ 1111 | " 1 1 \n", 1112 | "\u2500\u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500\u2500\n", 1113 | "a + 3 a + 2" 1114 | ] 1115 | } 1116 | ], 1117 | "prompt_number": 45 1118 | }, 1119 | { 1120 | "cell_type": "code", 1121 | "collapsed": false, 1122 | "input": [ 1123 | "together(f2)" 1124 | ], 1125 | "language": "python", 1126 | "metadata": {}, 1127 | "outputs": [ 1128 | { 1129 | "latex": [ 1130 | "$$\\frac{2 a + 5}{\\left(a + 2\\right) \\left(a + 3\\right)}$$" 1131 | ], 1132 | "metadata": {}, 1133 | "output_type": "pyout", 1134 | "prompt_number": 46, 1135 | "text": [ 1136 | " 2\u22c5a + 5 \n", 1137 | "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", 1138 | "(a + 2)\u22c5(a + 3)" 1139 | ] 1140 | } 1141 | ], 1142 | "prompt_number": 46 1143 | }, 1144 | { 1145 | "cell_type": "markdown", 1146 | "metadata": {}, 1147 | "source": [ 1148 | "Simplify usually combines fractions but does not factor: " 1149 | ] 1150 | }, 1151 | { 1152 | "cell_type": "code", 1153 | "collapsed": false, 1154 | "input": [ 1155 | "simplify(f2)" 1156 | ], 1157 | "language": "python", 1158 | "metadata": {}, 1159 | "outputs": [ 1160 | { 1161 | "latex": [ 1162 | "$$\\frac{2 a + 5}{\\left(a + 2\\right) \\left(a + 3\\right)}$$" 1163 | ], 1164 | "metadata": {}, 1165 | "output_type": "pyout", 1166 | "prompt_number": 47, 1167 | "text": [ 1168 | " 2\u22c5a + 5 \n", 1169 | "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", 1170 | "(a + 2)\u22c5(a + 3)" 1171 | ] 1172 | } 1173 | ], 1174 | "prompt_number": 47 1175 | }, 1176 | { 1177 | "cell_type": "heading", 1178 | "level": 2, 1179 | "metadata": {}, 1180 | "source": [ 1181 | "Calculus" 1182 | ] 1183 | }, 1184 | { 1185 | "cell_type": "markdown", 1186 | "metadata": {}, 1187 | "source": [ 1188 | "In addition to algebraic manipulations, the other main use of CAS is to do calculus, like derivatives and integrals of algebraic expressions." 1189 | ] 1190 | }, 1191 | { 1192 | "cell_type": "heading", 1193 | "level": 3, 1194 | "metadata": {}, 1195 | "source": [ 1196 | "Differentiation" 1197 | ] 1198 | }, 1199 | { 1200 | "cell_type": "markdown", 1201 | "metadata": {}, 1202 | "source": [ 1203 | "Differentiation is usually simple. Use the `diff` function. The first argument is the expression to take the derivative of, and the second argument is the symbol by which to take the derivative:" 1204 | ] 1205 | }, 1206 | { 1207 | "cell_type": "code", 1208 | "collapsed": false, 1209 | "input": [ 1210 | "y" 1211 | ], 1212 | "language": "python", 1213 | "metadata": {}, 1214 | "outputs": [ 1215 | { 1216 | "latex": [ 1217 | "$$\\left(x + \\pi\\right)^{2}$$" 1218 | ], 1219 | "metadata": {}, 1220 | "output_type": "pyout", 1221 | "prompt_number": 48, 1222 | "text": [ 1223 | " 2\n", 1224 | "(x + \u03c0) " 1225 | ] 1226 | } 1227 | ], 1228 | "prompt_number": 48 1229 | }, 1230 | { 1231 | "cell_type": "code", 1232 | "collapsed": false, 1233 | "input": [ 1234 | "diff(y**2, x)" 1235 | ], 1236 | "language": "python", 1237 | "metadata": {}, 1238 | "outputs": [ 1239 | { 1240 | "latex": [ 1241 | "$$4 \\left(x + \\pi\\right)^{3}$$" 1242 | ], 1243 | "metadata": {}, 1244 | "output_type": "pyout", 1245 | "prompt_number": 49, 1246 | "text": [ 1247 | " 3\n", 1248 | "4\u22c5(x + \u03c0) " 1249 | ] 1250 | } 1251 | ], 1252 | "prompt_number": 49 1253 | }, 1254 | { 1255 | "cell_type": "markdown", 1256 | "metadata": {}, 1257 | "source": [ 1258 | "For higher order derivatives we can do:" 1259 | ] 1260 | }, 1261 | { 1262 | "cell_type": "code", 1263 | "collapsed": false, 1264 | "input": [ 1265 | "diff(y**2, x, x)" 1266 | ], 1267 | "language": "python", 1268 | "metadata": {}, 1269 | "outputs": [ 1270 | { 1271 | "latex": [ 1272 | "$$12 \\left(x + \\pi\\right)^{2}$$" 1273 | ], 1274 | "metadata": {}, 1275 | "output_type": "pyout", 1276 | "prompt_number": 50, 1277 | "text": [ 1278 | " 2\n", 1279 | "12\u22c5(x + \u03c0) " 1280 | ] 1281 | } 1282 | ], 1283 | "prompt_number": 50 1284 | }, 1285 | { 1286 | "cell_type": "code", 1287 | "collapsed": false, 1288 | "input": [ 1289 | "diff(y**2, x, 2) # same as above" 1290 | ], 1291 | "language": "python", 1292 | "metadata": {}, 1293 | "outputs": [ 1294 | { 1295 | "latex": [ 1296 | "$$12 \\left(x + \\pi\\right)^{2}$$" 1297 | ], 1298 | "metadata": {}, 1299 | "output_type": "pyout", 1300 | "prompt_number": 51, 1301 | "text": [ 1302 | " 2\n", 1303 | "12\u22c5(x + \u03c0) " 1304 | ] 1305 | } 1306 | ], 1307 | "prompt_number": 51 1308 | }, 1309 | { 1310 | "cell_type": "markdown", 1311 | "metadata": {}, 1312 | "source": [ 1313 | "To calculate the derivative of a multivariate expression, we can do:" 1314 | ] 1315 | }, 1316 | { 1317 | "cell_type": "code", 1318 | "collapsed": false, 1319 | "input": [ 1320 | "x, y, z = symbols(\"x,y,z\")" 1321 | ], 1322 | "language": "python", 1323 | "metadata": {}, 1324 | "outputs": [], 1325 | "prompt_number": 52 1326 | }, 1327 | { 1328 | "cell_type": "code", 1329 | "collapsed": false, 1330 | "input": [ 1331 | "f = sin(x*y) + cos(y*z)" 1332 | ], 1333 | "language": "python", 1334 | "metadata": {}, 1335 | "outputs": [], 1336 | "prompt_number": 53 1337 | }, 1338 | { 1339 | "cell_type": "markdown", 1340 | "metadata": {}, 1341 | "source": [ 1342 | "$\\frac{d^3f}{dxdy^2}$" 1343 | ] 1344 | }, 1345 | { 1346 | "cell_type": "code", 1347 | "collapsed": false, 1348 | "input": [ 1349 | "diff(f, x, 1, y, 2)" 1350 | ], 1351 | "language": "python", 1352 | "metadata": {}, 1353 | "outputs": [ 1354 | { 1355 | "latex": [ 1356 | "$$- x \\left(x y \\cos{\\left (x y \\right )} + 2 \\sin{\\left (x y \\right )}\\right)$$" 1357 | ], 1358 | "metadata": {}, 1359 | "output_type": "pyout", 1360 | "prompt_number": 54, 1361 | "text": [ 1362 | "-x\u22c5(x\u22c5y\u22c5cos(x\u22c5y) + 2\u22c5sin(x\u22c5y))" 1363 | ] 1364 | } 1365 | ], 1366 | "prompt_number": 54 1367 | }, 1368 | { 1369 | "cell_type": "heading", 1370 | "level": 2, 1371 | "metadata": {}, 1372 | "source": [ 1373 | "Integration" 1374 | ] 1375 | }, 1376 | { 1377 | "cell_type": "markdown", 1378 | "metadata": {}, 1379 | "source": [ 1380 | "Integration is done in a similar fashion:" 1381 | ] 1382 | }, 1383 | { 1384 | "cell_type": "code", 1385 | "collapsed": false, 1386 | "input": [ 1387 | "f" 1388 | ], 1389 | "language": "python", 1390 | "metadata": {}, 1391 | "outputs": [ 1392 | { 1393 | "latex": [ 1394 | "$$\\sin{\\left (x y \\right )} + \\cos{\\left (y z \\right )}$$" 1395 | ], 1396 | "metadata": {}, 1397 | "output_type": "pyout", 1398 | "prompt_number": 55, 1399 | "text": [ 1400 | "sin(x\u22c5y) + cos(y\u22c5z)" 1401 | ] 1402 | } 1403 | ], 1404 | "prompt_number": 55 1405 | }, 1406 | { 1407 | "cell_type": "code", 1408 | "collapsed": false, 1409 | "input": [ 1410 | "integrate(f, x)" 1411 | ], 1412 | "language": "python", 1413 | "metadata": {}, 1414 | "outputs": [ 1415 | { 1416 | "latex": [ 1417 | "$$x \\cos{\\left (y z \\right )} + \\begin{cases} 0 & \\text{for}\\: y = 0 \\\\- \\frac{\\cos{\\left (x y \\right )}}{y} & \\text{otherwise} \\end{cases}$$" 1418 | ], 1419 | "metadata": {}, 1420 | "output_type": "pyout", 1421 | "prompt_number": 56, 1422 | "text": [ 1423 | " \u239b\u23a7 0 for y = 0\u239e\n", 1424 | " \u239c\u23aa \u239f\n", 1425 | "x\u22c5cos(y\u22c5z) + \u239c\u23a8-cos(x\u22c5y) \u239f\n", 1426 | " \u239c\u23aa\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 otherwise\u239f\n", 1427 | " \u239d\u23a9 y \u23a0" 1428 | ] 1429 | } 1430 | ], 1431 | "prompt_number": 56 1432 | }, 1433 | { 1434 | "cell_type": "markdown", 1435 | "metadata": {}, 1436 | "source": [ 1437 | "By providing limits for the integration variable we can evaluate definite integrals:" 1438 | ] 1439 | }, 1440 | { 1441 | "cell_type": "code", 1442 | "collapsed": false, 1443 | "input": [ 1444 | "integrate(f, (x, -1, 1))" 1445 | ], 1446 | "language": "python", 1447 | "metadata": {}, 1448 | "outputs": [ 1449 | { 1450 | "latex": [ 1451 | "$$2 \\cos{\\left (y z \\right )}$$" 1452 | ], 1453 | "metadata": {}, 1454 | "output_type": "pyout", 1455 | "prompt_number": 57, 1456 | "text": [ 1457 | "2\u22c5cos(y\u22c5z)" 1458 | ] 1459 | } 1460 | ], 1461 | "prompt_number": 57 1462 | }, 1463 | { 1464 | "cell_type": "markdown", 1465 | "metadata": {}, 1466 | "source": [ 1467 | "and also improper integrals" 1468 | ] 1469 | }, 1470 | { 1471 | "cell_type": "code", 1472 | "collapsed": false, 1473 | "input": [ 1474 | "integrate(exp(-x**2), (x, -oo, oo))" 1475 | ], 1476 | "language": "python", 1477 | "metadata": {}, 1478 | "outputs": [ 1479 | { 1480 | "latex": [ 1481 | "$$\\sqrt{\\pi}$$" 1482 | ], 1483 | "metadata": {}, 1484 | "output_type": "pyout", 1485 | "prompt_number": 58, 1486 | "text": [ 1487 | " ___\n", 1488 | "\u2572\u2571 \u03c0 " 1489 | ] 1490 | } 1491 | ], 1492 | "prompt_number": 58 1493 | }, 1494 | { 1495 | "cell_type": "markdown", 1496 | "metadata": {}, 1497 | "source": [ 1498 | "Remember, `oo` is the SymPy notation for inifinity." 1499 | ] 1500 | }, 1501 | { 1502 | "cell_type": "heading", 1503 | "level": 3, 1504 | "metadata": {}, 1505 | "source": [ 1506 | "Sums and products" 1507 | ] 1508 | }, 1509 | { 1510 | "cell_type": "markdown", 1511 | "metadata": {}, 1512 | "source": [ 1513 | "We can evaluate sums and products using the functions: 'Sum'" 1514 | ] 1515 | }, 1516 | { 1517 | "cell_type": "code", 1518 | "collapsed": false, 1519 | "input": [ 1520 | "n = Symbol(\"n\")" 1521 | ], 1522 | "language": "python", 1523 | "metadata": {}, 1524 | "outputs": [], 1525 | "prompt_number": 59 1526 | }, 1527 | { 1528 | "cell_type": "code", 1529 | "collapsed": false, 1530 | "input": [ 1531 | "Sum(1/n**2, (n, 1, 10))" 1532 | ], 1533 | "language": "python", 1534 | "metadata": {}, 1535 | "outputs": [ 1536 | { 1537 | "latex": [ 1538 | "$$\\sum_{n=1}^{10} n^{-2}$$" 1539 | ], 1540 | "metadata": {}, 1541 | "output_type": "pyout", 1542 | "prompt_number": 60, 1543 | "text": [ 1544 | " 10 \n", 1545 | " ____ \n", 1546 | " \u2572 \n", 1547 | " \u2572 1 \n", 1548 | " \u2572 \u2500\u2500\n", 1549 | " \u2571 2\n", 1550 | " \u2571 n \n", 1551 | " \u2571 \n", 1552 | " \u203e\u203e\u203e\u203e \n", 1553 | "n = 1 " 1554 | ] 1555 | } 1556 | ], 1557 | "prompt_number": 60 1558 | }, 1559 | { 1560 | "cell_type": "code", 1561 | "collapsed": false, 1562 | "input": [ 1563 | "Sum(1/n**2, (n,1, 10)).evalf()" 1564 | ], 1565 | "language": "python", 1566 | "metadata": {}, 1567 | "outputs": [ 1568 | { 1569 | "latex": [ 1570 | "$$1.54976773116654$$" 1571 | ], 1572 | "metadata": {}, 1573 | "output_type": "pyout", 1574 | "prompt_number": 61, 1575 | "text": [ 1576 | "1.54976773116654" 1577 | ] 1578 | } 1579 | ], 1580 | "prompt_number": 61 1581 | }, 1582 | { 1583 | "cell_type": "code", 1584 | "collapsed": false, 1585 | "input": [ 1586 | "Sum(1/n**2, (n, 1, oo)).evalf()" 1587 | ], 1588 | "language": "python", 1589 | "metadata": {}, 1590 | "outputs": [ 1591 | { 1592 | "latex": [ 1593 | "$$1.64493406684823$$" 1594 | ], 1595 | "metadata": {}, 1596 | "output_type": "pyout", 1597 | "prompt_number": 62, 1598 | "text": [ 1599 | "1.64493406684823" 1600 | ] 1601 | } 1602 | ], 1603 | "prompt_number": 62 1604 | }, 1605 | { 1606 | "cell_type": "markdown", 1607 | "metadata": {}, 1608 | "source": [ 1609 | "Products work much the same way:" 1610 | ] 1611 | }, 1612 | { 1613 | "cell_type": "code", 1614 | "collapsed": false, 1615 | "input": [ 1616 | "Product(n, (n, 1, 10)) # 10!" 1617 | ], 1618 | "language": "python", 1619 | "metadata": {}, 1620 | "outputs": [ 1621 | { 1622 | "latex": [ 1623 | "$$\\prod_{n=1}^{10} n$$" 1624 | ], 1625 | "metadata": {}, 1626 | "output_type": "pyout", 1627 | "prompt_number": 63, 1628 | "text": [ 1629 | " 10 \n", 1630 | "\u252c\u2500\u2500\u2500\u252c \n", 1631 | "\u2502 \u2502 n\n", 1632 | "\u2502 \u2502 \n", 1633 | "n = 1 " 1634 | ] 1635 | } 1636 | ], 1637 | "prompt_number": 63 1638 | }, 1639 | { 1640 | "cell_type": "heading", 1641 | "level": 2, 1642 | "metadata": {}, 1643 | "source": [ 1644 | "Limits" 1645 | ] 1646 | }, 1647 | { 1648 | "cell_type": "markdown", 1649 | "metadata": {}, 1650 | "source": [ 1651 | "Limits can be evaluated using the `limit` function. For example, " 1652 | ] 1653 | }, 1654 | { 1655 | "cell_type": "code", 1656 | "collapsed": false, 1657 | "input": [ 1658 | "limit(sin(x)/x, x, 0)" 1659 | ], 1660 | "language": "python", 1661 | "metadata": {}, 1662 | "outputs": [ 1663 | { 1664 | "latex": [ 1665 | "$$1$$" 1666 | ], 1667 | "metadata": {}, 1668 | "output_type": "pyout", 1669 | "prompt_number": 64, 1670 | "text": [ 1671 | "1" 1672 | ] 1673 | } 1674 | ], 1675 | "prompt_number": 64 1676 | }, 1677 | { 1678 | "cell_type": "markdown", 1679 | "metadata": {}, 1680 | "source": [ 1681 | "We can use 'limit' to check the result of derivation using the `diff` function:" 1682 | ] 1683 | }, 1684 | { 1685 | "cell_type": "code", 1686 | "collapsed": false, 1687 | "input": [ 1688 | "f" 1689 | ], 1690 | "language": "python", 1691 | "metadata": {}, 1692 | "outputs": [ 1693 | { 1694 | "latex": [ 1695 | "$$\\sin{\\left (x y \\right )} + \\cos{\\left (y z \\right )}$$" 1696 | ], 1697 | "metadata": {}, 1698 | "output_type": "pyout", 1699 | "prompt_number": 65, 1700 | "text": [ 1701 | "sin(x\u22c5y) + cos(y\u22c5z)" 1702 | ] 1703 | } 1704 | ], 1705 | "prompt_number": 65 1706 | }, 1707 | { 1708 | "cell_type": "code", 1709 | "collapsed": false, 1710 | "input": [ 1711 | "diff(f, x)" 1712 | ], 1713 | "language": "python", 1714 | "metadata": {}, 1715 | "outputs": [ 1716 | { 1717 | "latex": [ 1718 | "$$y \\cos{\\left (x y \\right )}$$" 1719 | ], 1720 | "metadata": {}, 1721 | "output_type": "pyout", 1722 | "prompt_number": 66, 1723 | "text": [ 1724 | "y\u22c5cos(x\u22c5y)" 1725 | ] 1726 | } 1727 | ], 1728 | "prompt_number": 66 1729 | }, 1730 | { 1731 | "cell_type": "markdown", 1732 | "metadata": {}, 1733 | "source": [ 1734 | "$\\displaystyle \\frac{\\mathrm{d}f(x,y)}{\\mathrm{d}x} = \\frac{f(x+h,y)-f(x,y)}{h}$" 1735 | ] 1736 | }, 1737 | { 1738 | "cell_type": "code", 1739 | "collapsed": false, 1740 | "input": [ 1741 | "h = Symbol(\"h\")" 1742 | ], 1743 | "language": "python", 1744 | "metadata": {}, 1745 | "outputs": [], 1746 | "prompt_number": 67 1747 | }, 1748 | { 1749 | "cell_type": "code", 1750 | "collapsed": false, 1751 | "input": [ 1752 | "limit((f.subs(x, x+h) - f)/h, h, 0)" 1753 | ], 1754 | "language": "python", 1755 | "metadata": {}, 1756 | "outputs": [ 1757 | { 1758 | "latex": [ 1759 | "$$y \\cos{\\left (x y \\right )}$$" 1760 | ], 1761 | "metadata": {}, 1762 | "output_type": "pyout", 1763 | "prompt_number": 68, 1764 | "text": [ 1765 | "y\u22c5cos(x\u22c5y)" 1766 | ] 1767 | } 1768 | ], 1769 | "prompt_number": 68 1770 | }, 1771 | { 1772 | "cell_type": "markdown", 1773 | "metadata": {}, 1774 | "source": [ 1775 | "OK!" 1776 | ] 1777 | }, 1778 | { 1779 | "cell_type": "markdown", 1780 | "metadata": {}, 1781 | "source": [ 1782 | "We can change the direction from which we approach the limiting point using the `dir` keywork argument:" 1783 | ] 1784 | }, 1785 | { 1786 | "cell_type": "code", 1787 | "collapsed": false, 1788 | "input": [ 1789 | "limit(1/x, x, 0, dir=\"+\")" 1790 | ], 1791 | "language": "python", 1792 | "metadata": {}, 1793 | "outputs": [ 1794 | { 1795 | "latex": [ 1796 | "$$\\infty$$" 1797 | ], 1798 | "metadata": {}, 1799 | "output_type": "pyout", 1800 | "prompt_number": 69, 1801 | "text": [ 1802 | "\u221e" 1803 | ] 1804 | } 1805 | ], 1806 | "prompt_number": 69 1807 | }, 1808 | { 1809 | "cell_type": "code", 1810 | "collapsed": false, 1811 | "input": [ 1812 | "limit(1/x, x, 0, dir=\"-\")" 1813 | ], 1814 | "language": "python", 1815 | "metadata": {}, 1816 | "outputs": [ 1817 | { 1818 | "latex": [ 1819 | "$$-\\infty$$" 1820 | ], 1821 | "metadata": {}, 1822 | "output_type": "pyout", 1823 | "prompt_number": 70, 1824 | "text": [ 1825 | "-\u221e" 1826 | ] 1827 | } 1828 | ], 1829 | "prompt_number": 70 1830 | }, 1831 | { 1832 | "cell_type": "heading", 1833 | "level": 2, 1834 | "metadata": {}, 1835 | "source": [ 1836 | "Series" 1837 | ] 1838 | }, 1839 | { 1840 | "cell_type": "markdown", 1841 | "metadata": {}, 1842 | "source": [ 1843 | "Series expansion is also one of the most useful features of a CAS. In SymPy we can perform a series expansion of an expression using the `series` function:" 1844 | ] 1845 | }, 1846 | { 1847 | "cell_type": "code", 1848 | "collapsed": false, 1849 | "input": [ 1850 | "series(exp(x), x)" 1851 | ], 1852 | "language": "python", 1853 | "metadata": {}, 1854 | "outputs": [ 1855 | { 1856 | "latex": [ 1857 | "$$1 + x + \\frac{1}{2} x^{2} + \\frac{1}{6} x^{3} + \\frac{1}{24} x^{4} + \\frac{1}{120} x^{5} + \\mathcal{O}\\left(x^{6}\\right)$$" 1858 | ], 1859 | "metadata": {}, 1860 | "output_type": "pyout", 1861 | "prompt_number": 71, 1862 | "text": [ 1863 | " 2 3 4 5 \n", 1864 | " x x x x \u239b 6\u239e\n", 1865 | "1 + x + \u2500\u2500 + \u2500\u2500 + \u2500\u2500 + \u2500\u2500\u2500 + O\u239dx \u23a0\n", 1866 | " 2 6 24 120 " 1867 | ] 1868 | } 1869 | ], 1870 | "prompt_number": 71 1871 | }, 1872 | { 1873 | "cell_type": "markdown", 1874 | "metadata": {}, 1875 | "source": [ 1876 | "By default it expands the expression around $x=0$, but we can expand around any value of $x$ by explicitly include a value in the function call:" 1877 | ] 1878 | }, 1879 | { 1880 | "cell_type": "code", 1881 | "collapsed": false, 1882 | "input": [ 1883 | "series(exp(x), x, 1)" 1884 | ], 1885 | "language": "python", 1886 | "metadata": {}, 1887 | "outputs": [ 1888 | { 1889 | "latex": [ 1890 | "$$e + e x + \\frac{1}{2} e x^{2} + \\frac{1}{6} e x^{3} + \\frac{1}{24} e x^{4} + \\frac{1}{120} e x^{5} + \\mathcal{O}\\left(x^{6}\\right)$$" 1891 | ], 1892 | "metadata": {}, 1893 | "output_type": "pyout", 1894 | "prompt_number": 72, 1895 | "text": [ 1896 | " 2 3 4 5 \n", 1897 | " \u212f\u22c5x \u212f\u22c5x \u212f\u22c5x \u212f\u22c5x \u239b 6\u239e\n", 1898 | "\u212f + \u212f\u22c5x + \u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500 + O\u239dx \u23a0\n", 1899 | " 2 6 24 120 " 1900 | ] 1901 | } 1902 | ], 1903 | "prompt_number": 72 1904 | }, 1905 | { 1906 | "cell_type": "markdown", 1907 | "metadata": {}, 1908 | "source": [ 1909 | "And we can explicitly define to which order the series expansion should be carried out:" 1910 | ] 1911 | }, 1912 | { 1913 | "cell_type": "code", 1914 | "collapsed": false, 1915 | "input": [ 1916 | "series(exp(x), x, 1, 10)" 1917 | ], 1918 | "language": "python", 1919 | "metadata": {}, 1920 | "outputs": [ 1921 | { 1922 | "latex": [ 1923 | "$$e + e x + \\frac{1}{2} e x^{2} + \\frac{1}{6} e x^{3} + \\frac{1}{24} e x^{4} + \\frac{1}{120} e x^{5} + \\frac{1}{720} e x^{6} + \\frac{1}{5040} e x^{7} + \\frac{1}{40320} e x^{8} + \\frac{1}{362880} e x^{9} + \\mathcal{O}\\left(x^{10}\\right)$$" 1924 | ], 1925 | "metadata": {}, 1926 | "output_type": "pyout", 1927 | "prompt_number": 73, 1928 | "text": [ 1929 | " 2 3 4 5 6 7 8 9 \n", 1930 | " \u212f\u22c5x \u212f\u22c5x \u212f\u22c5x \u212f\u22c5x \u212f\u22c5x \u212f\u22c5x \u212f\u22c5x \u212f\u22c5x \u239b 10\u239e\n", 1931 | "\u212f + \u212f\u22c5x + \u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500\u2500\u2500 + O\u239dx \u23a0\n", 1932 | " 2 6 24 120 720 5040 40320 362880 " 1933 | ] 1934 | } 1935 | ], 1936 | "prompt_number": 73 1937 | }, 1938 | { 1939 | "cell_type": "markdown", 1940 | "metadata": {}, 1941 | "source": [ 1942 | "The series expansion includes the order of the approximation, which is very useful for keeping track of the order of validity when we do calculations with series expansions of different order:" 1943 | ] 1944 | }, 1945 | { 1946 | "cell_type": "code", 1947 | "collapsed": false, 1948 | "input": [ 1949 | "s1 = cos(x).series(x, 0, 5)\n", 1950 | "s1" 1951 | ], 1952 | "language": "python", 1953 | "metadata": {}, 1954 | "outputs": [ 1955 | { 1956 | "latex": [ 1957 | "$$1 - \\frac{1}{2} x^{2} + \\frac{1}{24} x^{4} + \\mathcal{O}\\left(x^{5}\\right)$$" 1958 | ], 1959 | "metadata": {}, 1960 | "output_type": "pyout", 1961 | "prompt_number": 74, 1962 | "text": [ 1963 | " 2 4 \n", 1964 | " x x \u239b 5\u239e\n", 1965 | "1 - \u2500\u2500 + \u2500\u2500 + O\u239dx \u23a0\n", 1966 | " 2 24 " 1967 | ] 1968 | } 1969 | ], 1970 | "prompt_number": 74 1971 | }, 1972 | { 1973 | "cell_type": "code", 1974 | "collapsed": false, 1975 | "input": [ 1976 | "s2 = sin(x).series(x, 0, 2)\n", 1977 | "s2" 1978 | ], 1979 | "language": "python", 1980 | "metadata": {}, 1981 | "outputs": [ 1982 | { 1983 | "latex": [ 1984 | "$$x + \\mathcal{O}\\left(x^{2}\\right)$$" 1985 | ], 1986 | "metadata": {}, 1987 | "output_type": "pyout", 1988 | "prompt_number": 75, 1989 | "text": [ 1990 | " \u239b 2\u239e\n", 1991 | "x + O\u239dx \u23a0" 1992 | ] 1993 | } 1994 | ], 1995 | "prompt_number": 75 1996 | }, 1997 | { 1998 | "cell_type": "code", 1999 | "collapsed": false, 2000 | "input": [ 2001 | "expand(s1 * s2)" 2002 | ], 2003 | "language": "python", 2004 | "metadata": {}, 2005 | "outputs": [ 2006 | { 2007 | "latex": [ 2008 | "$$x + \\mathcal{O}\\left(x^{2}\\right)$$" 2009 | ], 2010 | "metadata": {}, 2011 | "output_type": "pyout", 2012 | "prompt_number": 76, 2013 | "text": [ 2014 | " \u239b 2\u239e\n", 2015 | "x + O\u239dx \u23a0" 2016 | ] 2017 | } 2018 | ], 2019 | "prompt_number": 76 2020 | }, 2021 | { 2022 | "cell_type": "markdown", 2023 | "metadata": {}, 2024 | "source": [ 2025 | "If we want to get rid of the order information we can use the `removeO` method:" 2026 | ] 2027 | }, 2028 | { 2029 | "cell_type": "code", 2030 | "collapsed": false, 2031 | "input": [ 2032 | "expand(s1.removeO() * s2.removeO())" 2033 | ], 2034 | "language": "python", 2035 | "metadata": {}, 2036 | "outputs": [ 2037 | { 2038 | "latex": [ 2039 | "$$\\frac{1}{24} x^{5} - \\frac{1}{2} x^{3} + x$$" 2040 | ], 2041 | "metadata": {}, 2042 | "output_type": "pyout", 2043 | "prompt_number": 77, 2044 | "text": [ 2045 | " 5 3 \n", 2046 | "x x \n", 2047 | "\u2500\u2500 - \u2500\u2500 + x\n", 2048 | "24 2 " 2049 | ] 2050 | } 2051 | ], 2052 | "prompt_number": 77 2053 | }, 2054 | { 2055 | "cell_type": "markdown", 2056 | "metadata": {}, 2057 | "source": [ 2058 | "But note that this is not the correct expansion of $\\cos(x)\\sin(x)$ to $5$th order:" 2059 | ] 2060 | }, 2061 | { 2062 | "cell_type": "code", 2063 | "collapsed": false, 2064 | "input": [ 2065 | "(cos(x)*sin(x)).series(x, 0, 6)" 2066 | ], 2067 | "language": "python", 2068 | "metadata": {}, 2069 | "outputs": [ 2070 | { 2071 | "latex": [ 2072 | "$$x - \\frac{2}{3} x^{3} + \\frac{2}{15} x^{5} + \\mathcal{O}\\left(x^{6}\\right)$$" 2073 | ], 2074 | "metadata": {}, 2075 | "output_type": "pyout", 2076 | "prompt_number": 78, 2077 | "text": [ 2078 | " 3 5 \n", 2079 | " 2\u22c5x 2\u22c5x \u239b 6\u239e\n", 2080 | "x - \u2500\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500 + O\u239dx \u23a0\n", 2081 | " 3 15 " 2082 | ] 2083 | } 2084 | ], 2085 | "prompt_number": 78 2086 | }, 2087 | { 2088 | "cell_type": "heading", 2089 | "level": 2, 2090 | "metadata": {}, 2091 | "source": [ 2092 | "Linear algebra" 2093 | ] 2094 | }, 2095 | { 2096 | "cell_type": "heading", 2097 | "level": 3, 2098 | "metadata": {}, 2099 | "source": [ 2100 | "Matrices" 2101 | ] 2102 | }, 2103 | { 2104 | "cell_type": "markdown", 2105 | "metadata": {}, 2106 | "source": [ 2107 | "Matrices are defined using the `Matrix` class:" 2108 | ] 2109 | }, 2110 | { 2111 | "cell_type": "code", 2112 | "collapsed": false, 2113 | "input": [ 2114 | "m11, m12, m21, m22 = symbols(\"m11, m12, m21, m22\")\n", 2115 | "b1, b2 = symbols(\"b1, b2\")" 2116 | ], 2117 | "language": "python", 2118 | "metadata": {}, 2119 | "outputs": [], 2120 | "prompt_number": 79 2121 | }, 2122 | { 2123 | "cell_type": "code", 2124 | "collapsed": false, 2125 | "input": [ 2126 | "A = Matrix([[m11, m12],[m21, m22]])\n", 2127 | "A" 2128 | ], 2129 | "language": "python", 2130 | "metadata": {}, 2131 | "outputs": [ 2132 | { 2133 | "latex": [ 2134 | "$$\\left[\\begin{smallmatrix}m_{11} & m_{12}\\\\m_{21} & m_{22}\\end{smallmatrix}\\right]$$" 2135 | ], 2136 | "metadata": {}, 2137 | "output_type": "pyout", 2138 | "prompt_number": 80, 2139 | "text": [ 2140 | "\u23a1m\u2081\u2081 m\u2081\u2082\u23a4\n", 2141 | "\u23a2 \u23a5\n", 2142 | "\u23a3m\u2082\u2081 m\u2082\u2082\u23a6" 2143 | ] 2144 | } 2145 | ], 2146 | "prompt_number": 80 2147 | }, 2148 | { 2149 | "cell_type": "code", 2150 | "collapsed": false, 2151 | "input": [ 2152 | "b = Matrix([[b1], [b2]])\n", 2153 | "b" 2154 | ], 2155 | "language": "python", 2156 | "metadata": {}, 2157 | "outputs": [ 2158 | { 2159 | "latex": [ 2160 | "$$\\left[\\begin{smallmatrix}b_{1}\\\\b_{2}\\end{smallmatrix}\\right]$$" 2161 | ], 2162 | "metadata": {}, 2163 | "output_type": "pyout", 2164 | "prompt_number": 81, 2165 | "text": [ 2166 | "\u23a1b\u2081\u23a4\n", 2167 | "\u23a2 \u23a5\n", 2168 | "\u23a3b\u2082\u23a6" 2169 | ] 2170 | } 2171 | ], 2172 | "prompt_number": 81 2173 | }, 2174 | { 2175 | "cell_type": "markdown", 2176 | "metadata": {}, 2177 | "source": [ 2178 | "With `Matrix` class instances we can do the usual matrix algebra operations:" 2179 | ] 2180 | }, 2181 | { 2182 | "cell_type": "code", 2183 | "collapsed": false, 2184 | "input": [ 2185 | "A**2" 2186 | ], 2187 | "language": "python", 2188 | "metadata": {}, 2189 | "outputs": [ 2190 | { 2191 | "latex": [ 2192 | "$$\\left[\\begin{smallmatrix}m_{11}^{2} + m_{12} m_{21} & m_{11} m_{12} + m_{12} m_{22}\\\\m_{11} m_{21} + m_{21} m_{22} & m_{12} m_{21} + m_{22}^{2}\\end{smallmatrix}\\right]$$" 2193 | ], 2194 | "metadata": {}, 2195 | "output_type": "pyout", 2196 | "prompt_number": 82, 2197 | "text": [ 2198 | "\u23a1 2 \u23a4\n", 2199 | "\u23a2 m\u2081\u2081 + m\u2081\u2082\u22c5m\u2082\u2081 m\u2081\u2081\u22c5m\u2081\u2082 + m\u2081\u2082\u22c5m\u2082\u2082\u23a5\n", 2200 | "\u23a2 \u23a5\n", 2201 | "\u23a2 2 \u23a5\n", 2202 | "\u23a3m\u2081\u2081\u22c5m\u2082\u2081 + m\u2082\u2081\u22c5m\u2082\u2082 m\u2081\u2082\u22c5m\u2082\u2081 + m\u2082\u2082 \u23a6" 2203 | ] 2204 | } 2205 | ], 2206 | "prompt_number": 82 2207 | }, 2208 | { 2209 | "cell_type": "code", 2210 | "collapsed": false, 2211 | "input": [ 2212 | "A * b" 2213 | ], 2214 | "language": "python", 2215 | "metadata": {}, 2216 | "outputs": [ 2217 | { 2218 | "latex": [ 2219 | "$$\\left[\\begin{smallmatrix}b_{1} m_{11} + b_{2} m_{12}\\\\b_{1} m_{21} + b_{2} m_{22}\\end{smallmatrix}\\right]$$" 2220 | ], 2221 | "metadata": {}, 2222 | "output_type": "pyout", 2223 | "prompt_number": 83, 2224 | "text": [ 2225 | "\u23a1b\u2081\u22c5m\u2081\u2081 + b\u2082\u22c5m\u2081\u2082\u23a4\n", 2226 | "\u23a2 \u23a5\n", 2227 | "\u23a3b\u2081\u22c5m\u2082\u2081 + b\u2082\u22c5m\u2082\u2082\u23a6" 2228 | ] 2229 | } 2230 | ], 2231 | "prompt_number": 83 2232 | }, 2233 | { 2234 | "cell_type": "markdown", 2235 | "metadata": {}, 2236 | "source": [ 2237 | "And calculate determinants and inverses, and the like:" 2238 | ] 2239 | }, 2240 | { 2241 | "cell_type": "code", 2242 | "collapsed": false, 2243 | "input": [ 2244 | "A.det()" 2245 | ], 2246 | "language": "python", 2247 | "metadata": {}, 2248 | "outputs": [ 2249 | { 2250 | "latex": [ 2251 | "$$m_{11} m_{22} - m_{12} m_{21}$$" 2252 | ], 2253 | "metadata": {}, 2254 | "output_type": "pyout", 2255 | "prompt_number": 84, 2256 | "text": [ 2257 | "m\u2081\u2081\u22c5m\u2082\u2082 - m\u2081\u2082\u22c5m\u2082\u2081" 2258 | ] 2259 | } 2260 | ], 2261 | "prompt_number": 84 2262 | }, 2263 | { 2264 | "cell_type": "code", 2265 | "collapsed": false, 2266 | "input": [ 2267 | "A.inv()" 2268 | ], 2269 | "language": "python", 2270 | "metadata": {}, 2271 | "outputs": [ 2272 | { 2273 | "latex": [ 2274 | "$$\\left[\\begin{smallmatrix}\\frac{1}{m_{11}} + \\frac{m_{12} m_{21}}{m_{11}^{2} \\left(m_{22} - \\frac{m_{12} m_{21}}{m_{11}}\\right)} & - \\frac{m_{12}}{m_{11} \\left(m_{22} - \\frac{m_{12} m_{21}}{m_{11}}\\right)}\\\\- \\frac{m_{21}}{m_{11} \\left(m_{22} - \\frac{m_{12} m_{21}}{m_{11}}\\right)} & \\frac{1}{m_{22} - \\frac{m_{12} m_{21}}{m_{11}}}\\end{smallmatrix}\\right]$$" 2275 | ], 2276 | "metadata": {}, 2277 | "output_type": "pyout", 2278 | "prompt_number": 85, 2279 | "text": [ 2280 | "\u23a1 1 m\u2081\u2082\u22c5m\u2082\u2081 -m\u2081\u2082 \u23a4\n", 2281 | "\u23a2\u2500\u2500\u2500 + \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u23a5\n", 2282 | "\u23a2m\u2081\u2081 2 \u239b m\u2081\u2082\u22c5m\u2082\u2081\u239e \u239b m\u2081\u2082\u22c5m\u2082\u2081\u239e\u23a5\n", 2283 | "\u23a2 m\u2081\u2081 \u22c5\u239cm\u2082\u2082 - \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u239f m\u2081\u2081\u22c5\u239cm\u2082\u2082 - \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u239f\u23a5\n", 2284 | "\u23a2 \u239d m\u2081\u2081 \u23a0 \u239d m\u2081\u2081 \u23a0\u23a5\n", 2285 | "\u23a2 \u23a5\n", 2286 | "\u23a2 -m\u2082\u2081 1 \u23a5\n", 2287 | "\u23a2 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u23a5\n", 2288 | "\u23a2 \u239b m\u2081\u2082\u22c5m\u2082\u2081\u239e m\u2081\u2082\u22c5m\u2082\u2081 \u23a5\n", 2289 | "\u23a2 m\u2081\u2081\u22c5\u239cm\u2082\u2082 - \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u239f m\u2082\u2082 - \u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u23a5\n", 2290 | "\u23a3 \u239d m\u2081\u2081 \u23a0 m\u2081\u2081 \u23a6" 2291 | ] 2292 | } 2293 | ], 2294 | "prompt_number": 85 2295 | }, 2296 | { 2297 | "cell_type": "heading", 2298 | "level": 2, 2299 | "metadata": {}, 2300 | "source": [ 2301 | "Solving equations" 2302 | ] 2303 | }, 2304 | { 2305 | "cell_type": "markdown", 2306 | "metadata": {}, 2307 | "source": [ 2308 | "For solving equations and systems of equations we can use the `solve` function:" 2309 | ] 2310 | }, 2311 | { 2312 | "cell_type": "code", 2313 | "collapsed": false, 2314 | "input": [ 2315 | "solve(x**2 - 1, x)" 2316 | ], 2317 | "language": "python", 2318 | "metadata": {}, 2319 | "outputs": [ 2320 | { 2321 | "latex": [ 2322 | "$$\\begin{bmatrix}-1, & 1\\end{bmatrix}$$" 2323 | ], 2324 | "metadata": {}, 2325 | "output_type": "pyout", 2326 | "prompt_number": 86, 2327 | "text": [ 2328 | "[-1, 1]" 2329 | ] 2330 | } 2331 | ], 2332 | "prompt_number": 86 2333 | }, 2334 | { 2335 | "cell_type": "code", 2336 | "collapsed": false, 2337 | "input": [ 2338 | "solve(x**4 - x**2 - 1, x)" 2339 | ], 2340 | "language": "python", 2341 | "metadata": {}, 2342 | "outputs": [ 2343 | { 2344 | "latex": [ 2345 | "$$\\begin{bmatrix}- i \\sqrt{- \\frac{1}{2} + \\frac{1}{2} \\sqrt{5}}, & i \\sqrt{- \\frac{1}{2} + \\frac{1}{2} \\sqrt{5}}, & - \\sqrt{\\frac{1}{2} + \\frac{1}{2} \\sqrt{5}}, & \\sqrt{\\frac{1}{2} + \\frac{1}{2} \\sqrt{5}}\\end{bmatrix}$$" 2346 | ], 2347 | "metadata": {}, 2348 | "output_type": "pyout", 2349 | "prompt_number": 87, 2350 | "text": [ 2351 | "\u23a1 _____________ _____________ ___________ ________\n", 2352 | "\u23a2 \u2571 ___ \u2571 ___ \u2571 ___ \u2571 _\n", 2353 | "\u23a2 \u2571 1 \u2572\u2571 5 \u2571 1 \u2572\u2571 5 \u2571 1 \u2572\u2571 5 \u2571 1 \u2572\u2571 \n", 2354 | "\u23a2-\u2148\u22c5 \u2571 - \u2500 + \u2500\u2500\u2500\u2500\u2500 , \u2148\u22c5 \u2571 - \u2500 + \u2500\u2500\u2500\u2500\u2500 , - \u2571 \u2500 + \u2500\u2500\u2500\u2500\u2500 , \u2571 \u2500 + \u2500\u2500\u2500\n", 2355 | "\u23a3 \u2572\u2571 2 2 \u2572\u2571 2 2 \u2572\u2571 2 2 \u2572\u2571 2 2\n", 2356 | "\n", 2357 | "___\u23a4\n", 2358 | "__ \u23a5\n", 2359 | "5 \u23a5\n", 2360 | "\u2500\u2500 \u23a5\n", 2361 | " \u23a6" 2362 | ] 2363 | } 2364 | ], 2365 | "prompt_number": 87 2366 | }, 2367 | { 2368 | "cell_type": "markdown", 2369 | "metadata": {}, 2370 | "source": [ 2371 | "System of equations:" 2372 | ] 2373 | }, 2374 | { 2375 | "cell_type": "code", 2376 | "collapsed": false, 2377 | "input": [ 2378 | "solve([x + y - 1, x - y - 1], [x,y])" 2379 | ], 2380 | "language": "python", 2381 | "metadata": {}, 2382 | "outputs": [ 2383 | { 2384 | "latex": [ 2385 | "$$\\begin{Bmatrix}x : 1, & y : 0\\end{Bmatrix}$$" 2386 | ], 2387 | "metadata": {}, 2388 | "output_type": "pyout", 2389 | "prompt_number": 88, 2390 | "text": [ 2391 | "{x: 1, y: 0}" 2392 | ] 2393 | } 2394 | ], 2395 | "prompt_number": 88 2396 | }, 2397 | { 2398 | "cell_type": "markdown", 2399 | "metadata": {}, 2400 | "source": [ 2401 | "In terms of other symbolic expressions:" 2402 | ] 2403 | }, 2404 | { 2405 | "cell_type": "code", 2406 | "collapsed": false, 2407 | "input": [ 2408 | "solve([x + y - a, x - y - c], [x,y])" 2409 | ], 2410 | "language": "python", 2411 | "metadata": {}, 2412 | "outputs": [ 2413 | { 2414 | "latex": [ 2415 | "$$\\begin{Bmatrix}x : \\frac{1}{2} a + \\frac{1}{2} c, & y : \\frac{1}{2} a - \\frac{1}{2} c\\end{Bmatrix}$$" 2416 | ], 2417 | "metadata": {}, 2418 | "output_type": "pyout", 2419 | "prompt_number": 89, 2420 | "text": [ 2421 | "\u23a7 a c a c\u23ab\n", 2422 | "\u23a8x: \u2500 + \u2500, y: \u2500 - \u2500\u23ac\n", 2423 | "\u23a9 2 2 2 2\u23ad" 2424 | ] 2425 | } 2426 | ], 2427 | "prompt_number": 89 2428 | }, 2429 | { 2430 | "cell_type": "heading", 2431 | "level": 2, 2432 | "metadata": {}, 2433 | "source": [ 2434 | "Quantum mechanics: noncommuting variables" 2435 | ] 2436 | }, 2437 | { 2438 | "cell_type": "markdown", 2439 | "metadata": {}, 2440 | "source": [ 2441 | "How about non-commuting symbols? In quantum mechanics we need to work with noncommuting operators, and SymPy has a nice support for noncommuting symbols and even a subpackage for quantum mechanics related calculations!" 2442 | ] 2443 | }, 2444 | { 2445 | "cell_type": "code", 2446 | "collapsed": false, 2447 | "input": [ 2448 | "from sympy.physics.quantum import *" 2449 | ], 2450 | "language": "python", 2451 | "metadata": {}, 2452 | "outputs": [], 2453 | "prompt_number": 5 2454 | }, 2455 | { 2456 | "cell_type": "heading", 2457 | "level": 2, 2458 | "metadata": {}, 2459 | "source": [ 2460 | "States" 2461 | ] 2462 | }, 2463 | { 2464 | "cell_type": "markdown", 2465 | "metadata": {}, 2466 | "source": [ 2467 | "We can define symbol states, kets and bras:" 2468 | ] 2469 | }, 2470 | { 2471 | "cell_type": "code", 2472 | "collapsed": false, 2473 | "input": [ 2474 | "Ket('psi')" 2475 | ], 2476 | "language": "python", 2477 | "metadata": {}, 2478 | "outputs": [ 2479 | { 2480 | "latex": [ 2481 | "$${\\left|\\psi\\right\\rangle }$$" 2482 | ], 2483 | "metadata": {}, 2484 | "output_type": "pyout", 2485 | "prompt_number": 91, 2486 | "text": [ 2487 | "\u2758\u03c8\u27e9" 2488 | ] 2489 | } 2490 | ], 2491 | "prompt_number": 91 2492 | }, 2493 | { 2494 | "cell_type": "code", 2495 | "collapsed": false, 2496 | "input": [ 2497 | "Bra('psi')" 2498 | ], 2499 | "language": "python", 2500 | "metadata": {}, 2501 | "outputs": [ 2502 | { 2503 | "latex": [ 2504 | "$${\\left\\langle \\psi\\right|}$$" 2505 | ], 2506 | "metadata": {}, 2507 | "output_type": "pyout", 2508 | "prompt_number": 92, 2509 | "text": [ 2510 | "\u27e8\u03c8\u2758" 2511 | ] 2512 | } 2513 | ], 2514 | "prompt_number": 92 2515 | }, 2516 | { 2517 | "cell_type": "code", 2518 | "collapsed": false, 2519 | "input": [ 2520 | "u = Ket('0')\n", 2521 | "d = Ket('1')\n", 2522 | "\n", 2523 | "a, b = symbols('alpha beta', complex=True)" 2524 | ], 2525 | "language": "python", 2526 | "metadata": {}, 2527 | "outputs": [], 2528 | "prompt_number": 93 2529 | }, 2530 | { 2531 | "cell_type": "code", 2532 | "collapsed": false, 2533 | "input": [ 2534 | "phi = a * u + sqrt(1-abs(a)**2) * d; phi" 2535 | ], 2536 | "language": "python", 2537 | "metadata": {}, 2538 | "outputs": [ 2539 | { 2540 | "latex": [ 2541 | "$$\\alpha {\\left|0\\right\\rangle } + \\sqrt{- \\left\\lvert{\\alpha}\\right\\rvert^{2} + 1} {\\left|1\\right\\rangle }$$" 2542 | ], 2543 | "metadata": {}, 2544 | "output_type": "pyout", 2545 | "prompt_number": 94, 2546 | "text": [ 2547 | " ____________ \n", 2548 | " \u2571 2 \n", 2549 | "\u03b1\u22c5\u27580\u27e9 + \u2572\u2571 - \u2502\u03b1\u2502 + 1 \u22c5\u27581\u27e9" 2550 | ] 2551 | } 2552 | ], 2553 | "prompt_number": 94 2554 | }, 2555 | { 2556 | "cell_type": "code", 2557 | "collapsed": false, 2558 | "input": [ 2559 | "Dagger(phi)" 2560 | ], 2561 | "language": "python", 2562 | "metadata": {}, 2563 | "outputs": [ 2564 | { 2565 | "latex": [ 2566 | "$$\\overline{\\alpha} {\\left\\langle 0\\right|} + \\overline{\\sqrt{- \\left\\lvert{\\alpha}\\right\\rvert^{2} + 1}} {\\left\\langle 1\\right|}$$" 2567 | ], 2568 | "metadata": {}, 2569 | "output_type": "pyout", 2570 | "prompt_number": 95, 2571 | "text": [ 2572 | " _______________ \n", 2573 | " ____________ \n", 2574 | "_ \u2571 2 \n", 2575 | "\u03b1\u22c5\u27e80\u2758 + \u2572\u2571 - \u2502\u03b1\u2502 + 1 \u22c5\u27e81\u2758" 2576 | ] 2577 | } 2578 | ], 2579 | "prompt_number": 95 2580 | }, 2581 | { 2582 | "cell_type": "code", 2583 | "collapsed": false, 2584 | "input": [ 2585 | "Dagger(phi) * d" 2586 | ], 2587 | "language": "python", 2588 | "metadata": {}, 2589 | "outputs": [ 2590 | { 2591 | "latex": [ 2592 | "$$\\left(\\overline{\\alpha} {\\left\\langle 0\\right|} + \\overline{\\sqrt{- \\left\\lvert{\\alpha}\\right\\rvert^{2} + 1}} {\\left\\langle 1\\right|}\\right) {\\left|1\\right\\rangle }$$" 2593 | ], 2594 | "metadata": {}, 2595 | "output_type": "pyout", 2596 | "prompt_number": 96, 2597 | "text": [ 2598 | "\u239b _______________ \u239e \n", 2599 | "\u239c ____________ \u239f \n", 2600 | "\u239c_ \u2571 2 \u239f \n", 2601 | "\u239d\u03b1\u22c5\u27e80\u2758 + \u2572\u2571 - \u2502\u03b1\u2502 + 1 \u22c5\u27e81\u2758\u23a0\u22c5\u27581\u27e9" 2602 | ] 2603 | } 2604 | ], 2605 | "prompt_number": 96 2606 | }, 2607 | { 2608 | "cell_type": "markdown", 2609 | "metadata": {}, 2610 | "source": [ 2611 | "Use `qapply` to distribute a mutiplication:" 2612 | ] 2613 | }, 2614 | { 2615 | "cell_type": "code", 2616 | "collapsed": false, 2617 | "input": [ 2618 | "qapply(Dagger(phi) * d)" 2619 | ], 2620 | "language": "python", 2621 | "metadata": {}, 2622 | "outputs": [ 2623 | { 2624 | "latex": [ 2625 | "$$\\overline{\\alpha} \\left\\langle 0 \\right. {\\left|1\\right\\rangle } + \\overline{\\sqrt{- \\left\\lvert{\\alpha}\\right\\rvert^{2} + 1}} \\left\\langle 1 \\right. {\\left|1\\right\\rangle }$$" 2626 | ], 2627 | "metadata": {}, 2628 | "output_type": "pyout", 2629 | "prompt_number": 97, 2630 | "text": [ 2631 | " _______________ \n", 2632 | " ____________ \n", 2633 | "_ \u2571 2 \n", 2634 | "\u03b1\u22c5\u27e80\u27581\u27e9 + \u2572\u2571 - \u2502\u03b1\u2502 + 1 \u22c5\u27e81\u27581\u27e9" 2635 | ] 2636 | } 2637 | ], 2638 | "prompt_number": 97 2639 | }, 2640 | { 2641 | "cell_type": "code", 2642 | "collapsed": false, 2643 | "input": [ 2644 | "qapply(Dagger(phi) * u)" 2645 | ], 2646 | "language": "python", 2647 | "metadata": {}, 2648 | "outputs": [ 2649 | { 2650 | "latex": [ 2651 | "$$\\overline{\\alpha} \\left\\langle 0 \\right. {\\left|0\\right\\rangle } + \\overline{\\sqrt{- \\left\\lvert{\\alpha}\\right\\rvert^{2} + 1}} \\left\\langle 1 \\right. {\\left|0\\right\\rangle }$$" 2652 | ], 2653 | "metadata": {}, 2654 | "output_type": "pyout", 2655 | "prompt_number": 98, 2656 | "text": [ 2657 | " _______________ \n", 2658 | " ____________ \n", 2659 | "_ \u2571 2 \n", 2660 | "\u03b1\u22c5\u27e80\u27580\u27e9 + \u2572\u2571 - \u2502\u03b1\u2502 + 1 \u22c5\u27e81\u27580\u27e9" 2661 | ] 2662 | } 2663 | ], 2664 | "prompt_number": 98 2665 | }, 2666 | { 2667 | "cell_type": "heading", 2668 | "level": 3, 2669 | "metadata": {}, 2670 | "source": [ 2671 | "Operators" 2672 | ] 2673 | }, 2674 | { 2675 | "cell_type": "code", 2676 | "collapsed": false, 2677 | "input": [ 2678 | "A = Operator('A')\n", 2679 | "B = Operator('B')" 2680 | ], 2681 | "language": "python", 2682 | "metadata": {}, 2683 | "outputs": [], 2684 | "prompt_number": 6 2685 | }, 2686 | { 2687 | "cell_type": "markdown", 2688 | "metadata": {}, 2689 | "source": [ 2690 | "Check if they are commuting!" 2691 | ] 2692 | }, 2693 | { 2694 | "cell_type": "code", 2695 | "collapsed": false, 2696 | "input": [ 2697 | "A * B == B * A" 2698 | ], 2699 | "language": "python", 2700 | "metadata": {}, 2701 | "outputs": [ 2702 | { 2703 | "latex": [ 2704 | "$$False$$" 2705 | ], 2706 | "metadata": {}, 2707 | "output_type": "pyout", 2708 | "prompt_number": 100, 2709 | "text": [ 2710 | "False" 2711 | ] 2712 | } 2713 | ], 2714 | "prompt_number": 100 2715 | }, 2716 | { 2717 | "cell_type": "code", 2718 | "collapsed": false, 2719 | "input": [ 2720 | "expand((A+B)**3)" 2721 | ], 2722 | "language": "python", 2723 | "metadata": {}, 2724 | "outputs": [ 2725 | { 2726 | "latex": [ 2727 | "$$A B A + A \\left(B\\right)^{2} + \\left(A\\right)^{2} B + \\left(A\\right)^{3} + B A B + B \\left(A\\right)^{2} + \\left(B\\right)^{2} A + \\left(B\\right)^{3}$$" 2728 | ], 2729 | "metadata": {}, 2730 | "output_type": "pyout", 2731 | "prompt_number": 101, 2732 | "text": [ 2733 | " 2 2 3 2 2 3\n", 2734 | "A\u22c5B\u22c5A + A\u22c5B + A \u22c5B + A + B\u22c5A\u22c5B + B\u22c5A + B \u22c5A + B " 2735 | ] 2736 | } 2737 | ], 2738 | "prompt_number": 101 2739 | }, 2740 | { 2741 | "cell_type": "code", 2742 | "collapsed": false, 2743 | "input": [ 2744 | "c = Commutator(A,B)\n", 2745 | "c" 2746 | ], 2747 | "language": "python", 2748 | "metadata": {}, 2749 | "outputs": [ 2750 | { 2751 | "latex": [ 2752 | "$$\\left[A,B\\right]$$" 2753 | ], 2754 | "metadata": {}, 2755 | "output_type": "pyout", 2756 | "prompt_number": 102, 2757 | "text": [ 2758 | "[A,B]" 2759 | ] 2760 | } 2761 | ], 2762 | "prompt_number": 102 2763 | }, 2764 | { 2765 | "cell_type": "markdown", 2766 | "metadata": {}, 2767 | "source": [ 2768 | "We can use the `doit` method to evaluate the commutator:" 2769 | ] 2770 | }, 2771 | { 2772 | "cell_type": "code", 2773 | "collapsed": false, 2774 | "input": [ 2775 | "c.doit()" 2776 | ], 2777 | "language": "python", 2778 | "metadata": {}, 2779 | "outputs": [ 2780 | { 2781 | "latex": [ 2782 | "$$A B - B A$$" 2783 | ], 2784 | "metadata": {}, 2785 | "output_type": "pyout", 2786 | "prompt_number": 103, 2787 | "text": [ 2788 | "A\u22c5B - B\u22c5A" 2789 | ] 2790 | } 2791 | ], 2792 | "prompt_number": 103 2793 | }, 2794 | { 2795 | "cell_type": "markdown", 2796 | "metadata": {}, 2797 | "source": [ 2798 | "We can mix quantum operators with C-numbers:" 2799 | ] 2800 | }, 2801 | { 2802 | "cell_type": "code", 2803 | "collapsed": false, 2804 | "input": [ 2805 | "c = Commutator(a * A, b * B)\n", 2806 | "c" 2807 | ], 2808 | "language": "python", 2809 | "metadata": {}, 2810 | "outputs": [ 2811 | { 2812 | "latex": [ 2813 | "$$\\alpha \\beta \\left[A,B\\right]$$" 2814 | ], 2815 | "metadata": {}, 2816 | "output_type": "pyout", 2817 | "prompt_number": 104, 2818 | "text": [ 2819 | "\u03b1\u22c5\u03b2\u22c5[A,B]" 2820 | ] 2821 | } 2822 | ], 2823 | "prompt_number": 104 2824 | }, 2825 | { 2826 | "cell_type": "markdown", 2827 | "metadata": {}, 2828 | "source": [ 2829 | "To expand the commutator, use the `expand` method with the `commutator=True` keyword argument:" 2830 | ] 2831 | }, 2832 | { 2833 | "cell_type": "code", 2834 | "collapsed": false, 2835 | "input": [ 2836 | "c = Commutator(A+B, A*B)\n", 2837 | "c.expand(commutator=True)" 2838 | ], 2839 | "language": "python", 2840 | "metadata": {}, 2841 | "outputs": [ 2842 | { 2843 | "latex": [ 2844 | "$$- \\left[A,B\\right] B + A \\left[A,B\\right]$$" 2845 | ], 2846 | "metadata": {}, 2847 | "output_type": "pyout", 2848 | "prompt_number": 105, 2849 | "text": [ 2850 | "-[A,B]\u22c5B + A\u22c5[A,B]" 2851 | ] 2852 | } 2853 | ], 2854 | "prompt_number": 105 2855 | }, 2856 | { 2857 | "cell_type": "code", 2858 | "collapsed": false, 2859 | "input": [ 2860 | "Dagger(Commutator(A, B))" 2861 | ], 2862 | "language": "python", 2863 | "metadata": {}, 2864 | "outputs": [ 2865 | { 2866 | "latex": [ 2867 | "$$- \\left[A^{\\dagger},B^{\\dagger}\\right]$$" 2868 | ], 2869 | "metadata": {}, 2870 | "output_type": "pyout", 2871 | "prompt_number": 106, 2872 | "text": [ 2873 | " \u23a1 \u2020 \u2020\u23a4\n", 2874 | "-\u23a3A ,B \u23a6" 2875 | ] 2876 | } 2877 | ], 2878 | "prompt_number": 106 2879 | }, 2880 | { 2881 | "cell_type": "code", 2882 | "collapsed": false, 2883 | "input": [ 2884 | "ac = AntiCommutator(A,B)" 2885 | ], 2886 | "language": "python", 2887 | "metadata": {}, 2888 | "outputs": [], 2889 | "prompt_number": 107 2890 | }, 2891 | { 2892 | "cell_type": "code", 2893 | "collapsed": false, 2894 | "input": [ 2895 | "ac.doit()" 2896 | ], 2897 | "language": "python", 2898 | "metadata": {}, 2899 | "outputs": [ 2900 | { 2901 | "latex": [ 2902 | "$$A B + B A$$" 2903 | ], 2904 | "metadata": {}, 2905 | "output_type": "pyout", 2906 | "prompt_number": 108, 2907 | "text": [ 2908 | "A\u22c5B + B\u22c5A" 2909 | ] 2910 | } 2911 | ], 2912 | "prompt_number": 108 2913 | }, 2914 | { 2915 | "cell_type": "heading", 2916 | "level": 4, 2917 | "metadata": {}, 2918 | "source": [ 2919 | "Example: Quadrature commutator" 2920 | ] 2921 | }, 2922 | { 2923 | "cell_type": "markdown", 2924 | "metadata": {}, 2925 | "source": [ 2926 | "Let's look at the commutator of the electromagnetic field quadatures $x$ and $p$. We can write the quadrature operators in terms of the creation and annihilation operators as:\n", 2927 | "\n", 2928 | "$\\displaystyle x = (a + a^\\dagger)/\\sqrt{2}$\n", 2929 | "\n", 2930 | "$\\displaystyle p = -i(a - a^\\dagger)/\\sqrt{2}$\n" 2931 | ] 2932 | }, 2933 | { 2934 | "cell_type": "code", 2935 | "collapsed": false, 2936 | "input": [ 2937 | "X = (A + Dagger(A))/sqrt(2)\n", 2938 | "X" 2939 | ], 2940 | "language": "python", 2941 | "metadata": {}, 2942 | "outputs": [ 2943 | { 2944 | "latex": [ 2945 | "$$\\frac{1}{2} \\sqrt{2} \\left(A^{\\dagger} + A\\right)$$" 2946 | ], 2947 | "metadata": {}, 2948 | "output_type": "pyout", 2949 | "prompt_number": 109, 2950 | "text": [ 2951 | " ___ \u239b \u2020 \u239e\n", 2952 | "\u2572\u2571 2 \u22c5\u239dA + A\u23a0\n", 2953 | "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", 2954 | " 2 " 2955 | ] 2956 | } 2957 | ], 2958 | "prompt_number": 109 2959 | }, 2960 | { 2961 | "cell_type": "code", 2962 | "collapsed": false, 2963 | "input": [ 2964 | "P = -I * (A - Dagger(A))/sqrt(2)\n", 2965 | "P" 2966 | ], 2967 | "language": "python", 2968 | "metadata": {}, 2969 | "outputs": [ 2970 | { 2971 | "latex": [ 2972 | "$$- \\frac{1}{2} \\sqrt{2} i \\left(- A^{\\dagger} + A\\right)$$" 2973 | ], 2974 | "metadata": {}, 2975 | "output_type": "pyout", 2976 | "prompt_number": 110, 2977 | "text": [ 2978 | " ___ \u239b \u2020 \u239e\n", 2979 | "-\u2572\u2571 2 \u22c5\u2148\u22c5\u239d- A + A\u23a0\n", 2980 | "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n", 2981 | " 2 " 2982 | ] 2983 | } 2984 | ], 2985 | "prompt_number": 110 2986 | }, 2987 | { 2988 | "cell_type": "markdown", 2989 | "metadata": {}, 2990 | "source": [ 2991 | "Let's expand the commutator $[x,p]$" 2992 | ] 2993 | }, 2994 | { 2995 | "cell_type": "code", 2996 | "collapsed": false, 2997 | "input": [ 2998 | "Commutator(X, P).expand(commutator=True).expand(commutator=True)" 2999 | ], 3000 | "language": "python", 3001 | "metadata": {}, 3002 | "outputs": [ 3003 | { 3004 | "latex": [ 3005 | "$$- i \\left[A^{\\dagger},A\\right]$$" 3006 | ], 3007 | "metadata": {}, 3008 | "output_type": "pyout", 3009 | "prompt_number": 111, 3010 | "text": [ 3011 | " \u23a1 \u2020 \u23a4\n", 3012 | "-\u2148\u22c5\u23a3A ,A\u23a6" 3013 | ] 3014 | } 3015 | ], 3016 | "prompt_number": 111 3017 | }, 3018 | { 3019 | "cell_type": "markdown", 3020 | "metadata": {}, 3021 | "source": [ 3022 | "Here we see directly that the well known commutation relation for the quadratures\n", 3023 | "\n", 3024 | "$[x,p]=i$\n", 3025 | "\n", 3026 | "is a directly related to\n", 3027 | "\n", 3028 | "$[A, A^\\dagger]=1$ \n", 3029 | "\n", 3030 | "(which SymPy does not know about, and does not simplify)." 3031 | ] 3032 | }, 3033 | { 3034 | "cell_type": "markdown", 3035 | "metadata": {}, 3036 | "source": [ 3037 | "For more details on the quantum module in SymPy, see:\n", 3038 | "\n", 3039 | "* http://docs.sympy.org/0.7.2/modules/physics/quantum/index.html\n", 3040 | "* http://nbviewer.ipython.org/urls/raw.github.com/ipython/ipython/master/docs/examples/notebooks/sympy_quantum_computing.ipynb" 3041 | ] 3042 | }, 3043 | { 3044 | "cell_type": "heading", 3045 | "level": 2, 3046 | "metadata": {}, 3047 | "source": [ 3048 | "Further reading" 3049 | ] 3050 | }, 3051 | { 3052 | "cell_type": "markdown", 3053 | "metadata": {}, 3054 | "source": [ 3055 | "* http://sympy.org/en/index.html - The SymPy projects web page.\n", 3056 | "* https://github.com/sympy/sympy - The source code of SymPy.\n", 3057 | "* http://live.sympy.org - Online version of SymPy for testing and demonstrations." 3058 | ] 3059 | }, 3060 | { 3061 | "cell_type": "heading", 3062 | "level": 2, 3063 | "metadata": {}, 3064 | "source": [ 3065 | "Versions" 3066 | ] 3067 | }, 3068 | { 3069 | "cell_type": "code", 3070 | "collapsed": false, 3071 | "input": [ 3072 | "%reload_ext version_information\n", 3073 | "\n", 3074 | "%version_information numpy, sympy" 3075 | ], 3076 | "language": "python", 3077 | "metadata": {}, 3078 | "outputs": [ 3079 | { 3080 | "html": [ 3081 | "
SoftwareVersion
Python3.3.2+ (default, Feb 28 2014, 00:52:16) [GCC 4.8.1]
IPython2.2.0
OSposix [linux]
numpy1.8.2
sympy0.7.5
Tue Aug 26 22:57:37 2014 JST
" 3082 | ], 3083 | "json": [ 3084 | "{ \"Software versions\" : [{ \"module\" : \"Python\", \"version\" : \"3.3.2+ (default, Feb 28 2014, 00:52:16) [GCC 4.8.1]\" }, { \"module\" : \"IPython\", \"version\" : \"2.2.0\" }, { \"module\" : \"OS\", \"version\" : \"posix [linux]\" }, { \"module\" : \"numpy\", \"version\" : \"1.8.2\" }, { \"module\" : \"sympy\", \"version\" : \"0.7.5\" } ] }" 3085 | ], 3086 | "latex": [ 3087 | "\\begin{table}\n", 3088 | "\\begin{tabular}{|l|l|}\\hline\n", 3089 | "{\\bf Software} & {\\bf Version} \\\\ \\hline\\hline\n", 3090 | "Python & 3.3.2+ (default, Feb 28 2014, 00:52:16) [GCC 4.8.1] \\\\ \\hline\n", 3091 | "IPython & 2.2.0 \\\\ \\hline\n", 3092 | "OS & posix [linux] \\\\ \\hline\n", 3093 | "numpy & 1.8.2 \\\\ \\hline\n", 3094 | "sympy & 0.7.5 \\\\ \\hline\n", 3095 | "\\hline \\multicolumn{2}{|l|}{Tue Aug 26 22:57:37 2014 JST} \\\\ \\hline\n", 3096 | "\\end{tabular}\n", 3097 | "\\end{table}\n" 3098 | ], 3099 | "metadata": {}, 3100 | "output_type": "pyout", 3101 | "prompt_number": 7, 3102 | "text": [ 3103 | "Software versions\n", 3104 | "Python 3.3.2+ (default, Feb 28 2014, 00:52:16) [GCC 4.8.1]\n", 3105 | "IPython 2.2.0\n", 3106 | "OS posix [linux]\n", 3107 | "numpy 1.8.2\n", 3108 | "sympy 0.7.5\n", 3109 | "\n", 3110 | "Tue Aug 26 22:57:37 2014 JST" 3111 | ] 3112 | } 3113 | ], 3114 | "prompt_number": 7 3115 | } 3116 | ], 3117 | "metadata": {} 3118 | } 3119 | ] 3120 | } --------------------------------------------------------------------------------