Use the math you already know, or are just learning, to get stronger in Python.
Use the Python you already know, or learned recently, to teach yourself more math.
Climb the spiral staircase to greater mastery of today's tools and technologies.
Age range: Open to anyone wanting to combine working out in Python, learning the language, while using high school level math topics as "grist for the mill".
Format: Home school format over Zoom. BYOD (bring your own device). Hands on. Be willing to install new software to your local machine. Be willing to share your screen on Zoom. Be willing to open free accounts in the cloud, and paid accounts optionally.
Make your own Jupyter Notebooks and share them with your peers.
Collaborate on coding projects.
Are you reading this as a PDF document? Then chances are, it was generated by an operating system level process looking something like this:
! jupyter nbconvert --to webpdf class_proposal.ipynb
[NbConvertApp] Converting notebook class_proposal.ipynb to webpdf [NbConvertApp] Building PDF [NbConvertApp] PDF successfully created [NbConvertApp] Writing 288776 bytes to class_proposal.pdf
Getting Jupyter Notebooks to render as PDFs, including with $\LaTeX$ and Unicode emoji, is cutting edge tech at the time of this writing (Fall, 2021).
As a webpdf, this document has no page breaks, so good luck trying to print it out. Adding page breaks to webpdfs is a good example of an ongoing community project.
import sys
print(sys.version)
3.7.9 (default, Aug 31 2020, 07:22:35) [Clang 10.0.0 ]
Plotting sine waves in color requires very little code when you start with numpy and pandas. But then we're already inside a Jupyter Notebook, which you may think of as your new desktop workspace. In the context of JupyterLab, you will have easy access to a Python console, interactive editing, other file type viewing.
import numpy as np
import pandas as pd
%matplotlib inline
domain = np.linspace(-10, 10, 400) # give me 400 points evenly spaced from -10 to 10
cos_wave = np.cos(domain) # cos(x) where x is every one of those 400 points
sin_wave = np.sin(domain) # ditto sin(x)
# build a table
tabular = pd.DataFrame({"domain": domain, "cosine": cos_wave, "sine": sin_wave})
# plot!
tabular.plot(x="domain", y=["cosine", "sine"], title="Trig Functions", grid=True);
The Python generator below yields successive rows of Pascal's Triangle.
Generators are a special construct in Python. They're similar to functions, but get nudged forward by next(), running until a next yield
statement is encountered, resuming execution from wherever the program last yielded.
A generator does not forget its internal state, between nudgings. Arriving at the same yield
statement over and over, inside a while True loop, is not atypical, as in the example below.
def pascal():
row = np.array([1])
while True:
yield row
row = np.append(row, 0) + np.insert(row, 0, 0)
iterator = pascal()
for _ in range(10):
print(next(iterator))
[1] [1 1] [1 2 1] [1 3 3 1] [1 4 6 4 1] [ 1 5 10 10 5 1] [ 1 6 15 20 15 6 1] [ 1 7 21 35 35 21 7 1] [ 1 8 28 56 70 56 28 8 1] [ 1 9 36 84 126 126 84 36 9 1]
Lets get some more rows and plot the last one to see what we get.
row = next(iterator) # run this multiple times
%matplotlib inline
binomial_distro = pd.DataFrame(row).plot()
Topics left on the back burner in the 1900s, become more front burner in the 2000s, with the rise of the internet and the need for quasi-instantaneous stranger-to-stranger secure transactions.
Instead of rushing through the primes versus composite distinction, as older high school curricula used to do, and giving short shrift to modulo arithmetic, we must now take a deeper dive, with notions of totient and totative.
The totatives of positive integer N is the set integers less than N, down to 1, including 1, that have no factors in common with N, other than 1.
from math import gcd
def totatives(N):
return [n for n in range(1, N) if gcd(n, N) == 1]
totatives(12)
[1, 5, 7, 11]
print(totatives(100))
[1, 3, 7, 9, 11, 13, 17, 19, 21, 23, 27, 29, 31, 33, 37, 39, 41, 43, 47, 49, 51, 53, 57, 59, 61, 63, 67, 69, 71, 73, 77, 79, 81, 83, 87, 89, 91, 93, 97, 99]
Do not confuse totatives of N with prime factors of N, another topic we will be sure to take up.
The number of totatives a number N has, is called its totient. Euler sometimes used $\phi$ for his totient function.
def totient(N):
return len(totatives(N))
totient(12)
4
Totatives of N multiply as a Group modulo N. For example the 40 totatives of 100, multiplied modulo 100, have the properties of Closure, Associativity, Inverse and Neutral element (CAIN). This group is also Abelian. In this course, we will talk about what all that means, using a "math object" (type) called a Modulo Number. We'll also use Permutations.
totient(100)
40
RSA public key cryptography is these days often only taken up in computer science after high school, but in this curriculum we bring in enough Group and Number Theory topics to make the RSA algorithm a door-opening application.
from primes import rsacrypto_test
Generating: p,q Generating: u Generating: d <_RSAobj @0x11bd4f310 n(1024),e,d,p,q,u,private>
Python's 3rd party community provides some useful cryptography packages. Lets used one.
The way RSA works is everybody publishes a huge composite number N, like an address, which has two prime factors p, q that each person stores secretly.
There's no reasonable way to work backwards to get from the public composite number N, to its component primes (p, q), given our current understanding of Number Theory.
Bob encrypts a message to Alice, by raising it in chunks to some power, with Alice's public key as the modulus.
p = rsacrypto_test.p
p
9720399903105459822060723185656936167945047457483806667538880527550406562427715158136554554165026194740251547794042724035455501132922783183410025086408291
q = rsacrypto_test.q
q
10042361290060786029960722120509929925462861609429081321815421527967157348653195550660718451008840150704377387415699863560935480568535755963179095743971401
rsacrypto_test.e # raise to 17th power modulo p*q
17
Alice's secret "DNA-like" components then spring into action and decipher Bob's message, by raising it to some still higher power, governed by the totient of p * q.
Alice can only decrypt messages intended for Alice (her public key address), and so on.
This system has worked well and is built in to every web browser as a way to handshake with public keys, in order to shift to a faster private key, once a trusted connection has been established.
crypt = rsacrypto_test.rsaobj # results of generating p, q, d
plain_text = b"no one will be able to read this without p, q"
cipher_text = crypt.encrypt(plain_text, b'K')[0]
print(crypt.decrypt(cipher_text))
b'no one will be able to read this without p, q'
If 1 is to a longer $\phi$, as $\phi$ is to a still longer $1+\phi$, then what is $\phi$?
That question may be expressed as a solvable polynomial, yield a specific number, called the Golden Mean.
Notice $\LaTeX$ is being used to make our math expressions.
By doing the same thing to both sides, as we do with polynomials, we may simplify:
$$ 1/\phi = \phi/(\phi + 1) \\ (\phi + 1)/\phi = \phi \\ (\phi + 1) = \phi^{2} \\ 0 = \phi^{2} - (\phi + 1) \\ \phi^{2} - \phi - 1 = 0 \\ $$And next, we may solve this equation, using sympy
.
from sympy import init_session
init_session()
IPython console for SymPy 1.7.1 (Python 3.7.9-64-bit) (ground types: gmpy) These commands were executed: >>> from __future__ import division >>> from sympy import * >>> x, y, z, t = symbols('x y z t') >>> k, m, n = symbols('k m n', integer=True) >>> f, g, h = symbols('f g h', cls=Function) >>> init_printing() Documentation can be found at https://docs.sympy.org/1.7.1/
𝜙 = symbols('𝜙')
from sympy.solvers import solve
solve(𝜙**2 - 𝜙 - 1, 𝜙)
sol = solve(𝜙**2 - 𝜙 - 1, 𝜙)
sol[1].evalf(30)
Python is a computer language, started in the Netherlands by Guido van Rossum in the 1990s, and still evolving.
Surrounding Python is the broader landscape of the computerized office, with many components in the cloud such as:
The list continues. With the exception of PythonAnywhere, all of the above are free.
But what if we're not always connected to the internet, and what about working locally in a personal workspace, with files on the local computer (such as a laptop or desktop)?
That's where downloading and installation comes in. We focus on beefing up your local computer quite a bit, and do not depend solely on cloud resources.