DEMO: Visualizing complex numbers#

import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline
%config InlineBackend.figure_format = 'retina'

Caluclations with complex numbers#

Consider the complex number \( z = 1 + \sqrt{3} i \).

z=1+np.sqrt(3)*1j
z
(1+1.7320508075688772j)
z.real, z.imag
(1.0, 1.7320508075688772)
zc=z.conj()
np.sqrt(z*zc)
(1.9999999999999998+0j)
abs(z)
2.0
z.conj
<function complex128.conj>

Adding, subtracting and multiplying comple numbers#

z1 = 2-1j
z2 = 1+7j
z1+z2   # Try adding, multiplying, dividing z1 and z2
(3+6j)
np.sqrt(z1+z2)
(2.2032026611843234+1.3616541287161306j)

Cartesian representation#

# Specify your complex number here. Feel free to modify
z = 1j/(3+7j)-1j

# Compute conjugate, absolute values
zc = z.conjugate()
z_abs = abs(z)


### Plot

plt.plot(z.real, z.imag, 'o',ms=12, color='blue') 

plt.plot(zc.real, zc.imag, 'o', ms=12, color='green') 

plt.plot(z_abs.real, z_abs.imag, 'o', ms=12, color='grey') 


#Plot grid and specify a legend

plt.grid('on')
plt.legend(["z: " + str(z)[1:10], "zc: " + str(zc)[1:10], "z_abs: " + str(z_abs)[:10]], fontsize=12)
plt.xlabel("Re(z)", fontsize=12)
plt.ylabel("Im(z)", fontsize=12)
Text(0, 0.5, 'Im(z)')
../_images/c0b9fc42c0f692d24e125caddb22711f4be497122cac60dab51b1ccffe8f0b9d.png

Let’s use Python to convert the trigonometric form of the complex number \(z\) to polar form and that visualize on a polar plot.

For \(z = 1 + \sqrt{3} i \), \( x = 1 \), \( y = \sqrt{3}\).

It follows that \(r = 2\) and \(\theta = \tan^{-1}(\sqrt{3}) = \frac{\pi}{3} = 60^o\).

import cmath  # python provides special methods to convert between representtions 
z=1+np.sqrt(3)*1j 
z
(1+1.7320508075688772j)
cmath.polar(z) # get the polar form
(2.0, 1.0471975511965976)
r, theta = cmath.polar(z)

r, theta
(2.0, 1.0471975511965976)
cmath.rect(1.9999999999999998, 1.0471975511965976)
(1+1.732050807568877j)

Polar plot of complex numbers#

# Specify complex number either by z or directly pecify r and theta

#z = 1+np.sqrt(3)*1j

r = 1         # cmath.polar(z)[0]                         
θ = np.pi/3   # cmath.polar(z)[1] 


# Plot
fig = plt.figure()
ax = plt.subplot(projection='polar')

ax.plot( θ,r, 'o', ms=10,color='blue')     # complex number    z     
ax.plot(-θ,r, 'o', ms=10,color='green')    # complex conjugate z
ax.plot( 0,r, 'o', ms=10, color='grey')
[<matplotlib.lines.Line2D at 0x7f6fb4748e50>]
../_images/ee45d03eabdfceef8711fa6413ebd066e53e9a1f98627fed3abd7fcdc5171724.png

With a few more options we can annote the plot to show connection with cartesian representation

# Set parameters
r = 1
θ = np.pi/3
x = r * np.cos(θ)

# Plot
fig = plt.figure(figsize=(6,6))
ax = plt.subplot(projection='polar')

ax.plot((0, θ),(0, r), '--o', color='red',ms=10)               # plot r


### Plot lines and annotate
x_range = np.linspace(0, x, 1000)
θ_range = np.linspace(0, θ, 1000)

ax.plot(np.zeros(x_range.shape), x_range, color='green')       # plot x
ax.plot(θ_range, x / np.cos(θ_range), color='blue')            # plot y
ax.plot(θ_range, np.ones(θ_range.shape) * 0.1, color='r')      # plot θ

ax.set_title("Trigonometry of complex numbers", va='bottom', fontsize='x-large')

ax.set_rmax(r)

ax.legend(["z = " + str(z)[1:10],  "r = " + str(r), "θ = " + str(θ)[:10] ])
<matplotlib.legend.Legend at 0x7f6fb4737bb0>
../_images/9c1820ba33cdcd3b3a364a819675c4e3159216fc14810013c3d3dd60b70324e9.png

Sympy and complex numbers#

Below we will use symbolic python to derive Euler’s relation by expanding sines, conse and exp in Taylor series. If you have used Mathematica, WolframAlpha, or another math software that uses symbols, then Sympy is essentially a Python version of that. The central objects in Sympy are variables which we define and then do symbolic operations such as expand in series, differentiate, simplify expression, integrate etc.

from sympy import *
x = Symbol('x', real=True)
y = Symbol('y', real=True)
z = Symbol('z', complex=True)
n = Symbol('n', real=True)
exp(x).series(x,0,4)                        # Taylor expand to power 4
\[\displaystyle 1 + x + \frac{x^{2}}{2} + \frac{x^{3}}{6} + O\left(x^{4}\right)\]
a=cos(x).series(x,0,4)
a
\[\displaystyle 1 - \frac{x^{2}}{2} + O\left(x^{4}\right)\]
b = I*sin(y).series(y,0,4) 
b
\[\displaystyle i \left(y - \frac{y^{3}}{6} + O\left(y^{4}\right)\right)\]
(a+b).simplify()         # simplify an expression
\[\displaystyle 1 + i \left(y - \frac{y^{3}}{6} + O\left(y^{4}\right)\right) - \frac{x^{2}}{2} + O\left(x^{4}\right)\]

Now let us use Sympy to evaluate \(\int_{-\pi}^{\pi} \cos(nx) \sin(nx) \, d\omega\)

integrate(cos(n*x)*sin(n*x), (x, -pi, pi))  # evaluate integral of cos(nx)sin(nx)
\[\displaystyle 0\]

Complex numbers, Julia sets and fractals.#

  • Fractal is a mathematically defined, self-similar object which has similarity and symmetry on a variety of scales. The Julia Set Fractal is a type of fractal defined by the behavior of a function that operates on input complex numbers. More explicitly, upon iterative updating of input complex number, the Julia Set Fractal represents the set of inputs whose resulting outputs either tend towards infinity or remain bounded.

  • Julia set fractals are normally generated by initializing a complex number \(z = x + yi\) where \(i^2 = -1\) and x and y are image pixel coordinates in the range of about -2 to 2. Then, z is repeatedly updated using: \(z = z^2 + c\) where c is another complex number that gives a specific Julia set. After numerous iterations, if the magnitude of z is less than 2 we say that pixel is in the Julia set and color it accordingly. Performing this calculation for a whole grid of pixels gives a fractal image.

import matplotlib.cm as cm
fig, ax = plt.subplots(figsize=(8,8))

# Image width and height; parameters for the plot
im_width, im_height = 1500, 1500

c = complex(-0.1, 0.65)

zabs_max = 10
nit_max = 1000

xmin, xmax = -1.5, 1.5
xwidth = xmax - xmin

ymin, ymax = -1.5, 1.5
yheight = ymax - ymin

julia = np.zeros((im_width, im_height))

for ix in range(im_width):
    for iy in range(im_height):
        
        nit = 0
        
        # Map pixel position to a point in the complex plane
        z = complex(ix / im_width * xwidth + xmin,
                    iy / im_height * yheight + ymin)

        # Do the iterations
        while abs(z) <= zabs_max and nit < nit_max:
            z = z**2 + c
            nit += 1
            
        shade = 1-np.sqrt(nit / nit_max)
        ratio = nit / nit_max
        julia[ix,iy] = ratio

ax.imshow(julia, interpolation='nearest', cmap=cm.rainbow)  #try cm.jet, cm.hot, cm.rainbow, etc
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Cell In[26], line 31
     29 # Do the iterations
     30 while abs(z) <= zabs_max and nit < nit_max:
---> 31     z = z**2 + c
     32     nit += 1
     34 shade = 1-np.sqrt(nit / nit_max)

KeyboardInterrupt: 
../_images/84fe465b32915325e2333e0beb4fc8b26fbaf76d5358db6037f6fda9932f004f.png