N or Space for next slide, P for previous slide, F for full screen, M for menu
Boaz Barak (instructor), Brian Sapozhnikov (Head TF), Albert Chalom, Alexis Ross, Charles O’Mara, Daniel Chen, David Li , Jambay Kinley, Jane Ahn, John Shen, Josh Seides, Laura Pierson, Pranay Tankala, Raymond Lin, Theresa Nguyen, Wanqian Yang, William Fu, Hikari Sorensen (Extension TF), Eric Lu (Patel Fellow)

Laptops/phones only on last 5 rows please.
Contact Patel fellow Eric Lu ericlu01@g.harvard.edu
NAND++ / Turing Machines / NAND<< / \(\lambda\) calculus/…: Everything you can do in 〈your favorite language〉
NAND / Boolean circuits / ANDORNOT / …: Everything you can do in 〈your favorite language〉 for \(n\) input bits, unrolling all loops.
Thm 1: “Equivalence of universal bases” NAND programs \(\equiv\) NAND circuits \(\equiv\) AND/OR/NOT circuits \(\equiv\) \(\mathscr{U}\)-circuits, for any universal \(\mathscr{U}\).
Thm 2: “Universality of NAND” Every function \(F:\{0,1\}^n \rightarrow \{0,1\}\) has a NAND program of \(O(2^n/n)\) lines.
Thm 3: “Counting lower bound” Some (in fact most) functions require \(\Omega(2^n/n)\) lines.
Thm 4: “If it’s finite and you can Python it, you can NAND it” NAND \(\cong\) NAND + sugar
Thm 5: “Universal Circuit” Evaluate \(P,x \mapsto P(x)\) in \(poly(|P|)\) gates.
Thm 6: “unrolling the loop” If \(F\) is computable by NAND++, restriction of \(F\) to \(\{0,1\}^n\) is computable by NAND with similar resources.
Thm 7: “Turing completeness” NAND++ = Turing machines = NAND<< = RAM machines = \(\lambda\) calculus = Python = cellular automata = …
Thm 8: “Universality” \(EVAL\) for TM/NAND++/\(\lambda\)/Python… is computable by TM/NAND++/\(\lambda\)/Python…
Next up:
Thm 9: “Uncomputablity” NAND++ \(\neq\) Everything.
Thm 10: “Halting and friends” There are interesting uncomputable functions.
Thm 7: “Turing completeness” NAND++ = NAND<< = \(\lambda\) calculus
Thm 8 ⃰: “Universality” There is a NAND<< (hence NAND++) program to compute \(P,x \mapsto P(x)\) where \(P\) is NAND++ (hence NAND<< ).
“Have the cake and eat it too” paradigm: Move between levels of abstractions and equivalent models.
Local storage - states (Turing machines) or scalar variables and current line (NAND++).
Unbounded size memory - tape (Turing machines) or array variables (NAND++)
Sequential access - head location (Turing machine) or index variable i moves one step at a time.
Can access arbitrary memory location at each step.
In C: foo = *bar or foo = Array[bar]
In Python: foo = Array[bar]
In NAND<< : foo = Array[bar]
Integer valued variables: arithmetic operations.
Indirect indexing: Bar[foo] is foo-th location at Bar
Trivial: If \(F\) is computable by NAND++ then \(F\) is computable by NAND<<
Harder: If \(F\) is computable by NAND<< then \(F\) is computable by NAND++
Exercise: Write NAND++ code to implement foo = Data[Index] where Data and Index are arrays and foo is scalar variable. Can use GOTO, inner loops, and i += var, i -= var sugar.
Integer valued variables: arithmetic operations.
Indirect indexing: Bar[foo] is foo-th location at Bar
Trivial: If \(F\) is computable by NAND++ then \(F\) is computable by NAND<<
Harder: If \(F\) is computable by NAND<< then \(F\) is computable by NAND++
Exercise: Write NAND++ code to implement foo = Data[Index] where Data and Index are arrays and foo is scalar variable. Can use GOTO, inner loops, recursion, and i += var, i -= var sugar.
def LOOKUP(Table,Index):
Temp = COPY(Index)
while not ZERO(Temp):
i += 1
DECREMENT(Temp)
return Table[i]
Step 1: Replace arrays of integers with two dimensional arrays of bits Array[i][j] is j-th bit of Array[i]
Step 2: Replace arithmetic operations with implementations - “syntactic sugar”
Step 3: Replace two dimensional arrays with one dimensional ones Array[i][j] becomes Array[pair(i,j)] \(pair:\mathbb{N}\times \mathbb{N} \rightarrow \mathbb{N}\) is computable and one to one.
Step 4: Replace indirection with lookup code: foo = Data[Index] becomes foo = EXERCISE(Data,Index). All arrays now indexed with i using i += blah , i -= blah
Step 5: Replace while with GOTO, replace GOTO with if (linetorun == thisline) { do something }, implement if via syntactic sugar.