Skip to content

Instantly share code, notes, and snippets.

@wmedlar
Created May 9, 2016 20:17
Show Gist options
  • Save wmedlar/e388473aea68ed1e460b63468dafd52a to your computer and use it in GitHub Desktop.
Save wmedlar/e388473aea68ed1e460b63468dafd52a to your computer and use it in GitHub Desktop.
Introduction to Complex Numbers with Python 3
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Introduction\n",
"\n",
"Complex numbers are numbers that have both a real and imaginary component, and can be thought of as two-dimensional vectors. Indeed, you'll often see complex numbers represented in Cartesian form as:\n",
"\n",
"$$\n",
"\\begin{array}{cccc}\n",
" z = x + iy && \\mathrm{where} && Re \\left( z \\right) \\equiv x && Im \\left( z \\right) \\equiv y \\\\\n",
"\\end{array}\n",
"$$\n",
"\n",
"Like a 2D vector, complex numbers can also be represented in polar coordinates, using the identities:\n",
"\n",
"$$\n",
"\\begin{array}{cccc}\n",
" z = r e^{i \\theta} && r = \\sqrt{x^2 + y^2} && \\theta = \\arctan{\\frac{x}{y}} \\\\\n",
"\\end{array}\n",
"$$\n",
"\n",
"The quantities $r$ and $\\theta$ are known as the *modulus* and *argument* (sometimes *phase*), respectively.\n",
"\n",
"Python contains a built-in `complex` type, which can be compared and operated on like any numeric type."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(5+3j) (2+0j) (4.5-0.3j)\n",
"True\n",
"(5+4j)\n",
"(69+7j)\n",
"(5.5+1.5j)\n"
]
}
],
"source": [
"print(complex(5, 3), complex(2), 4.5 - 0.3j)\n",
"print(type(complex(5, 3)) == type(complex(2)) == type(4.5 - 0.3j))\n",
"\n",
"print(11 + 3j - (6 - 1j))\n",
"print((11 + 3j) * (6 - 1j))\n",
"print((11 + 3j) / 2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You'll notice Python uses `j` instead of `i`. There has been much argument over the topic, however the general consensus is that Python follows the conventions of engineering, using *j* to avoid the ambiguity associated with *i* -- a common depiction of electrical current.\n",
"\n",
"The `cmath` module supports all of the operations of the `math` module for complex numbers."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import cmath"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### For the following problems, consider the complex number $z = \\sqrt{2} e^{\\frac{3 \\pi }{4} i}$.\n",
"\n",
"##### 1) What is the Cartesian representation of $z$?\n",
"\n",
"Using Euler's formula we can convert a complex number between polar and Cartesian representations:\n",
"\n",
"$$\n",
"\\sqrt{2} e^{\\frac{3 \\pi }{4} i} = \\sqrt{2} \\left( \\cos{\\frac{3 \\pi }{4}} + i \\sin{\\frac{3 \\pi }{4}} \\right) = \\sqrt{2} \\left( -\\frac{\\sqrt{2}}{2} + i \\frac{\\sqrt{2}}{2} \\right) = -1 + i\n",
"$$\n",
"\n",
"In Python this can be done using the `cmath.rect` function, which takes the modulus and argument as its parameters and returns a complex number in Cartesian (rectangular) form."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(-1+1.0000000000000002j)"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mod = cmath.sqrt(2).real # cmath.sqrt returns a complex type with no imaginary part (0j), however we need a float\n",
"arg = cmath.pi * 3 / 4\n",
"\n",
"z = cmath.rect(mod, arg); z"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 2) When plotted on the complex plane, $z$ falls in which quadrant?\n",
"\n",
"From inspection of the argument, we can see that the number will fall in the second quadrant when plotted. However it's not as simple to see for a number in Cartesian form; and care must be taken when evaluating the argument from x and y, as their signs must be considered.\n",
"\n",
"$$\n",
"\\frac{\\pi}{4} = \\arctan{\\frac{1}{1}} \\ne \\arctan{\\frac{-1}{-1}} = -\\frac{3 \\pi}{4}\n",
"$$\n",
"\n",
"Python handles this easily and gracefully with the `cmath.phase` function, which returns the corrected argument of a complex number. We can use this to write our own function and calculate the quadrant of our complex number."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def quadrant(z):\n",
" \n",
" # phase returns a result between [-pi, pi]\n",
" arg = cmath.phase(z)\n",
"\n",
" if 0 <= arg <= cmath.pi / 2:\n",
" q = 1\n",
" \n",
" elif cmath.pi / 2 < arg <= cmath.pi:\n",
" q = 2\n",
" \n",
" elif -cmath.pi < arg < -cmath.pi / 2:\n",
" q = 3\n",
" \n",
" elif -cmath.pi / 2 <= arg < 0:\n",
" q = 4\n",
" \n",
" return q\n",
"\n",
"quadrant(z)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 3) What results from adding $z$ and $2 \\sqrt{2} e^{- \\frac{\\pi}{4} i}$?\n",
"\n",
"In Cartesian form, complex numbers add component-wise, much like vectors; in polar form it's far easier to temporarily convert to Cartesian and return to polar afterwards, else you'll find yourself victim to some complicated algebra. Tedious math is best left to computers, and Python fully supports addition between two complex numbers.\n",
"\n",
"$$\n",
"z_1 + z_2 = \\left( x_1 + x_2 \\right) + i \\left( y_1 + y_2 \\right)\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(1.0000000000000004-0.9999999999999998j)"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mod2 = 2 * cmath.sqrt(2).real\n",
"arg2 = -cmath.pi / 4\n",
"z2 = cmath.rect(mod2, arg2)\n",
"\n",
"z + z2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### For the following problems, consider the complex function: $\\psi \\left( x \\right) = \\psi_{0} e^{a + ibx + cx^2}$.\n",
"\n",
"##### 4) What is the square magnitude of $\\psi \\left( x \\right)$?\n",
"\n",
"##### 5) What is the real part of $\\psi \\left( x \\right)$?\n",
"\n",
"##### 6) What is the imaginary part of $\\psi \\left( x \\right)$?\n",
"\n",
"Python can handle symbolic math through the use of the [SymPy library](http://www.sympy.org/en/index.html), however it's not quite as easy to use as a computer algebra system, like Maple or Mathematica. I'll have to update this notebook in the future with SymPy examples."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### For the following problems, consider the complex number: $z = 5 e^{- \\frac{\\pi}{4} i}$"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(3.5355339059327378-3.5355339059327373j)"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mod = 5\n",
"arg = -cmath.pi / 4\n",
"\n",
"z = cmath.rect(mod, arg); z"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 7) What is the magnitude of $z$?\n",
"\n",
"The magnitude of a complex number is simply a synonym for its modulus, and can be calculated using the built-in `abs` statement."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"5.0"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"abs(z)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 8) What is the argument of $z$?"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"-0.7853981633974483"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cmath.phase(z)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 9, 10) What is the real part of $z$? What is the imaginary part of $z$?\n",
"\n",
"Complex types in Python contain their real and imaginary parts as attributes."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(3.5355339059327378, -3.5355339059327373)"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"z.real, z.imag"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 11) What is the Cartesian representation of $z$?"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(3.5355339059327378-3.5355339059327373j)"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"z"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 12) When plotted on the complex plane, $z$ falls in which quadrant?"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"quadrant(z)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 13) What is the square magnitude of $z$?\n",
"\n",
"The square magnitude of a complex number is just that, the square of its magnitude."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"25.0"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"abs(z)**2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 14) What is the complex conjugate of $z$?\n",
"\n",
"The conjugate of a complex number is the same number, but with the sign of the imaginary part reversed.\n",
"\n",
"$$\n",
"z^\\ast = \\left( x + iy \\right)^\\ast = x + \\left( i \\right)^\\ast y = x + \\left( -i \\right) y = x - iy\n",
"$$\n",
"\n",
"Instances of complex numbers in Python have a useful `conjugate` method that takes no parameters. Since numeric types are immutable, this method returns a new instance of a complex number."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(3.5355339059327378+3.5355339059327373j)"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"z.conjugate()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 15) What results from adding $z$ and $2 e^{\\frac{\\pi}{4} i}$?"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(4.949747468305833-2.1213203435596424j)"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mod2 = 2\n",
"arg2 = cmath.pi / 4\n",
"z2 = cmath.rect(mod2, arg2)\n",
"\n",
"z + z2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 16) What results from dividing the complex number $-5 - 2i$ by the complex number $-2 - 5i$?\n",
"\n",
"For multiplication and division polar coordinates are far easier to work with; operations in this form are again carried out element-wise.\n",
"\n",
"$$\n",
"\\begin{array}{ c c }\n",
" z_1 z_2 = r_1 r_2 e^{i \\left( \\theta_1 + \\theta_2 \\right)} && \\frac{z_1}{z_2} = \\frac{r_1}{r_2} e^{i \\left( \\theta_1 - \\theta_2 \\right)} \\\\\n",
"\\end{array}\n",
"$$\n",
"\n",
"Complex types in Python also support multiplication and division by default, however we can take the slightly longer route to see how to use `cmath.polar` to convert from Cartesian form."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(0.6896551724137931-0.7241379310344828j)\n"
]
},
{
"data": {
"text/plain": [
"(0.6896551724137931-0.7241379310344827j)"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"z1 = -5 - 2j\n",
"z2 = -2 - 5j\n",
"print(z1 / z2)\n",
"\n",
"mod1, arg1 = cmath.polar(z1)\n",
"mod2, arg2 = cmath.polar(z2)\n",
"\n",
"cmath.rect(mod1 / mod2, arg1 - arg2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### For the following problems, consider the complex function $\\psi \\left( x \\right) = \\psi_{0} e^{-\\frac{1 + i}{a} x^2}$ where $\\psi_{0}$ and $a$ are real variables.\n",
"\n",
"##### 17) What is the square magnitude of $\\psi \\left( x \\right)$?\n",
"\n",
"##### 18) What is the real part of $\\psi \\left( x \\right)$?\n",
"\n",
"##### 19) What is the imaginary part of $\\psi \\left( x \\right)$?\n",
"\n",
"Will update later with SymPy."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.1"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
@wmedlar
Copy link
Author

wmedlar commented May 9, 2016

Originally uploaded in January 2016. Previously part of stattherm repo, didn't continue project due to time constraints.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment