{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Symbolic Math: Differentiation Program\n", "\n", "This notebook describes how to write a program that will manipulate mathematical expressions, with an emphasis on differentiation. The program can compute $\\frac{d}{dx} x^2 + \\sin(x)$ to get the result $2x + \\cos(x)$. Usually in a programming language, when we say `sin(x)` we are computing with *numbers*, not *symbolic expressions*. That is, programming languages have built-in functions like `sin` and numbers like 0 so that we can ask for the value of `sin(0)` and get back 0. But now we want to do something different: treat $\\sin(x)$ as a *symbolic expression* that represents any value of $x$. That facility is not built-in to most programming languages, so we need a way to represent and manipulate these symbolic expressions. Python has a large system called `sympy` to do just that, but we will develop a smaller, simpler system from scratch.\n", "\n", "# Representing Symbolic Expressions as Tuples\n", "\n", "Here is one simple way to represent symbolic expressions: We will represent numbers as themselves, because they are already built-in to Python. We will represent math variable (such as $x$) and constants (such as $\\pi$) as Python strings (such as `'x'` and `'pi'`). And we will represent compound expressions (such as $x + 1$) as Python tuples, such as `('x', '+', 1)`. \n", "\n", "We will use the notion of [arity](http://en.wikipedia.org/wiki/Arity) of an expression. An expression can be: \n", "\n", "* Binary (arity = 2): $(x + y)$ is a binary expression because it has two sub-expressions, $x$ and $y$.\n", "* Unary (arity = 1): $-x$ and $\\sin(x)$ are both unary expressions, because they each have one sub-expression, $x$.\n", "* Nullary (arity = 0): $x$ and $3$ are both nullary, or *atomic* expressions, because they have no sub-expressions,\n", "\n", "We can define this as a Python function:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def arity(expr):\n", " \"The number of sub-expressions in this expression.\"\n", " if isinstance(expr, tuple):\n", " return len(expr) - 1\n", " else:\n", " return 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For example:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "exp = ('x', '+', 1)\n", "arity(exp)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This table summarizes the kinds of expressions and how we will represent them:\n", "\n", "
Math Expression | Math Type | Arity | Python Representation | Python Type\n", " | |||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
$3$ | Integer | 0 | 3int\n",
" | $3.14$ | Number | 0 | 3.14 | float\n",
" | $x$ | Variable | 0 | 'x' | str\n",
" | $\\pi$ | Constant | 0 | 'pi' | str\n",
" | $-x$ | Unary op | 1 | ('-', 'x') | tuple\n",
" | $\\sin(x)$ | Unary func | 1 | ('sin', 'x') | tuple\n",
" | $x+1$ | Binary op | 2 | ('x', '+', 1) | tuple\n",
" | $3x - y/2$ | Nested | Binary op 2 | ((3, '*', 'x'), '-', | ('y', '/', 2)) tuple\n",
"\n",
" | |
Math Expression | Math Type | Arity | Python Representation | Python Type\n", " | |||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
$3$ | Integer | 0 | 3int\n",
" | $3.14$ | Number | 0 | 3.14 | float\n",
" | $x$ | Variable | 0 | Expression('x') | Expression\n",
" | $\\pi$ | Constant | 0 | Expression('pi') | Expression\n",
" | $-x$ | Unary op | 1 | Expression('-', 'x') | Expression\n",
" | $\\sin(x)$ | Unary func | 1 | Expression('sin', 'x') | Expression\n",
" | $x+1$ | Binary op | 2 | Expression('+', x, 1) (given def for `x`) | Expression\n",
" | $3x - y/2$ | Nested | Binary op 2 | 3 * x - y / 2 (given defs for `x`, `y`) | Expression\n",
" | |
Expression | Type | Arity | op | args\n", " |
---|---|---|---|---|
`sin` | `Function` | 0 | `'sin'` | `()`\n", " |
`sin(x)` | `Expression` | 1 | `sin` | `(x,)`\n", " |