Dream to Learn is shutting down...

We are very sorry to say that Dream to Learn will be shutting down as of December 28th, 2019. If you have content that you wish to keep, you should make a copy of it before that date.


The i's of March (repost from my friend Josh)

POSTED IN: Data Analytics & Visualization Blog

The i's of March - Imaginary Numbers for 2nd Graders, IPython 2.0, and Interactive Widgets

by Josh Bloom (profjsb at gmail com) [April 5, 2014] 


At the end of March, there was a minor confluence around the letter, meaning, and representation of i, all of this leading to this IPython notebook.

First, my oldest daughter (8 years old) was sick and home away from school for a few days. Her class has been doing a huge amount of addition and subtraction practice (Common Core!). To augment and challenge, at home I've been doing rudimentary multiplication, division, squares, square roots, and algebra. Since she was missing homework and getting a bit fed up, I thought it would be fun to introduce her to imaginary numbers. Imaginary numbers are a natural extension of square roots and she totally was digging the notion that the imaginary number line is just the second dimension (of the complex plane), an orthogonal sibling to the real number line. She knows now that:


has two solutions: (0+3i) and (0−3i).

Of course we can also get this from numpy:


In [1]:

import numpy ; numpy.roots([1,0,9])


array([-0.+3.j,  0.-3.j])

When she went back to school, and showed her teacher some of the problems we tried, her teacher emailed me and asked if I could come teach the kids about imaginary numbers. Super exciting, but if you've ever taught 2nd graders about something you think you know about, it's terrifying - how to make a subject like this accessible is a huge challenge.

Since I know little of the history of imaginary numbers, and all of their practical uses, I thought before heading into the classroom later this month, it would be fun to read up on it. I came across a Princeton Science Library book entitled "An Imaginary Tale: The Story of −1−−−√" (1998, Paul J. Nahin; Amazon link). It arrived in the mail today and, about half way in, it's a delightful history (Cardan, Bombelli, Leibniz, Decartes, ...) mixed with some pretty cool math.

The second incident around i was that the long-awaited IPython 2.0 was released to great fanfare (making the top link on Hackernews for awhile...my sad version of fanfare). The IPython Dev team took it upon themselves to remind everyone that the i in IPython is suppose to be capitalized. I've been meaning to try out some of the new features and the interactivewidgets are, for me, the most interesting since I often use IPython notebooks as a didactic tool. Given my upcoming imaginary number lecture, perhaps IPython + widgets could be the ticket...

Then, on April 2, in my twitter feed a posting to this site on polynominal roots visualizationpopped up. The visualization of all the (complex) roots of all polynomials of order 5 or less with integer coefficients is awesome:


(© 2011 John Baez, J. Daniel Christensen and Sam Derbyshire)

So, to wrap it all together, I thought I'd make an interactive IPython 2.0 widget that visualizes the complex roots of all polynomials of order X or less with integer coefficients less than Y. Without further ado:

In [2]:

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from IPython.html.widgets import interactive, interact
from IPython.display import display

In [3]:

import numpy as np
import itertools

## storage location of already-generated roots
root_dict = {}

## get some colorization of the different roots
cols = {1: "black", 2: "yellow", 3: "blue", 4: "red", 5: "orange"}
get_col = lambda x: cols.get(int(x),"black")

In [5]:

## Root generator.
def gen_roots(max_degree=3,min_coeff=-2,max_coeff=2):
    coeffs = []
    for m in range(2,max_degree+1):
        coeffs.extend([x for x in itertools.product(range(min_coeff,max_coeff+1,1),repeat=m) if x[0] != 0])
    for c in coeffs:
        if not root_dict.has_key(c):
            root_dict.update({c: np.array([ [float(x.real),float(x.imag),len(c)] for x in np.roots(c)])})
    return coeffs

def all_plot_roots(max_degree=3,min_coeff=-2,max_coeff=2,doplot=True):
    ## get the coefficients and generate the roots
    coeffs     = gen_roots(max_degree=max_degree,min_coeff=min_coeff,max_coeff=max_coeff)
    if doplot:
        all_points = np.vstack([root_dict[x] for x in coeffs])
                    s=np.ceil(80*(all_points[:,2])**(-2.5)),alpha=0.4,edgecolor="none") #,s=len(coeff)**2,alpha=len(coeff)**(-0.3))

# this will preload the root_dict for us        

We've preloaded the root_dict using the coefficients as the key and all the roots as the value. Now, let's interact with the roots.

In [6]:

interact(all_plot_roots, max_degree=(2,5,1), min_coeff=(-5,-2,1), max_coeff=(2,5,1))

And there we have it. A short little wrap up of the i of March (2014). If you're seeing this through nbviewer, you wont be able to see the widget slidebars nor will you be able to interact with the widget. Try downloading the notebook and play around live. I would love to get feedback and embellishments on this. The plotting technique and updating could probably be speed up and the root calculation could be easily parallelized. And most of all, I'd love to hear from people that have ideas of how to teach imaginary numbers to second graders.



Interested in more content by this author?

About the Author

Ryan Anderson

Ryan Anderson

Hi! I like to play with data, analytics and hack around with robots and gadgets in my garage. Lately I've been learning about machine learning.

About this blog

Description is...<br/>Data Analytics & Visualization Blog - Generating insights from Data since 2013

Created: July 25, 2014


Up Next