INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

650
BOAZ BARAK INTRODUCTION TO THEORETICAL COMPUTER SCIENCE TEXTBOOK IN PREPARATION. AVAILABLE ON HTTPS://INTROTCS.ORG

Transcript of INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Page 1: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

B OA Z BA R A K

I N T RO D U C T I O N TOT H E O R E T I CA LCO M P U T E R S C I E N C E

T E X T B O O K I N P R E PA R AT I O N .AVA I L A B L E O N HTTPS://INTROTCS.ORG

Page 2: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Text available on https://github.com/boazbk/tcs - please post any issues there - thank you!

This version was compiled on Wednesday 26th August, 2020 18:10

Copyright © 2020 Boaz Barak

This work is licensed under a CreativeCommons “Attribution-NonCommercial-NoDerivatives 4.0 International” license.

Page 3: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

To Ravit, Alma and Goren.

Page 4: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 5: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Contents

Preface 9

Preliminaries 17

0 Introduction 19

1 Mathematical Background 37

2 Computation and Representation 73

I Finite computation 111

3 Defining computation 113

4 Syntactic sugar, and computing every function 149

5 Code as data, data as code 175

II Uniform computation 205

6 Functions with Infinite domains, Automata, and Regularexpressions 207

7 Loops and infinity 241

8 Equivalent models of computation 271

9 Universality and uncomputability 315

10 Restricted computational models 347

11 Is every theorem provable? 365

Compiled on 8.26.2020 18:10

Page 6: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

6

III Efficient algorithms 385

12 Efficient computation: An informal introduction 387

13 Modeling running time 407

14 Polynomial-time reductions 439

15 NP, NP completeness, and the Cook-Levin Theorem 465

16 What if P equals NP? 483

17 Space bounded computation 503

IV Randomized computation 505

18 Probability Theory 101 507

19 Probabilistic computation 527

20 Modeling randomized computation 539

V Advanced topics 561

21 Cryptography 563

22 Proofs and algorithms 591

23 Quantum computing 593

VI Appendices 625

Page 7: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Contents (detailed)

Preface 90.1 To the student . . . . . . . . . . . . . . . . . . . . . . . . 10

0.1.1 Is the effort worth it? . . . . . . . . . . . . . . . . 110.2 To potential instructors . . . . . . . . . . . . . . . . . . . 120.3 Acknowledgements . . . . . . . . . . . . . . . . . . . . . 14

Preliminaries 17

0 Introduction 190.1 Integer multiplication: an example of an algorithm . . . 200.2 Extended Example: A faster way to multiply (optional) 220.3 Algorithms beyond arithmetic . . . . . . . . . . . . . . . 270.4 On the importance of negative results . . . . . . . . . . 280.5 Roadmap to the rest of this book . . . . . . . . . . . . . 29

0.5.1 Dependencies between chapters . . . . . . . . . . 300.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 320.7 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 33

1 Mathematical Background 371.1 This chapter: a reader’s manual . . . . . . . . . . . . . . 371.2 A quick overview of mathematical prerequisites . . . . 381.3 Reading mathematical texts . . . . . . . . . . . . . . . . 39

1.3.1 Definitions . . . . . . . . . . . . . . . . . . . . . . 401.3.2 Assertions: Theorems, lemmas, claims . . . . . . 401.3.3 Proofs . . . . . . . . . . . . . . . . . . . . . . . . . 40

1.4 Basic discrete math objects . . . . . . . . . . . . . . . . . 411.4.1 Sets . . . . . . . . . . . . . . . . . . . . . . . . . . 411.4.2 Special sets . . . . . . . . . . . . . . . . . . . . . . 421.4.3 Functions . . . . . . . . . . . . . . . . . . . . . . . 441.4.4 Graphs . . . . . . . . . . . . . . . . . . . . . . . . 461.4.5 Logic operators and quantifiers . . . . . . . . . . 491.4.6 Quantifiers for summations and products . . . . 501.4.7 Parsing formulas: bound and free variables . . . 501.4.8 Asymptotics and Big-𝑂 notation . . . . . . . . . . 52

Page 8: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

8

1.4.9 Some “rules of thumb” for Big-𝑂 notation . . . . 531.5 Proofs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

1.5.1 Proofs and programs . . . . . . . . . . . . . . . . 551.5.2 Proof writing style . . . . . . . . . . . . . . . . . . 551.5.3 Patterns in proofs . . . . . . . . . . . . . . . . . . 56

1.6 Extended example: Topological Sorting . . . . . . . . . 581.6.1 Mathematical induction . . . . . . . . . . . . . . . 601.6.2 Proving the result by induction . . . . . . . . . . 611.6.3 Minimality and uniqueness . . . . . . . . . . . . . 63

1.7 This book: notation and conventions . . . . . . . . . . . 651.7.1 Variable name conventions . . . . . . . . . . . . . 661.7.2 Some idioms . . . . . . . . . . . . . . . . . . . . . 67

1.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 691.9 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 71

2 Computation and Representation 732.1 Defining representations . . . . . . . . . . . . . . . . . . 75

2.1.1 Representing natural numbers . . . . . . . . . . . 762.1.2 Meaning of representations (discussion) . . . . . 78

2.2 Representations beyond natural numbers . . . . . . . . 782.2.1 Representing (potentially negative) integers . . . 792.2.2 Two’s complement representation (optional) . . 792.2.3 Rational numbers, and representing pairs of

strings . . . . . . . . . . . . . . . . . . . . . . . . . 802.3 Representing real numbers . . . . . . . . . . . . . . . . . 822.4 Cantor’s Theorem, countable sets, and string represen-

tations of the real numbers . . . . . . . . . . . . . . . . . 832.4.1 Corollary: Boolean functions are uncountable . . 892.4.2 Equivalent conditions for countability . . . . . . 89

2.5 Representing objects beyond numbers . . . . . . . . . . 902.5.1 Finite representations . . . . . . . . . . . . . . . . 912.5.2 Prefix-free encoding . . . . . . . . . . . . . . . . . 912.5.3 Making representations prefix-free . . . . . . . . 942.5.4 “Proof by Python” (optional) . . . . . . . . . . . 952.5.5 Representing letters and text . . . . . . . . . . . . 972.5.6 Representing vectors, matrices, images . . . . . . 992.5.7 Representing graphs . . . . . . . . . . . . . . . . . 992.5.8 Representing lists and nested lists . . . . . . . . . 992.5.9 Notation . . . . . . . . . . . . . . . . . . . . . . . . 100

2.6 Defining computational tasks as mathematical functions 1002.6.1 Distinguish functions from programs! . . . . . . 102

2.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 1042.8 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 108

Page 9: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

9

I Finite computation 111

3 Defining computation 1133.1 Defining computation . . . . . . . . . . . . . . . . . . . . 1153.2 Computing using AND, OR, and NOT. . . . . . . . . . . 116

3.2.1 Some properties of AND and OR . . . . . . . . . 1183.2.2 Extended example: Computing XOR from

AND, OR, and NOT . . . . . . . . . . . . . . . . . 1193.2.3 Informally defining “basic operations” and

“algorithms” . . . . . . . . . . . . . . . . . . . . . 1213.3 Boolean Circuits . . . . . . . . . . . . . . . . . . . . . . . 123

3.3.1 Boolean circuits: a formal definition . . . . . . . . 1243.3.2 Equivalence of circuits and straight-line programs 127

3.4 Physical implementations of computing devices (di-gression) . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

3.4.1 Transistors . . . . . . . . . . . . . . . . . . . . . . 1313.4.2 Logical gates from transistors . . . . . . . . . . . 1323.4.3 Biological computing . . . . . . . . . . . . . . . . 1323.4.4 Cellular automata and the game of life . . . . . . 1323.4.5 Neural networks . . . . . . . . . . . . . . . . . . . 1323.4.6 A computer made from marbles and pipes . . . . 133

3.5 The NAND function . . . . . . . . . . . . . . . . . . . . 1343.5.1 NAND Circuits . . . . . . . . . . . . . . . . . . . . 1353.5.2 More examples of NAND circuits (optional) . . . 1363.5.3 The NAND-CIRC Programming language . . . . 138

3.6 Equivalence of all these models . . . . . . . . . . . . . . 1403.6.1 Circuits with other gate sets . . . . . . . . . . . . 1413.6.2 Specification vs. implementation (again) . . . . . 142

3.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 1433.8 Biographical notes . . . . . . . . . . . . . . . . . . . . . . 146

4 Syntactic sugar, and computing every function 1494.1 Some examples of syntactic sugar . . . . . . . . . . . . . 151

4.1.1 User-defined procedures . . . . . . . . . . . . . . 1514.1.2 Proof by Python (optional) . . . . . . . . . . . . . 1534.1.3 Conditional statements . . . . . . . . . . . . . . . 154

4.2 Extended example: Addition and Multiplication (op-tional) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

4.3 The LOOKUP function . . . . . . . . . . . . . . . . . . . 1584.3.1 Constructing a NAND-CIRC program for

LOOKUP . . . . . . . . . . . . . . . . . . . . . . . 1594.4 Computing every function . . . . . . . . . . . . . . . . . 161

4.4.1 Proof of NAND’s Universality . . . . . . . . . . . 1624.4.2 Improving by a factor of 𝑛 (optional) . . . . . . . 163

Page 10: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

10

4.5 Computing every function: An alternative proof . . . . 1654.6 The class SIZE(𝑇 ) . . . . . . . . . . . . . . . . . . . . . . 1674.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 1704.8 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 174

5 Code as data, data as code 1755.1 Representing programs as strings . . . . . . . . . . . . . 1775.2 Counting programs, and lower bounds on the size of

NAND-CIRC programs . . . . . . . . . . . . . . . . . . . 1785.2.1 Size hierarchy theorem (optional) . . . . . . . . . 180

5.3 The tuples representation . . . . . . . . . . . . . . . . . 1825.3.1 From tuples to strings . . . . . . . . . . . . . . . . 183

5.4 A NAND-CIRC interpreter in NAND-CIRC . . . . . . . 1845.4.1 Efficient universal programs . . . . . . . . . . . . 1855.4.2 A NAND-CIRC interpeter in “pseudocode” . . . 1865.4.3 A NAND interpreter in Python . . . . . . . . . . 1875.4.4 Constructing the NAND-CIRC interpreter in

NAND-CIRC . . . . . . . . . . . . . . . . . . . . . 1885.5 A Python interpreter in NAND-CIRC (discussion) . . . 1915.6 The physical extended Church-Turing thesis (discus-

sion) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1935.6.1 Attempts at refuting the PECTT . . . . . . . . . . 195

5.7 Recap of Part I: Finite Computation . . . . . . . . . . . . 1995.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 2015.9 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 203

II Uniform computation 205

6 Functions with Infinite domains, Automata, and Regularexpressions 2076.1 Functions with inputs of unbounded length . . . . . . . 208

6.1.1 Varying inputs and outputs . . . . . . . . . . . . . 2096.1.2 Formal Languages . . . . . . . . . . . . . . . . . . 2116.1.3 Restrictions of functions . . . . . . . . . . . . . . . 211

6.2 Deterministic finite automata (optional) . . . . . . . . . 2126.2.1 Anatomy of an automaton (finite vs. unbounded) 2156.2.2 DFA-computable functions . . . . . . . . . . . . . 216

6.3 Regular expressions . . . . . . . . . . . . . . . . . . . . . 2176.3.1 Algorithms for matching regular expressions . . 221

6.4 Efficient matching of regular expressions (optional) . . 2236.4.1 Matching regular expressions using DFAs . . . . 2276.4.2 Equivalence of regular expressions and automata 2286.4.3 Closure properties of regular expressions . . . . 230

Page 11: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

11

6.5 Limitations of regular expressions and the pumpinglemma . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

6.6 Answering semantic questions about regular expres-sions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236

6.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 2396.8 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 240

7 Loops and infinity 2417.1 Turing Machines . . . . . . . . . . . . . . . . . . . . . . . 242

7.1.1 Extended example: A Turing machine for palin-dromes . . . . . . . . . . . . . . . . . . . . . . . . 244

7.1.2 Turing machines: a formal definition . . . . . . . 2457.1.3 Computable functions . . . . . . . . . . . . . . . . 2477.1.4 Infinite loops and partial functions . . . . . . . . 248

7.2 Turing machines as programming languages . . . . . . 2497.2.1 The NAND-TM Programming language . . . . . 2517.2.2 Sneak peak: NAND-TM vs Turing machines . . . 2547.2.3 Examples . . . . . . . . . . . . . . . . . . . . . . . 254

7.3 Equivalence of Turing machines and NAND-TM pro-grams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257

7.3.1 Specification vs implementation (again) . . . . . 2607.4 NAND-TM syntactic sugar . . . . . . . . . . . . . . . . . 261

7.4.1 “GOTO” and inner loops . . . . . . . . . . . . . . 2617.5 Uniformity, and NAND vs NAND-TM (discussion) . . 2647.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 2657.7 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 268

8 Equivalent models of computation 2718.1 RAM machines and NAND-RAM . . . . . . . . . . . . . 2738.2 The gory details (optional) . . . . . . . . . . . . . . . . . 277

8.2.1 Indexed access in NAND-TM . . . . . . . . . . . . 2778.2.2 Two dimensional arrays in NAND-TM . . . . . . 2798.2.3 All the rest . . . . . . . . . . . . . . . . . . . . . . 279

8.3 Turing equivalence (discussion) . . . . . . . . . . . . . . 2808.3.1 The “Best of both worlds” paradigm . . . . . . . 2818.3.2 Let’s talk about abstractions . . . . . . . . . . . . 2818.3.3 Turing completeness and equivalence, a formal

definition (optional) . . . . . . . . . . . . . . . . . 2838.4 Cellular automata . . . . . . . . . . . . . . . . . . . . . . 284

8.4.1 One dimensional cellular automata are Turingcomplete . . . . . . . . . . . . . . . . . . . . . . . 286

8.4.2 Configurations of Turing machines and thenext-step function . . . . . . . . . . . . . . . . . . 287

Page 12: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

12

8.5 Lambda calculus and functional programming lan-guages . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290

8.5.1 Applying functions to functions . . . . . . . . . . 2908.5.2 Obtaining multi-argument functions via Currying 2918.5.3 Formal description of the λ calculus . . . . . . . . 2928.5.4 Infinite loops in the λ calculus . . . . . . . . . . . 295

8.6 The “Enhanced” λ calculus . . . . . . . . . . . . . . . . 2958.6.1 Computing a function in the enhanced λ calculus 2978.6.2 Enhanced λ calculus is Turing-complete . . . . . 298

8.7 From enhanced to pure λ calculus . . . . . . . . . . . . 3018.7.1 List processing . . . . . . . . . . . . . . . . . . . . 3028.7.2 The Y combinator, or recursion without recursion 303

8.8 The Church-Turing Thesis (discussion) . . . . . . . . . 3068.8.1 Different models of computation . . . . . . . . . . 307

8.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 3088.10 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 312

9 Universality and uncomputability 3159.1 Universality or a meta-circular evaluator . . . . . . . . . 316

9.1.1 Proving the existence of a universal TuringMachine . . . . . . . . . . . . . . . . . . . . . . . . 318

9.1.2 Implications of universality (discussion) . . . . . 3209.2 Is every function computable? . . . . . . . . . . . . . . . 3219.3 The Halting problem . . . . . . . . . . . . . . . . . . . . 323

9.3.1 Is the Halting problem really hard? (discussion) 3269.3.2 A direct proof of the uncomputability of HALT

(optional) . . . . . . . . . . . . . . . . . . . . . . . 3279.4 Reductions . . . . . . . . . . . . . . . . . . . . . . . . . . 329

9.4.1 Example: Halting on the zero problem . . . . . . 3309.5 Rice’s Theorem and the impossibility of general soft-

ware verification . . . . . . . . . . . . . . . . . . . . . . . 3339.5.1 Rice’s Theorem . . . . . . . . . . . . . . . . . . . . 3359.5.2 Halting and Rice’s Theorem for other Turing-

complete models . . . . . . . . . . . . . . . . . . . 3399.5.3 Is software verification doomed? (discussion) . . 340

9.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 3429.7 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 345

10 Restricted computational models 34710.1 Turing completeness as a bug . . . . . . . . . . . . . . . 34710.2 Context free grammars . . . . . . . . . . . . . . . . . . . 349

10.2.1 Context-free grammars as a computational model 35110.2.2 The power of context free grammars . . . . . . . 35310.2.3 Limitations of context-free grammars (optional) 355

Page 13: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

13

10.3 Semantic properties of context free languages . . . . . . 35710.3.1 Uncomputability of context-free grammar

equivalence (optional) . . . . . . . . . . . . . . . 35710.4 Summary of semantic properties for regular expres-

sions and context-free grammars . . . . . . . . . . . . . 36010.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 36110.6 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 362

11 Is every theorem provable? 36511.1 Hilbert’s Program and Gödel’s Incompleteness Theorem 365

11.1.1 Defining “Proof Systems” . . . . . . . . . . . . . . 36711.2 Gödel’s Incompleteness Theorem: Computational

variant . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36811.3 Quantified integer statements . . . . . . . . . . . . . . . 37011.4 Diophantine equations and the MRDP Theorem . . . . 37211.5 Hardness of quantified integer statements . . . . . . . . 374

11.5.1 Step 1: Quantified mixed statements and com-putation histories . . . . . . . . . . . . . . . . . . 375

11.5.2 Step 2: Reducing mixed statements to integerstatements . . . . . . . . . . . . . . . . . . . . . . 378

11.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 38011.7 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 382

III Efficient algorithms 385

12 Efficient computation: An informal introduction 38712.1 Problems on graphs . . . . . . . . . . . . . . . . . . . . . 389

12.1.1 Finding the shortest path in a graph . . . . . . . . 39012.1.2 Finding the longest path in a graph . . . . . . . . 39212.1.3 Finding the minimum cut in a graph . . . . . . . 39212.1.4 Min-Cut Max-Flow and Linear programming . . 39312.1.5 Finding the maximum cut in a graph . . . . . . . 39512.1.6 A note on convexity . . . . . . . . . . . . . . . . . 395

12.2 Beyond graphs . . . . . . . . . . . . . . . . . . . . . . . . 39712.2.1 SAT . . . . . . . . . . . . . . . . . . . . . . . . . . 39712.2.2 Solving linear equations . . . . . . . . . . . . . . . 39812.2.3 Solving quadratic equations . . . . . . . . . . . . 399

12.3 More advanced examples . . . . . . . . . . . . . . . . . 39912.3.1 Determinant of a matrix . . . . . . . . . . . . . . . 39912.3.2 Permanent of a matrix . . . . . . . . . . . . . . . . 40112.3.3 Finding a zero-sum equilibrium . . . . . . . . . . 40112.3.4 Finding a Nash equilibrium . . . . . . . . . . . . 40212.3.5 Primality testing . . . . . . . . . . . . . . . . . . . 40212.3.6 Integer factoring . . . . . . . . . . . . . . . . . . . 403

Page 14: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

14

12.4 Our current knowledge . . . . . . . . . . . . . . . . . . . 40312.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 40412.6 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 40412.7 Further explorations . . . . . . . . . . . . . . . . . . . . 405

13 Modeling running time 40713.1 Formally defining running time . . . . . . . . . . . . . . 409

13.1.1 Polynomial and Exponential Time . . . . . . . . . 41013.2 Modeling running time using RAM Machines /

NAND-RAM . . . . . . . . . . . . . . . . . . . . . . . . . 41213.3 Extended Church-Turing Thesis (discussion) . . . . . . 41713.4 Efficient universal machine: a NAND-RAM inter-

preter in NAND-RAM . . . . . . . . . . . . . . . . . . . 41813.4.1 Timed Universal Turing Machine . . . . . . . . . 420

13.5 The time hierarchy theorem . . . . . . . . . . . . . . . . 42113.6 Non uniform computation . . . . . . . . . . . . . . . . . 425

13.6.1 Oblivious NAND-TM programs . . . . . . . . . . 42713.6.2 “Unrolling the loop”: algorithmic transforma-

tion of Turing Machines to circuits . . . . . . . . . 43013.6.3 Can uniform algorithms simulate non uniform

ones? . . . . . . . . . . . . . . . . . . . . . . . . . 43213.6.4 Uniform vs. Nonuniform computation: A recap . 434

13.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 43513.8 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 438

14 Polynomial-time reductions 43914.1 Formal definitions of problems . . . . . . . . . . . . . . 44014.2 Polynomial-time reductions . . . . . . . . . . . . . . . . 441

14.2.1 Whistling pigs and flying horses . . . . . . . . . . 44214.3 Reducing 3SAT to zero one and quadratic equations . . 444

14.3.1 Quadratic equations . . . . . . . . . . . . . . . . . 44714.4 The independent set problem . . . . . . . . . . . . . . . 44914.5 Some exercises and anatomy of a reduction. . . . . . . . 452

14.5.1 Dominating set . . . . . . . . . . . . . . . . . . . . 45314.5.2 Anatomy of a reduction . . . . . . . . . . . . . . . 456

14.6 Reducing Independent Set to Maximum Cut . . . . . . 45814.7 Reducing 3SAT to Longest Path . . . . . . . . . . . . . . 459

14.7.1 Summary of relations . . . . . . . . . . . . . . . . 46214.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 46214.9 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 463

15 NP, NP completeness, and the Cook-Levin Theorem 46515.1 The class NP . . . . . . . . . . . . . . . . . . . . . . . . . 465

15.1.1 Examples of functions in NP . . . . . . . . . . . . 46815.1.2 Basic facts about NP . . . . . . . . . . . . . . . . . 470

Page 15: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

15

15.2 From NP to 3SAT: The Cook-Levin Theorem . . . . . . . 47115.2.1 What does this mean? . . . . . . . . . . . . . . . . 47315.2.2 The Cook-Levin Theorem: Proof outline . . . . . 473

15.3 The NANDSAT Problem, and why it is NP hard . . . . 47415.4 The 3NAND problem . . . . . . . . . . . . . . . . . . . . 47615.5 From 3NAND to 3SAT . . . . . . . . . . . . . . . . . . . 47915.6 Wrapping up . . . . . . . . . . . . . . . . . . . . . . . . . 48015.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 48115.8 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 482

16 What if P equals NP? 48316.1 Search-to-decision reduction . . . . . . . . . . . . . . . . 48416.2 Optimization . . . . . . . . . . . . . . . . . . . . . . . . . 487

16.2.1 Example: Supervised learning . . . . . . . . . . . 49016.2.2 Example: Breaking cryptosystems . . . . . . . . . 491

16.3 Finding mathematical proofs . . . . . . . . . . . . . . . 49116.4 Quantifier elimination (advanced) . . . . . . . . . . . . 492

16.4.1 Application: self improving algorithm for 3SAT . 49516.5 Approximating counting problems and posterior

sampling (advanced, optional) . . . . . . . . . . . . . . 49516.6 What does all of this imply? . . . . . . . . . . . . . . . . 49616.7 Can P ≠ NP be neither true nor false? . . . . . . . . . . 49816.8 Is P = NP “in practice”? . . . . . . . . . . . . . . . . . . 49916.9 What if P ≠ NP? . . . . . . . . . . . . . . . . . . . . . . . 50016.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 50216.11 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 502

17 Space bounded computation 50317.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 50317.2 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 503

IV Randomized computation 505

18 Probability Theory 101 50718.1 Random coins . . . . . . . . . . . . . . . . . . . . . . . . 507

18.1.1 Random variables . . . . . . . . . . . . . . . . . . 51018.1.2 Distributions over strings . . . . . . . . . . . . . . 51218.1.3 More general sample spaces . . . . . . . . . . . . 512

18.2 Correlations and independence . . . . . . . . . . . . . . 51318.2.1 Independent random variables . . . . . . . . . . . 51418.2.2 Collections of independent random variables . . 516

18.3 Concentration and tail bounds . . . . . . . . . . . . . . . 51618.3.1 Chebyshev’s Inequality . . . . . . . . . . . . . . . 51818.3.2 The Chernoff bound . . . . . . . . . . . . . . . . . 519

Page 16: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

16

18.3.3 Application: Supervised learning and empiricalrisk minimization . . . . . . . . . . . . . . . . . . 520

18.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 52218.5 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 525

19 Probabilistic computation 52719.1 Finding approximately good maximum cuts . . . . . . . 528

19.1.1 Amplifying the success of randomized algorithms 52919.1.2 Success amplification . . . . . . . . . . . . . . . . 53019.1.3 Two-sided amplification . . . . . . . . . . . . . . . 53119.1.4 What does this mean? . . . . . . . . . . . . . . . . 53119.1.5 Solving SAT through randomization . . . . . . . 53219.1.6 Bipartite matching . . . . . . . . . . . . . . . . . . 534

19.2 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 53719.3 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 53719.4 Acknowledgements . . . . . . . . . . . . . . . . . . . . . 537

20 Modeling randomized computation 53920.1 Modeling randomized computation . . . . . . . . . . . 540

20.1.1 An alternative view: random coins as an “extrainput” . . . . . . . . . . . . . . . . . . . . . . . . . 542

20.1.2 Success amplification of two-sided error algo-rithms . . . . . . . . . . . . . . . . . . . . . . . . . 544

20.2 BPP and NP completeness . . . . . . . . . . . . . . . . . 54520.3 The power of randomization . . . . . . . . . . . . . . . . 547

20.3.1 Solving BPP in exponential time . . . . . . . . . . 54720.3.2 Simulating randomized algorithms by circuits . . 547

20.4 Derandomization . . . . . . . . . . . . . . . . . . . . . . 54920.4.1 Pseudorandom generators . . . . . . . . . . . . . 55020.4.2 From existence to constructivity . . . . . . . . . . 55220.4.3 Usefulness of pseudorandom generators . . . . . 553

20.5 P = NP and BPP vs P . . . . . . . . . . . . . . . . . . . . 55420.6 Non-constructive existence of pseudorandom genera-

tors (advanced, optional) . . . . . . . . . . . . . . . . . 55720.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 56020.8 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 560

V Advanced topics 561

21 Cryptography 56321.1 Classical cryptosystems . . . . . . . . . . . . . . . . . . . 56421.2 Defining encryption . . . . . . . . . . . . . . . . . . . . . 56621.3 Defining security of encryption . . . . . . . . . . . . . . 56721.4 Perfect secrecy . . . . . . . . . . . . . . . . . . . . . . . . 569

Page 17: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

17

21.4.1 Example: Perfect secrecy in the battlefield . . . . 57021.4.2 Constructing perfectly secret encryption . . . . . 571

21.5 Necessity of long keys . . . . . . . . . . . . . . . . . . . 57221.6 Computational secrecy . . . . . . . . . . . . . . . . . . . 574

21.6.1 Stream ciphers or the “derandomized one-timepad” . . . . . . . . . . . . . . . . . . . . . . . . . . 576

21.7 Computational secrecy and NP . . . . . . . . . . . . . . 57921.8 Public key cryptography . . . . . . . . . . . . . . . . . . 581

21.8.1 Defining public key encryption . . . . . . . . . . 58321.8.2 Diffie-Hellman key exchange . . . . . . . . . . . . 584

21.9 Other security notions . . . . . . . . . . . . . . . . . . . 58621.10 Magic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586

21.10.1 Zero knowledge proofs . . . . . . . . . . . . . . . 58621.10.2 Fully homomorphic encryption . . . . . . . . . . 58721.10.3 Multiparty secure computation . . . . . . . . . . 587

21.11 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 58921.12 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 589

22 Proofs and algorithms 59122.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 59122.2 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 591

23 Quantum computing 59323.1 The double slit experiment . . . . . . . . . . . . . . . . . 59423.2 Quantum amplitudes . . . . . . . . . . . . . . . . . . . . 594

23.2.1 Linear algebra quick review . . . . . . . . . . . . 59723.3 Bell’s Inequality . . . . . . . . . . . . . . . . . . . . . . . 59823.4 Quantum weirdness . . . . . . . . . . . . . . . . . . . . . 60023.5 Quantum computing and computation - an executive

summary . . . . . . . . . . . . . . . . . . . . . . . . . . . 60023.6 Quantum systems . . . . . . . . . . . . . . . . . . . . . . 602

23.6.1 Quantum amplitudes . . . . . . . . . . . . . . . . 60423.6.2 Quantum systems: an executive summary . . . . 605

23.7 Analysis of Bell’s Inequality (optional) . . . . . . . . . . 60523.8 Quantum computation . . . . . . . . . . . . . . . . . . . 608

23.8.1 Quantum circuits . . . . . . . . . . . . . . . . . . 60823.8.2 QNAND-CIRC programs (optional) . . . . . . . 61123.8.3 Uniform computation . . . . . . . . . . . . . . . . 612

23.9 Physically realizing quantum computation . . . . . . . 61323.10 Shor’s Algorithm: Hearing the shape of prime factors . 614

23.10.1 Period finding . . . . . . . . . . . . . . . . . . . . 61423.10.2 Shor’s Algorithm: A bird’s eye view . . . . . . . . 615

23.11 Quantum Fourier Transform (advanced, optional) . . . 617

Page 18: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

18

23.11.1 Quantum Fourier Transform over the BooleanCube: Simon’s Algorithm . . . . . . . . . . . . . . 619

23.11.2 From Fourier to Period finding: Simon’s Algo-rithm (advanced, optional) . . . . . . . . . . . . . 620

23.11.3 From Simon to Shor (advanced, optional) . . . . 62123.12 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . 62323.13 Bibliographical notes . . . . . . . . . . . . . . . . . . . . 623

VI Appendices 625

Page 19: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Preface

“We make ourselves no promises, but we cherish the hope that the unobstructedpursuit of useless knowledge will prove to have consequences in the futureas in the past” 
 “An institution which sets free successive generations ofhuman souls is amply justified whether or not this graduate or that makes aso-called useful contribution to human knowledge. A poem, a symphony, apainting, a mathematical truth, a new scientific fact, all bear in themselves allthe justification that universities, colleges, and institutes of research need orrequire”, Abraham Flexner, The Usefulness of Useless Knowledge, 1939.

“I suggest that you take the hardest courses that you can, because you learnthe most when you challenge yourself
 CS 121 I found pretty hard.”, MarkZuckerberg, 2005.

This is a textbook for an undergraduate introductory course onTheoretical Computer Science. The educational goals of this book areto convey the following:

‱ That computation arises in a variety of natural and human-madesystems, and not only in modern silicon-based computers.

‱ Similarly, beyond being an extremely important tool, computationalso serves as a useful lens to describe natural, physical, mathemati-cal and even social concepts.

‱ The notion of universality of many different computational models,and the related notion of the duality between code and data.

‱ The idea that one can precisely define a mathematical model ofcomputation, and then use that to prove (or sometimes only conjec-ture) lower bounds and impossibility results.

‱ Some of the surprising results and discoveries in modern theoreti-cal computer science, including the prevalence of NP-completeness,the power of interaction, the power of randomness on one handand the possibility of derandomization on the other, the abilityto use hardness “for good” in cryptography, and the fascinatingpossibility of quantum computing.

Compiled on 8.26.2020 18:10

Page 20: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

20

I hope that following this course, students would be able to rec-ognize computation, with both its power and pitfalls, as it arises invarious settings, including seemingly “static” content or “restricted”formalisms such as macros and scripts. They should be able to followthrough the logic of proofs about computation, including the cen-tral concept of a reduction, as well as understanding “self-referential”proofs (such as diagonalization-based proofs that involve programsgiven their own code as input). Students should understand thatsome problems are inherently intractable, and be able to recognize thepotential for intractability when they are faced with a new problem.While this book only touches on cryptography, students should un-derstand the basic idea of how we can use computational hardness forcryptographic purposes. However, more than any specific skill, thisbook aims to introduce students to a new way of thinking of computa-tion as an object in its own right and to illustrate how this new way ofthinking leads to far-reaching insights and applications.

My aim in writing this text is to try to convey these concepts in thesimplest possible way and try to make sure that the formal notationand model help elucidate, rather than obscure, the main ideas. I alsotried to take advantage of modern students’ familiarity (or at leastinterest!) in programming, and hence use (highly simplified) pro-gramming languages to describe our models of computation. Thatsaid, this book does not assume fluency with any particular program-ming language, but rather only some familiarity with the generalnotion of programming. We will use programming metaphors andidioms, occasionally mentioning specific programming languagessuch as Python, C, or Lisp, but students should be able to follow thesedescriptions even if they are not familiar with these languages.

Proofs in this book, including the existence of a universal TuringMachine, the fact that every finite function can be computed by somecircuit, the Cook-Levin theorem, and many others, are often con-structive and algorithmic, in the sense that they ultimately involvetransforming one program to another. While it is possible to followthese proofs without seeing the code, I do think that having accessto the code, and the ability to play around with it and see how it actson various programs, can make these theorems more concrete for thestudents. To that end, an accompanying website (which is still workin progress) allows executing programs in the various computationalmodels we define, as well as see constructive proofs of some of thetheorems.

0.1 TO THE STUDENT

This book can be challenging, mainly because it brings together avariety of ideas and techniques in the study of computation. There

Page 21: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

21

are quite a few technical hurdles to master, whether it is followingthe diagonalization argument for proving the Halting Problem isundecidable, combinatorial gadgets in NP-completeness reductions,analyzing probabilistic algorithms, or arguing about the adversary toprove the security of cryptographic primitives.

The best way to engage with this material is to read these notes ac-tively, so make sure you have a pen ready. While reading, I encourageyou to stop and think about the following:

‱ When I state a theorem, stop and take a shot at proving it on yourown before reading the proof. You will be amazed by how muchbetter you can understand a proof even after only 5 minutes ofattempting it on your own.

‱ When reading a definition, make sure that you understand whatthe definition means, and what the natural examples are of objectsthat satisfy it and objects that do not. Try to think of the motivationbehind the definition, and whether there are other natural ways toformalize the same concept.

‱ Actively notice which questions arise in your mind as you read thetext, and whether or not they are answered in the text.

As a general rule, it is more important that you understand thedefinitions than the theorems, and it is more important that youunderstand a theorem statement than its proof. After all, before youcan prove a theorem, you need to understand what it states, and tounderstand what a theorem is about, you need to know the definitionsof the objects involved. Whenever a proof of a theorem is at leastsomewhat complicated, I provide a “proof idea.” Feel free to skip theactual proof in a first reading, focusing only on the proof idea.

This book contains some code snippets, but this is by no meansa programming text. You don’t need to know how to program tofollow this material. The reason we use code is that it is a precise wayto describe computation. Particular implementation details are notas important to us, and so we will emphasize code readability at theexpense of considerations such as error handling, encapsulation, etc.that can be extremely important for real-world programming.

0.1.1 Is the effort worth it?This is not an easy book, and you might reasonably wonder whyshould you spend the effort in learning this material. A traditionaljustification for a “Theory of Computation” course is that you mightencounter these concepts later on in your career. Perhaps you willcome across a hard problem and realize it is NP complete, or find aneed to use what you learned about regular expressions. This might

Page 22: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

22

1 An earlier book that starts with circuits as the initialmodel is John Savage’s [Sav98].

very well be true, but the main benefit of this book is not in teachingyou any practical tool or technique, but instead in giving you a differ-ent way of thinking: an ability to recognize computational phenomenaeven when they occur in non-obvious settings, a way to model compu-tational tasks and questions, and to reason about them.

Regardless of any use you will derive from this book, I believelearning this material is important because it contains concepts thatare both beautiful and fundamental. The role that energy and matterplayed in the 20th century is played in the 21st by computation andinformation, not just as tools for our technology and economy, but alsoas the basic building blocks we use to understand the world. Thisbook will give you a taste of some of the theory behind those, andhopefully spark your curiosity to study more.

0.2 TO POTENTIAL INSTRUCTORS

I wrote this book for my Harvard course, but I hope that other lectur-ers will find it useful as well. To some extent, it is similar in contentto “Theory of Computation” or “Great Ideas” courses such as thosetaught at CMU or MIT.

The most significant difference between our approach and moretraditional ones (such as Hopcroft and Ullman’s [HU69; HU79] andSipser’s [Sip97]) is that we do not start with finite automata as our ini-tial computational model. Instead, our initial computational modelis Boolean Circuits.1 We believe that Boolean Circuits are more fun-damental to the theory of computing (and even its practice!) thanautomata. In particular, Boolean Circuits are a prerequisite for manyconcepts that one would want to teach in a modern course on Theoret-ical Computer Science, including cryptography, quantum computing,derandomization, attempts at proving P ≠ NP, and more. Even incases where Boolean Circuits are not strictly required, they can of-ten offer significant simplifications (as in the case of the proof of theCook-Levin Theorem).

Furthermore, I believe there are pedagogical reasons to start withBoolean circuits as opposed to finite automata. Boolean circuits are amore natural model of computation, and one that corresponds moreclosely to computing in silicon, making the connection to practicemore immediate to the students. Finite functions are arguably easierto grasp than infinite ones, as we can fully write down their truth ta-ble. The theorem that every finite function can be computed by someBoolean circuit is both simple enough and important enough to serveas an excellent starting point for this course. Moreover, many of themain conceptual points of the theory of computation, including thenotions of the duality between code and data, and the idea of universal-ity, can already be seen in this context.

Page 23: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

23

After Boolean circuits, we move on to Turing machines and proveresults such as the existence of a universal Turing machine, the un-computability of the halting problem, and Rice’s Theorem. Automataare discussed after we see Turing machines and undecidability, as anexample for a restricted computational model where problems such asdetermining halting can be effectively solved.

While this is not our motivation, the order we present circuits, Tur-ing machines, and automata roughly corresponds to the chronologicalorder of their discovery. Boolean algebra goes back to Boole’s andDeMorgan’s works in the 1840s [Boo47; De 47] (though the defini-tion of Boolean circuits and the connection to physical computationwas given 90 years later by Shannon [Sha38]). Alan Turing definedwhat we now call “Turing Machines” in the 1930s [Tur37], while finiteautomata were introduced in the 1943 work of McCulloch and Pitts[MP43] but only really understood in the seminal 1959 work of Rabinand Scott [RS59].

More importantly, while models such as finite-state machines, reg-ular expressions, and context-free grammars are incredibly importantfor practice, the main applications for these models (whether it is forparsing, for analyzing properties such as liveness and safety, or even forsoftware-defined routing tables) rely crucially on the fact that theseare tractable models for which we can effectively answer semantic ques-tions. This practical motivation can be better appreciated after studentssee the undecidability of semantic properties of general computingmodels.

The fact that we start with circuits makes proving the Cook-LevinTheorem much easier. In fact, our proof of this theorem can be (andis) done using a handful of lines of Python. Combining this proofwith the standard reductions (which are also implemented in Python)allows students to appreciate visually how a question about computa-tion can be mapped into a question about (for example) the existenceof an independent set in a graph.

Some other differences between this book and previous texts arethe following:

1. For measuring time complexity, we use the standard RAM machinemodel used (implicitly) in algorithms courses, rather than Tur-ing machines. While these two models are of course polynomiallyequivalent, and hence make no difference for the definitions of theclasses P, NP, and EXP, our choice makes the distinction betweennotions such as 𝑂(𝑛) or 𝑂(𝑛2) time more meaningful. This choicealso ensures that these finer-grained time complexity classes corre-spond to the informal definitions of linear and quadratic time that

Page 24: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

24

students encounter in their algorithms lectures (or their whiteboardcoding interviews
).

2. We use the terminology of functions rather than languages. That is,rather than saying that a Turing Machine 𝑀 decides a language 𝐿 ⊆0, 1∗, we say that it computes a function đč ∶ 0, 1∗ → 0, 1. Theterminology of “languages” arises from Chomsky’s work [Cho56],but it is often more confusing than illuminating. The languageterminology also makes it cumbersome to discuss concepts suchas algorithms that compute functions with more than one bit ofoutput (including basic tasks such as addition, multiplication,etc
). The fact that we use functions rather than languages meanswe have to be extra vigilant about students distinguishing betweenthe specification of a computational task (e.g., the function) and itsimplementation (e.g., the program). On the other hand, this point isso important that it is worth repeatedly emphasizing and drillinginto the students, regardless of the notation used. The book doesmention the language terminology and reminds of it occasionally,to make it easier for students to consult outside resources.

Reducing the time dedicated to finite automata and context-freelanguages allows instructors to spend more time on topics that a mod-ern course in the theory of computing needs to touch upon. Theseinclude randomness and computation, the interactions between proofsand programs (including Gödel’s incompleteness theorem, interactiveproof systems, and even a bit on the 𝜆-calculus and the Curry-Howardcorrespondence), cryptography, and quantum computing.

This book contains sufficient detail to enable its use for self-study.Toward that end, every chapter starts with a list of learning objectives,ends with a recap, and is peppered with “pause boxes” which encour-age students to stop and work out an argument or make sure theyunderstand a definition before continuing further.

Section 0.5 contains a “roadmap” for this book, with descriptionsof the different chapters, as well as the dependency structure betweenthem. This can help in planning a course based on this book.

0.3 ACKNOWLEDGEMENTS

This text is continually evolving, and I am getting input from manypeople, for which I am deeply grateful. Salil Vadhan co-taught withme the first iteration of this course and gave me a tremendous amountof useful feedback and insights during this process. Michele Amorettiand Marika Swanberg carefully read several chapters of this text andgave extremely helpful detailed comments. Dave Evans and RichardXu contributed many pull requests fixing errors and improving phras-

Page 25: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

25

ing. Thanks to Anil Ada, Venkat Guruswami, and Ryan O’Donnell forhelpful tips from their experience in teaching CMU 15-251.

Thanks to everyone that sent me comments, typo reports, or postedissues or pull requests on the GitHub repository https://github.com/boazbk/tcs. In particular I would like to acknowledge helpfulfeedback from Scott Aaronson, Michele Amoretti, Aadi Bajpai, Mar-guerite Basta, Anindya Basu, Sam Benkelman, JarosƂaw BƂasiok, EmilyChan, Christy Cheng, Michelle Chiang, Daniel Chiu, Chi-Ning Chou,Michael Colavita, Rodrigo Daboin Sanchez, Robert Darley Waddilove,Anlan Du, Juan Esteller, David Evans, Michael Fine, Simon Fischer,Leor Fishman, Zaymon Foulds-Cook, William Fu, Kent Furuie, PiotrGaluszka, Carolyn Ge, Mark Goldstein, Alexander Golovnev, SayanGoswami, Michael Haak, Rebecca Hao, Joosep Hook, Thomas HUET,Emily Jia, Chan Kang, Nina Katz-Christy, Vidak Kazic, Eddie Kohler,Estefania Lahera, Allison Lee, Benjamin Lee, Ondƙej LengĂĄl, RaymondLin, Emma Ling, Alex Lombardi, Lisa Lu, Aditya Mahadevan, Chris-tian May, Jacob Meyerson, Leon Mlodzian, George Moe, Glenn Moss,Hamish Nicholson, Owen Niles, Sandip Nirmel, Sebastian Oberhoff,Thomas Orton, Joshua Pan, Pablo Parrilo, Juan Perdomo, Banks Pick-ett, Aaron Sachs, Abdelrhman Saleh, Brian Sapozhnikov, AnthonyScemama, Peter SchĂ€fer, Josh Seides, Alaisha Sharma, Haneul Shin,Noah Singer, Matthew Smedberg, Miguel Solano, Hikari Sorensen,David Steurer, Alec Sun, Amol Surati, Everett Sussman, Marika Swan-berg, Garrett Tanzer, Eric Thomas, Sarah Turnill, Salil Vadhan, PatrickWatts, Jonah Weissman, Ryan Williams, Licheng Xu, Richard Xu, Wan-qian Yang, Elizabeth Yeoh-Wang, Josh Zelinsky, Fred Zhang, GraceZhang, and Jessica Zhu.

I am using many open source software packages in the productionof these notes for which I am grateful. In particular, I am thankful toDonald Knuth and Leslie Lamport for LaTeX and to John MacFarlanefor Pandoc. David Steurer wrote the original scripts to produce thistext. The current version uses Sergio Correia’s panflute. The templatesfor the LaTeX and HTML versions are derived from Tufte LaTeX,Gitbook and Bookdown. Thanks to Amy Hendrickson for some LaTeXconsulting. Juan Esteller and Gabe Montague initially implementedthe NAND* programming languages in OCaml and Javascript. I usedthe Jupyter project to write the supplemental code snippets.

Finally, I would like to thank my family: my wife Ravit, and mychildren Alma and Goren. Working on this book (and the correspond-ing course) took so much of my time that Alma wrote an essay for herfifth-grade class saying that “universities should not pressure profes-sors to work too much.” I’m afraid all I have to show for this effort is600 pages of ultra-boring mathematical text.

Page 26: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 27: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

PRELIMINARIES

Page 28: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 29: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

1 This quote is typically read as disparaging theimportance of actual physical computers in ComputerScience, but note that telescopes are absolutelyessential to astronomy as they provide us with themeans to connect theoretical predictions with actualexperimental observations.2 To be fair, in the following sentence Graham says“you need to know how to calculate time and spacecomplexity and about Turing completeness”. Thisbook includes these topics, as well as others such asNP-hardness, randomization, cryptography, quantumcomputing, and more.

0Introduction

“Computer Science is no more about computers than astronomy is abouttelescopes”, attributed to Edsger Dijkstra.1

“Hackers need to understand the theory of computation about as much aspainters need to understand paint chemistry.”, Paul Graham 2003.2

“The subject of my talk is perhaps most directly indicated by simply askingtwo questions: first, is it harder to multiply than to add? and second, why?
I(would like to) show that there is no algorithm for multiplication computation-ally as simple as that for addition, and this proves something of a stumblingblock.”, Alan Cobham, 1964

The origin of much of science and medicine can be traced back tothe ancient Babylonians. However, the Babylonians’ most significantcontribution to humanity was arguably the invention of the place-valuenumber system. The place-value system represents any number usinga collection of digits, whereby the position of the digit is used to de-termine its value, as opposed to a system such as Roman numerals,where every symbol has a fixed numerical value regardless of posi-tion. For example, the average distance to the moon is approximately238,900 of our miles or 259,956 Roman miles. The latter quantity, ex-pressed in standard Roman numerals isMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMDCCCCLVI

Writing the distance to the sun in Roman numerals would requireabout 100,000 symbols: a 50-page book just containing this singlenumber!

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Introduce and motivate the study of

computation for its own sake, irrespective ofparticular implementations.

‱ The notion of an algorithm and some of itshistory.

‱ Algorithms as not just tools, but also ways ofthinking and understanding.

‱ Taste of Big-𝑂 analysis and the surprisingcreativity in the design of efficientalgorithms.

Page 30: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

30 introduction to theoretical computer science

For someone who thinks of numbers in an additive system likeRoman numerals, quantities like the distance to the moon or sun arenot merely large—they are unspeakable: cannot be expressed or evengrasped. It’s no wonder that Eratosthenes, who was the first personto calculate the earth’s diameter (up to about ten percent error) andHipparchus who was the first to calculate the distance to the moon,did not use a Roman-numeral type system but rather the Babyloniansexagesimal (i.e., base 60) place-value system.

0.1 INTEGER MULTIPLICATION: AN EXAMPLE OF AN ALGORITHM

In the language of Computer Science, the place-value system for rep-resenting numbers is known as a data structure: a set of instructions,or “recipe”, for representing objects as symbols. An algorithm is a setof instructions, or “recipe”, for performing operations on such rep-resentations. Data structures and algorithms have enabled amazingapplications that have transformed human society, but their impor-tance goes beyond their practical utility. Structures from computerscience, such as bits, strings, graphs, and even the notion of a programitself, as well as concepts such as universality and replication, have notjust found (many) practical uses but contributed a new language anda new way to view the world.

In addition to coming up with the place-value system, the Babylo-nians also invented the “standard algorithms” that we were all taughtin elementary school for adding and multiplying numbers. These al-gorithms have been essential throughout the ages for people usingabaci, papyrus, or pencil and paper, but in our computer age, do theystill serve any purpose beyond torturing third graders? To see whythese algorithms are still very much relevant, let us compare the Baby-lonian digit-by-digit multiplication algorithm (“grade-school multi-plication”) with the naive algorithm that multiplies numbers throughrepeated addition. We start by formally describing both algorithms,see Algorithm 0.1 and Algorithm 0.2.

Algorithm 0.1 — Multiplication via repeated addition.

Input: Non-negative integers đ‘„, 𝑩Output: Product đ‘„ ⋅ 𝑩1: Let 𝑟𝑒𝑠𝑱𝑙𝑡 ← 0.2: for 𝑖 = 1, 
 , 𝑩 do3: 𝑟𝑒𝑠𝑱𝑙𝑡 ← 𝑟𝑒𝑠𝑱𝑙𝑡 + đ‘„4: end for5: return 𝑟𝑒𝑠𝑱𝑙𝑡

Page 31: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

introduction 31

Algorithm 0.2 — Grade-school multiplication.

Input: Non-negative integers đ‘„, 𝑩Output: Product đ‘„ ⋅ 𝑩1: Write đ‘„ = đ‘„đ‘›âˆ’1đ‘„đ‘›âˆ’2 ⋯ đ‘„0 and 𝑩 = 𝑩𝑚−1𝑩𝑚−2 ⋯ 𝑩0 in dec-

imal place-value notation. # đ‘„0 is the ones digit of đ‘„, đ‘„1 isthe tens digit, etc.

2: Let 𝑟𝑒𝑠𝑱𝑙𝑡 ← 03: for 𝑖 = 0, 
 , 𝑛 − 1 do4: for 𝑗 = 0, 
 , 𝑚 − 1 do5: 𝑟𝑒𝑠𝑱𝑙𝑡 ← 𝑟𝑒𝑠𝑱𝑙𝑡 + 10𝑖+𝑗 ⋅ đ‘„đ‘– ⋅ 𝑩𝑗6: end for7: end for8: return 𝑟𝑒𝑠𝑱𝑙𝑡

Both Algorithm 0.1 and Algorithm 0.2 assume that we alreadyknow how to add numbers, and Algorithm 0.2 also assumes that wecan multiply a number by a power of 10 (which is, after all, a sim-ple shift). Suppose that đ‘„ and 𝑩 are two integers of 𝑛 = 20 decimaldigits each. (This roughly corresponds to 64 binary digits, which isa common size in many programming languages.) Computing đ‘„ ⋅ 𝑩using Algorithm 0.1 entails adding đ‘„ to itself 𝑩 times which entails(since 𝑩 is a 20-digit number) at least 1019 additions. In contrast, thegrade-school algorithm (i.e., Algorithm 0.2) involves 𝑛2 shifts andsingle-digit products, and so at most 2𝑛2 = 800 single-digit opera-tions. To understand the difference, consider that a grade-schooler canperform a single-digit operation in about 2 seconds, and so would re-quire about 1, 600 seconds (about half an hour) to compute đ‘„ ⋅ 𝑩 usingAlgorithm 0.2. In contrast, even though it is more than a billion timesfaster than a human, if we used Algorithm 0.1 to compute đ‘„ ⋅ 𝑩 using amodern PC, it would take us 1020/109 = 1011 seconds (which is morethan three millennia!) to compute the same result.

Computers have not made algorithms obsolete. On the contrary,the vast increase in our ability to measure, store, and communicatedata has led to much higher demand for developing better and moresophisticated algorithms that empower us to make better decisionsbased on these data. We also see that in no small extent the notion ofalgorithm is independent of the actual computing device that executesit. The digit-by-digit multiplication algorithm is vastly better than iter-ated addition, regardless whether the technology we use to implementit is a silicon-based chip, or a third grader with pen and paper.

Theoretical computer science is concerned with the inherent proper-ties of algorithms and computation; namely, those properties that areindependent of current technology. We ask some questions that were

Page 32: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

32 introduction to theoretical computer science

already pondered by the Babylonians, such as “what is the best way tomultiply two numbers?”, but also questions that rely on cutting-edgescience such as “could we use the effects of quantum entanglement tofactor numbers faster?”.

RRemark 0.3 — Specification, implementation and analysisof algorithms.. A full description of an algorithm hasthree components:

‱ Specification: What is the task that the algorithmperforms (e.g., multiplication in the case of Algo-rithm 0.1 and Algorithm 0.2.)

‱ Implementation: How is the task accomplished:what is the sequence of instructions to be per-formed. Even though Algorithm 0.1 and Algo-rithm 0.2 perform the same computational task(i.e., they have the same specification), they do it indifferent ways (i.e., they have different implementa-tions).

‱ Analysis: Why does this sequence of instructionsachieve the desired task. A full description of Algo-rithm 0.1 and Algorithm 0.2 will include a proof foreach one of these algorithms that on input đ‘„, 𝑩, thealgorithm does indeed output đ‘„ ⋅ 𝑩.

Often as part of the analysis we show that the algo-rithm is not only correct but also efficient. That is, wewant to show that not only will the algorithm computethe desired task, but will do so in prescribed numberof operations. For example Algorithm 0.2 computesthe multiplication function on inputs of 𝑛 digits using𝑂(𝑛2) operations, while Algorithm 0.4 (describedbelow) computes the same function using 𝑂(𝑛1.6)operations. (We define the 𝑂 notations used here inSection 1.4.8.)

0.2 EXTENDED EXAMPLE: A FASTER WAY TO MULTIPLY (OP-TIONAL)

Once you think of the standard digit-by-digit multiplication algo-rithm, it seems like the “obviously best’ ’ way to multiply numbers.In 1960, the famous mathematician Andrey Kolmogorov organizeda seminar at Moscow State University in which he conjectured thatevery algorithm for multiplying two 𝑛 digit numbers would requirea number of basic operations that is proportional to 𝑛2 (Ω(𝑛2) opera-tions, using 𝑂-notation as defined in Chapter 1). In other words, Kol-mogorov conjectured that in any multiplication algorithm, doublingthe number of digits would quadruple the number of basic operationsrequired. A young student named Anatoly Karatsuba was in the au-

Page 33: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

introduction 33

Figure 1: The grade-school multiplication algorithmillustrated for multiplying đ‘„ = 10đ‘„ + đ‘„ and 𝑩 =10𝑩 + 𝑩. It uses the formula (10đ‘„ + đ‘„) × (10𝑩 + 𝑩) =100đ‘„đ‘Š + 10(đ‘„đ‘Š + đ‘„đ‘Š) + đ‘„đ‘Š.

3 If đ‘„ is a number then âŒŠđ‘„âŒ‹ is the integer obtained byrounding it down, see Section 1.7.

dience, and within a week he disproved Kolmogorov’s conjecture bydiscovering an algorithm that requires only about đ¶đ‘›1.6 operationsfor some constant đ¶. Such a number becomes much smaller than 𝑛2as 𝑛 grows and so for large 𝑛 Karatsuba’s algorithm is superior to thegrade-school one. (For example, Python’s implementation switchesfrom the grade-school algorithm to Karatsuba’s algorithm for num-bers that are 1000 bits or larger.) While the difference between an𝑂(𝑛1.6) and an 𝑂(𝑛2) algorithm can be sometimes crucial in practice(see Section 0.3 below), in this book we will mostly ignore such dis-tinctions. However, we describe Karatsuba’s algorithm below since itis a good example of how algorithms can often be surprising, as wellas a demonstration of the analysis of algorithms, which is central to thisbook and to theoretical computer science at large.

Karatsuba’s algorithm is based on a faster way to multiply two-digitnumbers. Suppose that đ‘„, 𝑩 ∈ [100] = 0, 
 , 99 are a pair of two-digit numbers. Let’s write đ‘„ for the “tens” digit of đ‘„, and đ‘„ for the“ones” digit, so that đ‘„ = 10đ‘„ + đ‘„, and write similarly 𝑩 = 10𝑩 + 𝑩 forđ‘„, đ‘„, 𝑩, 𝑩 ∈ [10]. The grade-school algorithm for multiplying đ‘„ and 𝑩 isillustrated in Fig. 1.

The grade-school algorithm can be thought of as transforming thetask of multiplying a pair of two-digit numbers into four single-digitmultiplications via the formula(10đ‘„ + đ‘„) × (10𝑩 + 𝑩) = 100đ‘„đ‘Š + 10(đ‘„đ‘Š + đ‘„đ‘Š) + đ‘„đ‘Š (1)

Generally, in the grade-school algorithm doubling the number ofdigits in the input results in quadrupling the number of operations,leading to an 𝑂(𝑛2) times algorithm. In contrast, Karatsuba’s algo-rithm is based on the observation that we can express Eq. (1) alsoas

(10đ‘„+đ‘„)×(10𝑩+𝑩) = (100−10)đ‘„đ‘Š+10 [(đ‘„ + đ‘„)(𝑩 + 𝑩)]−(10−1)đ‘„đ‘Š (2)

which reduces multiplying the two-digit number đ‘„ and 𝑩 to com-puting the following three simpler products: đ‘„đ‘Š, đ‘„đ‘Š and (đ‘„ + đ‘„)(𝑩 + 𝑩).By repeating the same strategy recursively, we can reduce the task ofmultiplying two 𝑛-digit numbers to the task of multiplying three pairsof ⌊𝑛/2⌋ + 1 digit numbers.3 Since every time we double the number ofdigits we triple the number of operations, we will be able to multiplynumbers of 𝑛 = 2ℓ digits using about 3ℓ = 𝑛log2 3 ∌ 𝑛1.585 operations.

The above is the intuitive idea behind Karatsuba’s algorithm, but isnot enough to fully specify it. A complete description of an algorithmentails a precise specification of its operations together with its analysis:proof that the algorithm does in fact do what it’s supposed to do. The

Page 34: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

34 introduction to theoretical computer science

Figure 2: Karatsuba’s multiplication algorithm illus-trated for multiplying đ‘„ = 10đ‘„ + đ‘„ and 𝑩 = 10𝑩 + 𝑩.We compute the three orange, green and purple prod-ucts đ‘„đ‘Š, đ‘„đ‘Š and (đ‘„ + đ‘„)(𝑩 + 𝑩) and then add andsubtract them to obtain the result.

Figure 3: Running time of Karatsuba’s algorithmvs. the grade-school algorithm. (Python implementa-tion available online.) Note the existence of a “cutoff”length, where for sufficiently large inputs Karat-suba becomes more efficient than the grade-schoolalgorithm. The precise cutoff location varies by imple-mentation and platform details, but will always occureventually.

operations of Karatsuba’s algorithm are detailed in Algorithm 0.4,while the analysis is given in Lemma 0.5 and Lemma 0.6.

Algorithm 0.4 — Karatsuba multiplication.

Input: nonnegative integers đ‘„, 𝑩 each of at most 𝑛 digitsOutput: đ‘„ ⋅ 𝑩1: procedure Karatsuba(đ‘„,𝑩)2: if 𝑛 ≀ 4 then return đ‘„ ⋅ 𝑩 ;3: Let 𝑚 = ⌊𝑛/2⌋4: Write đ‘„ = 10đ‘šđ‘„ + đ‘„ and 𝑩 = 10𝑚𝑩 + 𝑩5: 𝐮 ← Karatsuba(đ‘„, 𝑩)6: đ” ← Karatsuba(đ‘„ + đ‘„, 𝑩 + 𝑩)7: đ¶ ← Karatsuba(đ‘„, 𝑩)8: return (10𝑛 − 10𝑚) ⋅ 𝐮 + 10𝑚 ⋅ đ” + (1 − 10𝑚) ⋅ đ¶9: end procedure

Algorithm 0.4 is only half of the full description of Karatsuba’salgorithm. The other half is the analysis, which entails proving that (1)Algorithm 0.4 indeed computes the multiplication operation and (2)it does so using 𝑂(𝑛log2 3) operations. We now turn to showing bothfacts:Lemma 0.5 For every nonnegative integers đ‘„, 𝑩, when given input đ‘„, 𝑩Algorithm 0.4 will output đ‘„ ⋅ 𝑩.Proof. Let 𝑛 be the maximum number of digits of đ‘„ and 𝑩. We provethe lemma by induction on 𝑛. The base case is 𝑛 ≀ 4 where the algo-rithm returns đ‘„ ⋅ 𝑩 by definition. (It does not matter which algorithmwe use to multiply four-digit numbers - we can even use repeatedaddition.) Otherwise, if 𝑛 > 4, we define 𝑚 = ⌊𝑛/2⌋, and writeđ‘„ = 10đ‘šđ‘„ + đ‘„ and 𝑩 = 10𝑚𝑩 + 𝑩.

Plugging this into đ‘„ ⋅ 𝑩, we getđ‘„ ⋅ 𝑩 = 102đ‘šđ‘„đ‘Š + 10𝑚(đ‘„đ‘Š + đ‘„đ‘Š) + đ‘„đ‘Š . (3)

Rearranging the terms we see thatđ‘„ ⋅ 𝑩 = 102đ‘šđ‘„đ‘Š + 10𝑚 [(đ‘„ + đ‘„)(𝑩 + 𝑩) − đ‘„đ‘Š − đ‘„đ‘Š] + đ‘„đ‘Š . (4)

since the numbers đ‘„,đ‘„, 𝑩,𝑩,đ‘„ + đ‘„,𝑩 + 𝑩 all have at most 𝑚 + 1 < 𝑛 digits,the induction hypothesis implies that the values 𝐮, đ”, đ¶ computedby the recursive calls will satisfy 𝐮 = đ‘„đ‘Š, đ” = (đ‘„ + đ‘„)(𝑩 + 𝑩) andđ¶ = đ‘„đ‘Š. Plugging this into (4) we see that đ‘„ ⋅ 𝑩 equals the value(102𝑚 − 10𝑚) ⋅ 𝐮 + 10𝑚 ⋅ đ” + (1 − 10𝑚) ⋅ đ¶ computed by Algorithm 0.4.

Page 35: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

introduction 35

Lemma 0.6 If đ‘„, 𝑩 are integers of at most 𝑛 digits, Algorithm 0.4 willtake 𝑂(𝑛log2 3) operations on input đ‘„, 𝑩.Proof. Fig. 2 illustrates the idea behind the proof, which we onlysketch here, leaving filling out the details as Exercise 0.4. The proofis again by induction. We define 𝑇 (𝑛) to be the maximum number ofsteps that Algorithm 0.4 takes on inputs of length at most 𝑛. Since inthe base case 𝑛 ≀ 2, Exercise 0.4 performs a constant number of com-putation, we know that 𝑇 (2) ≀ 𝑐 for some constant 𝑐 and for 𝑛 > 2, itsatisfies the recursive equation𝑇 (𝑛) ≀ 3𝑇 (⌊𝑛/2⌋ + 1) + 𝑐â€Č𝑛 (5)

for some constant 𝑐â€Č (using the fact that addition can be done in 𝑂(𝑛)operations).

The recursive equation (5) solves to 𝑂(𝑛log2 3). The intuition be-hind this is presented in Fig. 2, and this is also a consequence of theso called “Master Theorem” on recurrence relations. As mentionedabove, we leave completing the proof to the reader as Exercise 0.4.

Figure 4: Karatsuba’s algorithm reduces an 𝑛-bitmultiplication to three 𝑛/2-bit multiplications,which in turn are reduced to nine 𝑛/4-bit multi-plications and so on. We can represent the compu-tational cost of all these multiplications in a 3-arytree of depth log2 𝑛, where at the root the extra costis 𝑐𝑛 operations, at the first level the extra cost is𝑐(𝑛/2) operations, and at each of the 3𝑖 nodes oflevel 𝑖, the extra cost is 𝑐(𝑛/2𝑖). The total cost is𝑐𝑛 ∑log2 𝑛𝑖=0 (3/2)𝑖 ≀ 10𝑐𝑛log2 3 by the formula forsumming a geometric series.

Karatsuba’s algorithm is by no means the end of the line for multi-plication algorithms. In the 1960’s, Toom and Cook extended Karat-suba’s ideas to get an 𝑂(𝑛log𝑘(2𝑘−1)) time multiplication algorithm forevery constant 𝑘. In 1971, Schönhage and Strassen got even better al-gorithms using the Fast Fourier Transform; their idea was to somehowtreat integers as “signals” and do the multiplication more efficientlyby moving to the Fourier domain. (The Fourier transform is a centraltool in mathematics and engineering, used in a great many applica-tions; if you have not seen it yet, you are likely encounter it at somepoint in your studies.) In the years that followed researchers kept im-proving the algorithm, and only very recently Harvey and Van Der

Page 36: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

36 introduction to theoretical computer science

Hoeven managed to obtain an 𝑂(𝑛 log𝑛) time algorithm for multipli-cation (though it only starts beating the Schönhage-Strassen algorithmfor truly astronomical numbers). Yet, despite all this progress, westill don’t know whether or not there is an 𝑂(𝑛) time algorithm formultiplying two 𝑛 digit numbers!

RRemark 0.7 — Matrix Multiplication (advanced note).(This book contains many “advanced” or “optional”notes and sections. These may assume backgroundthat not every student has, and can be safely skippedover as none of the future parts depends on them.)Ideas similar to Karatsuba’s can be used to speed upmatrix multiplications as well. Matrices are a powerfulway to represent linear equations and operations,widely used in a great many applications of scientificcomputing, graphics, machine learning, and manymany more.One of the basic operations one can do withtwo matrices is to multiply them. For example,

if đ‘„ = (đ‘„0,0 đ‘„0,1đ‘„1,0 đ‘„1,1) and 𝑩 = (𝑩0,0 𝑩0,1𝑩1,0 𝑩1,1)then the product of đ‘„ and 𝑩 is the matrix(đ‘„0,0𝑩0,0 + đ‘„0,1𝑩1,0 đ‘„0,0𝑩0,1 + đ‘„0,1𝑩1,1đ‘„1,0𝑩0,0 + đ‘„1,1𝑩1,0 đ‘„1,0𝑩0,1 + đ‘„1,1𝑩1,1). You can

see that we can compute this matrix by eight productsof numbers.Now suppose that 𝑛 is even and đ‘„ and 𝑩 are a pair of𝑛 × 𝑛 matrices which we can think of as each com-posed of four (𝑛/2) × (𝑛/2) blocks đ‘„0,0, đ‘„0,1, đ‘„1,0, đ‘„1,1and 𝑩0,0, 𝑩0,1, 𝑩1,0, 𝑩1,1. Then the formula for the matrixproduct of đ‘„ and 𝑩 can be expressed in the same wayas above, just replacing products đ‘„đ‘Ž,𝑏𝑩𝑐,𝑑 with matrixproducts, and addition with matrix addition. Thismeans that we can use the formula above to give analgorithm that doubles the dimension of the matricesat the expense of increasing the number of operationby a factor of 8, which for 𝑛 = 2ℓ results in 8ℓ = 𝑛3operations.In 1969 Volker Strassen noted that we can computethe product of a pair of two-by-two matrices usingonly seven products of numbers by observing thateach entry of the matrix đ‘„đ‘Š can be computed byadding and subtracting the following seven terms:𝑡1 = (đ‘„0,0 + đ‘„1,1)(𝑩0,0 + 𝑩1,1), 𝑡2 = (đ‘„0,0 + đ‘„1,1)𝑩0,0,𝑡3 = đ‘„0,0(𝑩0,1 − 𝑩1,1), 𝑡4 = đ‘„1,1(𝑩0,1 − 𝑩0,0),𝑡5 = (đ‘„0,0 + đ‘„0,1)𝑩1,1, 𝑡6 = (đ‘„1,0 − đ‘„0,0)(𝑩0,0 + 𝑩0,1),𝑡7 = (đ‘„0,1 − đ‘„1,1)(𝑩1,0 + 𝑩1,1). Indeed, one can verify

that đ‘„đ‘Š = (𝑡1 + 𝑡4 − 𝑡5 + 𝑡7 𝑡3 + 𝑡5𝑡2 + 𝑡4 𝑡1 + 𝑡3 − 𝑡2 + 𝑡6).

Page 37: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

introduction 37

Using this observation, we can obtain an algorithmsuch that doubling the dimension of the matricesresults in increasing the number of operations by afactor of 7, which means that for 𝑛 = 2ℓ the cost is7ℓ = 𝑛log2 7 ∌ 𝑛2.807. A long sequence of work hassince improved this algorithm, and the current recordhas running time about 𝑂(𝑛2.373). However, unlike thecase of integer multiplication, at the moment we don’tknow of any algorithm for matrix multiplication thatruns in time linear or even close to linear in the sizeof the input matrices (e.g., an 𝑂(𝑛2𝑝𝑜𝑙𝑩𝑙𝑜𝑔(𝑛)) timealgorithm). People have tried to use group represen-tations, which can be thought of as generalizations ofthe Fourier transform, to obtain faster algorithms, butthis effort has not yet succeeded.

0.3 ALGORITHMS BEYOND ARITHMETIC

The quest for better algorithms is by no means restricted to arithmetictasks such as adding, multiplying or solving equations. Many graphalgorithms, including algorithms for finding paths, matchings, span-ning trees, cuts, and flows, have been discovered in the last severaldecades, and this is still an intensive area of research. (For example,the last few years saw many advances in algorithms for the maximumflow problem, borne out of unexpected connections with electrical cir-cuits and linear equation solvers.) These algorithms are being usednot just for the “natural” applications of routing network traffic orGPS-based navigation, but also for applications as varied as drug dis-covery through searching for structures in gene-interaction graphs tocomputing risks from correlations in financial investments.

Google was founded based on the PageRank algorithm, which isan efficient algorithm to approximate the “principal eigenvector” of(a dampened version of) the adjacency matrix of the web graph. TheAkamai company was founded based on a new data structure, knownas consistent hashing, for a hash table where buckets are stored at dif-ferent servers. The backpropagation algorithm, which computes partialderivatives of a neural network in 𝑂(𝑛) instead of 𝑂(𝑛2) time, under-lies many of the recent phenomenal successes of learning deep neuralnetworks. Algorithms for solving linear equations under sparsityconstraints, a concept known as compressed sensing, have been usedto drastically reduce the amount and quality of data needed to ana-lyze MRI images. This made a critical difference for MRI imaging ofcancer tumors in children, where previously doctors needed to useanesthesia to suspend breath during the MRI exam, sometimes withdire consequences.

Page 38: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

38 introduction to theoretical computer science

Even for classical questions, studied through the ages, new dis-coveries are still being made. For example, for the question of de-termining whether a given integer is prime or composite, which hasbeen studied since the days of Pythagoras, efficient probabilistic algo-rithms were only discovered in the 1970s, while the first deterministicpolynomial-time algorithm was only found in 2002. For the relatedproblem of actually finding the factors of a composite number, newalgorithms were found in the 1980s, and (as we’ll see later in thiscourse) discoveries in the 1990s raised the tantalizing prospect ofobtaining faster algorithms through the use of quantum mechanicaleffects.

Despite all this progress, there are still many more questions thananswers in the world of algorithms. For almost all natural prob-lems, we do not know whether the current algorithm is the “best”,or whether a significantly better one is still waiting to be discovered.As alluded in Cobham’s opening quote for this chapter, even for thebasic problem of multiplying numbers we have not yet answered thequestion of whether there is a multiplication algorithm that is as ef-ficient as our algorithms for addition. But at least we now know theright way to ask it.

0.4 ON THE IMPORTANCE OF NEGATIVE RESULTS

Finding better algorithms for problems such as multiplication, solv-ing equations, graph problems, or fitting neural networks to data, isundoubtedly a worthwhile endeavor. But why is it important to provethat such algorithms don’t exist? One motivation is pure intellectualcuriosity. Another reason to study impossibility results is that theycorrespond to the fundamental limits of our world. In other words,impossibility results are laws of nature.

Here are some examples of impossibility results outside computerscience (see Section 0.7 for more about these). In physics, the impos-sibility of building a perpetual motion machine corresponds to the lawof conservation of energy. The impossibility of building a heat enginebeating Carnot’s bound corresponds to the second law of thermo-dynamics, while the impossibility of faster-than-light informationtransmission is a cornerstone of special relativity. In mathematics,while we all learned the formula for solving quadratic equations inhigh school, the impossibility of generalizing this formula to equationsof degree five or more gave birth to group theory. The impossibilityof proving Euclid’s fifth axiom from the first four gave rise to non-Euclidean geometries, which ended up crucial for the theory of generalrelativity.

In an analogous way, impossibility results for computation corre-spond to “computational laws of nature” that tell us about the fun-

Page 39: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

introduction 39

damental limits of any information processing apparatus, whetherbased on silicon, neurons, or quantum particles. Moreover, computerscientists found creative approaches to apply computational limitationsto achieve certain useful tasks. For example, much of modern Internettraffic is encrypted using the RSA encryption scheme, which relies onits security on the (conjectured) impossibility of efficiently factoringlarge integers. More recently, the Bitcoin system uses a digital ana-log of the “gold standard” where, instead of using a precious metal,new currency is obtained by “mining” solutions for computationallydifficult problems.

Chapter Recap

‱ The history of algorithms goes back thousandsof years; they have been essential much of hu-man progress and these days form the basis ofmulti-billion dollar industries, as well as life-savingtechnologies.

‱ There is often more than one algorithm to achievethe same computational task. Finding a faster al-gorithm can often make a much bigger differencethan improving computing hardware.

‱ Better algorithms and data structures don’t justspeed up calculations, but can yield new qualitativeinsights.

‱ One question we will study is to find out what isthe most efficient algorithm for a given problem.

‱ To show that an algorithm is the most efficient onefor a given problem, we need to be able to provethat it is impossible to solve the problem using asmaller amount of computational resources.

0.5 ROADMAP TO THE REST OF THIS BOOK

Often, when we try to solve a computational problem, whether it issolving a system of linear equations, finding the top eigenvector of amatrix, or trying to rank Internet search results, it is enough to use the“I know it when I see it” standard for describing algorithms. As longas we find some way to solve the problem, we are happy and mightnot care much on the exact mathematical model for our algorithm.But when we want to answer a question such as “does there exist analgorithm to solve the problem 𝑃 ?” we need to be much more precise.

In particular, we will need to (1) define exactly what it means tosolve 𝑃 , and (2) define exactly what an algorithm is. Even (1) cansometimes be non-trivial but (2) is particularly challenging; it is notat all clear how (and even whether) we can encompass all potentialways to design algorithms. We will consider several simple models of

Page 40: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

40 introduction to theoretical computer science

computation, and argue that, despite their simplicity, they do captureall “reasonable” approaches to achieve computing, including all thosethat are currently used in modern computing devices.

Once we have these formal models of computation, we can tryto obtain impossibility results for computational tasks, showing thatsome problems can not be solved (or perhaps can not be solved withinthe resources of our universe). Archimedes once said that given afulcrum and a long enough lever, he could move the world. We willsee how reductions allow us to leverage one hardness result into aslew of a great many others, illuminating the boundaries betweenthe computable and uncomputable (or tractable and intractable)problems.

Later in this book we will go back to examining our models ofcomputation, and see how resources such as randomness or quantumentanglement could potentially change the power of our model. Inthe context of probabilistic algorithms, we will see a glimpse of howrandomness has become an indispensable tool for understandingcomputation, information, and communication. We will also see howcomputational difficulty can be an asset rather than a hindrance, andbe used for the “derandomization” of probabilistic algorithms. Thesame ideas also show up in cryptography, which has undergone notjust a technological but also an intellectual revolution in the last fewdecades, much of it building on the foundations that we explore inthis course.

Theoretical Computer Science is a vast topic, branching out andtouching upon many scientific and engineering disciplines. This bookprovides a very partial (and biased) sample of this area. More thananything, I hope I will manage to “infect” you with at least some ofmy love for this field, which is inspired and enriched by the connec-tion to practice, but is also deep and beautiful regardless of applica-tions.

0.5.1 Dependencies between chaptersThis book is divided into the following parts, see Fig. 5.

‱ Preliminaries: Introduction, mathematical background, and repre-senting objects as strings.

‱ Part I: Finite computation (Boolean circuits): Equivalence of cir-cuits and straight-line programs. Universal gate sets. Existence of acircuit for every function, representing circuits as strings, universalcircuit, lower bound on circuit size using the counting argument.

‱ Part II: Uniform computation (Turing machines): Equivalence ofTuring machines and programs with loops. Equivalence of models

Page 41: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

introduction 41

(including RAM machines, 𝜆 calculus, and cellular automata), con-figurations of Turing machines, existence of a universal Turing ma-chine, uncomputable functions (including the Halting problem andRice’s Theorem), Gödel’s incompleteness theorem, restricted com-putational models models (regular and context free languages).

‱ Part III: Efficient computation: Definition of running time, timehierarchy theorem, P and NP, P/poly, NP completeness and theCook-Levin Theorem, space bounded computation.

‱ Part IV: Randomized computation: Probability, randomized algo-rithms, BPP, amplification, BPP ⊆ P/𝑝𝑜𝑙𝑩, pseudorandom genera-tors and derandomization.

‱ Part V: Advanced topics: Cryptography, proofs and algorithms(interactive and zero knowledge proofs, Curry-Howard correspon-dence), quantum computing.

Figure 5: The dependency structure of the differentparts. Part I introduces the model of Boolean cir-cuits to study finite functions with an emphasis onquantitative questions (how many gates to computea function). Part II introduces the model of Turingmachines to study functions that have unbounded inputlengths with an emphasis on qualitative questions (isthis function computable or not). Much of Part II doesnot depend on Part I, as Turing machines can be usedas the first computational model. Part III dependson both parts as it introduces a quantitative study offunctions with unbounded input length. The moreadvanced parts IV (randomized computation) andV (advanced topics) rely on the material of Parts I, IIand III.

The book largely proceeds in linear order, with each chapter build-ing on the previous ones, with the following exceptions:

‱ The topics of 𝜆 calculus (Section 8.5 and Section 8.5), Gödel’s in-completeness theorem (Chapter 11), Automata/regular expres-sions and context-free grammars (Chapter 10), and space-boundedcomputation (Chapter 17), are not used in the following chapters.Hence you can choose whether to cover or skip any subset of them.

‱ Part II (Uniform Computation / Turing Machines) does not havea strong dependency on Part I (Finite computation / Boolean cir-cuits) and it should be possible to teach them in the reverse order

Page 42: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

42 introduction to theoretical computer science

with minor modification. Boolean circuits are used Part III (efficientcomputation) for results such as P ⊆ P/poly and the Cook-LevinTheorem, as well as in Part IV (for BPP ⊆ P/poly and derandom-ization) and Part V (specifically in cryptography and quantumcomputing).

‱ All chapters in Part V (Advanced topics) are independent of oneanother and can be covered in any order.

A course based on this book can use all of Parts I, II, and III (possi-bly skipping over some or all of the 𝜆 calculus, Chapter 11, Chapter 10or Chapter 17), and then either cover all or some of Part IV (random-ized computation), and add a “sprinkling” of advanced topics fromPart V based on student or instructor interest.

0.6 EXERCISES

Exercise 0.1 Rank the significance of the following inventions in speed-ing up multiplication of large (that is 100-digit or more) numbers.That is, use “back of the envelope” estimates to order them in terms ofthe speedup factor they offered over the previous state of affairs.

a. Discovery of the grade-school digit by digit algorithm (improvingupon repeated addition)

b. Discovery of Karatsuba’s algorithm (improving upon the digit bydigit algorithm)

c. Invention of modern electronic computers (improving upon calcu-lations with pen and paper).

Exercise 0.2 The 1977 Apple II personal computer had a processorspeed of 1.023 Mhz or about 106 operations per seconds. At thetime of this writing the world’s fastest supercomputer performs 93“petaflops” (1015 floating point operations per second) or about 1018basic steps per second. For each one of the following running times(as a function of the input length 𝑛), compute for both computers howlarge an input they could handle in a week of computation, if they runan algorithm that has this running time:

a. 𝑛 operations.

b. 𝑛2 operations.

c. 𝑛 log𝑛 operations.

d. 2𝑛 operations.

Page 43: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

introduction 43

4 As we will see in Chapter Chapter 21, almost anycompany relying on cryptography needs to assumethe non existence of certain algorithms. In particular,RSA Security was founded based on the securityof the RSA cryptosystem, which presumes the nonexistence of an efficient algorithm to compute theprime factorization of large integers.5 Hint: Use a proof by induction - suppose that this istrue for all 𝑛’s from 1 to 𝑚 and prove that this is truealso for 𝑚 + 1.

e. 𝑛! operations.

Exercise 0.3 — Usefulness of algorithmic non-existence. In this chapter wementioned several companies that were founded based on the discov-ery of new algorithms. Can you give an example for a company thatwas founded based on the non existence of an algorithm? See footnotefor hint.4

Exercise 0.4 — Analysis of Karatsuba’s Algorithm. a. Suppose that𝑇1, 𝑇2, 𝑇3, 
 is a sequence of numbers such that 𝑇2 ≀ 10 andfor every 𝑛, 𝑇𝑛 ≀ 3𝑇⌊𝑛/2⌋+1 + đ¶đ‘› for some đ¶ ≄ 1. Prove that𝑇𝑛 ≀ 20đ¶đ‘›log2 3 for every 𝑛 > 2.5

b. Prove that the number of single-digit operations that Karatsuba’salgorithm takes to multiply two 𝑛 digit numbers is at most1000𝑛log2 3.

Exercise 0.5 Implement in the programming language of yourchoice functions Gradeschool_multiply(x,y) and Karat-suba_multiply(x,y) that take two arrays of digits x and y and returnan array representing the product of x and y (where x is identifiedwith the number x[0]+10*x[1]+100*x[2]+... etc..) using thegrade-school algorithm and the Karatsuba algorithm respectively.At what number of digits does the Karatsuba algorithm beat thegrade-school one?

Exercise 0.6 — Matrix Multiplication (optional, advanced). In this exercise, weshow that if for some 𝜔 > 2, we can write the product of two 𝑘 × 𝑘real-valued matrices 𝐮, đ” using at most 𝑘𝜔 multiplications, then wecan multiply two 𝑛 × 𝑛 matrices in roughly 𝑛𝜔 time for every largeenough 𝑛.

To make this precise, we need to make some notation that is unfor-tunately somewhat cumbersome. Assume that there is some 𝑘 ∈ ℕand 𝑚 ≀ 𝑘𝜔 such that for every 𝑘 × 𝑘 matrices 𝐮, đ”, đ¶ such thatđ¶ = AB, we can write for every 𝑖, 𝑗 ∈ [𝑘]:đ¶đ‘–,𝑗 = 𝑚−1∑ℓ=0 đ›Œâ„“đ‘–,𝑗𝑓ℓ(𝐮)𝑔ℓ(đ”) (6)

for some linear functions 𝑓0, 
 , 𝑓𝑚−1, 𝑔0, 
 , 𝑔𝑚−1 ∶ ℝ𝑛2 → ℝ andcoefficients đ›Œâ„“đ‘–,𝑗𝑖,𝑗∈[𝑘],ℓ∈[𝑚]. Prove that under this assumption forevery 𝜖 > 0, if 𝑛 is sufficiently large, then there is an algorithm thatcomputes the product of two 𝑛 × 𝑛 matrices using at most 𝑂(𝑛𝜔+𝜖)arithmetic operations. See footnote for hint.6

Page 44: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

44 introduction to theoretical computer science

0.7 BIBLIOGRAPHICAL NOTES

For a brief overview of what we’ll see in this book, you could do farworse than read Bernard Chazelle’s wonderful essay on the Algo-rithm as an Idiom of modern science. The book of Moore and Mertens[MM11] gives a wonderful and comprehensive overview of the theoryof computation, including much of the content discussed in this chap-ter and the rest of this book. Aaronson’s book [Aar13] is another greatread that touches upon many of the same themes.

For more on the algorithms the Babylonians used, see Knuth’spaper and Neugebauer’s classic book.

Many of the algorithms we mention in this chapter are coveredin algorithms textbooks such as those by Cormen, Leiserson, Rivert,and Stein [Cor+09], Kleinberg and Tardos [KT06], and Dasgupta, Pa-padimitriou and Vazirani [DPV08], as well as Jeff Erickson’s textbook.Erickson’s book is freely available online and contains a great exposi-tion of recursive algorithms in general and Karatsuba’s algorithm inparticular.

The story of Karatsuba’s discovery of his multiplication algorithmis recounted by him in [Kar95]. As mentioned above, further improve-ments were made by Toom and Cook [Too63; Coo66], Schönhage andStrassen [SS71], FĂŒrer [FĂŒr07], and recently by Harvey and Van DerHoeven [HV19], see this article for a nice overview. The last paperscrucially rely on the Fast Fourier transform algorithm. The fascinatingstory of the (re)discovery of this algorithm by John Tukey in the con-text of the cold war is recounted in [Coo87]. (We say re-discoverybecause it later turned out that the algorithm dates back to Gauss[HJB85].) The Fast Fourier Transform is covered in some of the booksmentioned below, and there are also online available lectures such asJeff Erickson’s. See also this popular article by David Austin. Fast ma-trix multiplication was discovered by Strassen [Str69], and since thenthis has been an active area of research. [BlĂ€13] is a recommendedself-contained survey of this area.

The Backpropagation algorithm for fast differentiation of neural net-works was invented by Werbos [Wer74]. The Pagerank algorithm wasinvented by Larry Page and Sergey Brin [Pag+99]. It is closely relatedto the HITS algorithm of Kleinberg [Kle99]. The Akamai company wasfounded based on the consistent hashing data structure described in[Kar+97]. Compressed sensing has a long history but two foundationalpapers are [CRT06; Don06]. [Lus+08] gives a survey of applicationsof compressed sensing to MRI; see also this popular article by Ellen-berg [Ell10]. The deterministic polynomial-time algorithm for testingprimality was given by Agrawal, Kayal, and Saxena [AKS04].

Page 45: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

introduction 45

We alluded briefly to classical impossibility results in mathematics,including the impossibility of proving Euclid’s fifth postulate fromthe other four, impossibility of trisecting an angle with a straightedgeand compass and the impossibility of solving a quintic equation viaradicals. A geometric proof of the impossibility of angle trisection(one of the three geometric problems of antiquity, going back to theancient Greeks) is given in this blog post of Tao. The book of MarioLivio [Liv05] covers some of the background and ideas behind theseimpossibility results. Some exciting recent research is focused ontrying to use computational complexity to shed light on fundamentalquestions in physics such understanding black holes and reconcilinggeneral relativity with quantum mechanics

Page 46: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 47: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

1Mathematical Background

“I found that every number, which may be expressed from one to ten, surpassesthe preceding by one unit: afterwards the ten is doubled or tripled 
 untila hundred; then the hundred is doubled and tripled in the same manner asthe units and the tens 
 and so forth to the utmost limit of numeration.”,Muhammad ibn MĆ«sā al-KhwārizmÄ«, 820, translation by Fredric Rosen,1831.

In this chapter we review some of the mathematical concepts thatwe use in this book. These concepts are typically covered in coursesor textbooks on “mathematics for computer science” or “discretemathematics”; see the “Bibliographical Notes” section (Section 1.9)for several excellent resources on these topics that are freely-availableonline.

A mathematician’s apology. Some students might wonder why thisbook contains so much math. The reason is that mathematics is sim-ply a language for modeling concepts in a precise and unambiguousway. In this book we use math to model the concept of computation.For example, we will consider questions such as “is there an efficientalgorithm to find the prime factors of a given integer?”. (We will see thatthis question is particularly interesting, touching on areas as far apartas Internet security and quantum mechanics!) To even phrase such aquestion, we need to give a precise definition of the notion of an algo-rithm, and of what it means for an algorithm to be efficient. Also, sincethere is no empirical experiment to prove the nonexistence of an algo-rithm, the only way to establish such a result is using a mathematicalproof.

1.1 THIS CHAPTER: A READER’S MANUAL

Depending on your background, you can approach this chapter in twodifferent ways:

‱ If you have already taken a “discrete mathematics”, “mathematicsfor computer science” or similar courses, you do not need to read

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Recall basic mathematical notions such as

sets, functions, numbers, logical operatorsand quantifiers, strings, and graphs.

‱ Rigorously define Big-𝑂 notation.‱ Proofs by induction.‱ Practice with reading mathematical

definitions, statements, and proofs.‱ Transform an intuitive argument into a

rigorous proof.

Page 48: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

48 introduction to theoretical computer science

the whole chapter. You can just take quick look at Section 1.2 to seethe main tools we will use, Section 1.7 for our notation and conven-tions, and then skip ahead to the rest of this book. Alternatively,you can sit back, relax, and read this chapter just to get familiarwith our notation, as well as to enjoy (or not) my philosophicalmusings and attempts at humor.

‱ If your background is less extensive, see Section 1.9 for some re-sources on these topics. This chapter briefly covers the conceptsthat we need, but you may find it helpful to see a more in-depthtreatment. As usual with math, the best way to get comfort withthis material is to work out exercises on your own.

‱ You might also want to start brushing up on discrete probability,which we’ll use later in this book (see Chapter 18).

1.2 A QUICK OVERVIEW OF MATHEMATICAL PREREQUISITES

The main mathematical concepts we will use are the following. Wejust list these notions below, deferring their definitions to the rest ofthis chapter. If you are familiar with all of these, then you might wantto just skip to Section 1.7 to see the full list of notation we use.

‱ Proofs: First and foremost, this book involves a heavy dose of for-mal mathematical reasoning, which includes mathematical defini-tions, statements, and proofs.

‱ Sets and set operations: We will use extensively mathematical sets.We use the basic set relations of membership (∈) and containment(⊆), and set operations, principally union (âˆȘ), intersection (∩), andset difference (⧔).

‱ Cartesian product and Kleene star operation: We also use theCartesian product of two sets 𝐮 and đ”, denoted as 𝐮 × đ” (that is,𝐮 × đ” the set of pairs (𝑎, 𝑏) where 𝑎 ∈ 𝐮 and 𝑏 ∈ đ”). We denote by𝐮𝑛 the 𝑛 fold Cartesian product (e.g., 𝐮3 = 𝐮 × 𝐮 × 𝐮) and by 𝐮∗(known as the Kleene star) the union of 𝐮𝑛 for all 𝑛 ∈ 0, 1, 2, 
.

‱ Functions: The domain and codomain of a function, properties suchas being one-to-one (also known as injective) or onto (also knownas surjective) functions, as well as partial functions (that, unlikestandard or “total” functions, are not necessarily defined on allelements of their domain).

‱ Logical operations: The operations AND (∧), OR (∹), and NOT(¬) and the quantifiers “there exists” (∃) and “for all” (∀).

‱ Basic combinatorics: Notions such as (𝑛𝑘) (the number of 𝑘-sizedsubsets of a set of size 𝑛).

Page 49: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 49

Figure 1.1: A snippet from the “methods” section ofthe “AlphaGo Zero” paper by Silver et al, Nature, 2017.

Figure 1.2: A snippet from the “Zerocash” paper ofBen-Sasson et al, that forms the basis of the cryptocur-rency startup Zcash.

‱ Graphs: Undirected and directed graphs, connectivity, paths, andcycles.

‱ Big-𝑂 notation: 𝑂, 𝑜, Ω, 𝜔, Θ notation for analyzing asymptoticgrowth of functions.

‱ Discrete probability: We will use probability theory, and specifi-cally probability over finite samples spaces such as tossing 𝑛 coins,including notions such as random variables, expectation, and concen-tration. We will only use probability theory in the second half ofthis text, and will review it beforehand in Chapter 18. However,probabilistic reasoning is a subtle (and extremely useful!) skill, andit’s always good to start early in acquiring it.

In the rest of this chapter we briefly review the above notions. Thisis partially to remind the reader and reinforce material that mightnot be fresh in your mind, and partially to introduce our notationand conventions which might occasionally differ from those you’veencountered before.

1.3 READING MATHEMATICAL TEXTS

Mathematicians use jargon for the same reason that it is used in manyother professions such engineering, law, medicine, and others. Wewant to make terms precise and introduce shorthand for conceptsthat are frequently reused. Mathematical texts tend to “pack a lotof punch” per sentence, and so the key is to read them slowly andcarefully, parsing each symbol at a time.

With time and practice you will see that reading mathematical textsbecomes easier and jargon is no longer an issue. Moreover, readingmathematical texts is one of the most transferable skills you could takefrom this book. Our world is changing rapidly, not just in the realmof technology, but also in many other human endeavors, whether itis medicine, economics, law or even culture. Whatever your futureaspirations, it is likely that you will encounter texts that use new con-cepts that you have not seen before (see Fig. 1.1 and Fig. 1.2 for tworecent examples from current “hot areas”). Being able to internalizeand then apply new definitions can be hugely important. It is a skillthat’s much easier to acquire in the relatively safe and stable context ofa mathematical course, where one at least has the guarantee that theconcepts are fully specified, and you have access to your teaching stafffor questions.

The basic components of a mathematical text are definitions, asser-tions and proofs.

Page 50: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

50 introduction to theoretical computer science

Figure 1.3: An annotated form of Definition 1.1,marking which part is being defined and how.

1.3.1 DefinitionsMathematicians often define new concepts in terms of old concepts.For example, here is a mathematical definition which you may haveencountered in the past (and will see again shortly):

Definition 1.1 — One to one function. Let 𝑆, 𝑇 be sets. We say that afunction 𝑓 ∶ 𝑆 → 𝑇 is one to one (also known as injective) if for everytwo elements đ‘„, đ‘„â€Č ∈ 𝑆, if đ‘„ ≠ đ‘„â€Č then 𝑓(đ‘„) ≠ 𝑓(đ‘„â€Č).Definition 1.1 captures a simple concept, but even so it uses quite

a bit of notation. When reading such a definition, it is often useful toannotate it with a pen as you’re going through it (see Fig. 1.3). Forexample, when you see an identifier such as 𝑓 , 𝑆 or đ‘„, make sure thatyou realize what sort of object is it: is it a set, a function, an element,a number, a gremlin? You might also find it useful to explain thedefinition in words to a friend (or to yourself).

1.3.2 Assertions: Theorems, lemmas, claimsTheorems, lemmas, claims and the like are true statements about theconcepts we defined. Deciding whether to call a particular statement a“Theorem”, a “Lemma” or a “Claim” is a judgement call, and does notmake a mathematical difference. All three correspond to statementswhich were proven to be true. The difference is that a Theorem refersto a significant result, that we would want to remember and highlight.A Lemma often refers to a technical result, that is not necessarily im-portant in its own right, but can be often very useful in proving othertheorems. A Claim is a “throw away” statement, that we need to usein order to prove some other bigger results, but do not care so muchabout for its own sake.

1.3.3 ProofsMathematical proofs are the arguments we use to demonstrate that ourtheorems, lemmas, and claims area indeed true. We discuss proofs inSection 1.5 below, but the main point is that the mathematical stan-dard of proof is very high. Unlike in some other realms, in mathe-matics a proof is an “airtight” argument that demonstrates that thestatement is true beyond a shadow of a doubt. Some examples in thissection for mathematical proofs are given in Solved Exercise 1.1 andSection 1.6. As mentioned in the preface, as a general rule, it is moreimportant you understand the definitions than the theorems, and it ismore important you understand a theorem statement than its proof.

Page 51: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 51

1.4 BASIC DISCRETE MATH OBJECTS

In this section we quickly review some of the mathematical objects(the “basic data structures” of mathematics, if you will) we use in thisbook.

1.4.1 SetsA set is an unordered collection of objects. For example, when wewrite 𝑆 = 2, 4, 7, we mean that 𝑆 denotes the set that contains thenumbers 2, 4, and 7. (We use the notation “2 ∈ 𝑆” to denote that 2 isan element of 𝑆.) Note that the set 2, 4, 7 and 7, 4, 2 are identical,since they contain the same elements. Also, a set either contains anelement or does not contain it – there is no notion of containing it“twice” – and so we could even write the same set 𝑆 as 2, 2, 4, 7(though that would be a little weird). The cardinality of a finite set 𝑆,denoted by |𝑆|, is the number of elements it contains. (Cardinality canbe defined for infinite sets as well; see the sources in Section 1.9.) So,in the example above, |𝑆| = 3. A set 𝑆 is a subset of a set 𝑇 , denotedby 𝑆 ⊆ 𝑇 , if every element of 𝑆 is also an element of 𝑇 . (We canalso describe this by saying that 𝑇 is a superset of 𝑆.) For example,2, 7 ⊆ 2, 4, 7. The set that contains no elements is known as theempty set and it is denoted by ∅. If 𝐮 is a subset of đ” that is not equalto đ” we say that 𝐮 is a strict subset of đ”, and denote this by 𝐮 ⊊ đ”.

We can define sets by either listing all their elements or by writingdown a rule that they satisfy such as

EVEN = đ‘„ | đ‘„ = 2𝑩 for some non-negative integer 𝑩 . (1.1)

Of course there is more than one way to write the same set, and of-ten we will use intuitive notation listing a few examples that illustratethe rule. For example, we can also define EVEN as

EVEN = 0, 2, 4, 
 . (1.2)Note that a set can be either finite (such as the set 2, 4, 7) or in-

finite (such as the set EVEN). Also, the elements of a set don’t haveto be numbers. We can talk about the sets such as the set 𝑎, 𝑒, 𝑖, 𝑜, 𝑱of all the vowels in the English language, or the set New York, LosAngeles, Chicago, Houston, Philadelphia, Phoenix, San Antonio,San Diego, Dallas of all cities in the U.S. with population more thanone million per the 2010 census. A set can even have other sets as ele-ments, such as the set ∅, 1, 2, 2, 3, 1, 3 of all even-sized subsetsof 1, 2, 3.Operations on sets: The union of two sets 𝑆, 𝑇 , denoted by 𝑆 âˆȘ 𝑇 ,is the set that contains all elements that are either in 𝑆 or in 𝑇 . Theintersection of 𝑆 and 𝑇 , denoted by 𝑆 ∩ 𝑇 , is the set of elements that are

Page 52: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

52 introduction to theoretical computer science

1 The letter Z stands for the German word “Zahlen”,which means numbers.

both in 𝑆 and in 𝑇 . The set difference of 𝑆 and 𝑇 , denoted by 𝑆 ⧔ 𝑇 (andin some texts also by 𝑆 − 𝑇 ), is the set of elements that are in 𝑆 but notin 𝑇 .

Tuples, lists, strings, sequences: A tuple is an ordered collection of items.For example (1, 5, 2, 1) is a tuple with four elements (also known asa 4-tuple or quadruple). Since order matters, this is not the sametuple as the 4-tuple (1, 1, 5, 2) or the 3-tuple (1, 5, 2). A 2-tuple is alsoknown as a pair. We use the terms tuples and lists interchangeably.A tuple where every element comes from some finite set ÎŁ (such as0, 1) is also known as a string. Analogously to sets, we denote thelength of a tuple 𝑇 by |𝑇 |. Just like sets, we can also think of infiniteanalogues of tuples, such as the ordered collection (1, 4, 9, 
) of allperfect squares. Infinite ordered collections are known as sequences;we might sometimes use the term “infinite sequence” to emphasizethis, and use “finite sequence” as a synonym for a tuple. (We canidentify a sequence (𝑎0, 𝑎1, 𝑎2, 
) of elements in some set 𝑆 with afunction 𝐮 ∶ ℕ → 𝑆 (where 𝑎𝑛 = 𝐮(𝑛) for every 𝑛 ∈ ℕ). Similarly,we can identify a 𝑘-tuple (𝑎0, 
 , 𝑎𝑘−1) of elements in 𝑆 with a function𝐮 ∶ [𝑘] → 𝑆.)

Cartesian product: If 𝑆 and 𝑇 are sets, then their Cartesian product,denoted by 𝑆 × 𝑇 , is the set of all ordered pairs (𝑠, 𝑡) where 𝑠 ∈ 𝑆 and𝑡 ∈ 𝑇 . For example, if 𝑆 = 1, 2, 3 and 𝑇 = 10, 12, then 𝑆 × 𝑇contains the 6 elements (1, 10), (2, 10), (3, 10), (1, 12), (2, 12), (3, 12).Similarly if 𝑆, 𝑇 , 𝑈 are sets then 𝑆 × 𝑇 × 𝑈 is the set of all orderedtriples (𝑠, 𝑡, 𝑱) where 𝑠 ∈ 𝑆, 𝑡 ∈ 𝑇 , and 𝑱 ∈ 𝑈 . More generally, forevery positive integer 𝑛 and sets 𝑆0, 
 , 𝑆𝑛−1, we denote by 𝑆0 × 𝑆1 ×⋯ × 𝑆𝑛−1 the set of ordered 𝑛-tuples (𝑠0, 
 , 𝑠𝑛−1) where 𝑠𝑖 ∈ 𝑆𝑖 forevery 𝑖 ∈ 0, 
 , 𝑛 − 1. For every set 𝑆, we denote the set 𝑆 × 𝑆 by 𝑆2,𝑆 × 𝑆 × 𝑆 by 𝑆3, 𝑆 × 𝑆 × 𝑆 × 𝑆 by 𝑆4, and so on and so forth.

1.4.2 Special setsThere are several sets that we will use in this book time and again. Theset ℕ = 0, 1, 2, 
 (1.3)contains all natural numbers, i.e., non-negative integers. For any naturalnumber 𝑛 ∈ ℕ, we define the set [𝑛] as 0, 
 , 𝑛 − 1 = 𝑘 ∈ ℕ âˆ¶đ‘˜ < 𝑛. (We start our indexing of both ℕ and [𝑛] from 0, while manyother texts index those sets from 1. Starting from zero or one is simplya convention that doesn’t make much difference, as long as one isconsistent about it.)

We will also occasionally use the set â„€ = 
 , −2, −1, 0, +1, +2, 
of (negative and non-negative) integers,1 as well as the set ℝ of real

Page 53: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 53

numbers. (This is the set that includes not just the integers, but alsofractional and irrational numbers; e.g., ℝ contains numbers such as+0.5, −𝜋, etc.) We denote by ℝ+ the set đ‘„ ∈ ℝ ∶ đ‘„ > 0 of positive realnumbers. This set is sometimes also denoted as (0, ∞).Strings: Another set we will use time and again is0, 1𝑛 = (đ‘„0, 
 , đ‘„đ‘›âˆ’1) ∶ đ‘„0, 
 , đ‘„đ‘›âˆ’1 ∈ 0, 1 (1.4)which is the set of all 𝑛-length binary strings for some natural number𝑛. That is 0, 1𝑛 is the set of all 𝑛-tuples of zeroes and ones. This isconsistent with our notation above: 0, 12 is the Cartesian product0, 1 × 0, 1, 0, 13 is the product 0, 1 × 0, 1 × 0, 1 and so on.

We will write the string (đ‘„0, đ‘„1, 
 , đ‘„đ‘›âˆ’1) as simply đ‘„0đ‘„1 ⋯ đ‘„đ‘›âˆ’1. Forexample, 0, 13 = 000, 001, 010, 011, 100, 101, 110, 111 . (1.5)

For every string đ‘„ ∈ 0, 1𝑛 and 𝑖 ∈ [𝑛], we write đ‘„đ‘– for the 𝑖𝑡ℎelement of đ‘„.

We will also often talk about the set of binary strings of all lengths,which is

0, 1∗ = (đ‘„0, 
 , đ‘„đ‘›âˆ’1) ∶ 𝑛 ∈ ℕ , , đ‘„0, 
 , đ‘„đ‘›âˆ’1 ∈ 0, 1 . (1.6)

Another way to write this set is as0, 1∗ = 0, 10 âˆȘ 0, 11 âˆȘ 0, 12 âˆȘ ⋯ (1.7)

or more concisely as 0, 1∗ = âˆȘ𝑛∈ℕ0, 1𝑛 . (1.8)The set 0, 1∗ includes the “string of length 0” or “the empty

string”, which we will denote by "". (In using this notation we fol-low the convention of many programming languages. Other textssometimes use 𝜖 or 𝜆 to denote the empty string.)

Generalizing the star operation: For every set ÎŁ, we defineΣ∗ = âˆȘ𝑛∈ℕΣ𝑛 . (1.9)For example, if ÎŁ = 𝑎, 𝑏, 𝑐, 𝑑, 
 , 𝑧 then Σ∗ denotes the set of all finitelength strings over the alphabet a-z.

Concatenation: The concatenation of two strings đ‘„ ∈ Σ𝑛 and 𝑩 ∈ Σ𝑚 isthe (𝑛 + 𝑚)-length string đ‘„đ‘Š obtained by writing 𝑩 after đ‘„. That is, ifđ‘„ ∈ 0, 1𝑛 and 𝑩 ∈ 0, 1𝑚, then đ‘„đ‘Š is equal to the string 𝑧 ∈ 0, 1𝑛+𝑚such that for 𝑖 ∈ [𝑛], 𝑧𝑖 = đ‘„đ‘– and for 𝑖 ∈ 𝑛, 
 , 𝑛 + 𝑚 − 1, 𝑧𝑖 = 𝑩𝑖−𝑛.

Page 54: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

54 introduction to theoretical computer science

2 For two natural numbers đ‘„ and 𝑎, đ‘„ mod 𝑎 (short-hand for “modulo”) denotes the remainder of đ‘„when it is divided by 𝑎. That is, it is the number 𝑟 in0, 
 , 𝑎 − 1 such that đ‘„ = 𝑎𝑘 + 𝑟 for some integer 𝑘.We sometimes also use the notation đ‘„ = 𝑩 ( mod 𝑎)to denote the assertion that đ‘„ mod 𝑎 is the same as 𝑩mod 𝑎.

1.4.3 FunctionsIf 𝑆 and 𝑇 are nonempty sets, a function đč mapping 𝑆 to 𝑇 , denotedby đč ∶ 𝑆 → 𝑇 , associates with every element đ‘„ ∈ 𝑆 an elementđč(đ‘„) ∈ 𝑇 . The set 𝑆 is known as the domain of đč and the set 𝑇is known as the codomain of đč . The image of a function đč is the setđč(đ‘„) | đ‘„ ∈ 𝑆 which is the subset of đč ’s codomain consisting of alloutput elements that are mapped from some input. (Some texts userange to denote the image of a function, while other texts use rangeto denote the codomain of a function. Hence we will avoid using theterm “range” altogether.) As in the case of sets, we can write a func-tion either by listing the table of all the values it gives for elementsin 𝑆 or by using a rule. For example if 𝑆 = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9and 𝑇 = 0, 1, then the table below defines a function đč ∶ 𝑆 → 𝑇 .Note that this function is the same as the function defined by the ruleđč(đ‘„) = (đ‘„ mod 2).2

Table 1.1: An example of a function.

Input Output0 01 12 03 14 05 16 07 18 09 1

If 𝑓 ∶ 𝑆 → 𝑇 satisfies that 𝑓(đ‘„) ≠ 𝑓(𝑩) for all đ‘„ ≠ 𝑩 then we saythat 𝑓 is one-to-one (Definition 1.1, also known as an injective functionor simply an injection). If đč satisfies that for every 𝑩 ∈ 𝑇 there is someđ‘„ ∈ 𝑆 such that đč(đ‘„) = 𝑩 then we say that đč is onto (also known as asurjective function or simply a surjection). A function that is both one-to-one and onto is known as a bijective function or simply a bijection.A bijection from a set 𝑆 to itself is also known as a permutation of 𝑆. Ifđč ∶ 𝑆 → 𝑇 is a bijection then for every 𝑩 ∈ 𝑇 there is a unique đ‘„ ∈ 𝑆such that đč(đ‘„) = 𝑩. We denote this value đ‘„ by đč −1(𝑩). Note that đč −1is itself a bijection from 𝑇 to 𝑆 (can you see why?).

Giving a bijection between two sets is often a good way to showthey have the same size. In fact, the standard mathematical definitionof the notion that “𝑆 and 𝑇 have the same cardinality” is that there

Page 55: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 55

Figure 1.4: We can represent finite functions as adirected graph where we put an edge from đ‘„ to𝑓(đ‘„). The onto condition corresponds to requiringthat every vertex in the codomain of the functionhas in-degree at least one. The one-to-one conditioncorresponds to requiring that every vertex in thecodomain of the function has in-degree at most one. Inthe examples above đč is an onto function, đș is one toone, and đ» is neither onto nor one to one.

exists a bijection 𝑓 ∶ 𝑆 → 𝑇 . Further, the cardinality of a set 𝑆 isdefined to be 𝑛 if there is a bijection from 𝑆 to the set 0, 
 , 𝑛 − 1.As we will see later in this book, this is a definition that generalizes todefining the cardinality of infinite sets.Partial functions: We will sometimes be interested in partial functionsfrom 𝑆 to 𝑇 . A partial function is allowed to be undefined on somesubset of 𝑆. That is, if đč is a partial function from 𝑆 to 𝑇 , then forevery 𝑠 ∈ 𝑆, either there is (as in the case of standard functions) anelement đč(𝑠) in 𝑇 , or đč(𝑠) is undefined. For example, the partial func-tion đč(đ‘„) = âˆšđ‘„ is only defined on non-negative real numbers. Whenwe want to distinguish between partial functions and standard (i.e.,non-partial) functions, we will call the latter total functions. When wesay “function” without any qualifier then we mean a total function.

The notion of partial functions is a strict generalization of func-tions, and so every function is a partial function, but not every partialfunction is a function. (That is, for every nonempty 𝑆 and 𝑇 , the setof partial functions from 𝑆 to 𝑇 is a proper superset of the set of totalfunctions from 𝑆 to 𝑇 .) When we want to emphasize that a function𝑓 from 𝐮 to đ” might not be total, we will write 𝑓 ∶ 𝐮 →𝑝 đ”. We canthink of a partial function đč from 𝑆 to 𝑇 also as a total function from𝑆 to 𝑇 âˆȘ ⊄ where ⊄ is a special “failure symbol”. So, instead ofsaying that đč is undefined at đ‘„, we can say that đč(đ‘„) = ⊄.Basic facts about functions: Verifying that you can prove the followingresults is an excellent way to brush up on functions:‱ If đč ∶ 𝑆 → 𝑇 and đș ∶ 𝑇 → 𝑈 are one-to-one functions, then their

composition đ» ∶ 𝑆 → 𝑈 defined as đ»(𝑠) = đș(đč(𝑠)) is also one toone.

‱ If đč ∶ 𝑆 → 𝑇 is one to one, then there exists an onto functionđș ∶ 𝑇 → 𝑆 such that đș(đč(𝑠)) = 𝑠 for every 𝑠 ∈ 𝑆.

‱ If đș ∶ 𝑇 → 𝑆 is onto then there exists a one-to-one function đč ∶ 𝑆 →𝑇 such that đș(đč(𝑠)) = 𝑠 for every 𝑠 ∈ 𝑆.

‱ If 𝑆 and 𝑇 are finite sets then the following conditions are equiva-lent to one another: (a) |𝑆| ≀ |𝑇 |, (b) there is a one-to-one functionđč ∶ 𝑆 → 𝑇 , and (c) there is an onto function đș ∶ 𝑇 → 𝑆. (This isactually true even for infinite 𝑆 and 𝑇 : in that case (b) (or equiva-lently (c)) is the commonly accepted definition for |𝑆| ≀ |𝑇 |.)

PYou can find the proofs of these results in many dis-crete math texts, including for example, Section 4.5in the Lehman-Leighton-Meyer notes. However, I

Page 56: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

56 introduction to theoretical computer science

3 It is possible, and sometimes useful, to think of anundirected graph as the special case of a directedgraph that has the special property that for every pair𝑱, 𝑣 either both the edges (𝑱, 𝑣) and (𝑣, 𝑱) are presentor neither of them is. However, in many settings thereis a significant difference between undirected anddirected graphs, and so it’s typically best to think ofthem as separate categories.

Figure 1.5: An example of an undirected and a di-rected graph. The undirected graph has vertex set1, 2, 3, 4 and edge set 1, 2, 2, 3, 2, 4. Thedirected graph has vertex set 𝑎, 𝑏, 𝑐 and the edgeset (𝑎, 𝑏), (𝑏, 𝑐), (𝑐, 𝑎), (𝑎, 𝑐).

strongly suggest you try to prove them on your own,or at least convince yourself that they are true byproving special cases of those for small sizes (e.g.,|𝑆| = 3, |𝑇 | = 4, |𝑈| = 5).

Let us prove one of these facts as an example:Lemma 1.2 If 𝑆, 𝑇 are non-empty sets and đč ∶ 𝑆 → 𝑇 is one to one, thenthere exists an onto function đș ∶ 𝑇 → 𝑆 such that đș(đč(𝑠)) = 𝑠 forevery 𝑠 ∈ 𝑆.

Proof. Choose some 𝑠0 ∈ 𝑆. We will define the function đș ∶ 𝑇 → 𝑆 asfollows: for every 𝑡 ∈ 𝑇 , if there is some 𝑠 ∈ 𝑆 such that đč(𝑠) = 𝑡 thenset đș(𝑡) = 𝑠 (the choice of 𝑠 is well defined since by the one-to-oneproperty of đč , there cannot be two distinct 𝑠, 𝑠â€Č that both map to 𝑡).Otherwise, set đș(𝑡) = 𝑠0. Now for every 𝑠 ∈ 𝑆, by the definition of đș,if 𝑡 = đč(𝑠) then đș(𝑡) = đș(đč(𝑠)) = 𝑠. Moreover, this also shows thatđș is onto, since it means that for every 𝑠 ∈ 𝑆 there is some 𝑡, namely𝑡 = đč(𝑠), such that đș(𝑡) = 𝑠.

1.4.4 GraphsGraphs are ubiquitous in Computer Science, and many other fields aswell. They are used to model a variety of data types including socialnetworks, scheduling constraints, road networks, deep neural nets,gene interactions, correlations between observations, and a greatmany more. Formal definitions of several kinds of graphs are givennext, but if you have not seen graphs before in a course, I urge you toread up on them in one of the sources mentioned in Section 1.9.

Graphs come in two basic flavors: undirected and directed.3

Definition 1.3 — Undirected graphs. An undirected graph đș = (𝑉 , 𝐾) con-sists of a set 𝑉 of vertices and a set 𝐾 of edges. Every edge is a sizetwo subset of 𝑉 . We say that two vertices 𝑱, 𝑣 ∈ 𝑉 are neighbors, ifthe edge 𝑱, 𝑣 is in 𝐾.

Given this definition, we can define several other properties ofgraphs and their vertices. We define the degree of 𝑱 to be the numberof neighbors 𝑱 has. A path in the graph is a tuple (𝑱0, 
 , 𝑱𝑘) ∈ 𝑉 𝑘+1,for some 𝑘 > 0 such that 𝑱𝑖+1 is a neighbor of 𝑱𝑖 for every 𝑖 ∈ [𝑘]. Asimple path is a path (𝑱0, 
 , 𝑱𝑘−1) where all the 𝑱𝑖’s are distinct. A cycleis a path (𝑱0, 
 , 𝑱𝑘) where 𝑱0 = 𝑱𝑘. We say that two vertices 𝑱, 𝑣 ∈ 𝑉are connected if either 𝑱 = 𝑣 or there is a path from (𝑱0, 
 , 𝑱𝑘) where𝑱0 = 𝑱 and 𝑱𝑘 = 𝑣. We say that the graph đș is connected if every pair ofvertices in it is connected.

Page 57: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 57

Here are some basic facts about undirected graphs. We give someinformal arguments below, but leave the full proofs as exercises (theproofs can be found in many of the resources listed in Section 1.9).Lemma 1.4 In any undirected graph đș = (𝑉 , 𝐾), the sum of the degreesof all vertices is equal to twice the number of edges.

Lemma 1.4 can be shown by seeing that every edge 𝑱, 𝑣 con-tributes twice to the sum of the degrees (once for 𝑱 and the secondtime for 𝑣).Lemma 1.5 The connectivity relation is transitive, in the sense that if 𝑱 isconnected to 𝑣, and 𝑣 is connected to đ‘€, then 𝑱 is connected to đ‘€.

Lemma 1.5 can be shown by simply attaching a path of the form(𝑱, 𝑱1, 𝑱2, 
 , 𝑱𝑘−1, 𝑣) to a path of the form (𝑣, 𝑱â€Č1, 
 , 𝑱â€Č𝑘â€Č−1, đ‘€) to obtainthe path (𝑱, 𝑱1, 
 , 𝑱𝑘−1, 𝑣, 𝑱â€Č1, 
 , 𝑱â€Č𝑘â€Č−1, đ‘€) that connects 𝑱 to đ‘€.Lemma 1.6 For every undirected graph đș = (𝑉 , 𝐾) and connected pair𝑱, 𝑣, the shortest path from 𝑱 to 𝑣 is simple. In particular, for everyconnected pair there exists a simple path that connects them.

Lemma 1.6 can be shown by “shortcutting” any non simple pathfrom 𝑱 to 𝑣 where the same vertex đ‘€ appears twice to remove it (seeFig. 1.6). It is a good exercise to transforming this intuitive reasoningto a formal proof:

Figure 1.6: If there is a path from 𝑱 to 𝑣 in a graphthat passes twice through a vertex đ‘€ then we can“shortcut” it by removing the loop from đ‘€ to itself tofind a path from 𝑱 to 𝑣 that only passes once throughđ‘€.

Solved Exercise 1.1 — Connected vertices have simple paths. Prove Lemma 1.6

Solution:

The proof follows the idea illustrated in Fig. 1.6. One complica-tion is that there can be more than one vertex that is visited twiceby a path, and so “shortcutting” might not necessarily result in a

Page 58: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

58 introduction to theoretical computer science

simple path; we deal with this by looking at a shortest path between𝑱 and 𝑣. Details follow.Let đș = (𝑉 , 𝐾) be a graph and 𝑱 and 𝑣 in 𝑉 be two connected

vertices in đș. We will prove that there is a simple graph between𝑱 and 𝑣. Let 𝑘 be the shortest length of a path between 𝑱 and 𝑣and let 𝑃 = (𝑱0, 𝑱1, 𝑱2, 
 , 𝑱𝑘−1, 𝑱𝑘) be a 𝑘-length path from 𝑱 to 𝑣(there can be more than one such path: if so we just choose one ofthem). (That is 𝑱0 = 𝑱, 𝑱𝑘 = 𝑣, and (𝑱ℓ, 𝑱ℓ+1) ∈ 𝐾 for all ℓ ∈ [𝑘].)We claim that 𝑃 is simple. Indeed, suppose otherwise that there issome vertex đ‘€ that occurs twice in the path: đ‘€ = 𝑱𝑖 and đ‘€ = 𝑱𝑗 forsome 𝑖 < 𝑗. Then we can “shortcut” the path 𝑃 by considering thepath 𝑃 â€Č = (𝑱0, 𝑱1, 
 , 𝑱𝑖−1, đ‘€, 𝑱𝑗+1, 
 , 𝑱𝑘) obtained by taking thefirst 𝑖 vertices of 𝑃 (from 𝑱0 = 0 to the first occurrence of đ‘€) andthe last 𝑘 − 𝑗 ones (from the vertex 𝑱𝑗+1 following the second oc-currence of đ‘€ to 𝑱𝑘 = 𝑣). The path 𝑃 â€Č is a valid path between 𝑱 and𝑣 since every consecutive pair of vertices in it is connected by anedge (in particular, since đ‘€ = 𝑱𝑖 = đ‘€đ‘—, both (𝑱𝑖−1, đ‘€) and (đ‘€, 𝑱𝑗+1)are edges in 𝐾), but since the length of 𝑃 â€Č is 𝑘 − (𝑗 − 𝑖) < 𝑘, thiscontradicts the minimality of 𝑃 .

RRemark 1.7 — Finding proofs. Solved Exercise 1.1 is agood example of the process of finding a proof. Youstart by ensuring you understand what the statementmeans, and then come up with an informal argumentwhy it should be true. You then transform the infor-mal argument into a rigorous proof. This proof neednot be very long or overly formal, but should clearlyestablish why the conclusion of the statement followsfrom its assumptions.

The concepts of degrees and connectivity extend naturally to di-rected graphs, defined as follows.

Definition 1.8 — Directed graphs. A directed graph đș = (𝑉 , 𝐾) consistsof a set 𝑉 and a set 𝐾 ⊆ 𝑉 × 𝑉 of ordered pairs of 𝑉 . We sometimesdenote the edge (𝑱, 𝑣) also as 𝑱 → 𝑣. If the edge 𝑱 → 𝑣 is presentin the graph then we say that 𝑣 is an out-neighbor of 𝑱 and 𝑱 is anin-neighbor of 𝑣.A directed graph might contain both 𝑱 → 𝑣 and 𝑣 → 𝑱 in which

case 𝑱 will be both an in-neighbor and an out-neighbor of 𝑣 and viceversa. The in-degree of 𝑱 is the number of in-neighbors it has, and theout-degree of 𝑣 is the number of out-neighbors it has. A path in the

Page 59: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 59

graph is a tuple (𝑱0, 
 , 𝑱𝑘) ∈ 𝑉 𝑘+1, for some 𝑘 > 0 such that 𝑱𝑖+1 is anout-neighbor of 𝑱𝑖 for every 𝑖 ∈ [𝑘]. As in the undirected case, a simplepath is a path (𝑱0, 
 , 𝑱𝑘−1) where all the 𝑱𝑖’s are distinct and a cycleis a path (𝑱0, 
 , 𝑱𝑘) where 𝑱0 = 𝑱𝑘. One type of directed graphs weoften care about is directed acyclic graphs or DAGs, which, as their nameimplies, are directed graphs without any cycles:

Definition 1.9 — Directed Acyclic Graphs. We say that đș = (𝑉 , 𝐾) is adirected acyclic graph (DAG) if it is a directed graph and there doesnot exist a list of vertices 𝑱0, 𝑱1, 
 , 𝑱𝑘 ∈ 𝑉 such that 𝑱0 = 𝑱𝑘 andfor every 𝑖 ∈ [𝑘], the edge 𝑱𝑖 → 𝑱𝑖+1 is in 𝐾.

The lemmas we mentioned above have analogs for directed graphs.We again leave the proofs (which are essentially identical to theirundirected analogs) as exercises.Lemma 1.10 In any directed graph đș = (𝑉 , 𝐾), the sum of the in-degrees is equal to the sum of the out-degrees, which is equal to thenumber of edges.Lemma 1.11 In any directed graph đș, if there is a path from 𝑱 to 𝑣 and apath from 𝑣 to đ‘€, then there is a path from 𝑱 to đ‘€.Lemma 1.12 For every directed graph đș = (𝑉 , 𝐾) and a pair 𝑱, 𝑣 suchthat there is a path from 𝑱 to 𝑣, the shortest path from 𝑱 to 𝑣 is simple.

RRemark 1.13 — Labeled graphs. For some applicationswe will consider labeled graphs, where the vertices oredges have associated labels (which can be numbers,strings, or members of some other set). We can thinkof such a graph as having an associated (possiblypartial) labelling function 𝐿 ∶ 𝑉 âˆȘ 𝐾 → ℒ, where ℒ isthe set of potential labels. However we will typicallynot refer explicitly to this labeling function and simplysay things such as “vertex 𝑣 has the label đ›Œâ€.

1.4.5 Logic operators and quantifiersIf 𝑃 and 𝑄 are some statements that can be true or false, then 𝑃 AND𝑄 (denoted as 𝑃 ∧ 𝑄) is a statement that is true if and only if both 𝑃and 𝑄 are true, and 𝑃 OR 𝑄 (denoted as 𝑃 ∹ 𝑄) is a statement that istrue if and only if either 𝑃 or 𝑄 is true. The negation of 𝑃 , denoted as¬𝑃 or 𝑃 , is true if and only if 𝑃 is false.

Suppose that 𝑃(đ‘„) is a statement that depends on some parameter đ‘„(also sometimes known as an unbound variable) in the sense that forevery instantiation of đ‘„ with a value from some set 𝑆, 𝑃(đ‘„) is eithertrue or false. For example, đ‘„ > 7 is a statement that is not a priori

Page 60: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

60 introduction to theoretical computer science

4 In this book, we place the variable bound by a quan-tifier in a subscript and so write âˆ€đ‘„âˆˆđ‘†đ‘ƒ(đ‘„). Manyother texts do not use this subscript notation and sowill write the same statement as âˆ€đ‘„ ∈ 𝑆, 𝑃(đ‘„).

true or false, but becomes true or false whenever we instantiate đ‘„ withsome real number. We denote by âˆ€đ‘„âˆˆđ‘†đ‘ƒ(đ‘„) the statement that is trueif and only if 𝑃(đ‘„) is true for every đ‘„ ∈ 𝑆.4 We denote by âˆƒđ‘„âˆˆđ‘†đ‘ƒ(đ‘„) thestatement that is true if and only if there exists some đ‘„ ∈ 𝑆 such that𝑃(đ‘„) is true.

For example, the following is a formalization of the true statementthat there exists a natural number 𝑛 larger than 100 that is not divisi-ble by 3: ∃𝑛∈ℕ(𝑛 > 100) ∧ (∀𝑘∈𝑁𝑘 + 𝑘 + 𝑘 ≠ 𝑛) . (1.10)

”For sufficiently large n.” One expression that we will see come uptime and again in this book is the claim that some statement 𝑃(𝑛) istrue “for sufficiently large 𝑛”. What this means is that there exists aninteger 𝑁0 such that 𝑃(𝑛) is true for every 𝑛 > 𝑁0. We can formalizethis as ∃𝑁0∈ℕ∀𝑛>𝑁0𝑃(𝑛).1.4.6 Quantifiers for summations and productsThe following shorthands for summing up or taking products of sev-eral numbers are often convenient. If 𝑆 = 𝑠0, 
 , 𝑠𝑛−1 is a finite setand 𝑓 ∶ 𝑆 → ℝ is a function, then we write âˆ‘đ‘„âˆˆđ‘† 𝑓(đ‘„) as shorthand for𝑓(𝑠0) + 𝑓(𝑠1) + 𝑓(𝑠2) + 
 + 𝑓(𝑠𝑛−1) , (1.11)

and âˆđ‘„âˆˆđ‘† 𝑓(đ‘„) as shorthand for𝑓(𝑠0) ⋅ 𝑓(𝑠1) ⋅ 𝑓(𝑠2) ⋅ 
 ⋅ 𝑓(𝑠𝑛−1) . (1.12)

For example, the sum of the squares of all numbers from 1 to 100can be written as ∑𝑖∈1,
,100 𝑖2 . (1.13)

Since summing up over intervals of integers is so common, thereis a special notation for it. For every two integers, 𝑎 ≀ 𝑏, ∑𝑏𝑖=𝑎 𝑓(𝑖)denotes ∑𝑖∈𝑆 𝑓(𝑖) where 𝑆 = đ‘„ ∈ â„€ ∶ 𝑎 ≀ đ‘„ ≀ 𝑏. Hence, we canwrite the sum (1.13) as 100∑𝑖=1 𝑖2 . (1.14)

1.4.7 Parsing formulas: bound and free variablesIn mathematics, as in coding, we often have symbolic “variables” or“parameters”. It is important to be able to understand, given someformula, whether a given variable is bound or free in this formula. For

Page 61: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 61

example, in the following statement 𝑛 is free but 𝑎 and 𝑏 are bound bythe ∃ quantifier: ∃𝑎,𝑏∈ℕ(𝑎 ≠ 1) ∧ (𝑎 ≠ 𝑛) ∧ (𝑛 = 𝑎 × 𝑏) (1.15)

Since 𝑛 is free, it can be set to any value, and the truth of the state-ment (1.15) depends on the value of 𝑛. For example, if 𝑛 = 8 then(1.15) is true, but for 𝑛 = 11 it is false. (Can you see why?)

The same issue appears when parsing code. For example, in thefollowing snippet from the C programming language

for (int i=0 ; i<n ; i=i+1) printf("*");

the variable i is bound within the for block but the variable n isfree.

The main property of bound variables is that we can rename them(as long as the new name doesn’t conflict with another used variable)without changing the meaning of the statement. Thus for example thestatement âˆƒđ‘„,𝑩∈ℕ(đ‘„ ≠ 1) ∧ (đ‘„ ≠ 𝑛) ∧ (𝑛 = đ‘„ × 𝑩) (1.16)

is equivalent to (1.15) in the sense that it is true for exactly the sameset of 𝑛’s.

Similarly, the code

for (int j=0 ; j<n ; j=j+1) printf("*");

produces the same result as the code above that used i instead of j.

RRemark 1.14 — Aside: mathematical vs programming no-tation. Mathematical notation has a lot of similaritieswith programming language, and for the same rea-sons. Both are formalisms meant to convey complexconcepts in a precise way. However, there are somecultural differences. In programming languages, weoften try to use meaningful variable names such asNumberOfVerticeswhile in math we often use shortidentifiers such as 𝑛. Part of it might have to do withthe tradition of mathematical proofs as being hand-written and verbally presented, as opposed to typedup and compiled. Another reason is if the wrongvariable name is used in a proof, at worst is causesconfusion to readers; when the wrong variable name

Page 62: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

62 introduction to theoretical computer science

is used in a program, planes might crash, patientsmight die, and rockets could explode.One consequence of that is that in mathematics weoften end up reusing identifiers, and also “run out”of letters and hence use Greek letters too, as well asdistinguish between small and capital letters anddifferent font faces. Similarly, mathematical notationtends to use quite a lot of “overloading”, using oper-ators such as + for a great variety of objects (e.g., realnumbers, matrices, finite field elements, etc..), andassuming that the meaning can be inferred from thecontext.Both fields have a notion of “types”, and in mathwe often try to reserve certain letters for variablesof a particular type. For example, variables such as𝑖, 𝑗, 𝑘, ℓ, 𝑚, 𝑛 will often denote integers, and 𝜖 willoften denote a small positive real number (see Sec-tion 1.7 for more on these conventions). When readingor writing mathematical texts, we usually don’t havethe advantage of a “compiler” that will check typesafety for us. Hence it is important to keep track of thetype of each variable, and see that the operations thatare performed on it “make sense”.Kun’s book [Kun18] contains an extensive discus-sion on the similarities and differences between thecultures of mathematics and programming.

1.4.8 Asymptotics and Big-𝑂 notation“log log log𝑛 has been proved to go to infinity, but has never been observed todo so.”, Anonymous, quoted by Carl Pomerance (2000)

It is often very cumbersome to describe precisely quantities suchas running time and is also not needed, since we are typically mostlyinterested in the “higher order terms”. That is, we want to understandthe scaling behavior of the quantity as the input variable grows. Forexample, as far as running time goes, the difference between an 𝑛5-time algorithm and an 𝑛2-time one is much more significant than thedifference between an 100𝑛2 + 10𝑛 time algorithm and an 10𝑛2 timealgorithm. For this purpose, 𝑂-notation is extremely useful as a wayto “declutter” our text and focus our attention on what really matters.For example, using 𝑂-notation, we can say that both 100𝑛2 + 10𝑛and 10𝑛2 are simply Θ(𝑛2) (which informally means “the same up toconstant factors”), while 𝑛2 = 𝑜(𝑛5) (which informally means that 𝑛2is “much smaller than” 𝑛5).

Generally (though still informally), if đč, đș are two functions map-ping natural numbers to non-negative reals, then “đč = 𝑂(đș)” meansthat đč(𝑛) ≀ đș(𝑛) if we don’t care about constant factors, while“đč = 𝑜(đș)” means that đč is much smaller than đș, in the sense that nomatter by what constant factor we multiply đč , if we take 𝑛 to be large

Page 63: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 63

Figure 1.7: If đč(𝑛) = 𝑜(đș(𝑛)) then for sufficientlylarge 𝑛, đč(𝑛) will be smaller than đș(𝑛). For example,if Algorithm 𝐮 runs in time 1000 ⋅ 𝑛 + 106 andAlgorithm đ” runs in time 0.01 ⋅ 𝑛2 then even thoughđ” might be more efficient for smaller inputs, whenthe inputs get sufficiently large, 𝐮 will run much fasterthan đ”.

enough then đș will be bigger (for this reason, sometimes đč = 𝑜(đș)is written as đč â‰Ș đș). We will write đč = Θ(đș) if đč = 𝑂(đș) andđș = 𝑂(đč), which one can think of as saying that đč is the same as đș ifwe don’t care about constant factors. More formally, we define Big-𝑂notation as follows:

Definition 1.15 — Big-𝑂 notation. Let ℝ+ = đ‘„ ∈ ℝ | đ‘„ > 0 be the setof positive real numbers. For two functions đč, đș ∶ ℕ → ℝ+, we saythat đč = 𝑂(đș) if there exist numbers 𝑎, 𝑁0 ∈ ℕ such that đč(𝑛) â‰€đ‘Ž ⋅ đș(𝑛) for every 𝑛 > 𝑁0. We say that đč = Θ(đș) if đč = 𝑂(đș) andđș = 𝑂(đč). We say that đč = Ω(đș) if đș = 𝑂(đč).

We say that đč = 𝑜(đș) if for every 𝜖 > 0 there is some 𝑁0 suchthat đč(𝑛) < 𝜖đș(𝑛) for every 𝑛 > 𝑁0. We say that đč = 𝜔(đș) ifđș = 𝑜(đč).It’s often convenient to use “anonymous functions” in the context of𝑂-notation. For example, when we write a statement such as đč(𝑛) =𝑂(𝑛3), we mean that đč = 𝑂(đș) where đș is the function defined byđș(𝑛) = 𝑛3. Chapter 7 in Jim Apsnes’ notes on discrete math provides

a good summary of 𝑂 notation; see also this tutorial for a gentler andmore programmer-oriented introduction.𝑂 is not equality. Using the equality sign for 𝑂-notation is extremelycommon, but is somewhat of a misnomer, since a statement such asđč = 𝑂(đș) really means that đč is in the set đșâ€Č ∶ ∃𝑁,𝑐 s.t. ∀𝑛>𝑁đșâ€Č(𝑛) â‰€đ‘đș(𝑛). If anything, it makes more sense to use inequalities and writeđč ≀ 𝑂(đș) and đč ≄ Ω(đș), reserving equality for đč = Θ(đș), andso we will sometimes use this notation too, but since the equalitynotation is quite firmly entrenched we often stick to it as well. (Sometexts write đč ∈ 𝑂(đș) instead of đč = 𝑂(đș), but we will not use thisnotation.) Despite the misleading equality sign, you should rememberthat a statement such as đč = 𝑂(đș) means that đč is “at most” đș insome rough sense when we ignore constants, and a statement such asđč = Ω(đș) means that đč is “at least” đș in the same rough sense.

1.4.9 Some “rules of thumb” for Big-𝑂 notationThere are some simple heuristics that can help when trying to com-pare two functions đč and đș:

‱ Multiplicative constants don’t matter in 𝑂-notation, and so ifđč(𝑛) = 𝑂(đș(𝑛)) then 100đč(𝑛) = 𝑂(đș(𝑛)).‱ When adding two functions, we only care about the larger one. For

example, for the purpose of 𝑂-notation, 𝑛3 + 100𝑛2 is the same as𝑛3, and in general in any polynomial, we only care about the largerexponent.

Page 64: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

64 introduction to theoretical computer science

‱ For every two constants 𝑎, 𝑏 > 0, 𝑛𝑎 = 𝑂(𝑛𝑏) if and only if 𝑎 ≀ 𝑏,and 𝑛𝑎 = 𝑜(𝑛𝑏) if and only if 𝑎 < 𝑏. For example, combining the twoobservations above, 100𝑛2 + 10𝑛 + 100 = 𝑜(𝑛3).

‱ Polynomial is always smaller than exponential: 𝑛𝑎 = 𝑜(2𝑛𝜖) forevery two constants 𝑎 > 0 and 𝜖 > 0 even if 𝜖 is much smaller than𝑎. For example, 100𝑛100 = 𝑜(2√𝑛).

‱ Similarly, logarithmic is always smaller than polynomial: (log𝑛)𝑎(which we write as log𝑎 𝑛) is 𝑜(𝑛𝜖) for every two constants 𝑎, 𝜖 > 0.For example, combining the observations above, 100𝑛2 log100 𝑛 =𝑜(𝑛3).

RRemark 1.16 — Big 𝑂 for other applications (optional).While Big-𝑂 notation is often used to analyze runningtime of algorithms, this is by no means the only ap-plication. We can use 𝑂 notation to bound asymptoticrelations between any functions mapping integersto positive numbers. It can be used regardless ofwhether these functions are a measure of runningtime, memory usage, or any other quantity that mayhave nothing to do with computation. Here is oneexample which is unrelated to this book (and henceone that you can feel free to skip): one way to state theRiemann Hypothesis (one of the most famous openquestions in mathematics) is that it corresponds tothe conjecture that the number of primes between 0and 𝑛 is equal to âˆ«đ‘›2 1

lnđ‘„ đ‘‘đ‘„ up to an additive error ofmagnitude at most 𝑂(√𝑛 log𝑛).

1.5 PROOFS

Many people think of mathematical proofs as a sequence of logicaldeductions that starts from some axioms and ultimately arrives at aconclusion. In fact, some dictionaries define proofs that way. This isnot entirely wrong, but at its essence mathematical proof of a state-ment X is simply an argument that convinces the reader that X is truebeyond a shadow of a doubt.

To produce such a proof you need to:

1. Understand precisely what X means.

2. Convince yourself that X is true.

3. Write your reasoning down in plain, precise and concise English(using formulas or notation only when they help clarity).

Page 65: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 65

In many cases, the first part is the most important one. Understand-ing what a statement means is oftentimes more than halfway towardsunderstanding why it is true. In third part, to convince the readerbeyond a shadow of a doubt, we will often want to break down thereasoning to “basic steps”, where each basic step is simple enoughto be “self evident”. The combination of all steps yields the desiredstatement.

1.5.1 Proofs and programsThere is a great deal of similarity between the process of writing proofsand that of writing programs, and both require a similar set of skills.Writing a program involves:

1. Understanding what is the task we want the program to achieve.

2. Convincing yourself that the task can be achieved by a computer,perhaps by planning on a whiteboard or notepad how you willbreak it up to simpler tasks.

3. Converting this plan into code that a compiler or interpreter canunderstand, by breaking up each task into a sequence of the basicoperations of some programming language.

In programs as in proofs, step 1 is often the most important one.A key difference is that the reader for proofs is a human being andthe reader for programs is a computer. (This difference is erodingwith time as more proofs are being written in a machine verifiable form;moreover, to ensure correctness and maintainability of programs, itis important that they can be read and understood by humans.) Thusour emphasis is on readability and having a clear logical flow for ourproof (which is not a bad idea for programs as well). When writing aproof, you should think of your audience as an intelligent but highlyskeptical and somewhat petty reader, that will “call foul” at every stepthat is not well justified.

1.5.2 Proof writing styleA mathematical proof is a piece of writing, but it is a specific genreof writing with certain conventions and preferred styles. As in anywriting, practice makes perfect, and it is also important to revise yourdrafts for clarity.

In a proof for the statement 𝑋, all the text between the words“Proof:” and “QED” should be focused on establishing that 𝑋 is true.Digressions, examples, or ruminations should be kept outside thesetwo words, so they do not confuse the reader. The proof should havea clear logical flow in the sense that every sentence or equation in itshould have some purpose and it should be crystal-clear to the reader

Page 66: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

66 introduction to theoretical computer science

what this purpose is. When you write a proof, for every equation orsentence you include, ask yourself:

1. Is this sentence or equation stating that some statement is true?

2. If so, does this statement follow from the previous steps, or are wegoing to establish it in the next step?

3. What is the role of this sentence or equation? Is it one step towardsproving the original statement, or is it a step towards proving someintermediate claim that you have stated before?

4. Finally, would the answers to questions 1-3 be clear to the reader?If not, then you should reorder, rephrase or add explanations.

Some helpful resources on mathematical writing include this hand-out by Lee, this handout by Hutching, as well as several of the excel-lent handouts in Stanford’s CS 103 class.

1.5.3 Patterns in proofs“If it was so, it might be; and if it were so, it would be; but as it isn’t, it ain’t.That’s logic.”, Lewis Carroll, Through the looking-glass.

Just like in programming, there are several common patterns ofproofs that occur time and again. Here are some examples:

Proofs by contradiction: One way to prove that 𝑋 is true is to showthat if 𝑋 was false it would result in a contradiction. Such proofsoften start with a sentence such as “Suppose, towards a contradiction,that 𝑋 is false” and end with deriving some contradiction (such as aviolation of one of the assumptions in the theorem statement). Here isan example:Lemma 1.17 There are no natural numbers 𝑎, 𝑏 such that

√2 = 𝑎𝑏 .Proof. Suppose, towards a contradiction that this is false, and so let𝑎 ∈ ℕ be the smallest number such that there exists some 𝑏 ∈ ℕsatisfying

√2 = 𝑎𝑏 . Squaring this equation we get that 2 = 𝑎2/𝑏2 or𝑎2 = 2𝑏2 (∗). But this means that 𝑎2 is even, and since the product oftwo odd numbers is odd, it means that 𝑎 is even as well, or in otherwords, 𝑎 = 2𝑎â€Č for some 𝑎â€Č ∈ ℕ. Yet plugging this into (∗) shows that4𝑎â€Č2 = 2𝑏2 which means 𝑏2 = 2𝑎â€Č2 is an even number as well. By thesame considerations as above we get that 𝑏 is even and hence 𝑎/2 and𝑏/2 are two natural numbers satisfying 𝑎/2𝑏/2 = √2, contradicting theminimality of 𝑎.

Page 67: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 67

Proofs of a universal statement: Often we want to prove a statement 𝑋 ofthe form “Every object of type 𝑂 has property 𝑃 .” Such proofs oftenstart with a sentence such as “Let 𝑜 be an object of type 𝑂” and end byshowing that 𝑜 has the property 𝑃 . Here is a simple example:Lemma 1.18 For every natural number 𝑛 ∈ 𝑁 , either 𝑛 or 𝑛 + 1 is even.

Proof. Let 𝑛 ∈ 𝑁 be some number. If 𝑛/2 is a whole number thenwe are done, since then 𝑛 = 2(𝑛/2) and hence it is even. Otherwise,𝑛/2 + 1/2 is a whole number, and hence 2(𝑛/2 + 1/2) = 𝑛 + 1 is even.

Proofs of an implication: Another common case is that the statement 𝑋has the form “𝐮 implies đ”â€. Such proofs often start with a sentencesuch as “Assume that 𝐮 is true” and end with a derivation of đ” from𝐮. Here is a simple example:Lemma 1.19 If 𝑏2 ≄ 4𝑎𝑐 then there is a solution to the quadratic equa-tion đ‘Žđ‘„2 + đ‘đ‘„ + 𝑐 = 0.Proof. Suppose that 𝑏2 ≄ 4𝑎𝑐. Then 𝑑 = 𝑏2 − 4𝑎𝑐 is a non-negativenumber and hence it has a square root 𝑠. Thus đ‘„ = (−𝑏 + 𝑠)/(2𝑎)satisfiesđ‘Žđ‘„2 + đ‘đ‘„ + 𝑐 = 𝑎(−𝑏 + 𝑠)2/(4𝑎2) + 𝑏(−𝑏 + 𝑠)/(2𝑎) + 𝑐= (𝑏2 − 2𝑏𝑠 + 𝑠2)/(4𝑎) + (−𝑏2 + 𝑏𝑠)/(2𝑎) + 𝑐 . (1.17)

Rearranging the terms of (1.17) we get𝑠2/(4𝑎) + 𝑐 − 𝑏2/(4𝑎) = (𝑏2 − 4𝑎𝑐)/(4𝑎) + 𝑐 − 𝑏2/(4𝑎) = 0 (1.18)

Proofs of equivalence: If a statement has the form “𝐮 if and only ifđ”â€ (often shortened as “𝐮 iff đ”â€) then we need to prove both that 𝐮implies đ” and that đ” implies 𝐮. We call the implication that 𝐮 impliesđ” the “only if” direction, and the implication that đ” implies 𝐮 the “if”direction.

Proofs by combining intermediate claims: When a proof is more complex,it is often helpful to break it apart into several steps. That is, to provethe statement 𝑋, we might first prove statements 𝑋1,𝑋2, and 𝑋3 andthen prove that 𝑋1 ∧ 𝑋2 ∧ 𝑋3 implies 𝑋. (Recall that ∧ denotes thelogical AND operator.)

Proofs by case distinction: This is a special case of the above, where toprove a statement 𝑋 we split into several cases đ¶1, 
 , đ¶đ‘˜, and provethat (a) the cases are exhaustive, in the sense that one of the cases đ¶đ‘–must happen and (b) go one by one and prove that each one of thecases đ¶đ‘– implies the result 𝑋 that we are after.

Page 68: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

68 introduction to theoretical computer science

Proofs by induction: We discuss induction and give an example inSection 1.6.1 below. We can think of such proofs as a variant of theabove, where we have an unbounded number of intermediate claims𝑋0, 𝑋2, 
 , 𝑋𝑘, and we prove that 𝑋0 is true, as well as that 𝑋0 implies𝑋1, and that 𝑋0 ∧ 𝑋1 implies 𝑋2, and so on and so forth. The websitefor CMU course 15-251 contains a useful handout on potential pitfallswhen making proofs by induction.

”Without loss of generality (w.l.o.g)”: This term can be initially quite con-fusing. It is essentially a way to simplify proofs by case distinctions.The idea is that if Case 1 is equal to Case 2 up to a change of variablesor a similar transformation, then the proof of Case 1 will also implythe proof of Case 2. It is always a statement that should be viewedwith suspicion. Whenever you see it in a proof, ask yourself if youunderstand why the assumption made is truly without loss of gen-erality, and when you use it, try to see if the use is indeed justified.When writing a proof, sometimes it might be easiest to simply repeatthe proof of the second case (adding a remark that the proof is verysimilar to the first one).

RRemark 1.20 — Hierarchical Proofs (optional). Mathe-matical proofs are ultimately written in English prose.The well-known computer scientist Leslie Lamportargues that this is a problem, and proofs should bewritten in a more formal and rigorous way. In hismanuscript he proposes an approach for structuredhierarchical proofs, that have the following form:

‱ A proof for a statement of the form “If 𝐮 then đ”â€is a sequence of numbered claims, starting withthe assumption that 𝐮 is true, and ending with theclaim that đ” is true.

‱ Every claim is followed by a proof showing howit is derived from the previous assumptions orclaims.

‱ The proof for each claim is itself a sequence ofsubclaims.

The advantage of Lamport’s format is that the rolethat every sentence in the proof plays is very clear.It is also much easier to transform such proofs intomachine-checkable forms. The disadvantage is thatsuch proofs can be tedious to read and write, withless differentiation between the important parts of thearguments versus the more routine ones.

Page 69: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 69

1.6 EXTENDED EXAMPLE: TOPOLOGICAL SORTING

In this section we will prove the following: every directed acyclicgraph (DAG, see Definition 1.9) can be arranged in layers so that forall directed edges 𝑱 → 𝑣, the layer of 𝑣 is larger than the layer of 𝑱.This result is known as topological sorting and is used in many appli-cations, including task scheduling, build systems, software packagemanagement, spreadsheet cell calculations, and many others (seeFig. 1.8). In fact, we will also use it ourselves later on in this book.

Figure 1.8: An example of topological sorting. We con-sider a directed graph corresponding to a prerequisitegraph of the courses in some Computer Science pro-gram. The edge 𝑱 → 𝑣 means that the course 𝑱 is aprerequisite for the course 𝑣. A layering or “topologi-cal sorting” of this graph is the same as mapping thecourses to semesters so that if we decide to take thecourse 𝑣 in semester 𝑓(𝑣), then we have already takenall the prerequisites for 𝑣 (i.e., its in-neighbors) inprior semesters.

We start with the following definition. A layering of a directedgraph is a way to assign for every vertex 𝑣 a natural number(corresponding to its layer), such that 𝑣’s in-neighbors are inlower-numbered layers than 𝑣, and 𝑣’s out-neighbors are inhigher-numbered layers. The formal definition is as follows:

Definition 1.21 — Layering of a DAG. Let đș = (𝑉 , 𝐾) be a directed graph.A layering of đș is a function 𝑓 ∶ 𝑉 → ℕ such that for every edge𝑱 → 𝑣 of đș, 𝑓(𝑱) < 𝑓(𝑣).In this section we prove that a directed graph is acyclic if and only if

it has a valid layering.

Theorem 1.22 — Topological Sort. Let đș be a directed graph. Then đș isacyclic if and only if there exists a layering 𝑓 of đș.

To prove such a theorem, we need to first understand what itmeans. Since it is an “if and only if” statement, Theorem 1.22 corre-sponds to two statements:Lemma 1.23 For every directed graph đș, if đș is acyclic then it has alayering.Lemma 1.24 For every directed graph đș, if đș has a layering, then it isacyclic.

Page 70: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

70 introduction to theoretical computer science

Figure 1.9: Some examples of DAGs of one, two andthree vertices, and valid ways to assign layers to thevertices.

To prove Theorem 1.22 we need to prove both Lemma 1.23 andLemma 1.24. Lemma 1.24 is actually not that hard to prove. Intuitively,if đș contains a cycle, then it cannot be the case that all edges on thecycle increase in layer number, since if we travel along the cycle atsome point we must come back to the place we started from. Theformal proof is as follows:

Proof. Let đș = (𝑉 , 𝐾) be a directed graph and let 𝑓 ∶ 𝑉 → ℕ be alayering of đș as per Definition 1.21 . Suppose, towards a contradiction,that đș is not acyclic, and hence there exists some cycle 𝑱0, 𝑱1, 
 , 𝑱𝑘such that 𝑱0 = 𝑱𝑘 and for every 𝑖 ∈ [𝑘] the edge 𝑱𝑖 → 𝑱𝑖+1 is present inđș. Since 𝑓 is a layering, for every 𝑖 ∈ [𝑘], 𝑓(𝑱𝑖) < 𝑓(𝑱𝑖+1), which meansthat 𝑓(𝑱0) < 𝑓(𝑱1) < ⋯ < 𝑓(𝑱𝑘) (1.19)

but this is a contradiction since 𝑱0 = 𝑱𝑘 and hence 𝑓(𝑱0) = 𝑓(𝑱𝑘).

Lemma 1.23 corresponds to the more difficult (and useful) direc-tion. To prove it, we need to show how given an arbitrary DAG đș, wecan come up with a layering of the vertices of đș so that all edges “goup”.

PIf you have not seen the proof of this theorem before(or don’t remember it), this would be an excellentpoint to pause and try to prove it yourself. One wayto do it would be to describe an algorithm that given asinput a directed acyclic graph đș on 𝑛 vertices and 𝑛−2or fewer edges, constructs an array đč of length 𝑛 suchthat for every edge 𝑱 → 𝑣 in the graph đč[𝑱] < đč[𝑣].

1.6.1 Mathematical inductionThere are several ways to prove Lemma 1.23. One approach to do isto start by proving it for small graphs, such as graphs with 1, 2 or 3vertices (see Fig. 1.9, for which we can check all the cases, and then tryto extend the proof for larger graphs. The technical term for this proofapproach is proof by induction.

Induction is simply an application of the self-evident Modus Ponensrule that says that if

(a) 𝑃 is trueand

(b) 𝑃 implies 𝑄then 𝑄 is true.

Page 71: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 71

In the setting of proofs by induction we typically have a statement𝑄(𝑘) that is parameterized by some integer 𝑘, and we prove that (a)𝑄(0) is true, and (b) For every 𝑘 > 0, if 𝑄(0), 
 , 𝑄(𝑘 − 1) are all truethen 𝑄(𝑘) is true. (Usually proving (b) is the hard part, though thereare examples where the “base case” (a) is quite subtle.) By applyingModus Ponens, we can deduce from (a) and (b) that 𝑄(1) is true.Once we did so, since we now know that both 𝑄(0) and 𝑄(1) are true,then we can use this and (b) to deduce (again using Modus Ponens)that 𝑄(2) is true. We can repeat the same reasoning again and againto obtain that 𝑄(𝑘) is true for every 𝑘. The statement (a) is called the“base case”, while (b) is called the “inductive step”. The assumptionin (b) that 𝑄(𝑖) holds for 𝑖 < 𝑘 is called the “inductive hypothesis”.(The form of induction described here is sometimes called “stronginduction” as opposed to “weak induction” where we replace (b)by the statement (b’) that if 𝑄(𝑘 − 1) is true then 𝑄(𝑘) is true; weakinduction can be thought of as the special case of strong inductionwhere we don’t use the assumption that 𝑄(0), 
 , 𝑄(𝑘 − 2) are true.)

RRemark 1.25 — Induction and recursion. Proofs by in-duction are closely related to algorithms by recursion.In both cases we reduce solving a larger problem tosolving a smaller instance of itself. In a recursive algo-rithm to solve some problem P on an input of length𝑘 we ask ourselves “what if someone handed me away to solve P on instances smaller than 𝑘?”. In aninductive proof to prove a statement Q parameterizedby a number 𝑘, we ask ourselves “what if I alreadyknew that 𝑄(𝑘â€Č) is true for 𝑘â€Č < 𝑘?”. Both inductionand recursion are crucial concepts for this course andComputer Science at large (and even other areas ofinquiry, including not just mathematics but othersciences as well). Both can be confusing at first, butwith time and practice they become clearer. For moreon proofs by induction and recursion, you might findthe following Stanford CS 103 handout, this MIT 6.00lecture or this excerpt of the Lehman-Leighton bookuseful.

1.6.2 Proving the result by inductionThere are several ways to use induction to prove Lemma 1.23 by in-duction. We will use induction on the number 𝑛 of vertices, and so wewill define the statement 𝑄(𝑛) as follows:

𝑄(𝑛) is “For every DAG đș = (𝑉 , 𝐾) with 𝑛 vertices, there is a layering of đș.”

Page 72: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

72 introduction to theoretical computer science

5 QED stands for “quod erat demonstrandum”, whichis Latin for “what was to be demonstrated” or “thevery thing it was required to have shown”.

6 Using 𝑛 = 0 as the base case is logically valid, butcan be confusing. If you find the trivial 𝑛 = 0 caseto be confusing, you can always directly verify thestatement for 𝑛 = 1 and then use both 𝑛 = 0 and𝑛 = 1 as the base cases.

The statement for 𝑄(0) (where the graph contains no vertices) istrivial. Thus it will suffice to prove the following: for every 𝑛 > 0, if𝑄(𝑛 − 1) is true then 𝑄(𝑛) is true.

To do so, we need to somehow find a way, given a graph đș of 𝑛vertices, to reduce the task of finding a layering for đș into the task offinding a layering for some other graph đșâ€Č of 𝑛−1 vertices. The idea isthat we will find a source of đș: a vertex 𝑣 that has no in-neighbors. Wecan then assign to 𝑣 the layer 0, and layer the remaining vertices usingthe inductive hypothesis in layers 1, 2, 
.

The above is the intuition behind the proof of Lemma 1.23, butwhen writing the formal proof below, we use the benefit of hind-sight, and try to streamline what was a messy journey into a linearand easy-to-follow flow of logic that starts with the word “Proof:”and ends with “QED” or the symbol .5 Discussions, examples anddigressions can be very insightful, but we keep them outside the spacedelimited between these two words, where (as described by this ex-cellent handout) “every sentence must be load bearing”. Just like wedo in programming, we can break the proof into little “subroutines”or “functions” (known as lemmas or claims in math language), whichwill be smaller statements that help us prove the main result. How-ever, the proof should be structured in a way that ensures that it isalways crystal-clear to the reader in what stage we are of the proof.The reader should be able to tell what is the role of every sentence inthe proof and which part it belongs to. We now present the formalproof of Lemma 1.23.

Proof of Lemma 1.23. Let đș = (𝑉 , 𝐾) be a DAG and 𝑛 = |𝑉 | be thenumber of its vertices. We prove the lemma by induction on 𝑛. Thebase case is 𝑛 = 0 where there are no vertices, and so the statement istrivially true.6 For the case of 𝑛 > 0, we make the inductive hypothesisthat every DAG đșâ€Č of at most 𝑛 − 1 vertices has a layering.

We make the following claim:Claim: đș must contain a vertex 𝑣 of in-degree zero.Proof of Claim: Suppose otherwise that every vertex 𝑣 ∈ 𝑉 has an

in-neighbor. Let 𝑣0 be some vertex of đș, let 𝑣1 be an in-neighbor of 𝑣0,𝑣2 be an in-neighbor of 𝑣1, and continue in this way for 𝑛 steps untilwe construct a list 𝑣0, 𝑣1, 
 , 𝑣𝑛 such that for every 𝑖 ∈ [𝑛], 𝑣𝑖+1 is anin-neighbor of 𝑣𝑖, or in other words the edge 𝑣𝑖+1 → 𝑣𝑖 is present in thegraph. Since there are only 𝑛 vertices in this graph, one of the 𝑛 + 1vertices in this sequence must repeat itself, and so there exists 𝑖 < 𝑗such that 𝑣𝑖 = 𝑣𝑗. But then the sequence 𝑣𝑗 → 𝑣𝑗−1 → ⋯ → 𝑣𝑖 is a cyclein đș, contradicting our assumption that it is acyclic. (QED Claim)

Given the claim, we can let 𝑣0 be some vertex of in-degree zero inđș, and let đșâ€Č be the graph obtained by removing 𝑣0 from đș. đșâ€Č has

Page 73: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 73

𝑛 − 1 vertices and hence per the inductive hypothesis has a layering𝑓 â€Č ∶ (𝑉 ⧔ 𝑣0) → ℕ. We define 𝑓 ∶ 𝑉 → ℕ as follows:

𝑓(𝑣) = âŽ§âŽšâŽ©đ‘“ â€Č(𝑣) + 1 𝑣 ≠ 𝑣00 𝑣 = 𝑣0 . (1.20)

We claim that 𝑓 is a valid layering, namely that for every edge 𝑱 →𝑣, 𝑓(𝑱) < 𝑓(𝑣). To prove this, we split into cases:

‱ Case 1: 𝑱 ≠ 𝑣0, 𝑣 ≠ 𝑣0. In this case the edge 𝑱 → 𝑣 exists in thegraph đșâ€Č and hence by the inductive hypothesis 𝑓 â€Č(𝑱) < 𝑓 â€Č(𝑣)which implies that 𝑓 â€Č(𝑱) + 1 < 𝑓 â€Č(𝑣) + 1.

‱ Case 2: 𝑱 = 𝑣0, 𝑣 ≠ 𝑣0. In this case 𝑓(𝑱) = 0 and 𝑓(𝑣) = 𝑓 â€Č(𝑣) + 1 >0.‱ Case 3: 𝑱 ≠ 𝑣0, 𝑣 = 𝑣0. This case can’t happen since 𝑣0 does not

have in-neighbors.

‱ Case 4: 𝑱 = 𝑣0, 𝑣 = 𝑣0. This case again can’t happen since it meansthat 𝑣0 is its own-neighbor — it is involved in a self loop which is aform cycle that is disallowed in an acyclic graph.

Thus, 𝑓 is a valid layering for đș which completes the proof.

PReading a proof is no less of an important skill thanproducing one. In fact, just like understanding code,it is a highly non-trivial skill in itself. Therefore Istrongly suggest that you re-read the above proof, ask-ing yourself at every sentence whether the assumptionit makes is justified, and whether this sentence trulydemonstrates what it purports to achieve. Anothergood habit is to ask yourself when reading a proof forevery variable you encounter (such as 𝑱, 𝑖, đșâ€Č, 𝑓 â€Č, etc.in the above proof) the following questions: (1) Whattype of variable is it? is it a number? a graph? a vertex?a function? and (2) What do we know about it? Is itan arbitrary member of the set? Have we shown somefacts about it?, and (3) What are we trying to showabout it?.

1.6.3 Minimality and uniquenessTheorem 1.22 guarantees that for every DAG đș = (𝑉 , 𝐾) there existssome layering 𝑓 ∶ 𝑉 → ℕ but this layering is not necessarily unique.For example, if 𝑓 ∶ 𝑉 → ℕ is a valid layering of the graph then so isthe function 𝑓 â€Č defined as 𝑓 â€Č(𝑣) = 2 ⋅ 𝑓(𝑣). However, it turns out that

Page 74: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

74 introduction to theoretical computer science

the minimal layering is unique. A minimal layering is one where everyvertex is given the smallest layer number possible. We now formallydefine minimality and state the uniqueness theorem:

Theorem 1.26 — Minimal layering is unique. Let đș = (𝑉 , 𝐾) be a DAG. Wesay that a layering 𝑓 ∶ 𝑉 → ℕ is minimal if for every vertex 𝑣 ∈ 𝑉 , if𝑣 has no in-neighbors then 𝑓(𝑣) = 0 and if 𝑣 has in-neighbors thenthere exists an in-neighbor 𝑱 of 𝑣 such that 𝑓(𝑱) = 𝑓(𝑣) − 1.

For every layering 𝑓, 𝑔 ∶ 𝑉 → ℕ of đș, if both 𝑓 and 𝑔 are minimalthen 𝑓 = 𝑔.The definition of minimality in Theorem 1.26 implies that for every

vertex 𝑣 ∈ 𝑉 , we cannot move it to a lower layer without makingthe layering invalid. If 𝑣 is a source (i.e., has in-degree zero) thena minimal layering 𝑓 must put it in layer 0, and for every other 𝑣, if𝑓(𝑣) = 𝑖, then we cannot modify this to set 𝑓(𝑣) ≀ 𝑖 − 1 since thereis an-neighbor 𝑱 of 𝑣 satisfying 𝑓(𝑱) = 𝑖 − 1. What Theorem 1.26says is that a minimal layering 𝑓 is unique in the sense that every otherminimal layering is equal to 𝑓 .Proof Idea:

The idea is to prove the theorem by induction on the layers. If 𝑓 and𝑔 are minimal then they must agree on the source vertices, since both𝑓 and 𝑔 should assign these vertices to layer 0. We can then show thatif 𝑓 and 𝑔 agree up to layer 𝑖 − 1, then the minimality property impliesthat they need to agree in layer 𝑖 as well. In the actual proof we usea small trick to save on writing. Rather than proving the statementthat 𝑓 = 𝑔 (or in other words that 𝑓(𝑣) = 𝑔(𝑣) for every 𝑣 ∈ 𝑉 ),we prove the weaker statement that 𝑓(𝑣) ≀ 𝑔(𝑣) for every 𝑣 ∈ 𝑉 .(This is a weaker statement since the condition that 𝑓(𝑣) is lesser orequal than to 𝑔(𝑣) is implied by the condition that 𝑓(𝑣) is equal to𝑔(𝑣).) However, since 𝑓 and 𝑔 are just labels we give to two minimallayerings, by simply changing the names “𝑓” and “𝑔” the same proofalso shows that 𝑔(𝑣) ≀ 𝑓(𝑣) for every 𝑣 ∈ 𝑉 and hence that 𝑓 = 𝑔.⋆Proof of Theorem 1.26. Let đș = (𝑉 , 𝐾) be a DAG and 𝑓, 𝑔 ∶ 𝑉 → ℕ betwo minimal valid layering of đș. We will prove that for every 𝑣 ∈ 𝑉 ,𝑓(𝑣) ≀ 𝑔(𝑣). Since we didn’t assume anything about 𝑓, 𝑔 except theirminimality, the same proof will imply that for every 𝑣 ∈ 𝑉 , 𝑔(𝑣) ≀ 𝑓(𝑣)and hence that 𝑓(𝑣) = 𝑔(𝑣) for every 𝑣 ∈ 𝑉 , which is what we neededto show.

We will prove that 𝑓(𝑣) ≀ 𝑔(𝑣) for every 𝑣 ∈ 𝑉 by induction on𝑖 = 𝑓(𝑣). The case 𝑖 = 0 is immediate: since in this case 𝑓(𝑣) = 0,𝑔(𝑣) must be at least 𝑓(𝑣). For the case 𝑖 > 0, by the minimality of 𝑓 ,

Page 75: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 75

if 𝑓(𝑣) = 𝑖 then there must exist some in-neighbor 𝑱 of 𝑣 such that𝑓(𝑱) = 𝑖 − 1. By the induction hypothesis we get that 𝑔(𝑱) ≄ 𝑖 − 1, andsince 𝑔 is a valid layering it must hold that 𝑔(𝑣) > 𝑔(𝑱) which meansthat 𝑔(𝑣) ≄ 𝑖 = 𝑓(𝑣).

PThe proof of Theorem 1.26 is fully rigorous, but iswritten in a somewhat terse manner. Make sure thatyou read through it and understand why this is indeedan airtight proof of the Theorem’s statement.

1.7 THIS BOOK: NOTATION AND CONVENTIONS

Most of the notation we use in this book is standard and is used inmost mathematical texts. The main points where we diverge are:

‱ We index the natural numbers ℕ starting with 0 (though manyother texts, especially in computer science, do the same).

‱ We also index the set [𝑛] starting with 0, and hence define it as0, 
 , 𝑛−1. In other texts it is often defined as 1, 
 , 𝑛. Similarly,we index our strings starting with 0, and hence a string đ‘„ ∈ 0, 1𝑛is written as đ‘„0đ‘„1 ⋯ đ‘„đ‘›âˆ’1.

‱ If 𝑛 is a natural number then 1𝑛 does not equal the number 1 butrather this is the length 𝑛 string 11 ⋯ 1 (that is a string of 𝑛 ones).Similarly, 0𝑛 refers to the length 𝑛 string 00 ⋯ 0.

‱ Partial functions are functions that are not necessarily defined onall inputs. When we write 𝑓 ∶ 𝐮 → đ” this means that 𝑓 is a totalfunction unless we say otherwise. When we want to emphasize that𝑓 can be a partial function, we will sometimes write 𝑓 ∶ 𝐮 →𝑝 đ”.

‱ As we will see later on in the course, we will mostly describe ourcomputational problems in terms of computing a Boolean function𝑓 ∶ 0, 1∗ → 0, 1. In contrast, many other textbooks refer to thesame task as deciding a language 𝐿 ⊆ 0, 1∗. These two viewpointsare equivalent, since for every set 𝐿 ⊆ 0, 1∗ there is a correspond-ing function đč such that đč(đ‘„) = 1 if and only if đ‘„ ∈ 𝐿. Computingpartial functions corresponds to the task known in the literatureas a solving a promise problem. Because the language notation isso prevalent in other textbooks, we will occasionally remind thereader of this correspondence.

‱ We use âŒˆđ‘„âŒ‰ and âŒŠđ‘„âŒ‹ for the “ceiling” and “floor” operators thatcorrespond to “rounding up” or “rounding down” a number to the

Page 76: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

76 introduction to theoretical computer science

nearest integer. We use (đ‘„ mod 𝑩) to denote the “remainder” of đ‘„when divided by 𝑩. That is, (đ‘„ mod 𝑩) = đ‘„ − đ‘ŠâŒŠđ‘„/𝑩⌋. In contextwhen an integer is expected we’ll typically “silently round” thequantities to an integer. For example, if we say that đ‘„ is a string oflength √𝑛 then this means that đ‘„ is of length ⌈√𝑛 ⌉. (We round upfor the sake of convention, but in most such cases, it will not make adifference whether we round up or down.)

‱ Like most Computer Science texts, we default to the logarithm inbase two. Thus, log𝑛 is the same as log2 𝑛.

‱ We will also use the notation 𝑓(𝑛) = 𝑝𝑜𝑙𝑩(𝑛) as a shorthand for𝑓(𝑛) = 𝑛𝑂(1) (i.e., as shorthand for saying that there are someconstants 𝑎, 𝑏 such that 𝑓(𝑛) ≀ 𝑎 ⋅ 𝑛𝑏 for every sufficiently large𝑛). Similarly, we will use 𝑓(𝑛) = 𝑝𝑜𝑙𝑩𝑙𝑜𝑔(𝑛) as shorthand for𝑓(𝑛) = 𝑝𝑜𝑙𝑩(log𝑛) (i.e., as shorthand for saying that there aresome constants 𝑎, 𝑏 such that 𝑓(𝑛) ≀ 𝑎 ⋅ (log𝑛)𝑏 for every sufficientlylarge 𝑛).

‱ As in often the case in mathematical literature, we use the apostro-phe character to enrich our set of identifiers. Typically if đ‘„ denotessome object, then đ‘„â€Č, đ‘„â€ł, etc. will denote other objects of the sametype.

‱ To save on “cognitive load” we will often use round constants suchas 10, 100, 1000 in the statements of both theorems and problemset questions. When you see such a “round” constant, you cantypically assume that it has no special significance and was justchosen arbitrarily. For example, if you see a theorem of the form“Algorithm 𝐮 takes at most 1000 ⋅ 𝑛2 steps to compute function đčon inputs of length 𝑛” then probably the number 1000 is an abitrarysufficiently large constant, and one could prove the same theoremwith a bound of the form 𝑐 ⋅ 𝑛2 for a constant 𝑐 that is smaller than1000. Similarly, if a problem asks you to prove that some quantity isat least 𝑛/100, it is quite possible that in truth the quantity is at least𝑛/𝑑 for some constant 𝑑 that is smaller than 100.

1.7.1 Variable name conventionsLike programming, mathematics is full of variables. Whenever you seea variable, it is always important to keep track of what is its type (e.g.,whether the variable is a number, a string, a function, a graph, etc.).To make this easier, we try to stick to certain conventions and consis-tently use certain identifiers for variables of the same type. Some ofthese conventions are listed in Section 1.7.1 below. These conventionsare not immutable laws and we might occasionally deviate from them.

Page 77: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 77

Also, such conventions do not replace the need to explicitly declare foreach new variable the type of object that it denotes.

Table 1.2: Conventions for identifiers in this book

Identifier Often denotes object of type𝑖,𝑗,𝑘,ℓ,𝑚,𝑛Natural numbers (i.e., in ℕ = 0, 1, 2, 
)𝜖, 𝛿 Small positive real numbers (very close to 0)đ‘„, 𝑩, 𝑧, đ‘€ Typically strings in 0, 1∗ though sometimes numbers orother objects. We often identify an object with itsrepresentation as a string.đș A graph. The set of đș’s vertices is typically denoted by 𝑉 .Often 𝑉 = [𝑛]. The set of đș’s edges is typically denoted by𝐾.𝑆 Set𝑓, 𝑔, ℎ Functions. We often (though not always) use lowercaseidentifiers for finite functions, which map 0, 1𝑛 to 0, 1𝑚(often 𝑚 = 1).đč, đș, đ» Infinite (unbounded input) functions mapping 0, 1∗ to0, 1∗ or 0, 1∗ to 0, 1𝑚 for some 𝑚. Based on context,the identifiers đș, đ» are sometimes used to denotefunctions and sometimes graphs.𝐮, đ”, đ¶ Boolean circuits𝑀, 𝑁 Turing machines𝑃 , 𝑄 Programs𝑇 A function mapping ℕ to ℕ that corresponds to a timebound.𝑐 A positive number (often an unspecified constant; e.g.,𝑇 (𝑛) = 𝑂(𝑛) corresponds to the existence of 𝑐 s.t.𝑇 (𝑛) ≀ 𝑐 ⋅ 𝑛 every 𝑛 > 0). We sometimes use 𝑎, 𝑏 in asimilar way.ÎŁ Finite set (often used as the alphabet for a set of strings).

1.7.2 Some idiomsMathematical texts often employ certain conventions or “idioms”.Some examples of such idioms that we use in this text include thefollowing:

‱ “Let 𝑋 be 
”, “let 𝑋 denote 
”, or “let 𝑋 = 
”: These are alldifferent ways for us to say that we are defining the symbol 𝑋 tostand for whatever expression is in the 
. When 𝑋 is a property ofsome objects we might define 𝑋 by writing something along thelines of “We say that 
 has the property 𝑋 if 
.”. While we often

Page 78: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

78 introduction to theoretical computer science

try to define terms before they are used, sometimes a mathematicalsentence reads easier if we use a term before defining it, in whichcase we add “Where 𝑋 is 
” to explain how 𝑋 is defined in thepreceding expression.

‱ Quantifiers: Mathematical texts involve many quantifiers such as“for all” and “exists”. We sometimes spell these in words as in “forall 𝑖 ∈ ℕ” or “there is đ‘„ ∈ 0, 1∗”, and sometimes use the formalsymbols ∀ and ∃. It is important to keep track on which variable isquantified in what way the dependencies between the variables. Forexample, a sentence fragment such as “for every 𝑘 > 0 there exists𝑛” means that 𝑛 can be chosen in a way that depends on 𝑘. The orderof quantifiers is important. For example, the following is a truestatement: “for every natural number 𝑘 > 1 there exists a prime number𝑛 such that 𝑛 divides 𝑘.” In contrast, the following statement is false:“there exists a prime number 𝑛 such that for every natural number 𝑘 > 1,𝑛 divides 𝑘.”

‱ Numbered equations, theorems, definitions: To keep track of allthe terms we define and statements we prove, we often assign thema (typically numeric) label, and then refer back to them in otherparts of the text.

‱ (i.e.,), (e.g.,): Mathematical texts tend to contain quite a few ofthese expressions. We use 𝑋 (i.e., 𝑌 ) in cases where 𝑌 is equivalentto 𝑋 and 𝑋 (e.g., 𝑌 ) in cases where 𝑌 is an example of 𝑋 (e.g., onecan use phrases such as “a natural number (i.e., a non-negativeinteger)” or “a natural number (e.g., 7)”).

‱ “Thus”, “Therefore” , “We get that”: This means that the followingsentence is implied by the preceding one, as in “The 𝑛-vertex graphđș is connected. Therefore it contains at least 𝑛 − 1 edges.” Wesometimes use “indeed” to indicate that the following text justifiesthe claim that was made in the preceding sentence as in “The 𝑛-vertex graph đș has at least 𝑛 − 1 edges. Indeed, this follows since đș isconnected.”

‱ Constants: In Computer Science, we typically care about how ouralgorithms’ resource consumption (such as running time) scaleswith certain quantities (such as the length of the input). We refer toquantities that do not depend on the length of the input as constantsand so often use statements such as “there exists a constant 𝑐 > 0 suchthat for every 𝑛 ∈ ℕ, Algorithm 𝐮 runs in at most 𝑐 ⋅ 𝑛2 steps on inputs oflength 𝑛.” The qualifier “constant” for 𝑐 is not strictly needed but isadded to emphasize that 𝑐 here is a fixed number independent of 𝑛.In fact sometimes, to reduce cognitive load, we will simply replace 𝑐

Page 79: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 79

by a sufficiently large round number such as 10, 100, or 1000, or use𝑂-notation and write “Algorithm 𝐮 runs in 𝑂(𝑛2) time.”

Chapter Recap

‱ The basic “mathematical data structures” we’llneed are numbers, sets, tuples, strings, graphs andfunctions.

‱ We can use basic objects to define more complexnotions. For example, graphs can be defined as a listof pairs.

‱ Given precise definitions of objects, we can stateunambiguous and precise statements. We can thenuse mathematical proofs to determine whether thesestatements are true or false.

‱ A mathematical proof is not a formal ritual butrather a clear, precise and “bulletproof” argumentcertifying the truth of a certain statement.

‱ Big-𝑂 notation is an extremely useful formalismto suppress less significant details and allows usto focus on the high level behavior of quantities ofinterest.

‱ The only way to get comfortable with mathematicalnotions is to apply them in the contexts of solvingproblems. You should expect to need to go backtime and again to the definitions and notation inthis chapter as you work through problems in thiscourse.

1.8 EXERCISES

Exercise 1.1 — Logical expressions. a. Write a logical expression 𝜑(đ‘„)involving the variables đ‘„0, đ‘„1, đ‘„2 and the operators ∧ (AND), √(OR), and ÂŹ (NOT), such that 𝜑(đ‘„) is true if the majority of theinputs are True.

b. Write a logical expression 𝜑(đ‘„) involving the variables đ‘„0, đ‘„1, đ‘„2and the operators ∧ (AND), √ (OR), and ÂŹ (NOT), such that 𝜑(đ‘„)is true if the sum ∑2𝑖=0 đ‘„đ‘– (identifying “true” with 1 and “false”with 0) is odd.

Exercise 1.2 — Quantifiers. Use the logical quantifiers ∀ (for all), ∃ (thereexists), as well as ∧, ∹, ¬ and the arithmetic operations +, ×, =, >, < towrite the following:a. An expression 𝜑(𝑛, 𝑘) such that for every natural numbers 𝑛, 𝑘,𝜑(𝑛, 𝑘) is true if and only if 𝑘 divides 𝑛.b. An expression 𝜑(𝑛) such that for every natural number 𝑛, 𝜑(𝑛) is

true if and only if 𝑛 is a power of three.

Page 80: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

80 introduction to theoretical computer science

Exercise 1.3 Describe the following statement in English words:∀𝑛∈ℕ∃𝑝>𝑛∀𝑎, 𝑏 ∈ ℕ(𝑎 × 𝑏 ≠ 𝑝) ∹ (𝑎 = 1).

Exercise 1.4 — Set construction notation. Describe in words the followingsets:

a. 𝑆 = đ‘„ ∈ 0, 1100 ∶ ∀𝑖∈0,
,99đ‘„đ‘– = đ‘„99−𝑖b. 𝑇 = đ‘„ ∈ 0, 1∗ ∶ ∀𝑖,𝑗∈2,
,|đ‘„|−1𝑖 ⋅ 𝑗 ≠ |đ‘„|

Exercise 1.5 — Existence of one to one mappings. For each one of the fol-lowing pairs of sets (𝑆, 𝑇 ), prove or disprove the following statement:there is a one to one function 𝑓 mapping 𝑆 to 𝑇 .

a. Let 𝑛 > 10. 𝑆 = 0, 1𝑛 and 𝑇 = [𝑛] × [𝑛] × [𝑛].b. Let 𝑛 > 10. 𝑆 is the set of all functions mapping 0, 1𝑛 to 0, 1.𝑇 = 0, 1𝑛3 .c. Let 𝑛 > 100. 𝑆 = 𝑘 ∈ [𝑛] | 𝑘 is prime, 𝑇 = 0, 1⌈log𝑛−1⌉.

Exercise 1.6 — Inclusion Exclusion. a. Let 𝐮, đ” be finite sets. Prove that|𝐮 âˆȘ đ”| = |𝐮| + |đ”| − |𝐮 ∩ đ”|.b. Let 𝐮0, 
 , 𝐮𝑘−1 be finite sets. Prove that |𝐮0 âˆȘ ⋯ âˆȘ 𝐮𝑘−1| â‰„âˆ‘đ‘˜âˆ’1𝑖=0 |𝐮𝑖| − ∑0â‰€đ‘–<𝑗<𝑘 |𝐮𝑖 ∩ 𝐮𝑗|.c. Let 𝐮0, 
 , 𝐮𝑘−1 be finite subsets of 1, 
 , 𝑛, such that |𝐮𝑖| = 𝑚 for

every 𝑖 ∈ [𝑘]. Prove that if 𝑘 > 100𝑛, then there exist two distinctsets 𝐮𝑖, 𝐮𝑗 s.t. |𝐮𝑖 ∩ 𝐮𝑗| ≄ 𝑚2/(10𝑛).

Exercise 1.7 Prove that if 𝑆, 𝑇 are finite and đč ∶ 𝑆 → 𝑇 is one to onethen |𝑆| ≀ |𝑇 |.

Exercise 1.8 Prove that if 𝑆, 𝑇 are finite and đč ∶ 𝑆 → 𝑇 is onto then|𝑆| ≄ |𝑇 |.

Exercise 1.9 Prove that for every finite 𝑆, 𝑇 , there are (|𝑇 | + 1)|𝑆| partialfunctions from 𝑆 to 𝑇 .

Exercise 1.10 Suppose that 𝑆𝑛𝑛∈ℕ is a sequence such that 𝑆0 ≀ 10 andfor 𝑛 > 1 𝑆𝑛 ≀ 5𝑆⌊ 𝑛5 ⌋ + 2𝑛. Prove by induction that 𝑆𝑛 ≀ 100𝑛 log𝑛 forevery 𝑛.

Page 81: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

mathematical background 81

7 one way to do this is to use Stirling’s approximationfor the factorial function..

Exercise 1.11 Prove that for every undirected graph đș of 100 vertices,if every vertex has degree at most 4, then there exists a subset 𝑆 of atleast 20 vertices such that no two vertices in 𝑆 are neighbors of oneanother.

Exercise 1.12 — 𝑂-notation. For every pair of functions đč, đș below, deter-mine which of the following relations holds: đč = 𝑂(đș), đč = Ω(đș),đč = 𝑜(đș) or đč = 𝜔(đș).a. đč(𝑛) = 𝑛, đș(𝑛) = 100𝑛.b. đč(𝑛) = 𝑛, đș(𝑛) = √𝑛.c. đč(𝑛) = 𝑛 log𝑛, đș(𝑛) = 2(log(𝑛))2 .d. đč(𝑛) = √𝑛, đș(𝑛) = 2√log𝑛e. đč(𝑛) = ( 𝑛⌈0.2𝑛⌉) , đș(𝑛) = 20.1𝑛 (where (𝑛𝑘) is the number of 𝑘-sized

subsets of a set of size 𝑛) and 𝑔(𝑛) = 20.1𝑛. See footnote for hint.7

Exercise 1.13 Give an example of a pair of functions đč, đș ∶ ℕ → ℕ suchthat neither đč = 𝑂(đș) nor đș = 𝑂(đč) holds.

Exercise 1.14 Prove that for every undirected graph đș on 𝑛 vertices, if đșhas at least 𝑛 edges then đș contains a cycle.

Exercise 1.15 Prove that for every undirected graph đș of 1000 vertices,if every vertex has degree at most 4, then there exists a subset 𝑆 of atleast 200 vertices such that no two vertices in 𝑆 are neighbors of oneanother.

1.9 BIBLIOGRAPHICAL NOTES

The heading “A Mathematician’s Apology”, refers to Hardy’s classicbook [Har41]. Even when Hardy is wrong, he is very much worthreading.

There are many online sources for the mathematical backgroundneeded for this book. In particular, the lecture notes for MIT 6.042“Mathematics for Computer Science” [LLM18] are extremely com-prehensive, and videos and assignments for this course are availableonline. Similarly, Berkeley CS 70: “Discrete Mathematics and Proba-bility Theory” has extensive lecture notes online.

Page 82: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

82 introduction to theoretical computer science

Other sources for discrete mathematics are Rosen [Ros19] andJim Aspens’ online book [Asp18]. Lewis and Zax [LZ19], as wellas the online book of Fleck [Fle18], give a more gentle overview ofthe much of the same material. Solow [Sol14] is a good introductionto proof reading and writing. Kun [Kun18] gives an introductionto mathematics aimed at readers with programming background.Stanford’s CS 103 course has a wonderful collections of handouts onmathematical proof techniques and discrete mathematics.

The word graph in the sense of Definition 1.3 was coined by themathematician Sylvester in 1878 in analogy with the chemical graphsused to visualize molecules. There is an unfortunate confusion be-tween this term and the more common usage of the word “graph” asa way to plot data, and in particular a plot of some function 𝑓(đ‘„) as afunction of đ‘„. One way to relate these two notions is to identify everyfunction 𝑓 ∶ 𝐮 → đ” with the directed graph đș𝑓 over the vertex set𝑉 = 𝐮 âˆȘ đ” such that đș𝑓 contains the edge đ‘„ → 𝑓(đ‘„) for every đ‘„ ∈ 𝐮. Ina graph đș𝑓 constructed in this way, every vertex in 𝐮 has out-degreeequal to one. If the function 𝑓 is one to one then every vertex in đ” hasin-degree at most one. If the function 𝑓 is onto then every vertex in đ”has in-degree at least one. If 𝑓 is a bijection then every vertex in đ” hasin-degree exactly equal to one.

Carl Pomerance’s quote is taken from the home page of DoronZeilberger.

Page 83: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Figure 2.1: Our basic notion of computation is someprocess that maps an input to an output

2Computation and Representation

“The alphabet (sic) was a great invention, which enabled men (sic) to storeand to learn with little effort what others had learned the hard way – that is, tolearn from books rather than from direct, possibly painful, contact with the realworld.”, B.F. Skinner

“The name of the song is called ‘HADDOCK’S EYES.”’ [said the Knight]“Oh, that’s the name of the song, is it?” Alice said, trying to feel interested.“No, you don’t understand,” the Knight said, looking a little vexed. “That’swhat the name is CALLED. The name really is ‘THE AGED AGEDMAN.”’“Then I ought to have said ‘That’s what the SONG is called’?” Alice cor-rected herself.“No, you oughtn’t: that’s quite another thing! The SONG is called ‘WAYSANDMEANS’: but that’s only what it’s CALLED, you know!”“Well, what IS the song, then?” said Alice, who was by this time com-pletely bewildered.“I was coming to that,” the Knight said. “The song really IS ‘A-SITTING ONA GATE’: and the tune’s my own invention.”Lewis Carroll, Through the Looking-Glass

To a first approximation, computation is a process that maps an inputto an output.

When discussing computation, it is essential to separate the ques-tion of what is the task we need to perform (i.e., the specification) fromthe question of how we achieve this task (i.e., the implementation).For example, as we’ve seen, there is more than one way to achieve thecomputational task of computing the product of two integers.

In this chapter we focus on the what part, namely defining compu-tational tasks. For starters, we need to define the inputs and outputs.Capturing all the potential inputs and outputs that we might everwant to compute on seems challenging, since computation today isapplied to a wide variety of objects. We do not compute merely onnumbers, but also on texts, images, videos, connection graphs of social

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Distinguish between specification and

implementation, or equivalently betweenmathematical functions andalgorithms/programs.

‱ Representing an object as a string (often ofzeroes and ones).

‱ Examples of representations for commonobjects such as numbers, vectors, lists, graphs.

‱ Prefix-free representations.‱ Cantor’s Theorem: The real numbers cannot

be represented exactly as finite strings.

Page 84: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

84 introduction to theoretical computer science

Figure 2.2: We represent numbers, texts, images, net-works and many other objects using strings of zeroesand ones. Writing the zeroes and ones themselves ingreen font over a black background is optional.

networks, MRI scans, gene data, and even other programs. We willrepresent all these objects as strings of zeroes and ones, that is objectssuch as 0011101 or 1011 or any other finite list of 1’s and 0’s. (Thischoice is for convenience: there is nothing “holy” about zeroes andones, and we could have used any other finite collection of symbols.)

Today, we are so used to the notion of digital representation thatwe are not surprised by the existence of such an encoding. But it isactually a deep insight with significant implications. Many animalscan convey a particular fear or desire, but what is unique about hu-mans is language: we use a finite collection of basic symbols to describea potentially unlimited range of experiences. Language allows trans-mission of information over both time and space and enables soci-eties that span a great many people and accumulate a body of sharedknowledge over time.

Over the last several decades, we have seen a revolution in what wecan represent and convey in digital form. We can capture experienceswith almost perfect fidelity, and disseminate it essentially instanta-neously to an unlimited audience. Moreover, once information is indigital form, we can compute over it, and gain insights from data thatwere not accessible in prior times. At the heart of this revolution is thesimple but profound observation that we can represent an unboundedvariety of objects using a finite set of symbols (and in fact using onlythe two symbols 0 and 1).

In later chapters, we will typically take such representations forgranted, and hence use expressions such as “program 𝑃 takes đ‘„ asinput” when đ‘„ might be a number, a vector, a graph, or any otherobject, when we really mean that 𝑃 takes as input the representation ofđ‘„ as a binary string. However, in this chapter we will dwell a bit moreon how we can construct such representations.

This chapter: A non-mathy overviewThe main takeaways from this chapter are:

‱ We can represent all kinds of objects we want to use as in-puts and outputs using binary strings. For example, we canuse the binary basis to represent integers and rational num-bers as binary strings (see Section 2.1.1 and Section 2.2).

‱ We can use compose the representations of simple objectsto represent more complex objects. In this way, we canrepresent lists of integers or rational numbers, and usethat to represent objects such as matrices, images, andgraphs. Prefix-free encoding is one way to achieve such acomposition (see Section 2.5.2).

Page 85: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 85

‱ A computational task specifies a map between an input to anoutput— a function. It is crucially important to distinguishbetween the “what” and the “how”, or the specificationand implementation (see Section 2.6.1). A function simplydefines which output corresponds to which input. It doesnot specify how to compute the output from the input, andas we’ve seen in the context of multiplication, there can bemore than one way to compute the same function.

‱ While the set of all possible binary strings is infinite, itstill cannot represent everything. In particular, there is norepresentation of the real numbers (with absolute accuracy)as binary strings. This result is also known as “Cantor’sTheorem” (see Section 2.4) and is typically referred to asthe result that the “reals are uncountable”. It is also im-plies that there are different levels of infinity though we willnot get into this topic in this book (see Remark 2.10).

The two “big ideas’ ’ we discuss are Big Idea 1 - we can com-pose representations for simple objects to represent morecomplex objects and Big Idea 2 - it is crucial to distinguishbetween functions (“what”) and programs (“how”). The latterwill be a theme we will come back to time and again in thisbook.

2.1 DEFINING REPRESENTATIONS

Every time we store numbers, images, sounds, databases, or other ob-jects on a computer, what we actually store in the computer’s memoryis the representation of these objects. Moreover, the idea of representa-tion is not restricted to digital computers. When we write down text ormake a drawing we are representing ideas or experiences as sequencesof symbols (which might as well be strings of zeroes and ones). Evenour brain does not store the actual sensory inputs we experience, butrather only a representation of them.

To use objects such as numbers, images, graphs, or others as inputsfor computation, we need to define precisely how to represent theseobjects as binary strings. A representation scheme is a way to map an ob-ject đ‘„ to a binary string 𝐾(đ‘„) ∈ 0, 1∗. For example, a representationscheme for natural numbers is a function 𝐾 ∶ ℕ → 0, 1∗. Of course,we cannot merely represent all numbers as the string “0011” (for ex-ample). A minimal requirement is that if two numbers đ‘„ and đ‘„â€Č aredifferent then they would be represented by different strings. Anotherway to say this is that we require the encoding function 𝐾 to be one toone.

Page 86: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

86 introduction to theoretical computer science

Figure 2.3: Representing each one the digits0, 1, 2, 
 , 9 as a 12 × 8 bitmap image, which can bethought of as a string in 0, 196. Using this schemewe can represent a natural number đ‘„ of 𝑛 decimaldigits as a string in 0, 196𝑛. Image taken from blogpost of A. C. Andersen.

2.1.1 Representing natural numbersWe now show how we can represent natural numbers as binarystrings. Over the years people have represented numbers in a varietyof ways, including Roman numerals, tally marks, our own Hindu-Arabic decimal system, and many others. We can use any one ofthose as well as many others to represent a number as a string (seeFig. 2.3). However, for the sake of concreteness, we use the binarybasis as our default representation of natural numbers as strings.For example, we represent the number six as the string 110 since1 ⋅ 22 + 1 ⋅ 21 + 0 ⋅ 20 = 6, and similarly we represent the number thirty-five as the string 𝑩 = 100011 which satisfies ∑5𝑖=0 𝑩𝑖 ⋅ 2|𝑩|−𝑖−1 = 35.Some more examples are given in the table below.

Table 2.1: Representing numbers in the binary basis. The lefthandcolumn contains representations of natural numbers in the deci-mal basis, while the righthand column contains representationsof the same numbers in the binary basis.

Number (decimal representation) Number (binary representation)0 01 12 105 10116 1000040 10100053 110101389 1100001013750 111010100110

If 𝑛 is even, then the least significant digit of 𝑛’s binary representa-tion is 0, while if 𝑛 is odd then this digit equals 1. Just like the number⌊𝑛/10⌋ corresponds to “chopping off” the least significant decimaldigit (e.g., ⌊457/10⌋ = ⌊45.7⌋ = 45), the number ⌊𝑛/2⌋ correspondsto the “chopping off” the least significant binary digit. Hence the bi-nary representation can be formally defined as the following function𝑁𝑡𝑆 ∶ ℕ → 0, 1∗ (𝑁𝑡𝑆 stands for “natural numbers to strings”):

𝑁𝑡𝑆(𝑛) = ⎧⎚⎩0 𝑛 = 01 𝑛 = 1𝑁𝑡𝑆(⌊𝑛/2⌋)𝑝𝑎𝑟𝑖𝑡𝑩(𝑛) 𝑛 > 1 (2.1)

where 𝑝𝑎𝑟𝑖𝑡𝑩 ∶ ℕ → 0, 1 is the function defined as 𝑝𝑎𝑟𝑖𝑡𝑩(𝑛) = 0if 𝑛 is even and 𝑝𝑎𝑟𝑖𝑡𝑩(𝑛) = 1 if 𝑛 is odd, and as usual, for stringsđ‘„, 𝑩 ∈ 0, 1∗, đ‘„đ‘Š denotes the concatenation of đ‘„ and 𝑩. The function

Page 87: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 87

𝑁𝑡𝑆 is defined recursively: for every 𝑛 > 0 we define 𝑟𝑒𝑝(𝑛) in termsof the representation of the smaller number ⌊𝑛/2⌋. It is also possible todefine 𝑁𝑡𝑆 non-recursively, see Exercise 2.2.

Throughout most of this book, the particular choices of represen-tation of numbers as binary strings would not matter much: we justneed to know that such a representation exists. In fact, for many of ourpurposes we can even use the simpler representation of mapping anatural number 𝑛 to the length-𝑛 all-zero string 0𝑛.

RRemark 2.1 — Binary representation in python (optional).We can implement the binary representation in Pythonas follows:

def NtS(n):# natural numbers to stringsif n > 1:

return NtS(n // 2) + str(n % 2)else:

return str(n % 2)

print(NtS(236))# 11101100

print(NtS(19))# 10011

We can also use Python to implement the inversetransformation, mapping a string back to the naturalnumber it represents.

def StN(x):# String to numberk = len(x)-1return sum(int(x[i])*(2**(k-i)) for i in

range(k+1))print(StN(NtS(236)))# 236

RRemark 2.2 — Programming examples. In this book,we sometimes use code examples as in Remark 2.1.The point is always to emphasize that certain com-putations can be achieved concretely, rather thanillustrating the features of Python or any other pro-gramming language. Indeed, one of the messages ofthis book is that all programming languages are ina certain precise sense equivalent to one another, andhence we could have just as well used JavaScript, C,COBOL, Visual Basic or even BrainF*ck. This bookis not about programming, and it is absolutely OK if

Page 88: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

88 introduction to theoretical computer science

1 While the Babylonians already invented a positionalsystem much earlier, the decimal positional systemwe use today was invented by Indian mathematiciansaround the third century. Arab mathematicians tookit up in the 8th century. It first received significantattention in Europe with the publication of the 1202book “Liber Abaci” by Leonardo of Pisa, also known asFibonacci, but it did not displace Roman numerals incommon usage until the 15th century.

you are not familiar with Python or do not follow codeexamples such as those in Remark 2.1.

2.1.2 Meaning of representations (discussion)It is natural for us to think of 236 as the “actual” number, and of11101100 as “merely” its representation. However, for most Euro-peans in the middle ages CCXXXVI would be the “actual” number and236 (if they have even heard about it) would be the weird Hindu-Arabic positional representation.1 When our AI robot overlords ma-terialize, they will probably think of 11101100 as the “actual” numberand of 236 as “merely” a representation that they need to use whenthey give commands to humans.

So what is the “actual” number? This is a question that philoso-phers of mathematics have pondered over throughout history. Platoargued that mathematical objects exist in some ideal sphere of exis-tence (that to a certain extent is more “real” than the world we per-ceive via our senses, as this latter world is merely the shadow of thisideal sphere). In Plato’s vision, the symbols 236 are merely notationfor some ideal object, that, in homage to the late musician, we canrefer to as “the number commonly represented by 236”.

The Austrian philosopher Ludwig Wittgenstein, on the other hand,argued that mathematical objects do not exist at all, and the onlythings that exist are the actual marks on paper that make up 236,11101100 or CCXXXVI. In Wittgenstein’s view, mathematics is merelyabout formal manipulation of symbols that do not have any inherentmeaning. You can think of the “actual” number as (somewhat recur-sively) “that thing which is common to 236, 11101100 and CCXXXVIand all other past and future representations that are meant to capturethe same object”.

While reading this book, you are free to choose your own phi-losophy of mathematics, as long as you maintain the distinction be-tween the mathematical objects themselves and the various particularchoices of representing them, whether as splotches of ink, pixels on ascreen, zeroes and one, or any other form.

2.2 REPRESENTATIONS BEYOND NATURAL NUMBERS

We have seen that natural numbers can be represented as binarystrings. We now show that the same is true for other types of objects,including (potentially negative) integers, rational numbers, vectors,lists, graphs and many others. In many instances, choosing the “right”string representation for a piece of data is highly nontrivial, and find-ing the “best” one (e.g., most compact, best fidelity, most efficientlymanipulable, robust to errors, most informative features, etc.) is the

Page 89: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 89

object of intense research. But for now, we focus on presenting somesimple representations for various objects that we would like to use asinputs and outputs for computation.

2.2.1 Representing (potentially negative) integersSince we can represent natural numbers as strings, we canrepresent the full set of integers (i.e., members of the setâ„€ = 
 , −3, −2, −1, 0, +1, +2, +3, 
 ) by adding one more bitthat represents the sign. To represent a (potentially negative) number𝑚, we prepend to the representation of the natural number |𝑚| a bit 𝜎that equals 0 if 𝑚 ≄ 0 and equals 1 if 𝑚 < 0. Formally, we define thefunction 𝑍𝑡𝑆 ∶ â„€ → 0, 1∗ as follows𝑍𝑡𝑆(𝑚) = ⎧⎚⎩0 𝑁𝑡𝑆(𝑚) 𝑚 ≄ 01 𝑁𝑡𝑆(−𝑚) 𝑚 < 0 (2.2)

where 𝑁𝑡𝑆 is defined as in (2.1).While the encoding function of a representation needs to be one

to one, it does not have to be onto. For example, in the representationabove there is no number that is represented by the empty stringbut it is still a fine representation, since every integer is representeduniquely by some string.

RRemark 2.3 — Interpretation and context. Given a string𝑩 ∈ 0, 1∗, how do we know if it’s “supposed” torepresent a (nonnegative) natural number or a (po-tentially negative) integer? For that matter, even ifwe know 𝑩 is “supposed” to be an integer, how dowe know what representation scheme it uses? Theshort answer is that we do not necessarily know thisinformation, unless it is supplied from the context. (Inprogramming languages, the compiler or interpreterdetermines the representation of the sequence of bitscorresponding to a variable based on the variable’stype.) We can treat the same string 𝑩 as representing anatural number, an integer, a piece of text, an image,or a green gremlin. Whenever we say a sentence suchas “let 𝑛 be the number represented by the string 𝑩,”we will assume that we are fixing some canonical rep-resentation scheme such as the ones above. The choiceof the particular representation scheme will rarelymatter, except that we want to make sure to stick withthe same one for consistency.

2.2.2 Two’s complement representation (optional)Section 2.2.1’s approach of representing an integer using a specific“sign bit” is known as the Signed Magnitude Representation and was

Page 90: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

90 introduction to theoretical computer science

Figure 2.4: In the two’s complement representationwe represent a potentially negative integer 𝑘 ∈−2𝑛, 
 , 2𝑛 − 1 as an 𝑛 + 1 length string using thebinary representation of the integer 𝑘 mod 2𝑛+1. Onthe lefthand side: this representation for 𝑛 = 3 (thered integers are the numbers being represented bythe blue binary strings). If a microprocessor does notcheck for overflows, adding the two positive numbers6 and 5 might result in the negative number −5 (since−5 mod 16 = 11. The righthand side is a C programthat will on some 32 bit architecture print a negativenumber after adding two positive numbers. (Integeroverflow in C is considered undefined behavior whichmeans the result of this program, including whetherit runs or crashes, could differ depending on thearchitecture, compiler, and even compiler options andversion.)

used in some early computers. However, the two’s complement rep-resentation is much more common in practice. The two’s complementrepresentation of an integer 𝑘 in the set −2𝑛, −2𝑛 + 1, 
 , 2𝑛 − 1 is thestring 𝑍𝑡𝑆𝑛(𝑘) of length 𝑛 + 1 defined as follows:𝑍𝑡𝑆𝑛(𝑘) = âŽ§âŽšâŽ©đ‘đ‘Ąđ‘†đ‘›+1(𝑘) 0 ≀ 𝑘 ≀ 2𝑛 − 1𝑁𝑡𝑆𝑛+1(2𝑛+1 + 𝑘) −2𝑛 ≀ 𝑘 ≀ −1 , (2.3)

where 𝑁𝑡𝑆ℓ(𝑚) demotes the standard binary representation of a num-ber 𝑚 ∈ 0, 
 , 2ℓ as string of length ℓ, padded with leading zerosas needed. For example, if 𝑛 = 3 then 𝑍𝑡𝑆3(1) = 𝑁𝑡𝑆4(1) = 0001,𝑍𝑡𝑆3(2) = 𝑁𝑡𝑆4(2) = 0010, 𝑍𝑡𝑆3(−1) = 𝑁𝑡𝑆4(16 − 1) = 1111, and𝑍𝑡𝑆3(−8) = 𝑁𝑡𝑆4(16 − 8) = 1000. If 𝑘 is a negative number larger thanor equal to −2𝑛 then 2𝑛+1 + 𝑘 is a number between 2𝑛 and 2𝑛+1 − 1.Hence the two’s complement representation of such a number 𝑘 is astring of length 𝑛 + 1 with its first digit equal to 1.

Another way to say this is that we represent a potentially negativenumber 𝑘 ∈ −2𝑛, 
 , 2𝑛 −1 as the non-negative number 𝑘 mod 2𝑛+1(see also Fig. 2.4). This means that if two (potentially negative) num-bers 𝑘 and 𝑘â€Č are not too large (i.e., |𝑘| + |𝑘â€Č| < 2𝑛+1), then we cancompute the representation of 𝑘 + 𝑘â€Č by adding modulo 2𝑛+1 the rep-resentations of 𝑘 and 𝑘â€Č as if they were non-negative integers. Thisproperty of the two’s complement representation is its main attractionsince, depending on their architectures, microprocessors can oftenperform arithmetic operations modulo 2đ‘€ very efficiently (for certainvalues of đ‘€ such as 32 and 64). Many systems leave it to the pro-grammer to check that values are not too large and will carry out thismodular arithmetic regardless of the size of the numbers involved. Forthis reason, in some systems adding two large positive numbers canresult in a negative number (e.g., adding 2𝑛 − 100 and 2𝑛 − 200 mightresult in −300 since (2𝑛+1 − 300) mod 2𝑛+1 = −300, see also Fig. 2.4).

2.2.3 Rational numbers, and representing pairs of stringsWe can represent a rational number of the form 𝑎/𝑏 by represent-ing the two numbers 𝑎 and 𝑏. However, merely concatenating therepresentations of 𝑎 and 𝑏 will not work. For example, the binary rep-resentation of 4 is 100 and the binary representation of 43 is 101011,but the concatenation 100101011 of these strings is also the concatena-tion of the representation 10010 of 18 and the representation 1011 of11. Hence, if we used such simple concatenation then we would notbe able to tell if the string 100101011 is supposed to represent 4/43 or18/11.

We tackle this by giving a general representation for pairs of strings.If we were using a pen and paper, we would just use a separator sym-bol such as ‖ to represent, for example, the pair consisting of the num-

Page 91: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 91

bers represented by 10 and 110001 as the length-9 string “01‖110001”.In other words, there is a one to one map đč from pairs of stringsđ‘„, 𝑩 ∈ 0, 1∗ into a single string 𝑧 over the alphabet ÎŁ = 0, 1, ‖(in other words, 𝑧 ∈ Σ∗). Using such separators is similar to theway we use spaces and punctuation to separate words in English. Byadding a little redundancy, we achieve the same effect in the digitaldomain. We can map the three-element set ÎŁ to the three-element set00, 11, 01 ⊂ 0, 12 in a one-to-one fashion, and hence encode alength 𝑛 string 𝑧 ∈ Σ∗ as a length 2𝑛 string đ‘€ ∈ 0, 1∗.

Our final representation for rational numbers is obtained by com-posing the following steps:1. Representing a non-negative rational number as a pair of natural

numbers.2. Representing a natural number by a string via the binary represen-

tation.3. Combining 1 and 2 to obtain a representation of a rational number

as a pair of strings.4. Representing a pair of strings over 0, 1 as a single string overΣ = 0, 1, ‖.5. Representing a string over Σ as a longer string over 0, 1.

Example 2.4 — Representing a rational number as a string. Consider therational number 𝑟 = −5/8. We represent −5 as 1101 and +8 as01000, and so we can represent 𝑟 as the pair of strings (1101, 01000)and represent this pair as the length 10 string 1101‖01000 overthe alphabet 0, 1, ‖. Now, applying the map 0 ↩ 00, 1 ↩ 11,‖ ↩ 01, we can represent the latter string as the length 20 string𝑠 = 11110011010011000000 over the alphabet 0, 1.The same idea can be used to represent triples of strings, quadru-

ples, and so on as a string. Indeed, this is one instance of a very gen-eral principle that we use time and again in both the theory and prac-tice of computer science (for example, in Object Oriented program-ming):

Big Idea 1 If we can represent objects of type 𝑇 as strings, then wecan represent tuples of objects of type 𝑇 as strings as well.

Repeating the same idea, once we can represent objects of type 𝑇 ,we can also represent lists of lists of such objects, and even lists of listsof lists and so on and so forth. We will come back to this point whenwe discuss prefix free encoding in Section 2.5.2.

Page 92: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

92 introduction to theoretical computer science

Figure 2.6: XKCD cartoon on floating-point arithmetic.

2.3 REPRESENTING REAL NUMBERS

The set of real numbers ℝ contains all numbers including positive,negative, and fractional, as well as irrational numbers such as 𝜋 or 𝑒.Every real number can be approximated by a rational number, andthus we can represent every real number đ‘„ by a rational number 𝑎/𝑏that is very close to đ‘„. For example, we can represent 𝜋 by 22/7 withinan error of about 10−3. If we want a smaller error (e.g., about 10−4)then we can use 311/99, and so on and so forth.

Figure 2.5: The floating point representation of a realnumber đ‘„ ∈ ℝ is its approximation as a number ofthe form 𝜎𝑏 ⋅ 2𝑒 where 𝜎 ∈ ±1, 𝑒 is an (potentiallynegative) integer, and 𝑏 is a rational number between1 and 2 expressed as a binary fraction 1.𝑏0𝑏1𝑏2 
 𝑏𝑘for some 𝑏1, 
 , 𝑏𝑘 ∈ 0, 1 (that is 𝑏 = 1 + 𝑏1/2 +𝑏2/4 + 
 + 𝑏𝑘/2𝑘). Commonly-used floating pointrepresentations fix the numbers ℓ and 𝑘 of bits torepresent 𝑒 and 𝑏 respectively. In the example above,assuming we use two’s complement representationfor 𝑒, the number represented is −1 × 25 × (1 + 1/2 +1/4 + 1/64 + 1/512) = −56.5625.The above representation of real numbers via rational numbers

that approximate them is a fine choice for a representation scheme.However, typically in computing applications, it is more common touse the floating point representation scheme (see Fig. 2.5) to representreal numbers. In the floating point representation scheme we rep-resent đ‘„ ∈ ℝ by the pair (𝑏, 𝑒) of (positive or negative) integers ofsome prescribed sizes (determined by the desired accuracy) such that𝑏 × 2𝑒 is closest to đ‘„. Floating point representation is the base-twoversion of scientific notation, where one represents a number 𝑩 ∈ 𝑅as its approximation of the form 𝑏 × 10𝑒 for 𝑏, 𝑒. It is called “floatingpoint” because we can think of the number 𝑏 as specifying a sequenceof binary digits, and 𝑒 as describing the location of the “binary point”within this sequence. The use of floating representation is the reasonwhy in many programming systems, printing the expression 0.1+0.2will result in 0.30000000000000004 and not 0.3, see here, here andhere for more.

The reader might be (rightly) worried about the fact that the float-ing point representation (or the rational number one) can only ap-proximately represent real numbers. In many (though not all) com-putational applications, one can make the accuracy tight enough sothat this does not affect the final result, though sometimes we do needto be careful. Indeed, floating-point bugs can sometimes be no jok-ing matter. For example, floating point rounding errors have beenimplicated in the failure of a U.S. Patriot missile to intercept an IraqiScud missile, costing 28 lives, as well as a 100 million pound error incomputing payouts to British pensioners.

Page 93: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 93

2 𝑅𝑡𝑆 stands for “real numbers to strings”.

2.4 CANTOR’S THEOREM, COUNTABLE SETS, AND STRING REP-RESENTATIONS OF THE REAL NUMBERS

“For any collection of fruits, we can make more fruit salads than there arefruits. If not, we could label each salad with a different fruit, and consider thesalad of all fruits not in their salad. The label of this salad is in it if and only ifit is not.”, Martha Storey.

Given the issues with floating point approximations for real num-bers, a natural question is whether it is possible to represent real num-bers exactly as strings. Unfortunately, the following theorem showsthat this cannot be done:

Theorem 2.5 — Cantor’s Theorem. There does not exist a one-to-onefunction 𝑅𝑡𝑆 ∶ ℝ → 0, 1∗. 2

Countable sets. We say that a set 𝑆 is countable if there is an ontomap đ¶ ∶ ℕ → 𝑆, or in other words, we can write 𝑆 as the sequenceđ¶(0), đ¶(1), đ¶(2), 
. Since the binary representation yields an ontomap from 0, 1∗ to ℕ, and the composition of two onto maps is onto,a set 𝑆 is countable iff there is an onto map from 0, 1∗ to 𝑆. Usingthe basic properties of functions (see Section 1.4.3), a set is countableif and only if there is a one-to-one function from 𝑆 to 0, 1∗. Hence,we can rephrase Theorem 2.5 as follows:

Theorem 2.6 — Cantor’s Theorem (equivalent statement). The reals are un-countable. That is, there does not exist an onto function 𝑁𝑡𝑅 ∶ ℕ →ℝ.

Theorem 2.6 was proven by Georg Cantor in 1874. This result (andthe theory around it) was quite shocking to mathematicians at thetime. By showing that there is no one-to-one map from ℝ to 0, 1∗ (orℕ), Cantor showed that these two infinite sets have “different forms ofinfinity” and that the set of real numbers ℝ is in some sense “bigger”than the infinite set 0, 1∗. The notion that there are “shades of infin-ity” was deeply disturbing to mathematicians and philosophers at thetime. The philosopher Ludwig Wittgenstein (whom we mentioned be-fore) called Cantor’s results “utter nonsense” and “laughable.” Othersthought they were even worse than that. Leopold Kronecker calledCantor a “corrupter of youth,” while Henri PoincarĂ© said that Can-tor’s ideas “should be banished from mathematics once and for all.”The tide eventually turned, and these days Cantor’s work is univer-sally accepted as the cornerstone of set theory and the foundations ofmathematics. As David Hilbert said in 1925, “No one shall expel us fromthe paradise which Cantor has created for us.” As we will see later in this

Page 94: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

94 introduction to theoretical computer science

3 đč𝑡𝑆 stands for “functions to strings”.4 đč𝑡𝑅 stands for “functions to reals.”

book, Cantor’s ideas also play a huge role in the theory of computa-tion.

Now that we have discussed Theorem 2.5’s importance, let us seethe proof. It is achieved in two steps:

1. Define some infinite set 𝒳 for which it is easier for us to prove that𝒳 is not countable (namely, it’s easier for us to prove that there isno one-to-one function from 𝒳 to 0, 1∗).

2. Prove that there is a one-to-one function đș mapping 𝒳 to ℝ.

We can use a proof by contradiction to show that these two factstogether imply Theorem 2.5. Specifically, if we assume (towards thesake of contradiction) that there exists some one-to-one đč mapping ℝto 0, 1∗ then the function đ‘„ ↩ đč(đș(đ‘„)) obtained by composing đčwith the function đș from Step 2 above would be a one-to-one functionfrom 𝒳 to 0, 1∗, which contradicts what we proved in Step 1!

To turn this idea into a full proof of Theorem 2.5 we need to:

‱ Define the set 𝒳.

‱ Prove that there is no one-to-one function from 𝒳 to 0, 1∗‱ Prove that there is a one-to-one function from 𝒳 to ℝ.

We now proceed to do precisely that. That is, we will define the set0, 1∞, which will play the role of 𝒳, and then state and prove twolemmas that show that this set satisfies our two desired properties.

Definition 2.7 We denote by 0, 1∞ the set 𝑓 | 𝑓 ∶ ℕ → 0, 1.That is, 0, 1∞ is a set of functions, and a function 𝑓 is in 0, 1∞

iff its domain is ℕ and its codomain is 0, 1. We can also think of0, 1∞ as the set of all infinite sequences of bits, since a function 𝑓 ∶ℕ → 0, 1 can be identified with the sequence (𝑓(0), 𝑓(1), 𝑓(2), 
).The following two lemmas show that 0, 1∞ can play the role of 𝒳 toestablish Theorem 2.5.Lemma 2.8 There does not exist a one-to-one map đč𝑡𝑆 ∶ 0, 1∞ →0, 1∗.3Lemma 2.9 There does exist a one-to-one map đč𝑡𝑅 ∶ 0, 1∞ → ℝ.4

As we’ve seen above, Lemma 2.8 and Lemma 2.9 together implyTheorem 2.5. To repeat the argument more formally, suppose, forthe sake of contradiction, that there did exist a one-to-one function𝑅𝑡𝑆 ∶ ℝ → 0, 1∗. By Lemma 2.9, there exists a one-to-one functionđč𝑡𝑅 ∶ 0, 1∞ → ℝ. Thus, under this assumption, since the composi-tion of two one-to-one functions is one-to-one (see Exercise 2.12), the

Page 95: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 95

function đč𝑡𝑆 ∶ 0, 1∞ → 0, 1∗ defined as đč𝑡𝑆(𝑓) = 𝑅𝑡𝑆(đč𝑡𝑅(𝑓))will be one to one, contradicting Lemma 2.8. See Fig. 2.7 for a graphi-cal illustration of this argument.

Figure 2.7: We prove Theorem 2.5 by combiningLemma 2.8 and Lemma 2.9. Lemma 2.9, which usesstandard calculus tools, shows the existence of aone-to-one map đč𝑡𝑅 from the set 0, 1∞ to the realnumbers. So, if a hypothetical one-to-one map 𝑅𝑡𝑆 ∶ℝ → 0, 1∗ existed, then we could compose themto get a one-to-one map đč𝑡𝑆 ∶ 0, 1∞ → 0, 1∗.Yet this contradicts Lemma 2.8- the heart of the proof-which rules out the existence of such a map.

Now all that is left is to prove these two lemmas. We start by prov-ing Lemma 2.8 which is really the heart of Theorem 2.5.

Figure 2.8: We construct a function 𝑑 such that 𝑑 ≠𝑆𝑡đč(đ‘„) for every đ‘„ ∈ 0, 1∗ by ensuring that𝑑(𝑛(đ‘„)) ≠ 𝑆𝑡đč(đ‘„)(𝑛(đ‘„)) for every đ‘„ ∈ 0, 1∗with lexicographic order 𝑛(đ‘„). We can think of thisas building a table where the columns correspondto numbers 𝑚 ∈ ℕ and the rows correspond tođ‘„ ∈ 0, 1∗ (sorted according to 𝑛(đ‘„)). If the entryin the đ‘„-th row and the 𝑚-th column corresponds to𝑔(𝑚)) where 𝑔 = 𝑆𝑡đč(đ‘„) then 𝑑 is obtained by goingover the “diagonal” elements in this table (the entriescorresponding to the đ‘„-th row and 𝑛(đ‘„)-th column)and ensuring that 𝑑(đ‘„)(𝑛(đ‘„)) ≠ 𝑆𝑡đč(đ‘„)(đ‘„).

Warm-up: ”Baby Cantor”. The proof of Lemma 2.8 is rather subtle. Oneway to get intution for it is to consider the following finite statement”there is no onto function 𝑓 ∶ 0, 
 , 99 → 0, 1100. Of course weknow it’s true since the set 0, 1100 is bigger than the set [100], butlet’s see a direct proof. For every 𝑓 ∶ 0, 
 , 99 → 0, 1100, wecan define the string 𝑑 ∈ 0, 1100 as follows: 𝑑 = (1 − 𝑓(0)0, 1 −𝑓(1)1, 
 , 1 − 𝑓(99)99). If 𝑓 was onto, then there would exist some𝑛 ∈ [100] such that 𝑓(𝑛) = 𝑑(𝑛), but we claim that no such 𝑛 exists.

Page 96: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

96 introduction to theoretical computer science

Indeed, if there was such 𝑛, then the 𝑛-th coordinate of 𝑑 would equal𝑓(𝑛)𝑛 but by definition this coordinate equals 1 − 𝑓(𝑛)𝑛. See also a“proof by code” of this statement.

Proof of Lemma 2.8. We will prove that there does not exist an ontofunction 𝑆𝑡đč ∶ 0, 1∗ → 0, 1∞. This implies the lemma sincefor every two sets 𝐮 and đ”, there exists an onto function from 𝐮 tođ” if and only if there exists a one-to-one function from đ” to 𝐮 (seeLemma 1.2).

The technique of this proof is known as the “diagonal argument”and is illustrated in Fig. 2.8. We assume, towards a contradiction, thatthere exists such a function 𝑆𝑡đč ∶ 0, 1∗ → 0, 1∞. We will showthat 𝑆𝑡đč is not onto by demonstrating a function 𝑑 ∈ 0, 1∞ such that𝑑 ≠ 𝑆𝑡đč(đ‘„) for every đ‘„ ∈ 0, 1∗. Consider the lexicographic orderingof binary strings (i.e., "",0,1,00,01,
). For every 𝑛 ∈ ℕ, we let đ‘„đ‘› be the𝑛-th string in this order. That is đ‘„0 = "", đ‘„1 = 0, đ‘„2 = 1 and so on andso forth. We define the function 𝑑 ∈ 0, 1∞ as follows:𝑑(𝑛) = 1 − 𝑆𝑡đč(đ‘„đ‘›)(𝑛) (2.4)

for every 𝑛 ∈ ℕ. That is, to compute 𝑑 on input 𝑛 ∈ ℕ, we first com-pute 𝑔 = 𝑆𝑡đč(đ‘„đ‘›), where đ‘„đ‘› ∈ 0, 1∗ is the 𝑛-th string in the lexico-graphical ordering. Since 𝑔 ∈ 0, 1∞, it is a function mapping ℕ to0, 1. The value 𝑑(𝑛) is defined to be the negation of 𝑔(𝑛).

The definition of the function 𝑑 is a bit subtle. One way to thinkabout it is to imagine the function 𝑆𝑡đč as being specified by an in-finitely long table, in which every row corresponds to a string đ‘„ ∈0, 1∗ (with strings sorted in lexicographic order), and contains thesequence 𝑆𝑡đč(đ‘„)(0), 𝑆𝑡đč(đ‘„)(1), 𝑆𝑡đč(đ‘„)(2), 
. The diagonal elements inthis table are the values

𝑆𝑡đč("")(0), 𝑆𝑡đč(0)(1), 𝑆𝑡đč(1)(2), 𝑆𝑡đč(00)(3), 𝑆𝑡đč(01)(4), 
 (2.5)

which correspond to the elements 𝑆𝑡đč(đ‘„đ‘›)(𝑛) in the 𝑛-th row and𝑛-th column of this table for 𝑛 = 0, 1, 2, 
. The function 𝑑 we definedabove maps every 𝑛 ∈ ℕ to the negation of the 𝑛-th diagonal value.

To complete the proof that 𝑆𝑡đč is not onto we need to show that𝑑 ≠ 𝑆𝑡đč(đ‘„) for every đ‘„ ∈ 0, 1∗. Indeed, let đ‘„ ∈ 0, 1∗ be some stringand let 𝑔 = 𝑆𝑡đč(đ‘„). If 𝑛 is the position of đ‘„ in the lexicographicalorder then by construction 𝑑(𝑛) = 1 − 𝑔(𝑛) ≠ 𝑔(𝑛) which means that𝑔 ≠ 𝑑 which is what we wanted to prove.

Page 97: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 97

RRemark 2.10 — Generalizing beyond strings and reals.Lemma 2.8 doesn’t really have much to do with thenatural numbers or the strings. An examination ofthe proof shows that it really shows that for everyset 𝑆, there is no one-to-one map đč ∶ 0, 1𝑆 → 𝑆where 0, 1𝑆 denotes the set 𝑓 | 𝑓 ∶ 𝑆 → 0, 1of all Boolean functions with domain 𝑆. Since we canidentify a subset 𝑉 ⊆ 𝑆 with its characteristic function𝑓 = 1𝑉 (i.e., 1𝑉 (đ‘„) = 1 iff đ‘„ ∈ 𝑉 ), we can think of0, 1𝑆 also as the set of all subsets of 𝑆. This subsetis sometimes called the power set of 𝑆 and denoted byđ’«(𝑆) or 2𝑆 .The proof of Lemma 2.8 can be generalized to showthat there is no one-to-one map between a set and itspower set. In particular, it means that the set 0, 1ℝ is“even bigger” than ℝ. Cantor used these ideas to con-struct an infinite hierarchy of shades of infinity. Thenumber of such shades turns out to be much largerthan |ℕ| or even |ℝ|. He denoted the cardinality of ℕby â„”0 and denoted the next largest infinite numberby â„”1. (â„” is the first letter in the Hebrew alphabet.)Cantor also made the continuum hypothesis that|ℝ| = â„”1. We will come back to the fascinating storyof this hypothesis later on in this book. This lecture ofAaronson mentions some of these issues (see also thisBerkeley CS 70 lecture).

To complete the proof of Theorem 2.5, we need to show Lemma 2.9.This requires some calculus background but is otherwise straightfor-ward. If you have not had much experience with limits of a real seriesbefore, then the formal proof below might be a little hard to follow.This part is not the core of Cantor’s argument, nor are such limitsimportant to the remainder of this book, so you can feel free to takeLemma 2.9 on faith and skip the proof.

Proof Idea:

We define đč𝑡𝑅(𝑓) to be the number between 0 and 2 whose dec-imal expansion is 𝑓(0).𝑓(1)𝑓(2) 
, or in other words đč𝑡𝑅(𝑓) =∑∞𝑖=0 𝑓(𝑖) ⋅ 10−𝑖. If 𝑓 and 𝑔 are two distinct functions in 0, 1∞, thenthere must be some input 𝑘 in which they disagree. If we take theminimum such 𝑘, then the numbers 𝑓(0).𝑓(1)𝑓(2) 
 𝑓(𝑘 − 1)𝑓(𝑘) 
and 𝑔(0).𝑔(1)𝑔(2) 
 𝑔(𝑘) 
 agree with each other all the way up to the𝑘 − 1-th digit after the decimal point, and disagree on the 𝑘-th digit.But then these numbers must be distinct. Concretely, if 𝑓(𝑘) = 1 and𝑔(𝑘) = 0 then the first number is larger than the second, and otherwise(𝑓(𝑘) = 0 and 𝑔(𝑘) = 1) the first number is smaller than the second.In the proof we have to be a little careful since these are numbers withinfinite expansions. For example, the number one half has two decimal

Page 98: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

98 introduction to theoretical computer science

expansions 0.5 and 0.49999 ⋯. However, this issue does not come uphere, since we restrict attention only to numbers with decimal expan-sions that do not involve the digit 9.⋆Proof of Lemma 2.9. For every 𝑓 ∈ 0, 1∞, we define đč𝑡𝑅(𝑓) to be thenumber whose decimal expansion is 𝑓(0).𝑓(1)𝑓(2)𝑓(3) 
. Formally,đč𝑡𝑅(𝑓) = ∞∑𝑖=0 𝑓(𝑖) ⋅ 10−𝑖 (2.6)

It is a known result in calculus (whose proof we will not repeat here)that the series on the righthand side of (2.6) converges to a definitelimit in ℝ.

We now prove that đč𝑡𝑅 is one to one. Let 𝑓, 𝑔 be two distinct func-tions in 0, 1∞. Since 𝑓 and 𝑔 are distinct, there must be some inputon which they differ, and we define 𝑘 to be the smallest such inputand assume without loss of generality that 𝑓(𝑘) = 0 and 𝑔(𝑘) = 1.(Otherwise, if 𝑓(𝑘) = 1 and 𝑔(𝑘) = 0, then we can simply switch theroles of 𝑓 and 𝑔.) The numbers đč𝑡𝑅(𝑓) and đč𝑡𝑅(𝑔) agree with eachother up to the 𝑘−1-th digit up after the decimal point. Since this digitequals 0 for đč𝑡𝑅(𝑓) and equals 1 for đč𝑡𝑅(𝑔), we claim that đč𝑡𝑅(𝑔) isbigger than đč𝑡𝑅(𝑓) by at least 0.5 ⋅ 10−𝑘. To see this note that the dif-ference đč𝑡𝑅(𝑔) − đč𝑡𝑅(𝑓) will be minimized if 𝑔(ℓ) = 0 for every ℓ > 𝑘and 𝑓(ℓ) = 1 for every ℓ > 𝑘, in which case (since 𝑓 and 𝑔 agree up tothe 𝑘 − 1-th digit)

đč𝑡𝑅(𝑔) − đč𝑡𝑅(𝑓) = 10−𝑘 − 10−𝑘−1 − 10−𝑘−2 − 10−𝑘−3 − ⋯ (2.7)

Since the infinite series ∑∞𝑗=0 10−𝑖 converges to 10/9, it follows thatfor every such 𝑓 and 𝑔, đč𝑡𝑅(𝑔) − đč𝑡𝑅(𝑓) ≄ 10−𝑘 − 10−𝑘−1 ⋅ (10/9) > 0.In particular we see that for every distinct 𝑓, 𝑔 ∈ 0, 1∞, đč𝑡𝑅(𝑓) ≠đč𝑡𝑅(𝑔), implying that the function đč𝑡𝑅 is one to one.

RRemark 2.11 — Using decimal expansion (op-tional). In the proof above we used the fact that1 + 1/10 + 1/100 + ⋯ converges to 10/9, whichplugging into (2.7) yields that the difference betweenđč𝑡𝑅(𝑔) and đč𝑡𝑅(ℎ) is at least 10−𝑘−10−𝑘−1 ⋅(10/9) > 0.While the choice of the decimal representation for đč𝑡𝑅was arbitrary, we could not have used the binaryrepresentation in its place. Had we used the binaryexpansion instead of decimal, the corresponding se-quence 1 + 1/2 + 1/4 + ⋯ converges to 2/1 = 2,

Page 99: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 99

and since 2−𝑘 = 2−𝑘−1 ⋅ 2, we could not have de-duced that đč𝑡𝑅 is one to one. Indeed there do existpairs of distinct sequences 𝑓, 𝑔 ∈ 0, 1∞ such that∑∞𝑖=0 𝑓(𝑖)2−𝑖 = ∑∞𝑖=0 𝑔(𝑖)2−𝑖. (For example, the se-quence 1, 0, 0, 0, 
 and the sequence 0, 1, 1, 1, 
 havethis property.)

2.4.1 Corollary: Boolean functions are uncountableCantor’s Theorem yields the following corollary that we will useseveral times in this book: the set of all Boolean functions (mapping0, 1∗ to 0, 1) is not countable:

Theorem 2.12 — Boolean functions are uncountable. Let ALL be the set ofall functions đč ∶ 0, 1∗ → 0, 1. Then ALL is uncountable. Equiv-alently, there does not exist an onto map 𝑆𝑡𝐮𝐿𝐿 ∶ 0, 1∗ → ALL.

Proof Idea:

This is a direct consequence of Lemma 2.8, since we can use thebinary representation to show a one-to-one map from 0, 1∞ to ALL.Hence the uncountability of 0, 1∞ implies the uncountability ofALL.⋆Proof of Theorem 2.12. Since 0, 1∞ is uncountable, the result willfollow by showing a one-to-one map from 0, 1∞ to ALL. The reasonis that the existence of such a map implies that if ALL was countable,and hence there was a one-to-one map from ALL to ℕ, then therewould have been a one-to-one map from 0, 1∞ to ℕ, contradictingLemma 2.8.

We now show this one-to-one map. We simply map a function𝑓 ∈ 0, 1∞ to the function đč ∶ 0, 1∗ → 0, 1 as follows. We letđč(0) = 𝑓(0), đč(1) = 𝑓(1), đč(10) = đč(2), đč(11) = đč(3) and so on andso forth. That is, for every đ‘„ ∈ 0, 1∗ that represents a natural number𝑛 in the binary basis, we define đč(đ‘„) = 𝑓(𝑛). If đ‘„ does not representsuch a number (e.g., it has a leading zero), then we set đč(đ‘„) = 0.

This map is one-to-one since if 𝑓 ≠ 𝑔 are two distinct elements in0, 1∞, then there must be some input 𝑛 ∈ ℕ on which 𝑓(𝑛) ≠ 𝑔(𝑛).But then if đ‘„ ∈ 0, 1∗ is the string representing 𝑛, we see that đč(đ‘„) ≠đș(đ‘„) where đč is the function in ALL that 𝑓 mapped to, and đș is thefunction that 𝑔 is mapped to.

Page 100: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

100 introduction to theoretical computer science

2.4.2 Equivalent conditions for countabilityThe results above establish many equivalent ways to phrase the factthat a set is countable. Specifically, the following statements are allequivalent:

1. The set 𝑆 is countable

2. There exists an onto map from ℕ to 𝑆3. There exists an onto map from 0, 1∗ to 𝑆.

4. There exists a one-to-one map from 𝑆 to ℕ5. There exists a one-to-one map from 𝑆 to 0, 1∗.6. There exists an onto map from some countable set 𝑇 to 𝑆.

7. There exists a one-to-one map from 𝑆 to some countable set 𝑇 .

PMake sure you know how to prove the equivalence ofall the results above.

2.5 REPRESENTING OBJECTS BEYOND NUMBERS

Numbers are of course by no means the only objects that we can repre-sent as binary strings. A representation scheme for representing objectsfrom some set đ’Ș consists of an encoding function that maps an object inđ’Ș to a string, and a decoding function that decodes a string back to anobject in đ’Ș. Formally, we make the following definition:

Definition 2.13 — String representation. Let đ’Ș be any set. A representationscheme for đ’Ș is a pair of functions 𝐾, đ· where 𝐾 ∶ đ’Ș → 0, 1∗ is atotal one-to-one function, đ· ∶ 0, 1∗ →𝑝 đ’Ș is a (possibly partial)function, and such that đ· and 𝐾 satisfy that đ·(𝐾(𝑜)) = 𝑜 for every𝑜 ∈ đ’Ș. 𝐾 is known as the encoding function and đ· is known as thedecoding function.

Note that the condition đ·(𝐾(𝑜)) = 𝑜 for every 𝑜 ∈ đ’Ș impliesthat đ· is onto (can you see why?). It turns out that to construct arepresentation scheme we only need to find an encoding function. Thatis, every one-to-one encoding function has a corresponding decodingfunction, as shown in the following lemma:Lemma 2.14 Suppose that 𝐾 ∶ đ’Ș → 0, 1∗ is one-to-one. Then thereexists a function đ· ∶ 0, 1∗ → đ’Ș such that đ·(𝐾(𝑜)) = 𝑜 for every𝑜 ∈ đ’Ș.

Page 101: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 101

Proof. Let 𝑜0 be some arbitrary element of đ’Ș. For every đ‘„ ∈ 0, 1∗,there exists either zero or a single 𝑜 ∈ đ’Ș such that 𝐾(𝑜) = đ‘„ (otherwise𝐾 would not be one-to-one). We will define đ·(đ‘„) to equal 𝑜0 in thefirst case and this single object 𝑜 in the second case. By definitionđ·(𝐾(𝑜)) = 𝑜 for every 𝑜 ∈ đ’Ș.

RRemark 2.15 — Total decoding functions. While thedecoding function of a representation scheme can ingeneral be a partial function, the proof of Lemma 2.14implies that every representation scheme has a totaldecoding function. This observation can sometimes beuseful.

2.5.1 Finite representationsIf đ’Ș is finite, then we can represent every object in đ’Ș as a string oflength at most some number 𝑛. What is the value of 𝑛? Let us denoteby 0, 1â‰€đ‘› the set đ‘„ ∈ 0, 1∗ ∶ |đ‘„| ≀ 𝑛 of strings of length at most 𝑛.The size of 0, 1â‰€đ‘› is equal to|0, 10| + |0, 11| + |0, 12| + ⋯ + |0, 1𝑛| = 𝑛∑𝑖=0 2𝑖 = 2𝑛+1 − 1 (2.8)

using the standard formula for summing a geometric progression.To obtain a representation of objects in đ’Ș as strings of length at

most 𝑛 we need to come up with a one-to-one function from đ’Ș to0, 1â‰€đ‘›. We can do so, if and only if |đ’Ș| ≀ 2𝑛+1 − 1 as is implied bythe following lemma:Lemma 2.16 For every two finite sets 𝑆, 𝑇 , there exists a one-to-one𝐾 ∶ 𝑆 → 𝑇 if and only if |𝑆| ≀ |𝑇 |.Proof. Let 𝑘 = |𝑆| and 𝑚 = |𝑇 | and so write the elements of 𝑆 and𝑇 as 𝑆 = 𝑠0, 𝑠1, 
 , 𝑠𝑘−1 and 𝑇 = 𝑡0, 𝑡1, 
 , 𝑡𝑚−1. We need toshow that there is a one-to-one function 𝐾 ∶ 𝑆 → 𝑇 iff 𝑘 ≀ 𝑚. Forthe “if” direction, if 𝑘 ≀ 𝑚 we can simply define 𝐾(𝑠𝑖) = 𝑡𝑖 for every𝑖 ∈ [𝑘]. Clearly for 𝑖 ≠ 𝑗, 𝑡𝑖 = 𝐾(𝑠𝑖) ≠ 𝐾(𝑠𝑗) = 𝑡𝑗, and hence thisfunction is one-to-one. In the other direction, suppose that 𝑘 > 𝑚 and𝐾 ∶ 𝑆 → 𝑇 is some function. Then 𝐾 cannot be one-to-one. Indeed, for𝑖 = 0, 1, 
 , 𝑚 − 1 let us “mark” the element 𝑡𝑗 = 𝐾(𝑠𝑖) in 𝑇 . If 𝑡𝑗 wasmarked before, then we have found two objects in 𝑆 mapping to thesame element 𝑡𝑗. Otherwise, since 𝑇 has 𝑚 elements, when we get to𝑖 = 𝑚 − 1 we mark all the objects in 𝑇 . Hence, in this case, 𝐾(𝑠𝑚) mustmap to an element that was already marked before. (This observationis sometimes known as the “Pigeon Hole Principle”: the principle that

Page 102: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

102 introduction to theoretical computer science

if you have a pigeon coop with 𝑚 holes, and 𝑘 > 𝑚 pigeons, then theremust be two pigeons in the same hole. )

2.5.2 Prefix-free encodingWhen showing a representation scheme for rational numbers, we usedthe “hack” of encoding the alphabet 0, 1, ‖ to represent tuples ofstrings as a single string. This is a special case of the general paradigmof prefix-free encoding. The idea is the following: if our representationhas the property that no string đ‘„ representing an object 𝑜 is a prefix(i.e., an initial substring) of a string 𝑩 representing a different object𝑜â€Č, then we can represent a list of objects by merely concatenating therepresentations of all the list members. For example, because in En-glish every sentence ends with a punctuation mark such as a period,exclamation, or question mark, no sentence can be a prefix of anotherand so we can represent a list of sentences by merely concatenatingthe sentences one after the other. (English has some complicationssuch as periods used for abbreviations (e.g., “e.g.”) or sentence quotescontaining punctuation, but the high level point of a prefix-free repre-sentation for sentences still holds.)

It turns out that we can transform every representation to a prefix-free form. This justifies Big Idea 1, and allows us to transform a repre-sentation scheme for objects of a type 𝑇 to a representation scheme oflists of objects of the type 𝑇 . By repeating the same technique, we canalso represent lists of lists of objects of type 𝑇 , and so on and so forth.But first let us formally define prefix-freeness:

Definition 2.17 — Prefix free encoding. For two strings 𝑩, 𝑩â€Č, we say that 𝑩is a prefix of 𝑩â€Č if |𝑩| ≀ |𝑩â€Č| and for every 𝑖 < |𝑩|, 𝑩â€Č𝑖 = 𝑩𝑖.

Let đ’Ș be a non-empty set and 𝐾 ∶ đ’Ș → 0, 1∗ be a function. Wesay that 𝐾 is prefix-free if 𝐾(𝑜) is non-empty for every 𝑜 ∈ đ’Ș andthere does not exist a distinct pair of objects 𝑜, 𝑜â€Č ∈ đ’Ș such that𝐾(𝑜) is a prefix of 𝐾(𝑜â€Č).Recall that for every set đ’Ș, the set đ’Ș∗ consists of all finite length

tuples (i.e., lists) of elements in đ’Ș. The following theorem shows thatif 𝐾 is a prefix-free encoding of đ’Ș then by concatenating encodings wecan obtain a valid (i.e., one-to-one) representation of đ’Ș∗:

Theorem 2.18 — Prefix-free implies tuple encoding. Suppose that 𝐾 ∶ đ’Ș →0, 1∗ is prefix-free. Then the following map 𝐾 ∶ đ’Ș∗ → 0, 1∗ isone to one, for every 𝑜0, 
 , 𝑜𝑘−1 ∈ đ’Ș∗, we define𝐾(𝑜0, 
 , 𝑜𝑘−1) = 𝐾(𝑜0)𝐾(𝑜1) ⋯ 𝐾(𝑜𝑘−1) . (2.9)

Page 103: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 103

Figure 2.9: If we have a prefix-free representation ofeach object then we can concatenate the representa-tions of 𝑘 objects to obtain a representation for thetuple (𝑜0, 
 , 𝑜𝑘−1).

PTheorem 2.18 is an example of a theorem that is a littlehard to parse, but in fact is fairly straightforward toprove once you understand what it means. Therefore,I highly recommend that you pause here to makesure you understand the statement of this theorem.You should also try to prove it on your own beforeproceeding further.

Proof Idea:

The idea behind the proof is simple. Suppose that for examplewe want to decode a triple (𝑜0, 𝑜1, 𝑜2) from its representation đ‘„ =𝐾(𝑜0, 𝑜1, 𝑜2) = 𝐾(𝑜0)𝐾(𝑜1)𝐾(𝑜2). We will do so by first finding thefirst prefix đ‘„0 of đ‘„ that is a representation of some object. Then wewill decode this object, remove đ‘„0 from đ‘„ to obtain a new string đ‘„â€Č,and continue onwards to find the first prefix đ‘„1 of đ‘„â€Č and so on and soforth (see Exercise 2.9). The prefix-freeness property of 𝐾 will ensurethat đ‘„0 will in fact be 𝐾(𝑜0), đ‘„1 will be 𝐾(𝑜1), etc.⋆Proof of Theorem 2.18. We now show the formal proof. Suppose, to-wards the sake of contradiction, that there exist two distinct tuples(𝑜0, 
 , 𝑜𝑘−1) and (𝑜â€Č0, 
 , 𝑜â€Č𝑘â€Č−1) such that𝐾(𝑜0, 
 , 𝑜𝑘−1) = 𝐾(𝑜â€Č0, 
 , 𝑜â€Č𝑘â€Č−1) . (2.10)

We will denote the string 𝐾(𝑜0, 
 , 𝑜𝑘−1) by đ‘„.Let 𝑖 be the first index such that 𝑜𝑖 ≠ 𝑜â€Č𝑖. (If 𝑜𝑖 = 𝑜â€Č𝑖 for all 𝑖 then,

since we assume the two tuples are distinct, one of them must belarger than the other. In this case we assume without loss of generalitythat 𝑘â€Č > 𝑘 and let 𝑖 = 𝑘.) In the case that 𝑖 < 𝑘, we see that the stringđ‘„ can be written in two different ways:

đ‘„ = 𝐾(𝑜0, 
 , 𝑜𝑘−1) = đ‘„0 ⋯ đ‘„đ‘–âˆ’1𝐾(𝑜𝑖)𝐾(𝑜𝑖+1) ⋯ 𝐾(𝑜𝑘−1) (2.11)

and

đ‘„ = 𝐾(𝑜â€Č0, 
 , 𝑜â€Č𝑘â€Č−1) = đ‘„0 ⋯ đ‘„đ‘–âˆ’1𝐾(𝑜â€Č𝑖)𝐾(𝑜â€Č𝑖+1) ⋯ 𝐾(𝑜â€Č𝑘−1) (2.12)

where đ‘„đ‘— = 𝐾(𝑜𝑗) = 𝐾(𝑜â€Č𝑗) for all 𝑗 < 𝑖. Let 𝑩 be the string obtainedafter removing the prefix đ‘„0 ⋯ đ‘„đ‘–âˆ’đ‘– from đ‘„. We see that 𝑩 can be writ-ten as both 𝑩 = 𝐾(𝑜𝑖)𝑠 for some string 𝑠 ∈ 0, 1∗ and as 𝑩 = 𝐾(𝑜â€Č𝑖)𝑠â€Čfor some 𝑠â€Č ∈ 0, 1∗. But this means that one of 𝐾(𝑜𝑖) and 𝐾(𝑜â€Č𝑖) mustbe a prefix of the other, contradicting the prefix-freeness of 𝐾.

Page 104: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

104 introduction to theoretical computer science

In the case that 𝑖 = 𝑘 and 𝑘â€Č > 𝑘, we get a contradiction in thefollowing way. In this case

đ‘„ = 𝐾(𝑜0) ⋯ 𝐾(𝑜𝑘−1) = 𝐾(𝑜0) ⋯ 𝐾(𝑜𝑘−1)𝐾(𝑜â€Č𝑘) ⋯ 𝐾(𝑜â€Č𝑘â€Č−1) (2.13)

which means that 𝐾(𝑜â€Č𝑘) ⋯ 𝐾(𝑜â€Č𝑘â€Č−1) must correspond to the emptystring "". But in such a case 𝐾(𝑜â€Č𝑘) must be the empty string, which inparticular is the prefix of any other string, contradicting the prefix-freeness of 𝐾.

RRemark 2.19 — Prefix freeness of list representation.Even if the representation 𝐾 of objects in đ’Ș is prefixfree, this does not mean that our representation 𝐾of lists of such objects will be prefix free as well. Infact, it won’t be: for every three objects 𝑜, 𝑜â€Č, 𝑜″ therepresentation of the list (𝑜, 𝑜â€Č) will be a prefix of therepresentation of the list (𝑜, 𝑜â€Č, 𝑜″). However, as we seein Lemma 2.20 below, we can transform every repre-sentation into prefix-free form, and so will be able touse that transformation if needed to represent lists oflists, lists of lists of lists, and so on and so forth.

2.5.3 Making representations prefix-freeSome natural representations are prefix-free. For example, every fixedoutput length representation (i.e., one-to-one function 𝐾 ∶ đ’Ș → 0, 1𝑛)is automatically prefix-free, since a string đ‘„ can only be a prefix ofan equal-length đ‘„â€Č if đ‘„ and đ‘„â€Č are identical. Moreover, the approachwe used for representing rational numbers can be used to show thefollowing:Lemma 2.20 Let 𝐾 ∶ đ’Ș → 0, 1∗ be a one-to-one function. Then there isa one-to-one prefix-free encoding 𝐾 such that |𝐾(𝑜)| ≀ 2|𝐾(𝑜)| + 2 forevery 𝑜 ∈ đ’Ș.

PFor the sake of completeness, we will include theproof below, but it is a good idea for you to pausehere and try to prove it on your own, using the sametechnique we used for representing rational numbers.

Proof of Lemma 2.20. The idea behind the proof is to use the map 0 ↩00, 1 ↩ 11 to “double” every bit in the string đ‘„ and then mark theend of the string by concatenating to it the pair 01. If we encode a

Page 105: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 105

string đ‘„ in this way, it ensures that the encoding of đ‘„ is never a prefixof the encoding of a distinct string đ‘„â€Č. Formally, we define the functionPF ∶ 0, 1∗ → 0, 1∗ as follows:

PF(đ‘„) = đ‘„0đ‘„0đ‘„1đ‘„1 
 đ‘„đ‘›âˆ’1đ‘„đ‘›âˆ’101 (2.14)

for every đ‘„ ∈ 0, 1∗. If 𝐾 ∶ đ’Ș → 0, 1∗ is the (potentially notprefix-free) representation for đ’Ș, then we transform it into a prefix-free representation 𝐾 ∶ đ’Ș → 0, 1∗ by defining 𝐾(𝑜) = PF(𝐾(𝑜)).

To prove the lemma we need to show that (1) 𝐾 is one-to-one and(2) 𝐾 is prefix-free. In fact, prefix freeness is a stronger condition thanone-to-one (if two strings are equal then in particular one of them is aprefix of the other) and hence it suffices to prove (2), which we nowdo.

Let 𝑜 ≠ 𝑜â€Č in đ’Ș be two distinct objects. We will prove that 𝐾(𝑜)is a not a prefix of 𝐾(𝑜â€Č). Define đ‘„ = 𝐾(𝑜) and đ‘„â€Č = 𝐾(𝑜â€Č). Since𝐾 is one-to-one, đ‘„ ≠ đ‘„â€Č. Under our assumption, PF(đ‘„) is a prefixof PF(đ‘„â€Č). If |đ‘„| < |đ‘„â€Č| then the two bits in positions 2|đ‘„|, 2|đ‘„| + 1in PF(đ‘„) have the value 01 but the corresponding bits in PF(đ‘„â€Č) willequal either 00 or 11 (depending on the |đ‘„|-th bit of đ‘„â€Č) and hencePF(đ‘„) cannot be a prefix of PF(đ‘„â€Č). If |đ‘„| = |đ‘„â€Č| then, since đ‘„ ≠ đ‘„â€Č,there must be a coordinate 𝑖 in which they differ, meaning that thestrings PF(đ‘„) and PF(đ‘„â€Č) differ in the coordinates 2𝑖, 2𝑖 + 1, whichagain means that PF(đ‘„) cannot be a prefix of PF(đ‘„â€Č). If |đ‘„| > |đ‘„â€Č|then |PF(đ‘„)| = 2|đ‘„| + 2 > |PF(đ‘„â€Č)| = 2|đ‘„â€Č| + 2 and hence PF(đ‘„) islonger than (and cannot be a prefix of) PF(đ‘„â€Č). In all cases we see thatPF(đ‘„) = 𝐾(𝑜) is not a prefix of PF(đ‘„â€Č) = 𝐾(𝑜â€Č), hence completing theproof.

The proof of Lemma 2.20 is not the only or even the best way totransform an arbitrary representation into prefix-free form. Exer-cise 2.10 asks you to construct a more efficient prefix-free transforma-tion satisfying |𝐾(𝑜)| ≀ |𝐾(𝑜)| + 𝑂(log |𝐾(𝑜)|).2.5.4 “Proof by Python” (optional)The proofs of Theorem 2.18 and Lemma 2.20 are constructive in thesense that they give us:

‱ A way to transform the encoding and decoding functions of anyrepresentation of an object 𝑂 to encoding and decoding functionsthat are prefix-free, and

‱ A way to extend prefix-free encoding and decoding of single objectsto encoding and decoding of lists of objects by concatenation.

Page 106: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

106 introduction to theoretical computer science

Specifically, we could transform any pair of Python functions en-code and decode to functions pfencode and pfdecode that correspondto a prefix-free encoding and decoding. Similarly, given pfencode andpfdecode for single objects, we can extend them to encoding of lists.Let us show how this works for the case of the NtS and StN functionswe defined above.

We start with the “Python proof” of Lemma 2.20: a way to trans-form an arbitrary representation into one that is prefix free. The func-tion prefixfree below takes as input a pair of encoding and decodingfunctions, and returns a triple of functions containing prefix-free encod-ing and decoding functions, as well as a function that checks whethera string is a valid encoding of an object.

# takes functions encode and decode mapping# objects to lists of bits and vice versa,# and returns functions pfencode and pfdecode that# maps objects to lists of bits and vice versa# in a prefix-free way.# Also returns a function pfvalid that says# whether a list is a valid encodingdef prefixfree(encode, decode):

def pfencode(o):L = encode(o)return [L[i//2] for i in range(2*len(L))]+[0,1]

def pfdecode(L):return decode([L[j] for j in range(0,len(L)-2,2)])

def pfvalid(L):return (len(L) % 2 == 0 ) and all(L[2*i]==L[2*i+1]

for i in range((len(L)-2)//2)) andL[-2:]==[0,1]

return pfencode, pfdecode, pfvalid

pfNtS, pfStN , pfvalidN = prefixfree(NtS,StN)

NtS(234)# 11101010pfNtS(234)# 111111001100110001pfStN(pfNtS(234))# 234pfvalidM(pfNtS(234))# true

Page 107: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 107

PNote that the Python function prefixfree abovetakes two Python functions as input and outputsthree Python functions as output. (When it’s nottoo awkward, we use the term “Python function” or“subroutine” to distinguish between such snippets ofPython programs and mathematical functions.) Youdon’t have to know Python in this course, but you doneed to get comfortable with the idea of functions asmathematical objects in their own right, that can beused as inputs and outputs of other functions.

We now show a “Python proof” of Theorem 2.18. Namely, we showa function represlists that takes as input a prefix-free representationscheme (implemented via encoding, decoding, and validity testingfunctions) and outputs a representation scheme for lists of such ob-jects. If we want to make this representation prefix-free then we couldfit it into the function prefixfree above.

def represlists(pfencode,pfdecode,pfvalid):"""Takes functions pfencode, pfdecode and pfvalid,and returns functions encodelists, decodeliststhat can encode and decode lists of the objectsrespectively."""

def encodelist(L):"""Gets list of objects, encodes it as list of

bits"""return "".join([pfencode(obj) for obj in L])

def decodelist(S):"""Gets lists of bits, returns lists of objects"""i=0; j=1 ; res = []while j<=len(S):

if pfvalid(S[i:j]):res += [pfdecode(S[i:j])]i=j

j+= 1return res

return encodelist,decodelist

LtS , StL = represlists(pfNtS,pfStN,pfvalidN)

Page 108: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

108 introduction to theoretical computer science

Figure 2.10: The word “Binary” in “Grade 1” or“uncontracted” Unified English Braille. This word isencoded using seven symbols since the first one is amodifier indicating that the first letter is capitalized.

LtS([234,12,5])# 111111001100110001111100000111001101StL(LtS([234,12,5]))# [234, 12, 5]

2.5.5 Representing letters and textWe can represent a letter or symbol by a string, and then if this rep-resentation is prefix-free, we can represent a sequence of symbols bymerely concatenating the representation of each symbol. One suchrepresentation is the ASCII that represents 128 letters and symbols asstrings of 7 bits. Since the ASCII representation is fixed-length, it isautomatically prefix-free (can you see why?). Unicode is representa-tion of (at the time of this writing) about 128,000 symbols as numbers(known as code points) between 0 and 1, 114, 111. There are severaltypes of prefix-free representations of the code points, a popular onebeing UTF-8 that encodes every codepoint into a string of length be-tween 8 and 32.

Example 2.21 — The Braille representation. The Braille system is anotherway to encode letters and other symbols as binary strings. Specifi-cally, in Braille, every letter is encoded as a string in 0, 16, whichis written using indented dots arranged in two columns and threerows, see Fig. 2.10. (Some symbols require more than one six-bitstring to encode, and so Braille uses a more general prefix-freeencoding.)

The Braille system was invented in 1821 by Louis Braille whenhe was just 12 years old (though he continued working on it andimproving it throughout his life). Braille was a French boy wholost his eyesight at the age of 5 as the result of an accident.

Example 2.22 — Representing objects in C (optional). We can use pro-gramming languages to probe how our computing environmentrepresents various values. This is easiest to do in “unsafe” pro-gramming languages such as C that allow direct access to thememory.

Using a simple C program we have produced the followingrepresentations of various values. One can see that for integers,multiplying by 2 corresponds to a “left shift” inside each byte. Incontrast, for floating point numbers, multiplying by two corre-sponds to adding one to the exponent part of the representation.In the architecture we used, a negative number is represented

Page 109: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 109

using the two’s complement approach. C represents strings in aprefix-free form by ensuring that a zero byte is at their end.

int 2 : 00000010 00000000 00000000 00000000int 4 : 00000100 00000000 00000000 00000000int 513 : 00000001 00000010 00000000 00000000long 513 : 00000001 00000010 00000000 00000000

00000000 00000000 00000000 00000000int -1 : 11111111 11111111 11111111 11111111int -2 : 11111110 11111111 11111111 11111111string Hello: 01001000 01100101 01101100 01101100

01101111 00000000string abcd : 01100001 01100010 01100011 01100100

00000000float 33.0 : 00000000 00000000 00000100 01000010float 66.0 : 00000000 00000000 10000100 01000010float 132.0: 00000000 00000000 00000100 01000011double 132.0: 00000000 00000000 00000000 00000000

00000000 10000000 01100000 010000002.5.6 Representing vectors, matrices, imagesOnce we can represent numbers and lists of numbers, then we can alsorepresent vectors (which are just lists of numbers). Similarly, we canrepresent lists of lists, and thus, in particular, can represent matrices.To represent an image, we can represent the color at each pixel by alist of three numbers corresponding to the intensity of Red, Green andBlue. (We can restrict to three primary colors since most humans onlyhave three types of cones in their retinas; we would have needed 16primary colors to represent colors visible to the Mantis Shrimp.) Thusan image of 𝑛 pixels would be represented by a list of 𝑛 such length-three lists. A video can be represented as a list of images. Of coursethese representations are rather wasteful and much more compactrepresentations are typically used for images and videos, though thiswill not be our concern in this book.

2.5.7 Representing graphsA graph on 𝑛 vertices can be represented as an 𝑛 × 𝑛 adjacency matrixwhose (𝑖, 𝑗)𝑡ℎ entry is equal to 1 if the edge (𝑖, 𝑗) is present and isequal to 0 otherwise. That is, we can represent an 𝑛 vertex directedgraph đș = (𝑉 , 𝐾) as a string 𝐮 ∈ 0, 1𝑛2 such that 𝐮𝑖,𝑗 = 1 iff theedge 𝑖 𝑗 ∈ 𝐾. We can transform an undirected graph to a directedgraph by replacing every edge 𝑖, 𝑗 with both edges 𝑖 𝑗 and 𝑖 𝑗

Another representation for graphs is the adjacency list representa-tion. That is, we identify the vertex set 𝑉 of a graph with the set [𝑛]

Page 110: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

110 introduction to theoretical computer science

Figure 2.11: Representing the graph đș =(0, 1, 2, 3, 4, (1, 0), (4, 0), (1, 4), (4, 1), (2, 1), (3, 2), (4, 3))in the adjacency matrix and adjacency list representa-tions.

where 𝑛 = |𝑉 |, and represent the graph đș = (𝑉 , 𝐾) as a list of 𝑛lists, where the 𝑖-th list consists of the out-neighbors of vertex 𝑖. Thedifference between these representations can be significant for someapplications, though for us would typically be immaterial.

2.5.8 Representing lists and nested listsIf we have a way of representing objects from a set đ’Ș as binary strings,then we can represent lists of these objects by applying a prefix-freetransformation. Moreover, we can use a trick similar to the above tohandle nested lists. The idea is that if we have some representation𝐾 ∶ đ’Ș → 0, 1∗, then we can represent nested lists of items fromđ’Ș using strings over the five element alphabet ÎŁ = 0,1,[ , ] , , .For example, if 𝑜1 is represented by 0011, 𝑜2 is represented by 10011,and 𝑜3 is represented by 00111, then we can represent the nested list(𝑜1, (𝑜2, 𝑜3)) as the string "[0011,[10011,00111]]" over the alphabetÎŁ. By encoding every element of ÎŁ itself as a three-bit string, we cantransform any representation for objects đ’Ș into a representation thatenables representing (potentially nested) lists of these objects.

2.5.9 NotationWe will typically identify an object with its representation as a string.For example, if đč ∶ 0, 1∗ → 0, 1∗ is some function that mapsstrings to strings and 𝑛 is an integer, we might make statements suchas “đč(𝑛) + 1 is prime” to mean that if we represent 𝑛 as a string đ‘„,then the integer 𝑚 represented by the string đč(đ‘„) satisfies that 𝑚 + 1is prime. (You can see how this convention of identifying objects withtheir representation can save us a lot of cumbersome formalism.)Similarly, if đ‘„, 𝑩 are some objects and đč is a function that takes stringsas inputs, then by đč(đ‘„, 𝑩) we will mean the result of applying đč to therepresentation of the ordered pair (đ‘„, 𝑩). We use the same notation toinvoke functions on 𝑘-tuples of objects for every 𝑘.

This convention of identifying an object with its representation asa string is one that we humans follow all the time. For example, whenpeople say a statement such as “17 is a prime number”, what theyreally mean is that the integer whose decimal representation is thestring “17”, is prime.

When we say𝐮 is an algorithm that computes the multiplication function on natural num-bers.what we really mean is that𝐮 is an algorithm that computes the function đč ∶ 0, 1∗ → 0, 1∗ such thatfor every pair 𝑎, 𝑏 ∈ ℕ, if đ‘„ ∈ 0, 1∗ is a string representing the pair (𝑎, 𝑏)then đč(đ‘„) will be a string representing their product 𝑎 ⋅ 𝑏.

Page 111: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 111

2.6 DEFINING COMPUTATIONAL TASKS AS MATHEMATICAL FUNC-TIONS

Abstractly, a computational process is some process that takes an inputwhich is a string of bits and produces an output which is a stringof bits. This transformation of input to output can be done using amodern computer, a person following instructions, the evolution ofsome natural system, or any other means.

In future chapters, we will turn to mathematically defining com-putational processes, but, as we discussed above, at the moment wefocus on computational tasks. That is, we focus on the specification andnot the implementation. Again, at an abstract level, a computationaltask can specify any relation that the output needs to have with the in-put. However, for most of this book, we will focus on the simplest andmost common task of computing a function. Here are some examples:

‱ Given (a representation of) two integers đ‘„, 𝑩, compute the productđ‘„ × 𝑩. Using our representation above, this corresponds to com-puting a function from 0, 1∗ to 0, 1∗. We have seen that there ismore than one way to solve this computational task, and in fact, westill do not know the best algorithm for this problem.

‱ Given (a representation of) an integer 𝑧 > 1, compute its factoriza-tion; i.e., the list of primes 𝑝1 ≀ ⋯ ≀ 𝑝𝑘 such that 𝑧 = 𝑝1 ⋯ 𝑝𝑘. Thisagain corresponds to computing a function from 0, 1∗ to 0, 1∗.The gaps in our knowledge of the complexity of this problem areeven larger.

‱ Given (a representation of) a graph đș and two vertices 𝑠 and 𝑡,compute the length of the shortest path in đș between 𝑠 and 𝑡, or dothe same for the longest path (with no repeated vertices) between𝑠 and 𝑡. Both these tasks correspond to computing a function from0, 1∗ to 0, 1∗, though it turns out that there is a vast difference intheir computational difficulty.

‱ Given the code of a Python program, determine whether there is aninput that would force it into an infinite loop. This task correspondsto computing a partial function from 0, 1∗ to 0, 1 since not everystring corresponds to a syntactically valid Python program. We willsee that we do understand the computational status of this problem,but the answer is quite surprising.

‱ Given (a representation of) an image đŒ , decide if đŒ is a photo of acat or a dog. This corresponds to computing some (partial) func-tion from 0, 1∗ to 0, 1.

Page 112: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

112 introduction to theoretical computer science

Figure 2.12: A subset 𝐿 ⊆ 0, 1∗ can be identifiedwith the function đč ∶ 0, 1∗ → 0, 1 such thatđč(đ‘„) = 1 if đ‘„ ∈ 𝐿 and đč(đ‘„) = 0 if đ‘„ ∉ 𝐿. Functionswith a single bit of output are called Boolean functions,while subsets of strings are called languages. Theabove shows that the two are essentially the sameobject, and we can identify the task of decidingmembership in 𝐿 (known as deciding a language in theliterature) with the task of computing the function đč .

RRemark 2.23 — Boolean functions and languages. Animportant special case of computational tasks corre-sponds to computing Boolean functions, whose outputis a single bit 0, 1. Computing such functions corre-sponds to answering a YES/NO question, and hencethis task is also known as a decision problem. Given anyfunction đč ∶ 0, 1∗ → 0, 1 and đ‘„ ∈ 0, 1∗, the taskof computing đč(đ‘„) corresponds to the task of decidingwhether or not đ‘„ ∈ 𝐿 where 𝐿 = đ‘„ ∶ đč(đ‘„) = 1 isknown as the language that corresponds to the functionđč . (The language terminology is due to historicalconnections between the theory of computation andformal linguistics as developed by Noam Chomsky.)Hence many texts refer to such a computational taskas deciding a language.

For every particular function đč , there can be several possible algo-rithms to compute đč . We will be interested in questions such as:

‱ For a given function đč , can it be the case that there is no algorithm tocompute đč ?

‱ If there is an algorithm, what is the best one? Could it be that đč is“effectively uncomputable” in the sense that every algorithm forcomputing đč requires a prohibitively large amount of resources?

‱ If we cannot answer this question, can we show equivalence be-tween different functions đč and đč â€Č in the sense that either they areboth easy (i.e., have fast algorithms) or they are both hard?

‱ Can a function being hard to compute ever be a good thing? Can weuse it for applications in areas such as cryptography?

In order to do that, we will need to mathematically define the no-tion of an algorithm, which is what we will do in Chapter 3.

2.6.1 Distinguish functions from programs!You should always watch out for potential confusions between speci-fications and implementations or equivalently between mathematicalfunctions and algorithms/programs. It does not help that program-ming languages (Python included) use the term “functions” to denote(parts of) programs. This confusion also stems from thousands of yearsof mathematical history, where people typically defined functions bymeans of a way to compute them.

For example, consider the multiplication function on natural num-bers. This is the function MULT ∶ ℕ × ℕ → ℕ that maps a pair (đ‘„, 𝑩)of natural numbers to the number đ‘„ ⋅ 𝑩. As we mentioned, it can beimplemented in more than one way:

Page 113: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 113

Figure 2.13: A function is a mapping of inputs tooutputs. A program is a set of instructions on howto obtain an output given an input. A programcomputes a function, but it is not the same as a func-tion, popular programming language terminologynotwithstanding.

def mult1(x,y):res = 0while y>0:

res += xy -= 1

return res

def mult2(x,y):a = str(x) # represent x as string in decimal notationb = str(y) # represent y as string in decimal notationres = 0for i in range(len(a)):

for j in range(len(b)):res += int(a[len(a)-i])*int(b[len(b)-

j])*(10**(i+j))return res

print(mult1(12,7))# 84print(mult2(12,7))# 84

Both mult1 and mult2 produce the same output given the samepair of natural number inputs. (Though mult1 will take far longer todo so when the numbers become large.) Hence, even though these aretwo different programs, they compute the same mathematical function.This distinction between a program or algorithm 𝐮, and the function đčthat 𝐮 computes will be absolutely crucial for us in this course (see alsoFig. 2.13).

Big Idea 2 A function is not the same as a program. A programcomputes a function.

Distinguishing functions from programs (or other ways for comput-ing, including circuits and machines) is a crucial theme for this course.For this reason, this is often a running theme in questions that I (andmany other instructors) assign in homework and exams (hint, hint).

RRemark 2.24 — Computation beyond functions (advanced,optional). Functions capture quite a lot of compu-tational tasks, but one can consider more generalsettings as well. For starters, we can and will talkabout partial functions, that are not defined on allinputs. When computing a partial function, we only

Page 114: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

114 introduction to theoretical computer science

need to worry about the inputs on which the functionis defined. Another way to say it is that we can designan algorithm for a partial function đč under the as-sumption that someone “promised” us that all inputsđ‘„ would be such that đč(đ‘„) is defined (as otherwise,we do not care about the result). Hence such tasks arealso known as promise problems.Another generalization is to consider relations that mayhave more than one possible admissible output. Forexample, consider the task of finding any solution fora given set of equations. A relation 𝑅 maps a stringđ‘„ ∈ 0, 1∗ into a set of strings 𝑅(đ‘„) (for example, đ‘„might describe a set of equations, in which case 𝑅(đ‘„)would correspond to the set of all solutions to đ‘„). Wecan also identify a relation 𝑅 with the set of pairs ofstrings (đ‘„, 𝑩) where 𝑩 ∈ 𝑅(đ‘„). A computational pro-cess solves a relation if for every đ‘„ ∈ 0, 1∗, it outputssome string 𝑩 ∈ 𝑅(đ‘„).Later in this book, we will consider even more generaltasks, including interactive tasks, such as finding agood strategy in a game, tasks defined using proba-bilistic notions, and others. However, for much of thisbook, we will focus on the task of computing a func-tion, and often even a Boolean function, that has only asingle bit of output. It turns out that a great deal of thetheory of computation can be studied in the context ofthis task, and the insights learned are applicable in themore general settings.

Chapter Recap

‱ We can represent objects we want to compute onusing binary strings.

‱ A representation scheme for a set of objects đ’Ș is aone-to-one map from đ’Ș to 0, 1∗.

‱ We can use prefix-free encoding to “boost” a repre-sentation for a set đ’Ș into representations of lists ofelements in đ’Ș.

‱ A basic computational task is the task of computinga function đč ∶ 0, 1∗ → 0, 1∗. This task encom-passes not just arithmetical computations suchas multiplication, factoring, etc. but a great manyother tasks arising in areas as diverse as scientificcomputing, artificial intelligence, image processing,data mining and many many more.

‱ We will study the question of finding (or at leastgiving bounds on) what the best algorithm forcomputing đč for various interesting functions đč is.

Page 115: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 115

2.7 EXERCISES

Exercise 2.1 Which one of these objects can be represented by a binarystring?

a. An integer đ‘„b. An undirected graph đș.

c. A directed graph đ»d. All of the above.

Exercise 2.2 — Binary representation. a. Prove that the function 𝑁𝑡𝑆 ∶ ℕ →0, 1∗ of the binary representation defined in (2.1) satisfies that forevery 𝑛 ∈ ℕ, if đ‘„ = 𝑁𝑡𝑆(𝑛) then |đ‘„| = 1 + max(0, ⌊log2 𝑛⌋) andđ‘„đ‘– = âŒŠđ‘„/2⌊log2 𝑛⌋−𝑖⌋ mod 2.

b. Prove that 𝑁𝑡𝑆 is a one to one function by coming up with a func-tion 𝑆𝑡𝑁 ∶ 0, 1∗ → ℕ such that 𝑆𝑡𝑁(𝑁𝑡𝑆(𝑛)) = 𝑛 for every𝑛 ∈ ℕ.

Exercise 2.3 — More compact than ASCII representation. The ASCII encodingcan be used to encode a string of 𝑛 English letters as a 7𝑛 bit binarystring, but in this exercise, we ask about finding a more compact rep-resentation for strings of English lowercase letters.

1. Prove that there exists a representation scheme (𝐾, đ·) for stringsover the 26-letter alphabet 𝑎, 𝑏, 𝑐, 
 , 𝑧 as binary strings suchthat for every 𝑛 > 0 and length-𝑛 string đ‘„ ∈ 𝑎, 𝑏, 
 , 𝑧𝑛, therepresentation 𝐾(đ‘„) is a binary string of length at most 4.8𝑛 + 1000.In other words, prove that for every 𝑛, there exists a one-to-onefunction 𝐾 ∶ 𝑎, 𝑏, 
 , 𝑧𝑛 → 0, 1⌊4.8𝑛+1000⌋.

2. Prove that there exists no representation scheme for strings over thealphabet 𝑎, 𝑏, 
 , 𝑧 as binary strings such that for every length-𝑛string đ‘„ ∈ 𝑎, 𝑏, 
 , 𝑧𝑛, the representation 𝐾(đ‘„) is a binary string oflength ⌊4.6𝑛 + 1000⌋. In other words, prove that there exists some𝑛 > 0 such that there is no one-to-one function 𝐾 ∶ 𝑎, 𝑏, 
 , 𝑧𝑛 →0, 1⌊4.6𝑛+1000⌋.

3. Python’s bz2.compress function is a mapping from strings tostrings, which uses the lossless (and hence one to one) bzip2 algo-rithm for compression. After converting to lowercase, and truncat-ing spaces and numbers, the text of Tolstoy’s “War and Peace” con-tains 𝑛 = 2, 517, 262. Yet, if we run bz2.compress on the string ofthe text of “War and Peace” we get a string of length 𝑘 = 6, 274, 768

Page 116: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

116 introduction to theoretical computer science

5 Actually that particular fictional company uses ametric that focuses more on compression speed thenratio, see here and here.

bits, which is only 2.49𝑛 (and in particular much smaller than4.6𝑛). Explain why this does not contradict your answer to theprevious question.

4. Interestingly, if we try to apply bz2.compress on a random string,we get much worse performance. In my experiments, I got a ratioof about 4.78 between the number of bits in the output and thenumber of characters in the input. However, one could imagine thatone could do better and that there exists a company called “PiedPiper” with an algorithm that can losslessly compress a string of 𝑛random lowercase letters to fewer than 4.6𝑛 bits.5 Show that thisis not the case by proving that for every 𝑛 > 100 and one to onefunction 𝐾𝑛𝑐𝑜𝑑𝑒 ∶ 𝑎, 
 , 𝑧𝑛 → 0, 1∗, if we let 𝑍 be the randomvariable |𝐾𝑛𝑐𝑜𝑑𝑒(đ‘„)| (i.e., the length of 𝐾𝑛𝑐𝑜𝑑𝑒(đ‘„)) for đ‘„ chosenuniformly at random from the set 𝑎, 
 , 𝑧𝑛, then the expectedvalue of 𝑍 is at least 4.6𝑛.

Exercise 2.4 — Representing graphs: upper bound. Show that there is a stringrepresentation of directed graphs with vertex set [𝑛] and degree atmost 10 that uses at most 1000𝑛 log𝑛 bits. More formally, show thefollowing: Suppose we define for every 𝑛 ∈ ℕ, the set đș𝑛 as the setcontaining all directed graphs (with no self loops) over the vertexset [𝑛] where every vertex has degree at most 10. Then, prove that forevery sufficiently large 𝑛, there exists a one-to-one function 𝐾 ∶ đș𝑛 →0, 1⌊1000𝑛 log𝑛⌋.

Exercise 2.5 — Representing graphs: lower bound. 1. Define 𝑆𝑛 to be theset of one-to-one and onto functions mapping [𝑛] to [𝑛]. Prove thatthere is a one-to-one mapping from 𝑆𝑛 to đș2𝑛, where đș2𝑛 is the setdefined in Exercise 2.4 above.

2. In this question you will show that one cannot improve the rep-resentation of Exercise 2.4 to length 𝑜(𝑛 log𝑛). Specifically, provefor every sufficiently large 𝑛 ∈ ℕ there is no one-to-one function𝐾 ∶ đș𝑛 → 0, 1⌊0.001𝑛 log𝑛⌋+1000.

Exercise 2.6 — Multiplying in different representation. Recall that the grade-school algorithm for multiplying two numbers requires 𝑂(𝑛2) oper-ations. Suppose that instead of using decimal representation, we useone of the following representations 𝑅(đ‘„) to represent a number đ‘„between 0 and 10𝑛 − 1. For which one of these representations you canstill multiply the numbers in 𝑂(𝑛2) operations?

Page 117: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 117

a. The standard binary representation: đ”(đ‘„) = (đ‘„0, 
 , đ‘„đ‘˜) wheređ‘„ = ∑𝑘𝑖=0 đ‘„đ‘–2𝑖 and 𝑘 is the largest number s.t. đ‘„ ≄ 2𝑘.b. The reverse binary representation: đ”(đ‘„) = (đ‘„đ‘˜, 
 , đ‘„0) where đ‘„đ‘– is

defined as above for 𝑖 = 0, 
 , 𝑘 − 1.c. Binary coded decimal representation: đ”(đ‘„) = (𝑩0, 
 , 𝑩𝑛−1) where𝑩𝑖 ∈ 0, 14 represents the 𝑖𝑡ℎ decimal digit of đ‘„ mapping 0 to 0000,1 to 0001, 2 to 0010, etc. (i.e. 9 maps to 1001)d. All of the above.

Exercise 2.7 Suppose that 𝑅 ∶ ℕ → 0, 1∗ corresponds to representing anumber đ‘„ as a string of đ‘„ 1’s, (e.g., 𝑅(4) = 1111, 𝑅(7) = 1111111, etc.).If đ‘„, 𝑩 are numbers between 0 and 10𝑛 − 1, can we still multiply đ‘„ and𝑩 using 𝑂(𝑛2) operations if we are given them in the representation𝑅(⋅)?

Exercise 2.8 Recall that if đč is a one-to-one and onto function mappingelements of a finite set 𝑈 into a finite set 𝑉 then the sizes of 𝑈 and 𝑉are the same. Let đ” ∶ ℕ → 0, 1∗ be the function such that for everyđ‘„ ∈ ℕ, đ”(đ‘„) is the binary representation of đ‘„.1. Prove that đ‘„ < 2𝑘 if and only if |đ”(đ‘„)| ≀ 𝑘.2. Use 1. to compute the size of the set 𝑩 ∈ 0, 1∗ ∶ |𝑩| ≀ 𝑘 where |𝑩|

denotes the length of the string 𝑩.3. Use 1. and 2. to prove that 2𝑘 − 1 = 1 + 2 + 4 + ⋯ + 2𝑘−1.

Exercise 2.9 — Prefix-free encoding of tuples. Suppose that đč ∶ ℕ → 0, 1∗is a one-to-one function that is prefix-free in the sense that there is no𝑎 ≠ 𝑏 s.t. đč(𝑎) is a prefix of đč(𝑏).a. Prove that đč2 ∶ ℕ × ℕ → 0, 1∗, defined as đč2(𝑎, 𝑏) = đč(𝑎)đč(𝑏) (i.e.,

the concatenation of đč(𝑎) and đč(𝑏)) is a one-to-one function.

b. Prove that đč∗ ∶ ℕ∗ → 0, 1∗ defined as đč∗(𝑎1, 
 , 𝑎𝑘) =đč(𝑎1) ⋯ đč(𝑎𝑘) is a one-to-one function, where ℕ∗ denotes the set ofall finite-length lists of natural numbers.

Exercise 2.10 — More efficient prefix-free transformation. Suppose that đč âˆ¶đ‘‚ → 0, 1∗ is some (not necessarily prefix-free) representation of theobjects in the set 𝑂, and đș ∶ ℕ → 0, 1∗ is a prefix-free representa-tion of the natural numbers. Define đč â€Č(𝑜) = đș(|đč(𝑜)|)đč(𝑜) (i.e., theconcatenation of the representation of the length đč(𝑜) and đč(𝑜)).

Page 118: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

118 introduction to theoretical computer science

6 Hint: Think recursively how to represent the lengthof the string.

a. Prove that đč â€Č is a prefix-free representation of 𝑂.

b. Show that we can transform any representation to a prefix-free oneby a modification that takes a 𝑘 bit string into a string of length atmost 𝑘 + 𝑂(log 𝑘).

c. Show that we can transform any representation to a prefix-free oneby a modification that takes a 𝑘 bit string into a string of length atmost 𝑘 + log 𝑘 + 𝑂(log log 𝑘).6

Exercise 2.11 — Kraft’s Inequality. Suppose that 𝑆 ⊆ 0, 1𝑛 is some finiteprefix-free set.

a. For every 𝑘 ≀ 𝑛 and length-𝑘 string đ‘„ ∈ 𝑆, let 𝐿(đ‘„) ⊆ 0, 1𝑛 denoteall the length-𝑛 strings whose first 𝑘 bits are đ‘„0, 
 , đ‘„đ‘˜âˆ’1. Prove that(1) |𝐿(đ‘„)| = 2𝑛−|đ‘„| and (2) If đ‘„ ≠ đ‘„â€Č then 𝐿(đ‘„) is disjoint from𝐿(đ‘„â€Č).

b. Prove that âˆ‘đ‘„âˆˆđ‘† 2−|đ‘„| ≀ 1.c. Prove that there is no prefix-free encoding of strings with less than

logarithmic overhead. That is, prove that there is no function PF ∶0, 1∗ → 0, 1∗ s.t. |PF(đ‘„)| ≀ |đ‘„| + 0.9 log |đ‘„| for every đ‘„ ∈ 0, 1∗and such that the set PF(đ‘„) ∶ đ‘„ ∈ 0, 1∗ is prefix-free. The factor0.9 is arbitrary; all that matters is that it is less than 1.

Exercise 2.12 — Composition of one-to-one functions. Prove that for everytwo one-to-one functions đč ∶ 𝑆 → 𝑇 and đș ∶ 𝑇 → 𝑈 , the functionđ» ∶ 𝑆 → 𝑈 defined as đ»(đ‘„) = đș(đč(đ‘„)) is one to one.

Exercise 2.13 — Natural numbers and strings. 1. We have shown thatthe natural numbers can be represented as strings. Prove thatthe other direction holds as well: that there is a one-to-one map𝑆𝑡𝑁 ∶ 0, 1∗ → ℕ. (𝑆𝑡𝑁 stands for “strings to numbers.”)

2. Recall that Cantor proved that there is no one-to-one map 𝑅𝑡𝑁 ∶ℝ → ℕ. Show that Cantor’s result implies Theorem 2.5.

Exercise 2.14 — Map lists of integers to a number. Recall that for every set𝑆, the set 𝑆∗ is defined as the set of all finite sequences of mem-bers of 𝑆 (i.e., 𝑆∗ = (đ‘„0, 
 , đ‘„đ‘›âˆ’1) | 𝑛 ∈ ℕ , ∀𝑖∈[𝑛]đ‘„đ‘– ∈ 𝑆 ).Prove that there is a one-one-map from ℀∗ to ℕ where â„€ is the set of
 , −3, −2, −1, 0, +1, +2, +3, 
 of all integers.

Page 119: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

computation and representation 119

2.8 BIBLIOGRAPHICAL NOTES

The study of representing data as strings, including issues such ascompression and error corrections falls under the purview of informationtheory, as covered in the classic textbook of Cover and Thomas [CT06].Representations are also studied in the field of data structures design, ascovered in texts such as [Cor+09].

The question of whether to represent integers with the most signif-icant digit first or last is known as Big Endian vs. Little Endian repre-sentation. This terminology comes from Cohen’s [Coh81] entertainingand informative paper about the conflict between adherents of bothschools which he compared to the warring tribes in Jonathan Swift’s“Gulliver’s Travels”. The two’s complement representation of signedintegers was suggested in von Neumann’s classic report [Neu45]that detailed the design approaches for a stored-program computer,though similar representations have been used even earlier in abacusand other mechanical computation devices.

The idea that we should separate the definition or specification ofa function from its implementation or computation might seem “obvi-ous,” but it took quite a lot of time for mathematicians to arrive at thisviewpoint. Historically, a function đč was identified by rules or formu-las showing how to derive the output from the input. As we discussin greater depth in Chapter 9, in the 1800s this somewhat informalnotion of a function started “breaking at the seams,” and eventuallymathematicians arrived at the more rigorous definition of a functionas an arbitrary assignment of input to outputs. While many functionsmay be described (or computed) by one or more formulas, today wedo not consider that to be an essential property of functions, and alsoallow functions that do not correspond to any “nice” formula.

We have mentioned that all representations of the real numbersare inherently approximate. Thus an important endeavor is to under-stand what guarantees we can offer on the approximation quality ofthe output of an algorithm, as a function of the approximation qualityof the inputs. This question is known as the question of determiningthe numerical stability of given equations. The Floating Points Guidewebsite contains an extensive description of the floating point repre-sentation, as well the many ways in which it could subtly fail, see alsothe website 0.30000000000000004.com.

Dauben [Dau90] gives a biography of Cantor with emphasis onthe development of his mathematical ideas. [Hal60] is a classic text-book on set theory, including also Cantor’s theorem. Cantor’s Theo-rem is also covered in many texts on discrete mathematics, including[LLM18; LZ19].

Page 120: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

120 introduction to theoretical computer science

The adjacency matrix representation of graphs is not merely a con-venient way to map a graph into a binary string, but it turns out thatmany natural notions and operations on matrices are useful for graphsas well. (For example, Google’s PageRank algorithm relies on thisviewpoint.) The notes of Spielman’s course are an excellent source forthis area, known as spectral graph theory. We will return to this viewmuch later in this book when we talk about random walks.

Page 121: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

IFINITE COMPUTATION

Page 122: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 123: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Figure 3.1: Calculating wheels by Charles Babbage.Image taken from the Mark I ‘operating manual’

Figure 3.2: A 1944 Popular Mechanics article on theHarvard Mark I computer.

3Defining computation

“there is no reason why mental as well as bodily labor should not be economizedby the aid of machinery”, Charles Babbage, 1852

“If, unwarned by my example, any man shall undertake and shall succeedin constructing an engine embodying in itself the whole of the executive de-partment of mathematical analysis upon different principles or by simplermechanical means, I have no fear of leaving my reputation in his charge, for healone will be fully able to appreciate the nature of my efforts and the value oftheir results.”, Charles Babbage, 1864

“To understand a program you must become both the machine and the pro-gram.”, Alan Perlis, 1982

People have been computing for thousands of years, with aidsthat include not just pen and paper, but also abacus, slide rules, vari-ous mechanical devices, and modern electronic computers. A priori,the notion of computation seems to be tied to the particular mech-anism that you use. You might think that the “best” algorithm formultiplying numbers will differ if you implement it in Python on amodern laptop than if you use pen and paper. However, as we sawin the introduction (Chapter 0), an algorithm that is asymptoticallybetter would eventually beat a worse one regardless of the underly-ing technology. This gives us hope for a technology independent wayof defining computation. This is what we do in this chapter. We willdefine the notion of computing an output from an input by applying asequence of basic operations (see Fig. 3.3). Using this, we will be ableto precisely define statements such as “function 𝑓 can be computedby model 𝑋” or “function 𝑓 can be computed by model 𝑋 using 𝑠operations”.

This chapter: A non-mathy overviewThe main takeaways from this chapter are:

Compiled on 8.26.2020 18:10

Learning Objectives:‱ See that computation can be precisely

modeled.‱ Learn the computational model of Boolean

circuits / straight-line programs.‱ Equivalence of circuits and straight-line

programs.‱ Equivalence of AND/OR/NOT and NAND.‱ Examples of computing in the physical world.

Page 124: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

124 introduction to theoretical computer science

Figure 3.3: A function mapping strings to stringsspecifies a computational task, i.e., describes what thedesired relation between the input and the outputis. In this chapter we define models for implementingcomputational processes that achieve the desiredrelation, i.e., describe how to compute the outputfrom the input. We will see several examples of suchmodels using both Boolean circuits and straight-lineprogramming languages.

‱ We can use logical operations such as AND, OR, and NOT tocompute an output from an input (see Section 3.2).

‱ A Boolean circuit is a way to compose the basic logicaloperations to compute a more complex function (see Sec-tion 3.3). We can think of Boolean circuits as both a mathe-matical model (which is based on directed acyclic graphs)as well as physical devices we can construct in the realworld in a variety of ways, including not just silicon-basedsemi-conductors but also mechanical and even biologicalmechanisms (see Section 3.4).

‱ We can describe Boolean circuits also as straight-line pro-grams, which are programs that do not have any loopingconstructs (i.e., no while / for/ do .. until etc.), seeSection 3.3.2.

‱ It is possible to implement the AND, OR, and NOT oper-ations using the NAND operation (as well as vice versa).This means that circuits with AND/OR/NOT gates cancompute the same functions (i.e., are equivalent in power)to circuits with NAND gates, and we can use either modelto describe computation based on our convenience, seeSection 3.5. To give out a “spoiler”, we will see in Chap-ter 4 that such circuits can compute all finite functions.

One “big idea” of this chapter is the notion of equivalencebetween models (Big Idea 3). Two computational modelsare equivalent if they can compute the same set of functions.

Page 125: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 125

Figure 3.4: Text pages from Algebra manuscript withgeometrical solutions to two quadratic equations.Shelfmark: MS. Huntington 214 fol. 004v-005r

Figure 3.5: An explanation for children of the two digitaddition algorithm

Boolean circuits with AND/OR/NOT gates are equivalent tocircuits with NAND gates, but this is just one example of themore general phenomenon that we will see many times inthis book.

3.1 DEFINING COMPUTATION

The name “algorithm” is derived from the Latin transliteration ofMuhammad ibn Musa al-Khwarizmi’s name. Al-Khwarizmi was aPersian scholar during the 9th century whose books introduced thewestern world to the decimal positional numeral system, as well as tothe solutions of linear and quadratic equations (see Fig. 3.4). HoweverAl-Khwarizmi’s descriptions of algorithms were rather informal bytoday’s standards. Rather than use “variables” such as đ‘„, 𝑩, he usedconcrete numbers such as 10 and 39, and trusted the reader to beable to extrapolate from these examples, much as algorithms are stilltaught to children today.

Here is how Al-Khwarizmi described the algorithm for solving anequation of the form đ‘„2 + đ‘đ‘„ = 𝑐:

[How to solve an equation of the form ] “roots and squares are equal to num-bers”: For instance “one square , and ten roots of the same, amount to thirty-nine dirhems” that is to say, what must be the square which, when increasedby ten of its own root, amounts to thirty-nine? The solution is this: you halvethe number of the roots, which in the present instance yields five. This youmultiply by itself; the product is twenty-five. Add this to thirty-nine’ the sumis sixty-four. Now take the root of this, which is eight, and subtract from it halfthe number of roots, which is five; the remainder is three. This is the root of thesquare which you sought for; the square itself is nine.

For the purposes of this book, we will need a much more preciseway to describe algorithms. Fortunately (or is it unfortunately?), atleast at the moment, computers lag far behind school-age childrenin learning from examples. Hence in the 20th century, people cameup with exact formalisms for describing algorithms, namely program-ming languages. Here is al-Khwarizmi’s quadratic equation solvingalgorithm described in the Python programming language:

from math import sqrt#Pythonspeak to enable use of the sqrt function to compute

square roots.def solve_eq(b,c):

# return solution of x^2 + bx = c following AlKhwarizmi's instructions

# Al Kwarizmi demonstrates this for the case b=10 andc= 39

Page 126: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

126 introduction to theoretical computer science

val1 = b / 2.0 # "halve the number of the roots"val2 = val1 * val1 # "this you multiply by itself"val3 = val2 + c # "Add this to thirty-nine"val4 = sqrt(val3) # "take the root of this"val5 = val4 - val1 # "subtract from it half the number

of roots"return val5 # "This is the root of the square which

you sought for"# Test: solve x^2 + 10*x = 39print(solve_eq(10,39))# 3.0

We can define algorithms informally as follows:

Informal definition of an algorithm: An algorithm is a set of instruc-tions for how to compute an output from an input by following a se-quence of “elementary steps”.An algorithm 𝐮 computes a function đč if for every input đ‘„, if we followthe instructions of 𝐮 on the input đ‘„, we obtain the output đč(đ‘„).In this chapter we will make this informal definition precise using

the model of Boolean Circuits. We will show that Boolean Circuitsare equivalent in power to straight line programs that are written in“ultra simple” programming languages that do not even have loops.We will also see that the particular choice of elementary operations isimmaterial and many different choices yield models with equivalentpower (see Fig. 3.6). However, it will take us some time to get there.We will start by discussing what are “elementary operations” and howwe map a description of an algorithm into an actual physical processthat produces an output from an input in the real world.

Figure 3.6: An overview of the computational modelsdefined in this chapter. We will show several equiv-alent ways to represent a recipe for performing afinite computation. Specifically we will show that wecan model such a computation using either a Booleancircuit or a straight line program, and these two repre-sentations are equivalent to one another. We will alsoshow that we can choose as our basic operations ei-ther the set AND,OR,NOT or the set NAND andthese two choices are equivalent in power. By makingthe choice of whether to use circuits or programs,and whether to use AND,OR,NOT or NAND weobtain four equivalent ways of modeling finite com-putation. Moreover, there are many other choices ofsets of basic operations that are equivalent in power.

Page 127: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 127

3.2 COMPUTING USING AND, OR, AND NOT.

An algorithm breaks down a complex calculation into a series of sim-pler steps. These steps can be executed in a variety of different ways,including:

‱ Writing down symbols on a piece of paper.

‱ Modifying the current flowing on electrical wires.

‱ Binding a protein to a strand of DNA.

‱ Responding to a stimulus by a member of a collection (e.g., a bee ina colony, a trader in a market).

To formally define algorithms, let us try to “err on the side of sim-plicity” and model our “basic steps” as truly minimal. For example,here are some very simple functions:

‱ OR ∶ 0, 12 → 0, 1 defined as

OR(𝑎, 𝑏) = ⎧⎚⎩0 𝑎 = 𝑏 = 01 otherwise(3.1)

‱ AND ∶ 0, 12 → 0, 1 defined as

AND(𝑎, 𝑏) = ⎧⎚⎩1 𝑎 = 𝑏 = 10 otherwise(3.2)

‱ NOT ∶ 0, 1 → 0, 1 defined as

NOT(𝑎) = ⎧⎚⎩0 𝑎 = 11 𝑎 = 0 (3.3)

The functions AND, OR and NOT, are the basic logical operatorsused in logic and many computer systems. In the context of logic, it iscommon to use the notation 𝑎 ∧ 𝑏 for AND(𝑎, 𝑏), 𝑎 ∹ 𝑏 for OR(𝑎, 𝑏) and𝑎 and ¬𝑎 for NOT(𝑎), and we will use this notation as well.

Each one of the functions AND,OR,NOT takes either one or twosingle bits as input, and produces a single bit as output. Clearly, itcannot get much more basic than that. However, the power of compu-tation comes from composing such simple building blocks together.

Page 128: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

128 introduction to theoretical computer science

Example 3.1 — Majority from đŽđ‘đ·,𝑂𝑅 and 𝑁𝑂𝑇 . Consider the func-tion MAJ ∶ 0, 13 → 0, 1 that is defined as follows:

MAJ(đ‘„) = ⎧⎚⎩1 đ‘„0 + đ‘„1 + đ‘„2 ≄ 20 otherwise. (3.4)

That is, for every đ‘„ ∈ 0, 13, MAJ(đ‘„) = 1 if and only if the ma-jority (i.e., at least two out of the three) of đ‘„â€™s elements are equalto 1. Can you come up with a formula involving AND, OR andNOT to compute MAJ? (It would be useful for you to pause at thispoint and work out the formula for yourself. As a hint, althoughthe NOT operator is needed to compute some functions, you willnot need to use it to compute MAJ.)

Let us first try to rephrase MAJ(đ‘„) in words: “MAJ(đ‘„) = 1 if andonly if there exists some pair of distinct elements 𝑖, 𝑗 such that bothđ‘„đ‘– and đ‘„đ‘— are equal to 1.” In other words it means that MAJ(đ‘„) = 1iff either both đ‘„0 = 1 and đ‘„1 = 1, or both đ‘„1 = 1 and đ‘„2 = 1, or bothđ‘„0 = 1 and đ‘„2 = 1. Since the OR of three conditions 𝑐0, 𝑐1, 𝑐2 canbe written as OR(𝑐0,OR(𝑐1, 𝑐2)), we can now translate this into aformula as follows:

MAJ(đ‘„0, đ‘„1, đ‘„2) = OR (AND(đ‘„0, đ‘„1) , OR(AND(đ‘„1, đ‘„2) , AND(đ‘„0, đ‘„2)) ) .(3.5)

Recall that we can also write 𝑎 ∹ 𝑏 for OR(𝑎, 𝑏) and 𝑎 ∧ 𝑏 forAND(𝑎, 𝑏). With this notation, (3.5) can also be written as

MAJ(đ‘„0, đ‘„1, đ‘„2) = ((đ‘„0 ∧ đ‘„1) √ (đ‘„1 ∧ đ‘„2)) √ (đ‘„0 ∧ đ‘„2) . (3.6)

We can also write (3.5) in a “programming language” form,expressing it as a set of instructions for computing MAJ given thebasic operations AND,OR,NOT:

def MAJ(X[0],X[1],X[2]):firstpair = AND(X[0],X[1])secondpair = AND(X[1],X[2])thirdpair = AND(X[0],X[2])temp = OR(secondpair,thirdpair)return OR(firstpair,temp)

3.2.1 Some properties of AND and ORLike standard addition and multiplication, the functions AND and ORsatisfy the properties of commutativity: 𝑎 ∹ 𝑏 = 𝑏 ∹ 𝑎 and 𝑎 ∧ 𝑏 = 𝑏 ∧ 𝑎and associativity: (𝑎∹𝑏)∹𝑐 = 𝑎∹(𝑏∹𝑐) and (𝑎∧𝑏)∧𝑐 = 𝑎∧(𝑏∧𝑐). As in

Page 129: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 129

the case of addition and multiplication, we often drop the parenthesisand write 𝑎∹𝑏∹𝑐 ∹𝑑 for ((𝑎∹𝑏)∹𝑐)∹𝑑, and similarly OR’s and AND’sof more terms. They also satisfy a variant of the distributive law:Solved Exercise 3.1 — Distributive law for AND and OR. Prove that for every𝑎, 𝑏, 𝑐 ∈ 0, 1, 𝑎 ∧ (𝑏 ∹ 𝑐) = (𝑎 ∧ 𝑏) ∹ (𝑎 ∧ 𝑐).

Solution:

We can prove this by enumerating over all the 8 possible valuesfor 𝑎, 𝑏, 𝑐 ∈ 0, 1 but it also follows from the standard distributivelaw. Suppose that we identify any positive integer with “true” andthe value zero with “false”. Then for every numbers 𝑱, 𝑣 ∈ ℕ, 𝑱 + 𝑣is positive if and only if 𝑱 ∹ 𝑣 is true and 𝑱 ⋅ 𝑣 is positive if and onlyif 𝑱 ∧ 𝑣 is true. This means that for every 𝑎, 𝑏, 𝑐 ∈ 0, 1, the expres-sion 𝑎 ∧ (𝑏 ∹ 𝑐) is true if and only if 𝑎 ⋅ (𝑏 + 𝑐) is positive, and theexpression (𝑎 ∧ 𝑏) ∹ (𝑎 ∧ 𝑐) is true if and only if 𝑎 ⋅ 𝑏 + 𝑎 ⋅ 𝑐 is positive,But by the standard distributive law 𝑎 ⋅ (𝑏 + 𝑐) = 𝑎 ⋅ 𝑏 + 𝑎 ⋅ 𝑐 andhence the former expression is true if and only if the latter one is.

3.2.2 Extended example: Computing XOR from AND, OR, and NOTLet us see how we can obtain a different function from the samebuilding blocks. Define XOR ∶ 0, 12 → 0, 1 to be the functionXOR(𝑎, 𝑏) = 𝑎 + 𝑏 mod 2. That is, XOR(0, 0) = XOR(1, 1) = 0 andXOR(1, 0) = XOR(0, 1) = 1. We claim that we can construct XORusing only AND, OR, and NOT.

PAs usual, it is a good exercise to try to work out thealgorithm for XOR using AND, OR and NOT on yourown before reading further.

The following algorithm computes XOR using AND, OR, and NOT:

Algorithm 3.2 — 𝑋𝑂𝑅 from đŽđ‘đ·/𝑂𝑅/𝑁𝑂𝑇 .

Input: 𝑎, 𝑏 ∈ 0, 1.Output: 𝑋𝑂𝑅(𝑎, 𝑏)1: đ‘€1 ← đŽđ‘đ·(𝑎, 𝑏)2: đ‘€2 ← 𝑁𝑂𝑇 (đ‘€1)3: đ‘€3 ← 𝑂𝑅(𝑎, 𝑏)4: return đŽđ‘đ·(đ‘€2, đ‘€3)

Lemma 3.3 For every 𝑎, 𝑏 ∈ 0, 1, on input 𝑎, 𝑏, Algorithm 3.2 outputs𝑎 + 𝑏 mod 2.

Page 130: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

130 introduction to theoretical computer science

Proof. For every 𝑎, 𝑏, XOR(𝑎, 𝑏) = 1 if and only if 𝑎 is different from𝑏. On input 𝑎, 𝑏 ∈ 0, 1, Algorithm 3.2 outputs AND(đ‘€2, đ‘€3) wheređ‘€2 = NOT(AND(𝑎, 𝑏)) and đ‘€3 = OR(𝑎, 𝑏).‱ If 𝑎 = 𝑏 = 0 then đ‘€3 = OR(𝑎, 𝑏) = 0 and so the output will be 0.‱ If 𝑎 = 𝑏 = 1 then AND(𝑎, 𝑏) = 1 and so đ‘€2 = NOT(AND(𝑎, 𝑏)) = 0

and the output will be 0.‱ If 𝑎 = 1 and 𝑏 = 0 (or vice versa) then both đ‘€3 = OR(𝑎, 𝑏) = 1

and đ‘€1 = AND(𝑎, 𝑏) = 0, in which case the algorithm will outputOR(NOT(đ‘€1), đ‘€3) = 1.

We can also express Algorithm 3.2 using a programming language.Specifically, the following is a Python program that computes the XORfunction:

def AND(a,b): return a*bdef OR(a,b): return 1-(1-a)*(1-b)def NOT(a): return 1-a

def XOR(a,b):w1 = AND(a,b)w2 = NOT(w1)w3 = OR(a,b)return AND(w2,w3)

# Test out the codeprint([f"XOR(a,b)=XOR(a,b)" for a in [0,1] for b in

[0,1]])# ['XOR(0,0)=0', 'XOR(0,1)=1', 'XOR(1,0)=1', 'XOR(1,1)=0']

Solved Exercise 3.2 — Compute 𝑋𝑂𝑅 on three bits of input. Let XOR3 ∶0, 13 → 0, 1 be the function defined as XOR3(𝑎, 𝑏, 𝑐) = 𝑎 + 𝑏 + 𝑐mod 2. That is, XOR3(𝑎, 𝑏, 𝑐) = 1 if 𝑎+𝑏+𝑐 is odd, and XOR3(𝑎, 𝑏, 𝑐) =0 otherwise. Show that you can compute XOR3 using AND, OR, andNOT. You can express it as a formula, use a programming languagesuch as Python, or use a Boolean circuit.

Solution:

Addition modulo two satisfies the same properties of associativ-ity ((𝑎 + 𝑏) + 𝑐 = 𝑎 + (𝑏 + 𝑐)) and commutativity (𝑎 + 𝑏 = 𝑏 + 𝑎) asstandard addition. This means that, if we define 𝑎 ⊕ 𝑏 to equal 𝑎 + 𝑏

Page 131: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 131

mod 2, thenXOR3(𝑎, 𝑏, 𝑐) = (𝑎 ⊕ 𝑏) ⊕ 𝑐 (3.7)

or in other words

XOR3(𝑎, 𝑏, 𝑐) = XOR(XOR(𝑎, 𝑏), 𝑐) . (3.8)

Since we know how to compute XOR using AND, OR, andNOT, we can compose this to compute XOR3 using the same build-ing blocks. In Python this corresponds to the following program:

def XOR3(a,b,c):w1 = AND(a,b)w2 = NOT(w1)w3 = OR(a,b)w4 = AND(w2,w3)w5 = AND(w4,c)w6 = NOT(w5)w7 = OR(w4,c)return AND(w6,w7)

# Let's test this outprint([f"XOR3(a,b,c)=XOR3(a,b,c)" for a in [0,1]

for b in [0,1] for c in [0,1]])# ['XOR3(0,0,0)=0', 'XOR3(0,0,1)=1', 'XOR3(0,1,0)=1',

'XOR3(0,1,1)=0', 'XOR3(1,0,0)=1', 'XOR3(1,0,1)=0','XOR3(1,1,0)=0', 'XOR3(1,1,1)=1']

PTry to generalize the above examples to obtain a wayto compute XOR𝑛 ∶ 0, 1𝑛 → 0, 1 for every 𝑛 us-ing at most 4𝑛 basic steps involving applications of afunction in AND,OR,NOT to outputs or previouslycomputed values.

3.2.3 Informally defining “basic operations” and “algorithms”We have seen that we can obtain at least some examples of interestingfunctions by composing together applications of AND, OR, and NOT.This suggests that we can use AND, OR, and NOT as our “basic opera-tions”, hence obtaining the following definition of an “algorithm”:

Semi-formal definition of an algorithm: An algorithm consists of asequence of steps of the form “compute a new value by applying AND,OR, or NOT to previously computed values”.

Page 132: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

132 introduction to theoretical computer science

An algorithm 𝐮 computes a function đč if for every input đ‘„ to đč , if wefeed đ‘„ as input to the algorithm, the value computed in its last step isđč(đ‘„).There are several concerns that are raised by this definition:

1. First and foremost, this definition is indeed too informal. We do notspecify exactly what each step does, nor what it means to “feed đ‘„ asinput”.

2. Second, the choice of AND, OR or NOT seems rather arbitrary.Why not XOR and MAJ? Why not allow operations like additionand multiplication? What about any other logical constructionssuch if/then or while?

3. Third, do we even know that this definition has anything to dowith actual computing? If someone gave us a description of such analgorithm, could we use it to actually compute the function in thereal world?

PThese concerns will to a large extent guide us in theupcoming chapters. Thus you would be well advisedto re-read the above informal definition and see whatyou think about these issues.

A large part of this book will be devoted to addressing the aboveissues. We will see that:

1. We can make the definition of an algorithm fully formal, and sogive a precise mathematical meaning to statements such as “Algo-rithm 𝐮 computes function 𝑓”.

2. While the choice of AND/OR/NOT is arbitrary, and we could justas well have chosen other functions, we will also see this choicedoes not matter much. We will see that we would obtain the samecomputational power if we instead used addition and multiplica-tion, and essentially every other operation that could be reasonablythought of as a basic step.

3. It turns out that we can and do compute such “AND/OR/NOTbased algorithms” in the real world. First of all, such an algorithmis clearly well specified, and so can be executed by a human with apen and paper. Second, there are a variety of ways to mechanize thiscomputation. We’ve already seen that we can write Python codethat corresponds to following such a list of instructions. But in factwe can directly implement operations such as AND, OR, and NOT

Page 133: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 133

Figure 3.7: Standard symbols for the logical operationsor “gates” of AND, OR, NOT, as well as the operationNAND discussed in Section 3.5.

Figure 3.8: A circuit with AND, OR and NOT gates forcomputing the XOR function.

via electronic signals using components known as transistors. This ishow modern electronic computers operate.

In the remainder of this chapter, and the rest of this book, we willbegin to answer some of these questions. We will see more examplesof the power of simple operations to compute more complex opera-tions including addition, multiplication, sorting and more. We willalso discuss how to physically implement simple operations such asAND, OR and NOT using a variety of technologies.

3.3 BOOLEAN CIRCUITS

Boolean circuits provide a precise notion of “composing basic opera-tions together”. A Boolean circuit (see Fig. 3.9) is composed of gatesand inputs that are connected by wires. The wires carry a signal thatrepresents either the value 0 or 1. Each gate corresponds to either theOR, AND, or NOT operation. An OR gate has two incoming wires,and one or more outgoing wires. If these two incoming wires carrythe signals 𝑎 and 𝑏 (for 𝑎, 𝑏 ∈ 0, 1), then the signal on the outgoingwires will be OR(𝑎, 𝑏). AND and NOT gates are defined similarly. Theinputs have only outgoing wires. If we set a certain input to a value𝑎 ∈ 0, 1, then this value is propagated on all the wires outgoingfrom it. We also designate some gates as output gates, and their valuecorresponds to the result of evaluating the circuit. For example, ??gives such a circuit for the XOR function, following Section 3.2.2. Weevaluate an 𝑛-input Boolean circuit đ¶ on an input đ‘„ ∈ 0, 1𝑛 by plac-ing the bits of đ‘„ on the inputs, and then propagating the values on thewires until we reach an output, see Fig. 3.9.

RRemark 3.4 — Physical realization of Boolean circuits.Boolean circuits are a mathematical model that does notnecessarily correspond to a physical object, but theycan be implemented physically. In physical imple-mentation of circuits, the signal is often implementedby electric potential, or voltage, on a wire, where forexample voltage above a certain level is interpretedas a logical value of 1, and below a certain level isinterpreted as a logical value of 0. Section 3.4 dis-cusses physical implementation of Boolean circuits(with examples including using electrical signals suchas in silicon-based circuits, but also biological andmechanical implementations as well).

Solved Exercise 3.3 — All equal function. Define ALLEQ ∶ 0, 14 → 0, 1to be the function that on input đ‘„ ∈ 0, 14 outputs 1 if and only ifđ‘„0 = đ‘„1 = đ‘„2 = đ‘„3. Give a Boolean circuit for computing ALLEQ.

Page 134: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

134 introduction to theoretical computer science

Figure 3.9: A Boolean Circuit consists of gates that areconnected by wires to one another and the inputs. Theleft side depicts a circuit with 2 inputs and 5 gates,one of which is designated the output gate. The rightside depicts the evaluation of this circuit on the inputđ‘„ ∈ 0, 12 with đ‘„0 = 1 and đ‘„1 = 0. The value ofevery gate is obtained by applying the correspondingfunction (AND, OR, or NOT) to values on the wire(s)that enter it. The output of the circuit on a giveninput is the value of the output gate(s). In this case,the circuit computes the XOR function and hence itoutputs 1 on the input 10.

Figure 3.10: A Boolean circuit for computing the allequal function ALLEQ ∶ 0, 14 → 0, 1 that outputs1 on đ‘„ ∈ 0, 14 if and only if đ‘„0 = đ‘„1 = đ‘„2 = đ‘„3.

Solution:

Another way to describe the function ALLEQ is that it outputs1 on an input đ‘„ ∈ 0, 14 if and only if đ‘„ = 04 or đ‘„ = 14. We canphrase the condition đ‘„ = 14 as đ‘„0 ∧ đ‘„1 ∧ đ‘„2 ∧ đ‘„3 which can becomputed using three AND gates. Similarly we can phrase the con-dition đ‘„ = 04 as đ‘„0 ∧ đ‘„1 ∧ đ‘„2 ∧ đ‘„3 which can be computed using fourNOT gates and three AND gates. The output of ALLEQ is the ORof these two conditions, which results in the circuit of 4 NOT gates,6 AND gates, and one OR gate presented in Fig. 3.10.

3.3.1 Boolean circuits: a formal definitionWe defined Boolean circuits informally as obtained by connectingAND, OR, and NOT gates via wires so as to produce an output froman input. However, to be able to prove theorems about the existence ornon-existence of Boolean circuits for computing various functions weneed to:

1. Formally define a Boolean circuit as a mathematical object.

2. Formally define what it means for a circuit đ¶ to compute a function𝑓 .We now proceed to do so. We will define a Boolean circuit as a

labeled Directed Acyclic Graph (DAG). The vertices of the graph corre-spond to the gates and inputs of the circuit, and the edges of the graphcorrespond to the wires. A wire from an input or gate 𝑱 to a gate 𝑣 inthe circuit corresponds to a directed edge between the correspondingvertices. The inputs are vertices with no incoming edges, while eachgate has the appropriate number of incoming edges based on the func-tion it computes. (That is, AND and OR gates have two in-neighbors,while NOT gates have one in-neighbor.) The formal definition is asfollows (see also Fig. 3.11):

Page 135: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 135

Figure 3.11: A Boolean Circuit is a labeled directedacyclic graph (DAG). It has 𝑛 input vertices, which aremarked with X[0],
, X[𝑛 − 1] and have no incomingedges, and the rest of the vertices are gates. AND,OR, and NOT gates have two, two, and one incomingedges, respectively. If the circuit has 𝑚 outputs, then𝑚 of the gates are known as outputs and are markedwith Y[0],
,Y[𝑚 − 1]. When we evaluate a circuitđ¶ on an input đ‘„ ∈ 0, 1𝑛, we start by setting thevalue of the input vertices to đ‘„0, 
 , đ‘„đ‘›âˆ’1 and thenpropagate the values, assigning to each gate 𝑔 theresult of applying the operation of 𝑔 to the values of𝑔’s in-neighbors. The output of the circuit is the valueassigned to the output gates.

1 Having parallel edges means an AND or OR gate𝑱 can have both its in-neighbors be the same gate𝑣. Since AND(𝑎, 𝑎) = OR(𝑎, 𝑎) = 𝑎 for every 𝑎 ∈0, 1, such parallel edges don’t help in computingnew values in circuits with AND/OR/NOT gates.However, we will see circuits with more general setsof gates later on.

Definition 3.5 — Boolean Circuits. Let 𝑛, 𝑚, 𝑠 be positive integers with𝑠 ≄ 𝑚. A Boolean circuit with 𝑛 inputs, 𝑚 outputs, and 𝑠 gates, is alabeled directed acyclic graph (DAG) đș = (𝑉 , 𝐾) with 𝑠+𝑛 verticessatisfying the following properties:

‱ Exactly 𝑛 of the vertices have no in-neighbors. These verticesare known as inputs and are labeled with the 𝑛 labels X[0], 
,X[𝑛 − 1]. Each input has at least one out-neighbor.

‱ The other 𝑠 vertices are known as gates. Each gate is labeled with∧, ∹ or ¬. Gates labeled with ∧ (AND) or ∹ (OR) have two in-neighbors. Gates labeled with ¬ (NOT) have one in-neighbor.We will allow parallel edges. 1

‱ Exactly 𝑚 of the gates are also labeled with the 𝑚 labels Y[0], 
,Y[𝑚 − 1] (in addition to their label ∧/∹/¬). These are known asoutputs.

The size of a Boolean circuit is the number of gates it contains.

PThis is a non-trivial mathematical definition, so it isworth taking the time to read it slowly and carefully.As in all mathematical definitions, we are using aknown mathematical object — a directed acyclic graph(DAG) — to define a new object, a Boolean circuit.This might be a good time to review some of the basic

Page 136: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

136 introduction to theoretical computer science

properties of DAGs and in particular the fact that theycan be topologically sorted, see Section 1.6.

If đ¶ is a circuit with 𝑛 inputs and 𝑚 outputs, and đ‘„ ∈ 0, 1𝑛, thenwe can compute the output of đ¶ on the input đ‘„ in the natural way:assign the input vertices X[0], 
, X[𝑛 − 1] the values đ‘„0, 
 , đ‘„đ‘›âˆ’1,apply each gate on the values of its in-neighbors, and then output thevalues that correspond to the output vertices. Formally, this is definedas follows:

Definition 3.6 — Computing a function via a Boolean circuit. Let đ¶ be aBoolean circuit with 𝑛 inputs and 𝑚 outputs. For every đ‘„ ∈ 0, 1𝑛,the output of đ¶ on the input đ‘„, denoted by đ¶(đ‘„), is defined as theresult of the following process:

We let ℎ ∶ 𝑉 → ℕ be the minimal layering of đ¶ (aka topologicalsorting, see Theorem 1.26). We let 𝐿 be the maximum layer of ℎ,and for ℓ = 0, 1, 
 , 𝐿 we do the following:

‱ For every 𝑣 in the ℓ-th layer (i.e., 𝑣 such that ℎ(𝑣) = ℓ) do:

– If 𝑣 is an input vertex labeled with X[𝑖] for some 𝑖 ∈ [𝑛], thenwe assign to 𝑣 the value đ‘„đ‘–.

– If 𝑣 is a gate vertex labeled with ∧ and with two in-neighbors𝑱, đ‘€ then we assign to 𝑣 the AND of the values assigned to𝑱 and đ‘€. (Since 𝑱 and đ‘€ are in-neighbors of 𝑣, they are in alower layer than 𝑣, and hence their values have already beenassigned.)

– If 𝑣 is a gate vertex labeled with √ and with two in-neighbors𝑱, đ‘€ then we assign to 𝑣 the OR of the values assigned to 𝑱and đ‘€.

– If 𝑣 is a gate vertex labeled with ¬ and with one in-neighbor 𝑱then we assign to 𝑣 the negation of the value assigned to 𝑱.

‱ The result of this process is the value 𝑩 ∈ 0, 1𝑚 such that forevery 𝑗 ∈ [𝑚], 𝑩𝑗 is the value assigned to the vertex with labelY[𝑗].Let 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚. We say that the circuit đ¶ computes 𝑓 if

for every đ‘„ ∈ 0, 1𝑛, đ¶(đ‘„) = 𝑓(đ‘„).R

Remark 3.7 — Boolean circuits nitpicks (optional). Inphrasing Definition 3.5, we’ve made some technical

Page 137: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 137

choices that are not very important, but will be con-venient for us later on. Having parallel edges meansan AND or OR gate 𝑱 can have both its in-neighborsbe the same gate 𝑣. Since AND(𝑎, 𝑎) = OR(𝑎, 𝑎) = 𝑎for every 𝑎 ∈ 0, 1, such parallel edges don’t help incomputing new values in circuits with AND/OR/NOTgates. However, we will see circuits with more gen-eral sets of gates later on. The condition that everyinput vertex has at least one out-neighbor is also notvery important because we can always add “dummygates” that touch these inputs. However, it is conve-nient since it guarantees that (since every gate has atmost two in-neighbors) that the number of inputs in acircuit is never larger than twice its size.

3.3.2 Equivalence of circuits and straight-line programsWe have seen two ways to describe how to compute a function 𝑓 usingAND, OR and NOT:

‱ A Boolean circuit, defined in Definition 3.5, computes 𝑓 by connect-ing via wires AND, OR, and NOT gates to the inputs.

‱ We can also describe such a computation using a straight-lineprogram that has lines of the form foo = AND(bar,blah), foo =OR(bar,blah) and foo = NOT(bar)where foo, bar and blah arevariable names. (We call this a straight-line program since it containsno loops or branching (e.g., if/then) statements.)

We now formally define the AON-CIRC programming language(“AON” stands for AND/OR/NOT; “CIRC” stands for circuit) whichhas the above operations, and show that it is equivalent to Booleancircuits.

Definition 3.8 — AON-CIRC Programming language. An AON-CIRC pro-gram is a string of lines of the form foo = AND(bar,blah), foo= OR(bar,blah) and foo = NOT(bar)where foo, bar and blahare variable names. 2 Variables of the form X[𝑖] are known asinput variables, and variables of the form Y[𝑗] are known as outputvariables. In every line, the variables on the righthand side of theassignment operators must either be input variables or variablesthat have already been assigned a value.

A valid AON-CIRC program 𝑃 includes input variables of theform X[0],
,X[𝑛 − 1] and output variables of the form Y[0],
,Y[𝑚 − 1] for some 𝑛, 𝑚 ≄ 1. If 𝑃 is valid AON-CIRC program andđ‘„ ∈ 0, 1𝑛, then we define the output of 𝑃 on input đ‘„, denoted by𝑃(đ‘„), to be the string 𝑩 ∈ 0, 1𝑚 corresponding to the values ofthe output variables Y[0] ,
, Y[𝑚 − 1] in the execution of 𝑃 where

Page 138: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

138 introduction to theoretical computer science

2 We follow the common programming languagesconvention of using names such as foo, bar, baz,blah as stand-ins for generic identifiers. A variableidentifier in our programming language can beany combination of letters, numbers, underscores,and brackets. The appendix contains a full formalspecification of our programming language.

we initialize the input variables X[0],
,X[𝑛 − 1] to the valuesđ‘„0, 
 , đ‘„đ‘›âˆ’1.We say that such an AON-CIRC program 𝑃 computes a function𝑓 ∶ 0, 1𝑛 → 0, 1𝑚 if 𝑃(đ‘„) = 𝑓(đ‘„) for every đ‘„ ∈ 0, 1𝑛.

AON-CIRC is not a practical programming language: it was de-signed for pedagogical purposes only, as a way to model computationas composition of AND, OR, and NOT. However, AON-CIRC can stillbe easily implemented on a computer. The following solved exercisegives an example of an AON-CIRC program.Solved Exercise 3.4 Consider the following function CMP ∶ 0, 14 →0, 1 that on four input bits 𝑎, 𝑏, 𝑐, 𝑑 ∈ 0, 1, outputs 1 iff the numberrepresented by (𝑎, 𝑏) is larger than the number represented by (𝑐, 𝑑).That is CMP(𝑎, 𝑏, 𝑐, 𝑑) = 1 iff 2𝑎 + 𝑏 > 2𝑐 + 𝑑.

Write an AON-CIRC program to compute CMP.

Solution:

Writing such a program is tedious but not truly hard. To com-pare two numbers we first compare their most significant digit,and then go down to the next digit and so on and so forth. In thiscase where the numbers have just two binary digits, these compar-isons are particularly simple. The number represented by (𝑎, 𝑏) islarger than the number represented by (𝑐, 𝑑) if and only if one ofthe following conditions happens:

1. The most significant bit 𝑎 of (𝑎, 𝑏) is larger than the most signifi-cant bit 𝑐 of (𝑐, 𝑑).or

2. The two most significant bits 𝑎 and 𝑐 are equal, but 𝑏 > 𝑑.Another way to express the same condition is the following: the

number (𝑎, 𝑏) is larger than (𝑐, 𝑑) iff 𝑎 > 𝑐 OR (𝑎 ≄ 𝑐 AND 𝑏 > 𝑑).For binary digits đ›Œ, đ›œ, the condition đ›Œ > đ›œ is simply that đ›Œ = 1

and đ›œ = 0 or AND(đ›Œ,NOT(đ›œ)) = 1, and the condition đ›Œ ≄ đ›œ is sim-ply OR(đ›Œ,NOT(đ›œ)) = 1. Together these observations can be used togive the following AON-CIRC program to compute CMP:

temp_1 = NOT(X[2])temp_2 = AND(X[0],temp_1)temp_3 = OR(X[0],temp_1)temp_4 = NOT(X[3])

Page 139: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 139

Figure 3.12: A circuit for computing the CMP function.The evaluation of this circuit on (1, 1, 1, 0) yields theoutput 1, since the number 3 (represented in binaryas 11) is larger than the number 2 (represented inbinary as 10).

temp_5 = AND(X[1],temp_4)temp_6 = AND(temp_5,temp_3)Y[0] = OR(temp_2,temp_6)

We can also present this 8-line program as a circuit with 8 gates,see Fig. 3.12.

It turns out that AON-CIRC programs and Boolean circuits haveexactly the same power:

Theorem 3.9 — Equivalence of circuits and straight-line programs. Let𝑓 ∶ 0, 1𝑛 → 0, 1𝑚 and 𝑠 ≄ 𝑚 be some number. Then 𝑓 iscomputable by a Boolean circuit of 𝑠 gates if and only if 𝑓 is com-putable by an AON-CIRC program of 𝑠 lines.

Proof Idea:

The idea is simple - AON-CIRC programs and Boolean circuitsare just different ways of describing the exact same computationalprocess. For example, an AND gate in a Boolean circuit correspondingto computing the AND of two previously-computed values. In a AON-CIRC program this will correspond to the line that stores in a variablethe AND of two previously-computed variables.⋆

PThis proof of Theorem 3.9 is simple at heart, but allthe details it contains can make it a little cumbersometo read. You might be better off trying to work it outyourself before reading it. Our GitHub repository con-tains a “proof by Python” of Theorem 3.9: implemen-tation of functions circuit2prog and prog2circuitsmapping Boolean circuits to AON-CIRC programs andvice versa.

Proof of Theorem 3.9. Let 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚. Since the theorem is an“if and only if” statement, to prove it we need to show both directions:translating an AON-CIRC program that computes 𝑓 into a circuit thatcomputes 𝑓 , and translating a circuit that computes 𝑓 into an AON-CIRC program that does so.

We start with the first direction. Let 𝑃 be an 𝑠 line AON-CIRC thatcomputes 𝑓 . We define a circuit đ¶ as follows: the circuit will have 𝑛inputs and 𝑠 gates. For every 𝑖 ∈ [𝑠], if the 𝑖-th line has the form foo= AND(bar,blah) then the 𝑖-th gate in the circuit will be an ANDgate that is connected to gates 𝑗 and 𝑘 where 𝑗 and 𝑘 correspond tothe last lines before 𝑖 where the variables bar and blah (respectively)

Page 140: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

140 introduction to theoretical computer science

Figure 3.13: Two equivalent descriptions of the sameAND/OR/NOT computation as both an AON pro-gram and a Boolean circuit.

where written to. (For example, if 𝑖 = 57 and the last line bar waswritten to is 35 and the last line blah was written to is 17 then the twoin-neighbors of gate 57 will be gates 35 and 17.) If either bar or blah isan input variable then we connect the gate to the corresponding inputvertex instead. If foo is an output variable of the form Y[𝑗] then weadd the same label to the corresponding gate to mark it as an outputgate. We do the analogous operations if the 𝑖-th line involves an ORor a NOT operation (except that we use the corresponding OR or NOTgate, and in the latter case have only one in-neighbor instead of two).For every input đ‘„ ∈ 0, 1𝑛, if we run the program 𝑃 on đ‘„, then thevalue written that is computed in the 𝑖-th line is exactly the valuethat will be assigned to the 𝑖-th gate if we evaluate the circuit đ¶ on đ‘„.Hence đ¶(đ‘„) = 𝑃(đ‘„) for every đ‘„ ∈ 0, 1𝑛.

For the other direction, let đ¶ be a circuit of 𝑠 gates and 𝑛 inputs thatcomputes the function 𝑓 . We sort the gates according to a topologicalorder and write them as 𝑣0, 
 , 𝑣𝑠−1. We now can create a program𝑃 of 𝑠 lines as follows. For every 𝑖 ∈ [𝑠], if 𝑣𝑖 is an AND gate within-neighbors 𝑣𝑗, 𝑣𝑘 then we will add a line to 𝑃 of the form temp_𝑖= AND(temp_𝑗,temp_𝑘), unless one of the vertices is an input vertexor an output gate, in which case we change this to the form X[.] orY[.] appropriately. Because we work in topological ordering, we areguaranteed that the in-neighbors 𝑣𝑗 and 𝑣𝑘 correspond to variablesthat have already been assigned a value. We do the same for OR andNOT gates. Once again, one can verify that for every input đ‘„, thevalue 𝑃(đ‘„) will equal đ¶(đ‘„) and hence the program computes thesame function as the circuit. (Note that since đ¶ is a valid circuit, perDefinition 3.5, every input vertex of đ¶ has at least one out-neighborand there are exactly 𝑚 output gates labeled 0, 
 , 𝑚 − 1; hence all thevariables X[0], 
, X[𝑛 − 1] and Y[0] ,
, Y[𝑚 − 1] will appear in theprogram 𝑃 .)

3.4 PHYSICAL IMPLEMENTATIONS OF COMPUTING DEVICES (DI-GRESSION)

Computation is an abstract notion that is distinct from its physicalimplementations. While most modern computing devices are obtainedby mapping logical gates to semiconductor based transistors, overhistory people have computed using a huge variety of mechanisms,including mechanical systems, gas and liquid (known as fluidics),biological and chemical processes, and even living creatures (e.g., seeFig. 3.14 or this video for how crabs or slime mold can be used to docomputations).

Page 141: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 141

Figure 3.14: Crab-based logic gates from the paper“Robust soldier-crab ball gate” by Gunji, Nishiyamaand Adamatzky. This is an example of an AND gatethat relies on the tendency of two swarms of crabsarriving from different directions to combine to asingle swarm that continues in the average of thedirections.

Figure 3.15: We can implement the logic of transistorsusing water. The water pressure from the gate closesor opens a faucet between the source and the sink.

In this section we will review some of these implementations, bothso you can get an appreciation of how it is possible to directly translateBoolean circuits to the physical world, without going through the en-tire stack of architecture, operating systems, and compilers, as well asto emphasize that silicon-based processors are by no means the onlyway to perform computation. Indeed, as we will see in Chapter 23,a very exciting recent line of work involves using different media forcomputation that would allow us to take advantage of quantum me-chanical effects to enable different types of algorithms.

Such a cool way to explain logic gates. pic.twitter.com/6Wgu2ZKFCx— Lionel Page (@page_eco) October 28, 2019

3.4.1 TransistorsA transistor can be thought of as an electric circuit with two inputs,known as the source and the gate and an output, known as the sink.The gate controls whether current flows from the source to the sink. Ina standard transistor, if the gate is “ON” then current can flow from thesource to the sink and if it is “OFF” then it can’t. In a complementarytransistor this is reversed: if the gate is “OFF” then current can flowfrom the source to the sink and if it is “ON” then it can’t.

There are several ways to implement the logic of a transistor. Forexample, we can use faucets to implement it using water pressure(e.g. Fig. 3.15). This might seem as merely a curiosity, but there isa field known as fluidics concerned with implementing logical op-erations using liquids or gasses. Some of the motivations includeoperating in extreme environmental conditions such as in space or abattlefield, where standard electronic equipment would not survive.

The standard implementations of transistors use electrical current.One of the original implementations used vacuum tubes. As its nameimplies, a vacuum tube is a tube containing nothing (i.e., a vacuum)and where a priori electrons could freely flow from the source (awire) to the sink (a plate). However, there is a gate (a grid) betweenthe two, where modulating its voltage can block the flow of electrons.

Early vacuum tubes were roughly the size of lightbulbs (andlooked very much like them too). In the 1950’s they were supplantedby transistors, which implement the same logic using semiconduc-tors which are materials that normally do not conduct electricity butwhose conductivity can be modified and controlled by inserting impu-rities (“doping”) and applying an external electric field (this is knownas the field effect). In the 1960’s computers started to be implementedusing integrated circuits which enabled much greater density. In 1965,Gordon Moore predicted that the number of transistors per integratedcircuit would double every year (see Fig. 3.16), and that this wouldlead to “such wonders as home computers —or at least terminals con-

Page 142: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

142 introduction to theoretical computer science

Figure 3.16: The number of transistors per integratedcircuits from 1959 till 1965 and a prediction that ex-ponential growth will continue for at least anotherdecade. Figure taken from “Cramming More Com-ponents onto Integrated Circuits”, Gordon Moore,1965

Figure 3.17: Cartoon from Gordon Moore’s article“predicting” the implications of radically improvingtransistor density.

Figure 3.18: The exponential growth in computingpower over the last 120 years. Graph by Steve Jurvet-son, extending a prior graph of Ray Kurzweil.

Figure 3.19: Implementing logical gates using transis-tors. Figure taken from Rory Mangles’ website.

nected to a central computer— automatic controls for automobiles,and personal portable communications equipment”. Since then, (ad-justed versions of) this so-called “Moore’s law” have been runningstrong, though exponential growth cannot be sustained forever, andsome physical limitations are already becoming apparent.

3.4.2 Logical gates from transistorsWe can use transistors to implement various Boolean functions such asAND, OR, and NOT. For each a two-input gate đș ∶ 0, 12 → 0, 1,such an implementation would be a system with two input wires đ‘„, 𝑩and one output wire 𝑧, such that if we identify high voltage with “1”and low voltage with “0”, then the wire 𝑧 will equal to “1” if and onlyif applying đș to the values of the wires đ‘„ and 𝑩 is 1 (see Fig. 3.19 andFig. 3.20). This means that if there exists a AND/OR/NOT circuit tocompute a function 𝑔 ∶ 0, 1𝑛 → 0, 1𝑚, then we can compute 𝑔 inthe physical world using transistors as well.

3.4.3 Biological computingComputation can be based on biological or chemical systems. For ex-ample the lac operon produces the enzymes needed to digest lactoseonly if the conditions đ‘„ ∧ (¬𝑩) hold where đ‘„ is “lactose is present” and𝑩 is “glucose is present”. Researchers have managed to create transis-tors, and from them logic gates, based on DNA molecules (see alsoFig. 3.21). One motivation for DNA computing is to achieve increasedparallelism or storage density; another is to create “smart biologicalagents” that could perhaps be injected into bodies, replicate them-selves, and fix or kill cells that were damaged by a disease such ascancer. Computing in biological systems is not restricted, of course, toDNA: even larger systems such as flocks of birds can be considered ascomputational processes.

3.4.4 Cellular automata and the game of lifeCellular automata is a model of a system composed of a sequence ofcells, each of which can have a finite state. At each step, a cell updatesits state based on the states of its neighboring cells and some simplerules. As we will discuss later in this book (see Section 8.4), cellularautomata such as Conway’s “Game of Life” can be used to simulatecomputation gates .

3.4.5 Neural networksOne computation device that we all carry with us is our own brain.Brains have served humanity throughout history, doing computationsthat range from distinguishing prey from predators, through makingscientific discoveries and artistic masterpieces, to composing witty 280character messages. The exact working of the brain is still not fully

Page 143: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 143

Figure 3.20: Implementing a NAND gate (see Sec-tion 3.5) using transistors.

Figure 3.21: Performance of DNA-based logic gates.Figure taken from paper of Bonnet et al, Science, 2013.

Figure 3.22: An AND gate using a “Game of Life”configuration. Figure taken from Jean-PhilippeRennard’s paper.

understood, but one common mathematical model for it is a (verylarge) neural network.

A neural network can be thought of as a Boolean circuit that insteadof AND/OR/NOT uses some other gates as the basic basis. For exam-ple, one particular basis we can use are threshold gates. For every vectorđ‘€ = (đ‘€0, 
 , đ‘€đ‘˜âˆ’1) of integers and integer 𝑡 (some or all of whichcould be negative), the threshold function corresponding to đ‘€, 𝑡 is thefunction đ‘‡đ‘€,𝑡 ∶ 0, 1𝑘 → 0, 1 that maps đ‘„ ∈ 0, 1𝑘 to 1 if and only if∑𝑘−1𝑖=0 đ‘€đ‘–đ‘„đ‘– ≄ 𝑡. For example, the threshold function đ‘‡đ‘€,𝑡 correspond-ing to đ‘€ = (1, 1, 1, 1, 1) and 𝑡 = 3 is simply the majority function MAJ5on 0, 15. Threshold gates can be thought of as an approximation forneuron cells that make up the core of human and animal brains. To afirst approximation, a neuron has 𝑘 inputs and a single output, andthe neurons “fires” or “turns on” its output when those signals passsome threshold.

Many machine learning algorithms use artificial neural networkswhose purpose is not to imitate biology but rather to perform somecomputational tasks, and hence are not restricted to threshold orother biologically-inspired gates. Generally, a neural network is oftendescribed as operating on signals that are real numbers, rather than0/1 values, and where the output of a gate on inputs đ‘„0, 
 , đ‘„đ‘˜âˆ’1 isobtained by applying 𝑓(∑𝑖 đ‘€đ‘–đ‘„đ‘–) where 𝑓 ∶ ℝ → ℝ is an activationfunction such as rectified linear unit (ReLU), Sigmoid, or many others(see Fig. 3.23). However, for the purposes of our discussion, all ofthe above are equivalent (see also Exercise 3.13). In particular we canreduce the setting of real inputs to binary inputs by representing areal number in the binary basis, and multiplying the weight of the bitcorresponding to the 𝑖𝑡ℎ digit by 2𝑖.3.4.6 A computer made from marbles and pipesWe can implement computation using many other physical media,without any electronic, biological, or chemical components. Manysuggestions for mechanical computers have been put forward, goingback at least to Gottfried Leibniz’ computing machines from the 1670sand Charles Babbage’s 1837 plan for a mechanical “Analytical Engine”.As one example, Fig. 3.24 shows a simple implementation of a NAND(negation of AND, see Section 3.5) gate using marbles going throughpipes. We represent a logical value in 0, 1 by a pair of pipes, suchthat there is a marble flowing through exactly one of the pipes. Wecall one of the pipes the “0 pipe” and the other the “1 pipe”, and sothe identity of the pipe containing the marble determines the logicalvalue. A NAND gate corresponds to a mechanical object with twopairs of incoming pipes and one pair of outgoing pipes, such that forevery 𝑎, 𝑏 ∈ 0, 1, if two marbles are rolling toward the object in the

Page 144: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

144 introduction to theoretical computer science

Figure 3.23: Common activation functions used inNeural Networks, including rectified linear units(ReLU), sigmoids, and hyperbolic tangent. All ofthose can be thought of as continuous approximationsto simple the step function. All of these can be usedto compute the NAND gate (see Exercise 3.13). Thisproperty enables neural networks to (approximately)compute any function that can be computed by aBoolean circuit.

Figure 3.24: A physical implementation of a NANDgate using marbles. Each wire in a Boolean circuit ismodeled by a pair of pipes representing the values0 and 1 respectively, and hence a gate has four inputpipes (two for each logical input) and two outputpipes. If one of the input pipes representing the value0 has a marble in it then that marble will flow to theoutput pipe representing the value 1. (The dashedline represents a gadget that will ensure that at mostone marble is allowed to flow onward in the pipe.)If both the input pipes representing the value 1 havemarbles in them, then the first marble will be stuckbut the second one will flow onwards to the outputpipe representing the value 0.

Figure 3.25: A “gadget” in a pipe that ensures that atmost one marble can pass through it. The first marblethat passes causes the barrier to lift and block newones.

𝑎 pipe of the first pair and the 𝑏 pipe of the second pair, then a marblewill roll out of the object in the NAND(𝑎, 𝑏)-pipe of the outgoing pair.In fact, there is even a commercially-available educational game thatuses marbles as a basis of computing, see Fig. 3.26.

3.5 THE NAND FUNCTION

The NAND function is another simple function that is extremely use-ful for defining computation. It is the function mapping 0, 12 to0, 1 defined by:

NAND(𝑎, 𝑏) = ⎧⎚⎩0 𝑎 = 𝑏 = 11 otherwise. (3.9)

As its name implies, NAND is the NOT of AND (i.e., NAND(𝑎, 𝑏) =NOT(AND(𝑎, 𝑏))), and so we can clearly compute NAND using ANDand NOT. Interestingly, the opposite direction holds as well:

Theorem 3.10 — NAND computes AND,OR,NOT. We can compute AND,OR, and NOT by composing only the NAND function.

Proof. We start with the following observation. For every 𝑎 ∈ 0, 1,AND(𝑎, 𝑎) = 𝑎. Hence, NAND(𝑎, 𝑎) = NOT(AND(𝑎, 𝑎)) = NOT(𝑎).This means that NAND can compute NOT. By the principle of “dou-ble negation”, AND(𝑎, 𝑏) = NOT(NOT(AND(𝑎, 𝑏))), and hencewe can use NAND to compute AND as well. Once we can computeAND and NOT, we can compute OR using “De Morgan’s Law”:OR(𝑎, 𝑏) = NOT(AND(NOT(𝑎),NOT(𝑏))) (which can also be writ-ten as 𝑎 ∹ 𝑏 = 𝑎 ∧ 𝑏) for every 𝑎, 𝑏 ∈ 0, 1.

PTheorem 3.10’s proof is very simple, but you shouldmake sure that (i) you understand the statement ofthe theorem, and (ii) you follow its proof. In partic-ular, you should make sure you understand why DeMorgan’s law is true.

We can use NAND to compute many other functions, as demon-strated in the following exercise.Solved Exercise 3.5 — Compute majority with NAND. Let MAJ ∶ 0, 13 →0, 1 be the function that on input 𝑎, 𝑏, 𝑐 outputs 1 iff 𝑎 + 𝑏 + 𝑐 ≄ 2.Show how to compute MAJ using a composition of NAND’s.

Page 145: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 145

Figure 3.26: The game “Turing Tumble” contains animplementation of logical gates using marbles.

Figure 3.27: A circuit with NAND gates to computethe Majority function on three bits

Solution:

Recall that (3.5) states that

MAJ(đ‘„0, đ‘„1, đ‘„2) = OR (AND(đ‘„0, đ‘„1) , OR(AND(đ‘„1, đ‘„2) , AND(đ‘„0, đ‘„2)) ) .(3.10)

We can use Theorem 3.10 to replace all the occurrences of ANDand OR with NAND’s. Specifically, we can use the equivalenceAND(𝑎, 𝑏) = NOT(NAND(𝑎, 𝑏)), OR(𝑎, 𝑏) = NAND(NOT(𝑎),NOT(𝑏)),and NOT(𝑎) = NAND(𝑎, 𝑎) to replace the righthand side of(3.10) with an expression involving only NAND, yielding thatMAJ(𝑎, 𝑏, 𝑐) is equivalent to the (somewhat unwieldy) expression

NAND(NAND(NAND(NAND(𝑎, 𝑏),NAND(𝑎, 𝑐)),NAND(NAND(𝑎, 𝑏),NAND(𝑎, 𝑐)) ),

NAND(𝑏, 𝑐) ) (3.11)

The same formula can also be expressed as a circuit with NANDgates, see Fig. 3.27.

3.5.1 NAND CircuitsWe define NAND Circuits as circuits in which all the gates are NANDoperations. Such a circuit again corresponds to a directed acyclicgraph (DAG) since all the gates correspond to the same function (i.e.,NAND), we do not even need to label them, and all gates have in-degree exactly two. Despite their simplicity, NAND circuits can bequite powerful.

Example 3.11 — đ‘đŽđ‘đ· circuit for 𝑋𝑂𝑅. Recall the XOR functionwhich maps đ‘„0, đ‘„1 ∈ 0, 1 to đ‘„0 + đ‘„1 mod 2. We have seen inSection 3.2.2 that we can compute XOR using AND, OR, and NOT,and so by Theorem 3.10 we can compute it using only NAND’s.However, the following is a direct construction of computing XORby a sequence of NAND operations:

1. Let 𝑱 = NAND(đ‘„0, đ‘„1).2. Let 𝑣 = NAND(đ‘„0, 𝑱)3. Let đ‘€ = NAND(đ‘„1, 𝑱).4. The XOR of đ‘„0 and đ‘„1 is 𝑩0 = NAND(𝑣, đ‘€).

Page 146: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

146 introduction to theoretical computer science

Figure 3.28: A circuit with NAND gates to computethe XOR of two bits.

One can verify that this algorithm does indeed compute XORby enumerating all the four choices for đ‘„0, đ‘„1 ∈ 0, 1. We can alsorepresent this algorithm graphically as a circuit, see Fig. 3.28.

In fact, we can show the following theorem:

Theorem 3.12 — NAND is a universal operation. For every Boolean circuitđ¶ of 𝑠 gates, there exists a NAND circuit đ¶â€Č of at most 3𝑠 gates thatcomputes the same function as đ¶.

Proof Idea:

The idea of the proof is to just replace every AND, OR and NOTgate with their NAND implementation following the proof of Theo-rem 3.10.⋆Proof of Theorem 3.12. If đ¶ is a Boolean circuit, then since, as we’veseen in the proof of Theorem 3.10, for every 𝑎, 𝑏 ∈ 0, 1‱ NOT(𝑎) = NAND(𝑎, 𝑎)‱ AND(𝑎, 𝑏) = NAND(NAND(𝑎, 𝑏),NAND(𝑎, 𝑏))‱ OR(𝑎, 𝑏) = NAND(NAND(𝑎, 𝑎),NAND(𝑏, 𝑏))

we can replace every gate of đ¶ with at most three NAND gates toobtain an equivalent circuit đ¶â€Č. The resulting circuit will have at most3𝑠 gates.

Big Idea 3 Two models are equivalent in power if they can be usedto compute the same set of functions.

3.5.2 More examples of NAND circuits (optional)Here are some more sophisticated examples of NAND circuits:

Incrementing integers. Consider the task of computing, given as inputa string đ‘„ ∈ 0, 1𝑛 that represents a natural number 𝑋 ∈ ℕ, therepresentation of 𝑋 + 1. That is, we want to compute the functionINC𝑛 ∶ 0, 1𝑛 → 0, 1𝑛+1 such that for every đ‘„0, 
 , đ‘„đ‘›âˆ’1, INC𝑛(đ‘„) =𝑩 which satisfies ∑𝑛𝑖=0 𝑩𝑖2𝑖 = (∑𝑛−1𝑖=0 đ‘„đ‘–2𝑖) + 1. (For simplicity ofnotation, in this example we use the representation where the leastsignificant digit is first rather than last.)

The increment operation can be very informally described as fol-lows: “Add 1 to the least significant bit and propagate the carry”. A little

Page 147: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 147

Figure 3.29: NAND circuit with computing the incre-ment function on 4 bits.

more precisely, in the case of the binary representation, to obtain theincrement of đ‘„, we scan đ‘„ from the least significant bit onwards, andflip all 1’s to 0’s until we encounter a bit equal to 0, in which case weflip it to 1 and stop.

Thus we can compute the increment of đ‘„0, 
 , đ‘„đ‘›âˆ’1 by doing thefollowing:

Algorithm 3.13 — Compute Increment Function.

Input: đ‘„0, đ‘„1, 
 , đ‘„đ‘›âˆ’1 representing the number ∑𝑛−1𝑖=0 đ‘„đ‘– ⋅ 2𝑖# we use LSB-first representation

Output: 𝑩 ∈ 0, 1𝑛+1 such that ∑𝑛𝑖=0 𝑩𝑖 ⋅2𝑖 = ∑𝑛−1𝑖=0 đ‘„đ‘– ⋅2𝑖+11: Let 𝑐0 ← 1 # we pretend we have a ”carry” of 1 initially2: for 𝑖 = 0, 
 , 𝑛 − 1 do3: Let 𝑩𝑖 ← 𝑋𝑂𝑅(đ‘„đ‘–, 𝑐𝑖).4: if 𝑐𝑖 = đ‘„đ‘– = 1 then5: 𝑐𝑖+1 = 16: else7: 𝑐𝑖+1 = 08: end if9: end for

10: Let 𝑩𝑛 ← 𝑐𝑛.Algorithm 3.13 describes precisely how to compute the increment

operation, and can be easily transformed into Python code that per-forms the same computation, but it does not seem to directly yielda NAND circuit to compute this. However, we can transform thisalgorithm line by line to a NAND circuit. For example, since for ev-ery 𝑎, NAND(𝑎,NOT(𝑎)) = 1, we can replace the initial statement𝑐0 = 1 with 𝑐0 = NAND(đ‘„0,NAND(đ‘„0, đ‘„0)). We already knowhow to compute XOR using NAND and so we can use this to im-plement the operation 𝑩𝑖 ← XOR(đ‘„đ‘–, 𝑐𝑖). Similarly, we can writethe “if” statement as saying 𝑐𝑖+1 ← AND(𝑐𝑖, đ‘„đ‘–), or in other words𝑐𝑖+1 ← NAND(NAND(𝑐𝑖, đ‘„đ‘–),NAND(𝑐𝑖, đ‘„đ‘–)). Finally, the assignment𝑩𝑛 = 𝑐𝑛 can be written as 𝑩𝑛 = NAND(NAND(𝑐𝑛, 𝑐𝑛),NAND(𝑐𝑛, 𝑐𝑛)).Combining these observations yields for every 𝑛 ∈ ℕ, a NAND circuitto compute INC𝑛. For example, Fig. 3.29 shows what this circuit lookslike for 𝑛 = 4.From increment to addition. Once we have the increment operation,we can certainly compute addition by repeatedly incrementing (i.e.,compute đ‘„+𝑩 by performing INC(đ‘„) 𝑩 times). However, that would bequite inefficient and unnecessary. With the same idea of keeping trackof carries we can implement the “grade-school” addition algorithmand compute the function ADD𝑛 ∶ 0, 12𝑛 → 0, 1𝑛+1 that on

Page 148: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

148 introduction to theoretical computer science

input đ‘„ ∈ 0, 12𝑛 outputs the binary representation of the sum of thenumbers represented by đ‘„0, 
 , đ‘„đ‘›âˆ’1 and đ‘„đ‘›+1, 
 , đ‘„đ‘›:

Algorithm 3.14 — Addition using NAND.

Input: 𝑱 ∈ 0, 1𝑛, 𝑣 ∈ 0, 1𝑛 representing numbers inLSB-first binary representation.

Output: LSB-first binary representation of đ‘„ + 𝑩.1: Let 𝑐0 ← 02: for 𝑖 = 0, 
 , 𝑛 − 1 do3: Let 𝑩𝑖 ← 𝑱𝑖 + 𝑣𝑖 mod 24: if 𝑱𝑖 + 𝑣𝑖 + 𝑐𝑖 ≄ 2 then5: 𝑐𝑖+1 ← 16: else7: 𝑐𝑖+1 ← 08: end if9: end for

10: Let 𝑩𝑛 ← 𝑐𝑛Once again, Algorithm 3.14 can be translated into a NAND cir-

cuit. The crucial observation is that the “if/then” statement simplycorresponds to 𝑐𝑖+1 ← MAJ3(𝑱𝑖, 𝑣𝑖, 𝑣𝑖) and we have seen in SolvedExercise 3.5 that the function MAJ3 ∶ 0, 13 → 0, 1 can be computedusing NANDs.

3.5.3 The NAND-CIRC Programming languageJust like we did for Boolean circuits, we can define a programming-language analog of NAND circuits. It is even simpler than the AON-CIRC language since we only have a single operation. We define theNAND-CIRC Programming Language to be a programming languagewhere every line has the following form:

foo = NAND(bar,blah)

where foo, bar and blah are variable identifiers.

Example 3.15 — Our first NAND-CIRC program. Here is an example of aNAND-CIRC program:

u = NAND(X[0],X[1])v = NAND(X[0],u)w = NAND(X[1],u)Y[0] = NAND(v,w)

Page 149: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 149

Figure 3.30: A NAND program and the correspondingcircuit. Note how every line in the program corre-sponds to a gate in the circuit.

PDo you know what function this program computes?Hint: you have seen it before.

Formally, just like we did in Definition 3.8 for AON-CIRC, we candefine the notion of computation by a NAND-CIRC program in thenatural way:

Definition 3.16 — Computing by a NAND-CIRC program. Let 𝑓 ∶ 0, 1𝑛 →0, 1𝑚 be some function, and let 𝑃 be a NAND-CIRC program.We say that 𝑃 computes the function 𝑓 if:

1. 𝑃 has 𝑛 input variables X[0], 
 ,X[𝑛−1] and 𝑚 output variablesY[0],
,Y[𝑚 − 1].

2. For every đ‘„ ∈ 0, 1𝑛, if we execute 𝑃 when we assign toX[0], 
 ,X[𝑛 − 1] the values đ‘„0, 
 , đ‘„đ‘›âˆ’1, then at the end ofthe execution, the output variables Y[0],
,Y[𝑚 − 1] have thevalues 𝑩0, 
 , 𝑩𝑚−1 where 𝑩 = 𝑓(đ‘„).

As before we can show that NAND circuits are equivalent toNAND-CIRC programs (see Fig. 3.30):

Theorem 3.17 — NAND circuits and straight-line program equivalence. Forevery 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚 and 𝑠 ≄ 𝑚, 𝑓 is computable by aNAND-CIRC program of 𝑠 lines if and only if 𝑓 is computable by aNAND circuit of 𝑠 gates.

We omit the proof of Theorem 3.17 since it follows along exactlythe same lines as the equivalence of Boolean circuits and AON-CIRCprogram (Theorem 3.9). Given Theorem 3.17 and Theorem 3.12, weknow that we can translate every 𝑠-line AON-CIRC program 𝑃 intoan equivalent NAND-CIRC program of at most 3𝑠 lines. In fact, thistranslation can be easily done by replacing every line of the formfoo = AND(bar,blah), foo = OR(bar,blah) or foo = NOT(bar)with the equivalent 1-3 lines that use the NAND operation. Our GitHubrepository contains a “proof by code”: a simple Python programAON2NAND that transforms an AON-CIRC into an equivalent NAND-CIRC program.

RRemark 3.18 — Is the NAND-CIRC programming languageTuring Complete? (optional note). You might have heardof a term called “Turing Complete” that is sometimes

Page 150: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

150 introduction to theoretical computer science

used to describe programming languages. (If youhaven’t, feel free to ignore the rest of this remark: wedefine this term precisely in Chapter 8.) If so, youmight wonder if the NAND-CIRC programming lan-guage has this property. The answer is no, or perhapsmore accurately, the term “Turing Completeness” isnot really applicable for the NAND-CIRC program-ming language. The reason is that, by design, theNAND-CIRC programming language can only com-pute finite functions đč ∶ 0, 1𝑛 → 0, 1𝑚 that take afixed number of input bits and produce a fixed num-ber of outputs bits. The term “Turing Complete” isonly applicable to programming languages for infinitefunctions that can take inputs of arbitrary length. Wewill come back to this distinction later on in this book.

3.6 EQUIVALENCE OF ALL THESE MODELS

If we put together Theorem 3.9, Theorem 3.12, and Theorem 3.17, weobtain the following result:

Theorem 3.19 — Equivalence between models of finite computation. Forevery sufficiently large 𝑠, 𝑛, 𝑚 and 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚, thefollowing conditions are all equivalent to one another:

‱ 𝑓 can be computed by a Boolean circuit (with ∧, ∹, ¬ gates) of atmost 𝑂(𝑠) gates.

‱ 𝑓 can be computed by an AON-CIRC straight-line program of atmost 𝑂(𝑠) lines.

‱ 𝑓 can be computed by a NAND circuit of at most 𝑂(𝑠) gates.

‱ 𝑓 can be computed by a NAND-CIRC straight-line program of atmost 𝑂(𝑠) lines.

By “𝑂(𝑠)” we mean that the bound is at most 𝑐 ⋅ 𝑠 where 𝑐 is a con-stant that is independent of 𝑛. For example, if 𝑓 can be computed by aBoolean circuit of 𝑠 gates, then it can be computed by a NAND-CIRCprogram of at most 3𝑠 lines, and if 𝑓 can be computed by a NANDcircuit of 𝑠 gates, then it can be computed by an AON-CIRC programof at most 2𝑠 lines.

Proof Idea:

We omit the formal proof, which is obtained by combining Theo-rem 3.9, Theorem 3.12, and Theorem 3.17. The key observation is thatthe results we have seen allow us to translate a program/circuit thatcomputes 𝑓 in one of the above models into a program/circuit that

Page 151: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 151

computes 𝑓 in another model by increasing the lines/gates by at mosta constant factor (in fact this constant factor is at most 3).⋆

Theorem 3.9 is a special case of a more general result. We can con-sider even more general models of computation, where instead ofAND/OR/NOT or NAND, we use other operations (see Section 3.6.1below). It turns out that Boolean circuits are equivalent in power tosuch models as well. The fact that all these different ways to definecomputation lead to equivalent models shows that we are “on theright track”. It justifies the seemingly arbitrary choices that we’vemade of using AND/OR/NOT or NAND as our basic operations,since these choices do not affect the power of our computationalmodel. Equivalence results such as Theorem 3.19 mean that we caneasily translate between Boolean circuits, NAND circuits, NAND-CIRC programs and the like. We will use this ability later on in thisbook, often shifting to the most convenient formulation without mak-ing a big deal about it. Hence we will not worry too much about thedistinction between, for example, Boolean circuits and NAND-CIRCprograms.

In contrast, we will continue to take special care to distinguishbetween circuits/programs and functions (recall Big Idea 2). A func-tion corresponds to a specification of a computational task, and it isa fundamentally different object than a program or a circuit, whichcorresponds to the implementation of the task.

3.6.1 Circuits with other gate setsThere is nothing special about AND/OR/NOT or NAND. For everyset of functions 𝒱 = đș0, 
 , đș𝑘−1, we can define a notion of circuitsthat use elements of 𝒱 as gates, and a notion of a “𝒱 programminglanguage” where every line involves assigning to a variable foo the re-sult of applying some đș𝑖 ∈ 𝒱 to previously defined or input variables.Specifically, we can make the following definition:

Definition 3.20 — General straight-line programs. Let ℱ = 𝑓0, 
 , 𝑓𝑡−1be a finite collection of Boolean functions, such that 𝑓𝑖 ∶ 0, 1𝑘𝑖 →0, 1 for some 𝑘𝑖 ∈ ℕ. An ℱ program is a sequence of lines, each ofwhich assigns to some variable the result of applying some 𝑓𝑖 ∈ ℱto 𝑘𝑖 other variables. As above, we use X[𝑖] and Y[𝑗] to denote theinput and output variables.

We say that ℱ is a universal set of operations (also known as a uni-versal gate set) if there exists a ℱ program to compute the functionNAND.

Page 152: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

152 introduction to theoretical computer science

3 One can also define these functions as taking alength zero input. This makes no difference for thecomputational power of the model.

AON-CIRC programs correspond to đŽđ‘đ·,OR,NOT programs,NAND-CIRC programs corresponds to ℱ programs for the setℱ that only contains the NAND function, but we can also defineIF,ZERO,ONE programs (see below), or use any other set.

We can also define ℱ circuits, which will be directed graphs inwhich each gate corresponds to applying a function 𝑓𝑖 ∈ ℱ, and willeach have 𝑘𝑖 incoming wires and a single outgoing wire. (If the func-tion 𝑓𝑖 is not symmetric, in the sense that the order of its input mattersthen we need to label each wire entering a gate as to which parameterof the function it corresponds to.) As in Theorem 3.9, we can showthat ℱ circuits and ℱ programs are equivalent. We have seen that forℱ = AND,OR,NOT, the resulting circuits/programs are equivalentin power to the NAND-CIRC programming language, as we can com-pute NAND using AND/OR/NOT and vice versa. This turns out to bea special case of a general phenomena— the universality of NAND andother gate sets — that we will explore more in depth later in this book.

Example 3.21 — IF,ZERO,ONE circuits. Let ℱ = IF,ZERO,ONEwhere ZERO ∶ 0, 1 → 0 and ONE ∶ 0, 1 → 1 are theconstant zero and one functions, 3 and IF ∶ 0, 13 → 0, 1 is thefunction that on input (𝑎, 𝑏, 𝑐) outputs 𝑏 if 𝑎 = 1 and 𝑐 otherwise.Then ℱ is universal.

Indeed, we can demonstrate that IF,ZERO,ONE is universalusing the following formula for NAND:

NAND(𝑎, 𝑏) = IF(𝑎, IF(𝑏,ZERO,ONE),ONE) . (3.12)

There are also some sets ℱ that are more restricted in power. Forexample it can be shown that if we use only AND or OR gates (with-out NOT) then we do not get an equivalent model of computation.The exercises cover several examples of universal and non-universalgate sets.

3.6.2 Specification vs. implementation (again)As we discussed in Section 2.6.1, one of the most important distinc-tions in this book is that of specification versus implementation or sep-arating “what” from “how” (see Fig. 3.31). A function correspondsto the specification of a computational task, that is what output shouldbe produced for every particular input. A program (or circuit, or anyother way to specify algorithms) corresponds to the implementation ofhow to compute the desired output from the input. That is, a programis a set of instructions how to compute the output from the input.Even within the same computational model there can be many differ-ent ways to compute the same function. For example, there is more

Page 153: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 153

Figure 3.31: It is crucial to distinguish between thespecification of a computational task, namely what isthe function that is to be computed and the implemen-tation of it, namely the algorithm, program, or circuitthat contains the instructions defining how to mapan input to an output. The same function could becomputed in many different ways.

than one NAND-CIRC program that computes the majority function,more than one Boolean circuit to compute the addition function, andso on and so forth.

Confusing specification and implementation (or equivalently func-tions and programs) is a common mistake, and one that is unfortu-nately encouraged by the common programming-language termi-nology of referring to parts of programs as “functions”. However, inboth the theory and practice of computer science, it is important tomaintain this distinction, and it is particularly important for us in thisbook.

Chapter Recap

‱ An algorithm is a recipe for performing a compu-tation as a sequence of “elementary” or “simple”operations.

‱ One candidate definition for “elementary” opera-tions is the set AND, OR and NOT.

‱ Another candidate definition for an “elementary”operation is the NAND operation. It is an operationthat is easily implementable in the physical worldin a variety of methods including by electronictransistors.

‱ We can use NAND to compute many other func-tions, including majority, increment, and others.

‱ There are other equivalent choices, including thesets đŽđ‘đ·,OR,NOT and IF,ZERO,ONE.

‱ We can formally define the notion of a functionđč ∶ 0, 1𝑛 → 0, 1𝑚 being computable using theNAND-CIRC Programming language.

‱ For every set of basic operations, the notions of be-ing computable by a circuit and being computableby a straight-line program are equivalent.

Page 154: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

154 introduction to theoretical computer science

4 Hint: Use the fact that MAJ(𝑎, 𝑏, 𝑐) = đ‘€đŽđœ(𝑎, 𝑏, 𝑐)to prove that every 𝑓 ∶ 0, 1𝑛 → 0, 1 computableby a circuit with only MAJ and NOT gates satisfies𝑓(0, 0, 
 , 0) ≠ 𝑓(1, 1, 
 , 1). Thanks to NathanBrunelle and David Evans for suggesting this exercise.

3.7 EXERCISES

Exercise 3.1 — Compare 4 bit numbers. Give a Boolean circuit(with AND/OR/NOT gates) that computes the functionCMP8 ∶ 0, 18 → 0, 1 such that CMP8(𝑎0, 𝑎1, 𝑎2, 𝑎3, 𝑏0, 𝑏1, 𝑏2, 𝑏3) = 1if and only if the number represented by 𝑎0𝑎1𝑎2𝑎3 is larger than thenumber represented by 𝑏0𝑏1𝑏2𝑏3.

Exercise 3.2 — Compare 𝑛 bit numbers. Prove that there exists a constant 𝑐such that for every 𝑛 there is a Boolean circuit (with AND/OR/NOTgates) đ¶ of at most 𝑐 ⋅ 𝑛 gates that computes the function CMP2𝑛 ∶0, 12𝑛 → 0, 1 such that CMP2𝑛(𝑎0 ⋯ 𝑎𝑛−1𝑏0 ⋯ 𝑏𝑛−1) = 1 if andonly if the number represented by 𝑎0 ⋯ 𝑎𝑛−1 is larger than the numberrepresented by 𝑏0 ⋯ 𝑏𝑛−1.

Exercise 3.3 — OR,NOT is universal. Prove that the set OR,NOT is univer-sal, in the sense that one can compute NAND using these gates.

Exercise 3.4 — AND,OR is not universal. Prove that for every 𝑛-bit inputcircuit đ¶ that contains only AND and OR gates, as well as gates thatcompute the constant functions 0 and 1, đ¶ is monotone, in the sensethat if đ‘„, đ‘„â€Č ∈ 0, 1𝑛, đ‘„đ‘– ≀ đ‘„â€Č𝑖 for every 𝑖 ∈ [𝑛], then đ¶(đ‘„) ≀ đ¶(đ‘„â€Č).

Conclude that the set AND,OR, 0, 1 is not universal.

Exercise 3.5 — XOR is not universal. Prove that for every 𝑛-bit input circuitđ¶ that contains only XOR gates, as well as gates that compute theconstant functions 0 and 1, đ¶ is affine or linear modulo two, in the sensethat there exists some 𝑎 ∈ 0, 1𝑛 and 𝑏 ∈ 0, 1 such that for everyđ‘„ ∈ 0, 1𝑛, đ¶(đ‘„) = ∑𝑛−1𝑖=0 đ‘Žđ‘–đ‘„đ‘– + 𝑏 mod 2.

Conclude that the set XOR, 0, 1 is not universal.

Exercise 3.6 — MAJ,NOT, 1 is universal. Let MAJ ∶ 0, 13 → 0, 1 be themajority function. Prove that MAJ,NOT, 1 is a universal set of gates.

Exercise 3.7 — MAJ,NOT is not universal. Prove that MAJ,NOT is not auniversal set. See footnote for hint.4

Exercise 3.8 — NOR is universal. Let NOR ∶ 0, 12 → 0, 1 defined asNOR(𝑎, 𝑏) = NOT(OR(𝑎, 𝑏)). Prove that NOR is a universal set ofgates.

Page 155: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 155

5 Thanks to Alec Sun and Simon Fischer for commentson this problem.

6 Hint: Use the conditions of Definition 3.5 stipulatingthat every input vertex has at least one out-neighborand there are exactly 𝑚 output gates. See also Re-mark 3.7.

Exercise 3.9 — Lookup is universal. Prove that LOOKUP1, 0, 1 is a uni-versal set of gates where 0 and 1 are the constant functions andLOOKUP1 ∶ 0, 13 → 0, 1 satisfies LOOKUP1(𝑎, 𝑏, 𝑐) equals 𝑎 if𝑐 = 0 and equals 𝑏 if 𝑐 = 1.

Exercise 3.10 — Bound on universal basis size (challenge). Prove that for ev-ery subset đ” of the functions from 0, 1𝑘 to 0, 1, if đ” is universalthen there is a đ”-circuit of at most 𝑂(1) gates to compute the NANDfunction (you can start by showing that there is a đ” circuit of at most𝑂(𝑘16) gates).5

Exercise 3.11 — Size and inputs / outputs. Prove that for every NAND cir-cuit of size 𝑠 with 𝑛 inputs and 𝑚 outputs, 𝑠 ≄ min𝑛/2, 𝑚. Seefootnote for hint.6

Exercise 3.12 — Threshold using NANDs. Prove that there is some constant𝑐 such that for every 𝑛 > 1, and integers 𝑎0, 
 , 𝑎𝑛−1, 𝑏 ∈ −2𝑛, −2𝑛 +1, 
 , −1, 0, +1, 
 , 2𝑛, there is a NAND circuit with at most 𝑐𝑛4 gatesthat computes the threshold function 𝑓𝑎0,
,𝑎𝑛−1,𝑏 ∶ 0, 1𝑛 → 0, 1 thaton input đ‘„ ∈ 0, 1𝑛 outputs 1 if and only if ∑𝑛−1𝑖=0 đ‘Žđ‘–đ‘„đ‘– > 𝑏.

Exercise 3.13 — NANDs from activation functions. We say that a function𝑓 ∶ ℝ2 → ℝ is a NAND approximator if it has the following property: forevery 𝑎, 𝑏 ∈ ℝ, if min|𝑎|, |1 − 𝑎| ≀ 1/3 and min|𝑏|, |1 − 𝑏| ≀ 1/3 then|𝑓(𝑎, 𝑏) − NAND(⌊𝑎⌉, ⌊𝑏⌉)| ≀ 1/3 where we denote by âŒŠđ‘„âŒ‰ the integerclosest to đ‘„. That is, if 𝑎, 𝑏 are within a distance 1/3 to 0, 1 then wewant 𝑓(𝑎, 𝑏) to equal the NAND of the values in 0, 1 that are closestto 𝑎 and 𝑏 respectively. Otherwise, we do not care what the output of𝑓 is on 𝑎 and 𝑏.

In this exercise you will show that you can construct a NAND ap-proximator from many common activation functions used in deepneural networks. As a corollary you will obtain that deep neural net-works can simulate NAND circuits. Since NAND circuits can alsosimulate deep neural networks, these two computational models areequivalent to one another.

1. Show that there is a NAND approximator 𝑓 defined as 𝑓(𝑎, 𝑏) =𝐿(𝑅𝑒𝐿𝑈(𝐿â€Č(𝑎, 𝑏))) where 𝐿â€Č ∶ ℝ2 → ℝ is an affine function (ofthe form 𝐿â€Č(𝑎, 𝑏) = đ›Œđ‘Ž + đ›œđ‘ + đ›Ÿ for some đ›Œ, đ›œ, đ›Ÿ ∈ ℝ), 𝐿 is anaffine function (of the form 𝐿(𝑩) = đ›Œđ‘Š + đ›œ for đ›Œ, đ›œ ∈ ℝ), and𝑅𝑒𝐿𝑈 ∶ ℝ → ℝ, is the function defined as 𝑅𝑒𝐿𝑈(đ‘„) = max0, đ‘„.

Page 156: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

156 introduction to theoretical computer science

7 One approach to solve this is using recursion andanalyzing it using the so called “Master Theorem”.

8 Hint: Vertices in layers beyond the output can besafely removed without changing the functionality ofthe circuit.

2. Show that there is a NAND approximator 𝑓 defined as 𝑓(𝑎, 𝑏) =𝐿(𝑠𝑖𝑔𝑚𝑜𝑖𝑑(𝐿â€Č(𝑎, 𝑏))) where 𝐿â€Č, 𝐿 are affine as above and 𝑠𝑖𝑔𝑚𝑜𝑖𝑑 ∶ℝ → ℝ is the function defined as 𝑠𝑖𝑔𝑚𝑜𝑖𝑑(đ‘„) = đ‘’đ‘„/(đ‘’đ‘„ + 1).3. Show that there is a NAND approximator 𝑓 defined as 𝑓(𝑎, 𝑏) =𝐿(𝑡𝑎𝑛ℎ(𝐿â€Č(𝑎, 𝑏))) where 𝐿â€Č, 𝐿 are affine as above and 𝑡𝑎𝑛ℎ ∶ ℝ → ℝ

is the function defined as 𝑡𝑎𝑛ℎ(đ‘„) = (đ‘’đ‘„ − đ‘’âˆ’đ‘„)/(đ‘’đ‘„ + đ‘’âˆ’đ‘„).4. Prove that for every NAND-circuit đ¶ with 𝑛 inputs and one output

that computes a function 𝑔 ∶ 0, 1𝑛 → 0, 1, if we replace everygate of đ¶ with a NAND-approximator and then invoke the result-ing circuit on some đ‘„ ∈ 0, 1𝑛, the output will be a number 𝑩 suchthat |𝑩 − 𝑔(đ‘„)| ≀ 1/3.

Exercise 3.14 — Majority with NANDs efficiently. Prove that there is someconstant 𝑐 such that for every 𝑛 > 1, there is a NAND circuit of atmost 𝑐 ⋅ 𝑛 gates that computes the majority function on 𝑛 input bitsMAJ𝑛 ∶ 0, 1𝑛 → 0, 1. That is MAJ𝑛(đ‘„) = 1 iff ∑𝑛−1𝑖=0 đ‘„đ‘– > 𝑛/2. Seefootnote for hint.7

Exercise 3.15 — Output at last layer. Prove that for every 𝑓 ∶ 0, 1𝑛 →0, 1, if there is a Boolean circuit đ¶ of 𝑠 gates that computes 𝑓 thenthere is a Boolean circuit đ¶â€Č of at most 𝑠 gates such that in the minimallayering of đ¶â€Č, the output gate of đ¶â€Č is placed in the last layer. Seefootnote for hint.8

3.8 BIOGRAPHICAL NOTES

The excerpt from Al-Khwarizmi’s book is from “The Algebra of Ben-Musa”, Fredric Rosen, 1831.

Charles Babbage (1791-1871) was a visionary scientist, mathemati-cian, and inventor (see [Swa02; CM00]). More than a century beforethe invention of modern electronic computers, Babbage realized thatcomputation can be in principle mechanized. His first design for amechanical computer was the difference engine that was designed to dopolynomial interpolation. He then designed the analytical engine whichwas a much more general machine and the first prototype for a pro-grammable general purpose computer. Unfortunately, Babbage wasnever able to complete the design of his prototypes. One of the earliestpeople to realize the engine’s potential and far reaching implicationswas Ada Lovelace (see the notes for Chapter 7).

Boolean algebra was first investigated by Boole and DeMorganin the 1840’s [Boo47; De 47]. The definition of Boolean circuits and

Page 157: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

defining computation 157

connection to electrical relay circuits was given in Shannon’s MastersThesis [Sha38]. (Howard Gardener called Shannon’s thesis “possiblythe most important, and also the most famous, master’s thesis of the[20th] century”.) Savage’s book [Sav98], like this one, introducesthe theory of computation starting with Boolean circuits as the firstmodel. Jukna’s book [Juk12] contains a modern in-depth exposition ofBoolean circuits, see also [Weg87].

The NAND function was shown to be universal by Sheffer [She13],though this also appears in the earlier work of Peirce, see [Bur78].Whitehead and Russell used NAND as the basis for their logic intheir magnum opus Principia Mathematica [WR12]. In her Ph.D thesis,Ernst [Ern09] investigates empirically the minimal NAND circuitsfor various functions. Nisan and Shocken’s book [NS05] builds acomputing system starting from NAND gates and ending with highlevel programs and games (“NAND to Tetris”); see also the websitenandtotetris.org.

Page 158: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 159: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

4Syntactic sugar, and computing every function

“[In 1951] I had a running compiler and nobody would touch it because,they carefully told me, computers could only do arithmetic; they could not doprograms.”, Grace Murray Hopper, 1986.

“Syntactic sugar causes cancer of the semicolon.”, Alan Perlis, 1982.

The computational models we considered thus far are as “barebones” as they come. For example, our NAND-CIRC “programminglanguage” has only the single operation foo = NAND(bar,blah). Inthis chapter we will see that these simple models are actually equiv-alent to more sophisticated ones. The key observation is that we canimplement more complex features using our basic building blocks,and then use these new features themselves as building blocks foreven more sophisticated features. This is known as “syntactic sugar”in the field of programming language design since we are not modi-fying the underlying programming model itself, but rather we merelyimplement new features by syntactically transforming a program thatuses such features into one that doesn’t.

This chapter provides a “toolkit” that can be used to show thatmany functions can be computed by NAND-CIRC programs, andhence also by Boolean circuits. We will also use this toolkit to provea fundamental theorem: every finite function 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚can be computed by a Boolean circuit, see Theorem 4.13 below. Whilethe syntactic sugar toolkit is important in its own right, Theorem 4.13can also be proven directly without using this toolkit. We present thisalternative proof in Section 4.5. See Fig. 4.1 for an outline of the resultsof this chapter.

This chapter: A non-mathy overviewIn this chapter we will see our first major result: every fi-nite function can be computed some Boolean circuit (seeTheorem 4.13 and Big Idea 5). This is sometimes known as

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Get comfortable with syntactic sugar or

automatic translation of higher level logic tolow level gates.

‱ Learn proof of major result: every finitefunction can be computed by a Booleancircuit.

‱ Start thinking quantitatively about numberof lines required for computation.

Page 160: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

160 introduction to theoretical computer science

Figure 4.1: An outline of the results of this chapter. InSection 4.1 we give a toolkit of “syntactic sugar” trans-formations showing how to implement features suchas programmer-defined functions and conditionalstatements in NAND-CIRC. We use these tools inSection 4.3 to give a NAND-CIRC program (or alter-natively a Boolean circuit) to compute the LOOKUPfunction. We then build on this result to show in Sec-tion 4.4 that NAND-CIRC programs (or equivalently,Boolean circuits) can compute every finite function.An alternative direct proof of the same result is givenin Section 4.5.

the “universality” of AND, OR, and NOT (and, using theequivalence of Chapter 3, of NAND as well)Despite being an important result, Theorem 4.13 is actuallynot that hard to prove. Section 4.5 presents a relatively sim-ple direct proof of this result. However, in Section 4.1 andSection 4.3 we derive this result using the concept of “syntac-tic sugar” (see Big Idea 4). This is an important concept forprogramming languages theory and practice. The idea be-hind “syntactic sugar” is that we can extend a programminglanguage by implementing advanced features from its basiccomponents. For example, we can take the AON-CIRC andNAND-CIRC programming languages we saw in Chapter 3,and extend them to achieve features such as user-definedfunctions (e.g., def Foo(...)), condtional statements (e.g.,if blah ...), and more. Once we have these features, itis not that hard to show that we can take the “truth table”(table of all inputs and outputs) of any function, and use thatto create an AON-CIRC or NAND-CIRC program that mapseach input to its corresponding output.We will also get our first glimpse of quantitative measures inthis chapter. While Theorem 4.13 tells us that every func-tion can be computed by some circuit, the number of gatesin this circuit can be exponentially large. (We are not usinghere “exponentially” as some colloquial term for “very verybig” but in a very precise mathematical sense, which alsohappens to coincide with being very very big.) It turns outthat some functions (for example, integer addition and multi-

Page 161: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 161

plication) can be in fact computed using far fewer gates. Wewill explore this issue of “gate complexity” more deeply inChapter 5 and following chapters.

4.1 SOME EXAMPLES OF SYNTACTIC SUGAR

We now present some examples of “syntactic sugar” transformationsthat we can use in constructing straightline programs or circuits. Wefocus on the straight-line programming language view of our computa-tional models, and specifically (for the sake of concreteness) on theNAND-CIRC programming language. This is convenient becausemany of the syntactic sugar transformations we present are easiest tothink about in terms of applying “search and replace” operations tothe source code of a program. However, by Theorem 3.19, all of ourresults hold equally well for circuits, whether ones using NAND gatesor Boolean circuits that use the AND, OR, and NOT operations. Enu-merating the examples of such syntactic sugar transformations can bea little tedious, but we do it for two reasons:

1. To convince you that despite their seeming simplicity and limita-tions, simple models such as Boolean circuits or the NAND-CIRCprogramming language are actually quite powerful.

2. So you can realize how lucky you are to be taking a theory of com-putation course and not a compilers course
 :)

4.1.1 User-defined proceduresOne staple of almost any programming language is the ability todefine and then execute procedures or subroutines. (These are oftenknown as functions in some programming languages, but we preferthe name procedures to avoid confusion with the function that a pro-gram computes.) The NAND-CIRC programming language doesnot have this mechanism built in. However, we can achieve the sameeffect using the time honored technique of “copy and paste”. Specifi-cally, we can replace code which defines a procedure such as

def Proc(a,b):proc_codereturn c

some_codef = Proc(d,e)some_more_code

with the following code where we “paste” the code of Proc

Page 162: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

162 introduction to theoretical computer science

some_codeproc_code'some_more_code

and where proc_code' is obtained by replacing all occurrencesof a with d, b with e, and c with f. When doing that we will need toensure that all other variables appearing in proc_code' don’t interferewith other variables. We can always do so by renaming variables tonew names that were not used before. The above reasoning leads tothe proof of the following theorem:

Theorem 4.1 — Procedure definition synctatic sugar. Let NAND-CIRC-PROC be the programming language NAND-CIRC augmentedwith the syntax above for defining procedures. Then for everyNAND-CIRC-PROC program 𝑃 , there exists a standard (i.e.,“sugar free”) NAND-CIRC program 𝑃 â€Č that computes the samefunction as 𝑃 .

RRemark 4.2 — No recursive procedure. NAND-CIRC-PROC only allows non recursive procedures. In particu-lar, the code of a procedure Proc cannot call Proc butonly use procedures that were defined before it. With-out this restriction, the above “search and replace”procedure might never terminate and Theorem 4.1would not be true.

Theorem 4.1 can be proven using the transformation above, butsince the formal proof is somewhat long and tedious, we omit it here.

Example 4.3 — Computing Majority from NAND using syntactic sugar. Pro-cedures allow us to express NAND-CIRC programs much morecleanly and succinctly. For example, because we can computeAND, OR, and NOT using NANDs, we can compute the Majorityfunction as follows:

def NOT(a):return NAND(a,a)

def AND(a,b):temp = NAND(a,b)return NOT(temp)

def OR(a,b):temp1 = NOT(a)temp2 = NOT(b)

Page 163: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 163

return NAND(temp1,temp2)

def MAJ(a,b,c):and1 = AND(a,b)and2 = AND(a,c)and3 = AND(b,c)or1 = OR(and1,and2)return OR(or1,and3)

print(MAJ(0,1,1))# 1

Fig. 4.2 presents the “sugar free” NAND-CIRC program (andthe corresponding circuit) that is obtained by “expanding out” thisprogram, replacing the calls to procedures with their definitions.

Big Idea 4 Once we show that a computational model 𝑋 is equiv-alent to a model that has feature 𝑌 , we can assume we have 𝑌 whenshowing that a function 𝑓 is computable by 𝑋.

Figure 4.2: A standard (i.e., “sugar free”) NAND-CIRC program that is obtained by expanding out theprocedure definitions in the program for Majorityof Example 4.3. The corresponding circuit is onthe right. Note that this is not the most efficientNAND circuit/program for majority: we can save onsome gates by “short cutting” steps where a gate 𝑱computes NAND(𝑣, 𝑣) and then a gate đ‘€ computesNAND(𝑱, 𝑱) (as indicated by the dashed greenarrows in the above figure).

RRemark 4.4 — Counting lines. While we can use syn-tactic sugar to present NAND-CIRC programs in morereadable ways, we did not change the definition ofthe language itself. Therefore, whenever we say thatsome function 𝑓 has an 𝑠-line NAND-CIRC programwe mean a standard “sugar free” NAND-CIRC pro-gram, where all syntactic sugar has been expandedout. For example, the program of Example 4.3 is a12-line program for computing the MAJ function,

Page 164: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

164 introduction to theoretical computer science

even though it can be written in fewer lines usingNAND-CIRC-PROC.

4.1.2 Proof by Python (optional)We can write a Python program that implements the proof of Theo-rem 4.1. This is a Python program that takes a NAND-CIRC-PROCprogram 𝑃 that includes procedure definitions and uses simple“search and replace” to transform 𝑃 into a standard (i.e., “sugarfree”) NAND-CIRC program 𝑃 â€Č that computes the same functionas 𝑃 without using any procedures. The idea is simple: if the program𝑃 contains a definition of a procedure Proc of two arguments x and y,then whenever we see a line of the form foo = Proc(bar,blah), wecan replace this line by:

1. The body of the procedure Proc (replacing all occurrences of x andy with bar and blah respectively).

2. A line foo = exp, where exp is the expression following the re-turn statement in the definition of the procedure Proc.

To make this more robust we add a prefix to the internal variablesused by Proc to ensure they don’t conflict with the variables of 𝑃 ;for simplicity we ignore this issue in the code below though it can beeasily added.

The code of the Python function desugar below achieves such atransformation.

Fig. 4.2 shows the result of applying desugar to the program of Ex-ample 4.3 that uses syntactic sugar to compute the Majority function.Specifically, we first apply desugar to remove usage of the OR func-tion, then apply it to remove usage of the AND function, and finallyapply it a third time to remove usage of the NOT function.

RRemark 4.5 — Parsing function definitions (optional). Thefunction desugar in Fig. 4.3 assumes that it is giventhe procedure already split up into its name, argu-ments, and body. It is not crucial for our purposes todescribe precisely how to scan a definition and split itup into these components, but in case you are curious,it can be achieved in Python via the following code:

def parse_func(code):"""Parse a function definition into name,

arguments and body"""lines = [l.strip() for l in code.split('\n')]regexp = r'def\s+([a-zA-Z\_0-9]+)\(([\sa-zA-

Z0-9\_,]+)\)\s*:\s*'

Page 165: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 165

Figure 4.3: Python code for transforming NAND-CIRC-PROC programs into standard sugar free NAND-CIRC programs.

def desugar(code, func_name, func_args,func_body):"""Replaces all occurences of

foo = func_name(func_args)with

func_body[x->a,y->b]foo = [result returned in func_body]

"""# Uses Python regular expressions to simplify the search and replace,# see https://docs.python.org/3/library/re.html and Chapter 9 of the book

# regular expression for capturing a list of variable names separated by commasarglist = ",".join([r"([a-zA-Z0-9\_\[\]]+)" for i in range(len(func_args))])# regular expression for capturing a statement of the form# "variable = func_name(arguments)"regexp = fr'([a-zA-Z0-9\_\[\]]+)\s*=\s*func_name\(arglist\)\s*$'while True:

m = re.search(regexp, code, re.MULTILINE)if not m: breaknewcode = func_body# replace function arguments by the variables from the function invocationfor i in range(len(func_args)):

newcode = newcode.replace(func_args[i], m.group(i+2))# Splice the new code insidenewcode = newcode.replace('return', m.group(1) + " = ")code = code[:m.start()] + newcode + code[m.end()+1:]

return code

Page 166: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

166 introduction to theoretical computer science

m = re.match(regexp,lines[0])return m.group(1), m.group(2).split(','),

'\n'.join(lines[1:])

4.1.3 Conditional statementsAnother sorely missing feature in NAND-CIRC is a conditionalstatement such as the if/then constructs that are found in manyprogramming languages. However, using procedures, we can ob-tain an ersatz if/then construct. First we can compute the functionIF ∶ 0, 13 → 0, 1 such that IF(𝑎, 𝑏, 𝑐) equals 𝑏 if 𝑎 = 1 and 𝑐 if 𝑎 = 0.

PBefore reading onward, try to see how you could com-pute the IF function using NAND’s. Once you do that,see how you can use that to emulate if/then types ofconstructs.

The IF function can be implemented from NANDs as follows (seeExercise 4.2):

def IF(cond,a,b):notcond = NAND(cond,cond)temp = NAND(b,notcond)temp1 = NAND(a,cond)return NAND(temp,temp1)

The IF function is also known as a multiplexing function, since 𝑐𝑜𝑛𝑑can be thought of as a switch that controls whether the output is con-nected to 𝑎 or 𝑏. Once we have a procedure for computing the IF func-tion, we can implement conditionals in NAND. The idea is that wereplace code of the form

if (condition): assign blah to variable foo

with code of the form

foo = IF(condition, blah, foo)

that assigns to foo its old value when condition equals 0, andassign to foo the value of blah otherwise. More generally we canreplace code of the form

if (cond):a = ...b = ...c = ...

Page 167: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 167

with code of the form

temp_a = ...temp_b = ...temp_c = ...a = IF(cond,temp_a,a)b = IF(cond,temp_b,b)c = IF(cond,temp_c,c)

Using such transformations, we can prove the following theorem.Once again we omit the (not too insightful) full formal proof, thoughsee Section 4.1.2 for some hints on how to obtain it.

Theorem 4.6 — Conditional statements synctatic sugar. Let NAND-CIRC-IF be the programming language NAND-CIRC augmented withif/then/else statements for allowing code to be conditionallyexecuted based on whether a variable is equal to 0 or 1.

Then for every NAND-CIRC-IF program 𝑃 , there exists a stan-dard (i.e., “sugar free”) NAND-CIRC program 𝑃 â€Č that computesthe same function as 𝑃 .

4.2 EXTENDED EXAMPLE: ADDITION AND MULTIPLICATION (OP-TIONAL)

Using “syntactic sugar”, we can write the integer addition function asfollows:

# Add two n-bit integers# Use LSB first notation for simplicitydef ADD(A,B):

Result = [0]*(n+1)Carry = [0]*(n+1)Carry[0] = zero(A[0])for i in range(n):

Result[i] = XOR(Carry[i],XOR(A[i],B[i]))Carry[i+1] = MAJ(Carry[i],A[i],B[i])

Result[n] = Carry[n]return Result

ADD([1,1,1,0,0],[1,0,0,0,0]);;# [0, 0, 0, 1, 0, 0]

where zero is the constant zero function, and MAJ and XOR corre-spond to the majority and XOR functions respectively. While we usePython syntax for convenience, in this example 𝑛 is some fixed integerand so for every such 𝑛, ADD is a finite function that takes as input 2𝑛

Page 168: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

168 introduction to theoretical computer science

1 The value of 𝑐 can be improved to 9, see Exercise 4.5.

Figure 4.5: The number of lines in our NAND-CIRCprogram to add two 𝑛 bit numbers, as a function of𝑛, for 𝑛’s between 1 and 100. This is not the mostefficient program for this task, but the important pointis that it has the form 𝑂(𝑛).

bits and outputs 𝑛 + 1 bits. In particular for every 𝑛 we can removethe loop construct for i in range(n) by simply repeating the code 𝑛times, replacing the value of i with 0, 1, 2, 
 , 𝑛 − 1. By expanding outall the features, for every value of 𝑛 we can translate the above pro-gram into a standard (“sugar free”) NAND-CIRC program. Fig. 4.4depicts what we get for 𝑛 = 2.

Figure 4.4: The NAND-CIRC program and corre-sponding NAND circuit for adding two-digit binarynumbers that are obtained by “expanding out” all thesyntactic sugar. The program/circuit has 43 lines/-gates which is by no means necessary. It is possibleto add 𝑛 bit numbers using 9𝑛 NAND gates, seeExercise 4.5.

By going through the above program carefully and accounting forthe number of gates, we can see that it yields a proof of the followingtheorem (see also Fig. 4.5):

Theorem 4.7 — Addition using NAND-CIRC programs. For every 𝑛 ∈ ℕ,let ADD𝑛 ∶ 0, 12𝑛 → 0, 1𝑛+1 be the function that, givenđ‘„, đ‘„â€Č ∈ 0, 1𝑛 computes the representation of the sum of the num-bers that đ‘„ and đ‘„â€Č represent. Then there is a constant 𝑐 ≀ 30 suchthat for every 𝑛 there is a NAND-CIRC program of at most 𝑐𝑛 linescomputing ADD𝑛. 1

Once we have addition, we can use the grade-school algorithm toobtain multiplication as well, thus obtaining the following theorem:

Theorem 4.8 — Multiplication using NAND-CIRC programs. For every 𝑛,let MULT𝑛 ∶ 0, 12𝑛 → 0, 12𝑛 be the function that, givenđ‘„, đ‘„â€Č ∈ 0, 1𝑛 computes the representation of the product of thenumbers that đ‘„ and đ‘„â€Č represent. Then there is a constant 𝑐 suchthat for every 𝑛, there is a NAND-CIRC program of at most 𝑐𝑛2that computes the function MULT𝑛.We omit the proof, though in Exercise 4.7 we ask you to supply

a “constructive proof” in the form of a program (in your favorite

Page 169: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 169

programming language) that on input a number 𝑛, outputs the codeof a NAND-CIRC program of at most 1000𝑛2 lines that computes theMULT𝑛 function. In fact, we can use Karatsuba’s algorithm to showthat there is a NAND-CIRC program of 𝑂(𝑛log2 3) lines to computeMULT𝑛 (and can get even further asymptotic improvements usingbetter algorithms).

4.3 THE LOOKUP FUNCTION

The LOOKUP function will play an important role in this chapter andlater. It is defined as follows:

Definition 4.9 — Lookup function. For every 𝑘, the lookup function oforder 𝑘, LOOKUP𝑘 ∶ 0, 12𝑘+𝑘 → 0, 1 is defined as follows: Forevery đ‘„ ∈ 0, 12𝑘 and 𝑖 ∈ 0, 1𝑘,

LOOKUP𝑘(đ‘„, 𝑖) = đ‘„đ‘– (4.1)

where đ‘„đ‘– denotes the 𝑖𝑡ℎ entry of đ‘„, using the binary representationto identify 𝑖 with a number in 0, 
 , 2𝑘 − 1.

Figure 4.6: The LOOKUP𝑘 function takes an inputin 0, 12𝑘+𝑘, which we denote by đ‘„, 𝑖 (with đ‘„ ∈0, 12𝑘 and 𝑖 ∈ 0, 1𝑘). The output is đ‘„đ‘–: the 𝑖-thcoordinate of đ‘„, where we identify 𝑖 as a numberin [𝑘] using the binary representation. In the aboveexample đ‘„ ∈ 0, 116 and 𝑖 ∈ 0, 14. Since 𝑖 = 0110is the binary representation of the number 6, theoutput of LOOKUP4(đ‘„, 𝑖) in this case is đ‘„6 = 1.

See Fig. 4.6 for an illustration of the LOOKUP function. It turnsout that for every 𝑘, we can compute LOOKUP𝑘 using a NAND-CIRCprogram:

Theorem 4.10 — Lookup function. For every 𝑘 > 0, there is a NAND-CIRC program that computes the function LOOKUP𝑘 ∶ 0, 12𝑘+𝑘 →0, 1. Moreover, the number of lines in this program is at most4 ⋅ 2𝑘.An immediate corollary of Theorem 4.10 is that for every 𝑘 > 0,

LOOKUP𝑘 can be computed by a Boolean circuit (with AND, OR andNOT gates) of at most 8 ⋅ 2𝑘 gates.

4.3.1 Constructing a NAND-CIRC program for LOOKUPWe prove Theorem 4.10 by induction. For the case 𝑘 = 1, LOOKUP1maps (đ‘„0, đ‘„1, 𝑖) ∈ 0, 13 to đ‘„đ‘–. In other words, if 𝑖 = 0 then it outputs

Page 170: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

170 introduction to theoretical computer science

đ‘„0 and otherwise it outputs đ‘„1, which (up to reordering variables) isthe same as the IF function presented in Section 4.1.3, which can becomputed by a 4-line NAND-CIRC program.

As a warm-up for the case of general 𝑘, let us consider the caseof 𝑘 = 2. Given input đ‘„ = (đ‘„0, đ‘„1, đ‘„2, đ‘„3) for LOOKUP2 and anindex 𝑖 = (𝑖0, 𝑖1), if the most significant bit 𝑖0 of the index is 0 thenLOOKUP2(đ‘„, 𝑖) will equal đ‘„0 if 𝑖1 = 0 and equal đ‘„1 if 𝑖1 = 1. Similarly,if the most significant bit 𝑖0 is 1 then LOOKUP2(đ‘„, 𝑖) will equal đ‘„2 if𝑖1 = 0 and will equal đ‘„3 if 𝑖1 = 1. Another way to say this is that wecan write LOOKUP2 as follows:

def LOOKUP2(X[0],X[1],X[2],X[3],i[0],i[1]):if i[0]==1:

return LOOKUP1(X[2],X[3],i[1])else:

return LOOKUP1(X[0],X[1],i[1])

or in other words,

def LOOKUP2(X[0],X[1],X[2],X[3],i[0],i[1]):a = LOOKUP1(X[2],X[3],i[1])b = LOOKUP1(X[0],X[1],i[1])return IF( i[0],a,b)

More generally, as shown in the following lemma, we can computeLOOKUP𝑘 using two invocations of LOOKUP𝑘−1 and one invocationof IF:Lemma 4.11 — Lookup recursion. For every 𝑘 ≄ 2, LOOKUP𝑘(đ‘„0, 
 , đ‘„2𝑘−1, 𝑖0, 
 , 𝑖𝑘−1)is equal to

IF (𝑖0,LOOKUP𝑘−1(đ‘„2𝑘−1 , 
 , đ‘„2𝑘−1, 𝑖1, 
 , 𝑖𝑘−1),LOOKUP𝑘−1(đ‘„0, 
 , đ‘„2𝑘−1−1, 𝑖1, 
 , 𝑖𝑘−1))(4.2)

Proof. If the most significant bit 𝑖0 of 𝑖 is zero, then the index 𝑖 isin 0, 
 , 2𝑘−1 − 1 and hence we can perform the lookup on the“first half” of đ‘„ and the result of LOOKUP𝑘(đ‘„, 𝑖) will be the same as𝑎 = LOOKUP𝑘−1(đ‘„0, 
 , đ‘„2𝑘−1−1, 𝑖1, 
 , 𝑖𝑘−1). On the other hand, if thismost significant bit 𝑖0 is equal to 1, then the index is in 2𝑘−1, 
 , 2𝑘 −1, in which case the result of LOOKUP𝑘(đ‘„, 𝑖) is the same as 𝑏 =LOOKUP𝑘−1(đ‘„2𝑘−1 , 
 , đ‘„2𝑘−1, 𝑖1, 
 , 𝑖𝑘−1). Thus we can computeLOOKUP𝑘(đ‘„, 𝑖) by first computing 𝑎 and 𝑏 and then outputtingIF(𝑖𝑘−1, 𝑎, 𝑏).

Proof of Theorem 4.10 from Lemma 4.11. Now that we have Lemma 4.11,we can complete the proof of Theorem 4.10. We will prove by induc-tion on 𝑘 that there is a NAND-CIRC program of at most 4 ⋅ (2𝑘 − 1)

Page 171: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 171

Figure 4.7: The number of lines in our implementationof the LOOKUP_k function as a function of 𝑘 (i.e., thelength of the index). The number of lines in ourimplementation is roughly 3 ⋅ 2𝑘.

lines for LOOKUP𝑘. For 𝑘 = 1 this follows by the four line program forIF we’ve seen before. For 𝑘 > 1, we use the following pseudocode:

a = LOOKUP_(k-1)(X[0],...,X[2^(k-1)-1],i[1],...,i[k-1])b = LOOKUP_(k-1)(X[2^(k-1)],...,Z[2^(k-1)],i[1],...,i[k-

1])return IF(i[0],b,a)

If we let 𝐿(𝑘) be the number of lines required for LOOKUP𝑘, thenthe above pseudo-code shows that𝐿(𝑘) ≀ 2𝐿(𝑘 − 1) + 4 . (4.3)

Since under our induction hypothesis 𝐿(𝑘 − 1) ≀ 4(2𝑘−1 − 1), we getthat 𝐿(𝑘) ≀ 2 ⋅ 4(2𝑘−1 − 1) + 4 = 4(2𝑘 − 1) which is what we wantedto prove. See Fig. 4.7 for a plot of the actual number of lines in ourimplementation of LOOKUP𝑘.4.4 COMPUTING EVERY FUNCTION

At this point we know the following facts about NAND-CIRC pro-grams (and so equivalently about Boolean circuits and our otherequivalent models):

1. They can compute at least some non trivial functions.

2. Coming up with NAND-CIRC programs for various functions is avery tedious task.

Thus I would not blame the reader if they were not particularlylooking forward to a long sequence of examples of functions that canbe computed by NAND-CIRC programs. However, it turns out we arenot going to need this, as we can show in one fell swoop that NAND-CIRC programs can compute every finite function:

Theorem 4.12 — Universality of NAND. There exists some constant 𝑐 > 0such that for every 𝑛, 𝑚 > 0 and function 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚,there is a NAND-CIRC program with at most 𝑐⋅𝑚2𝑛 lines that com-putes the function 𝑓 .

By Theorem 3.19, the models of NAND circuits, NAND-CIRC pro-grams, AON-CIRC programs, and Boolean circuits, are all equivalentto one another, and hence Theorem 4.12 holds for all these models. Inparticular, the following theorem is equivalent to Theorem 4.12:

Theorem 4.13 — Universality of Boolean circuits. There exists someconstant 𝑐 > 0 such that for every 𝑛, 𝑚 > 0 and function

Page 172: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

172 introduction to theoretical computer science

2 In case you are curious, this is the function on input𝑖 ∈ 0, 14 (which we interpret as a number in [16]),that outputs the 𝑖-th digit of 𝜋 in the binary basis.

𝑓 ∶ 0, 1𝑛 → 0, 1𝑚, there is a Boolean circuit with at most𝑐 ⋅ 𝑚2𝑛 gates that computes the function 𝑓 .

Big Idea 5 Every finite function can be computed by a largeenough Boolean circuit.

Improved bounds. Though it will not be of great importance to us, itis possible to improve on the proof of Theorem 4.12 and shave an extrafactor of 𝑛, as well as optimize the constant 𝑐, and so prove that forevery 𝜖 > 0, 𝑚 ∈ ℕ and sufficiently large 𝑛, if 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚then 𝑓 can be computed by a NAND circuit of at most (1 + 𝜖) 𝑚⋅2𝑛𝑛gates. The proof of this result is beyond the scope of this book, but wedo discuss how to obtain a bound of the form 𝑂( 𝑚⋅2𝑛𝑛 ) in Section 4.4.2;see also the biographical notes.

4.4.1 Proof of NAND’s UniversalityTo prove Theorem 4.12, we need to give a NAND circuit, or equiva-lently a NAND-CIRC program, for every possible function. We willrestrict our attention to the case of Boolean functions (i.e., 𝑚 = 1).Exercise 4.9 asks you to extend the proof for all values of 𝑚. A func-tion đč ∶ 0, 1𝑛 → 0, 1 can be specified by a table of its values foreach one of the 2𝑛 inputs. For example, the table below describes oneparticular function đș ∶ 0, 14 → 0, 1:2

Table 4.1: An example of a function đș ∶ 0, 14 → 0, 1.Input (đ‘„) Output (đș(đ‘„))0000 10001 10010 00011 00100 10101 00110 00111 11000 01001 01010 01011 01100 11101 11110 11111 1

Page 173: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 173

For every đ‘„ ∈ 0, 14, đș(đ‘„) = LOOKUP4(1100100100001111, đ‘„), andso the following is NAND-CIRC “pseudocode” to compute đș usingsyntactic sugar for the LOOKUP_4 procedure.

G0000 = 1G1000 = 1G0100 = 0...G0111 = 1G1111 = 1Y[0] = LOOKUP_4(G0000,G1000,...,G1111,

X[0],X[1],X[2],X[3])

We can translate this pseudocode into an actual NAND-CIRC pro-gram by adding three lines to define variables zero and one that areinitialized to 0 and 1 respectively, and then replacing a statement suchas Gxxx = 0 with Gxxx = NAND(one,one) and a statement such asGxxx = 1 with Gxxx = NAND(zero,zero). The call to LOOKUP_4 willbe replaced by the NAND-CIRC program that computes LOOKUP4,plugging in the appropriate inputs.

There was nothing about the above reasoning that was particular tothe function đș above. Given every function đč ∶ 0, 1𝑛 → 0, 1, wecan write a NAND-CIRC program that does the following:

1. Initialize 2𝑛 variables of the form F00...0 till F11...1 so that forevery 𝑧 ∈ 0, 1𝑛, the variable corresponding to 𝑧 is assigned thevalue đč(𝑧).

2. Compute LOOKUP𝑛 on the 2𝑛 variables initialized in the previ-ous step, with the index variable being the input variables X[0],
,X[2𝑛 − 1 ]. That is, just like in the pseudocode for G above, weuse Y[0] = LOOKUP(F00..00,...,F11..1,X[0],..,x[𝑛 − 1])The total number of lines in the resulting program is 3 + 2𝑛 lines for

initializing the variables plus the 4 ⋅ 2𝑛 lines that we pay for computingLOOKUP𝑛. This completes the proof of Theorem 4.12.

RRemark 4.14 — Result in perspective. While Theo-rem 4.12 seems striking at first, in retrospect, it isperhaps not that surprising that every finite functioncan be computed with a NAND-CIRC program. Afterall, a finite function đč ∶ 0, 1𝑛 → 0, 1𝑚 can berepresented by simply the list of its outputs for eachone of the 2𝑛 input values. So it makes sense that wecould write a NAND-CIRC program of similar sizeto compute it. What is more interesting is that somefunctions, such as addition and multiplication, have

Page 174: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

174 introduction to theoretical computer science

3 The constant 𝑐 in this theorem is at most 10 and infact can be arbitrarily close to 1, see Section 4.8.

Figure 4.8: We can compute 𝑓 ∶ 0, 1𝑛 → 0, 1 oninput đ‘„ = 𝑎𝑏 where 𝑎 ∈ 0, 1𝑘 and 𝑏 ∈ 0, 1𝑛−𝑘by first computing the 2𝑛−𝑘 long string 𝑔(𝑎) thatcorresponds to all 𝑓’s values on inputs that begin with𝑎, and then outputting the 𝑏-th coordinate of thisstring.

a much more efficient representation: one that onlyrequires 𝑂(𝑛2) or even fewer lines.

4.4.2 Improving by a factor of 𝑛 (optional)By being a little more careful, we can improve the bound of Theo-rem 4.12 and show that every function đč ∶ 0, 1𝑛 → 0, 1𝑚 can becomputed by a NAND-CIRC program of at most 𝑂(𝑚2𝑛/𝑛) lines. Inother words, we can prove the following improved version:

Theorem 4.15 — Universality of NAND circuits, improved bound. There ex-ists a constant 𝑐 > 0 such that for every 𝑛, 𝑚 > 0 and function𝑓 ∶ 0, 1𝑛 → 0, 1𝑚, there is a NAND-CIRC program with at most𝑐 ⋅ 𝑚2𝑛/𝑛 lines that computes the function 𝑓 . 3

Proof. As before, it is enough to prove the case that 𝑚 = 1. Hencewe let 𝑓 ∶ 0, 1𝑛 → 0, 1, and our goal is to prove that there existsa NAND-CIRC program of 𝑂(2𝑛/𝑛) lines (or equivalently a Booleancircuit of 𝑂(2𝑛/𝑛) gates) that computes 𝑓 .

We let 𝑘 = log(𝑛 − 2 log𝑛) (the reasoning behind this choice willbecome clear later on). We define the function 𝑔 ∶ 0, 1𝑘 → 0, 12𝑛−𝑘as follows: 𝑔(𝑎) = 𝑓(𝑎0𝑛−𝑘)𝑓(𝑎0𝑛−𝑘−11) ⋯ 𝑓(𝑎1𝑛−𝑘) . (4.4)

In other words, if we use the usual binary representation to identifythe numbers 0, 
 , 2𝑛−𝑘 − 1 with the strings 0, 1𝑛−𝑘, then for every𝑎 ∈ 0, 1𝑘 and 𝑏 ∈ 0, 1𝑛−𝑘𝑔(𝑎)𝑏 = 𝑓(𝑎𝑏) . (4.5)

(4.5) means that for every đ‘„ ∈ 0, 1𝑛, if we write đ‘„ = 𝑎𝑏 with𝑎 ∈ 0, 1𝑘 and 𝑏 ∈ 0, 1𝑛−𝑘 then we can compute 𝑓(đ‘„) by firstcomputing the string 𝑇 = 𝑔(𝑎) of length 2𝑛−𝑘, and then computingLOOKUP𝑛−𝑘(𝑇 , 𝑏) to retrieve the element of 𝑇 at the position cor-responding to 𝑏 (see Fig. 4.8). The cost to compute the LOOKUP𝑛−𝑘is 𝑂(2𝑛−𝑘) lines/gates and the cost in NAND-CIRC lines (or Booleangates) to compute 𝑓 is at most𝑐𝑜𝑠𝑡(𝑔) + 𝑂(2𝑛−𝑘) , (4.6)

where 𝑐𝑜𝑠𝑡(𝑔) is the number of operations (i.e., lines of NAND-CIRCprograms or gates in a circuit) needed to compute 𝑔.

To complete the proof we need to give a bound on 𝑐𝑜𝑠𝑡(𝑔). Since 𝑔is a function mapping 0, 1𝑘 to 0, 12𝑛−𝑘 , we can also think of it as acollection of 2𝑛−𝑘 functions 𝑔0, 
 , 𝑔2𝑛−𝑘−1 ∶ 0, 1𝑘 → 0, 1, where

Page 175: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 175

Figure 4.9: If 𝑔0, 
 , 𝑔𝑁−1 is a collection of functionseach mapping 0, 1𝑘 to 0, 1 such that at most 𝑆of them are distinct then for every 𝑎 ∈ 0, 1𝑘, wecan compute all the values 𝑔0(𝑎), 
 , 𝑔𝑁−1(𝑎) usingat most 𝑂(𝑆 ⋅ 2𝑘 + 𝑁) operations by first computingthe distinct functions and then copying the resultingvalues.

𝑔𝑖(đ‘„) = 𝑔(𝑎)𝑖 for every 𝑎 ∈ 0, 1𝑘 and 𝑖 ∈ [2𝑛−𝑘]. (That is, 𝑔𝑖(𝑎) isthe 𝑖-th bit of 𝑔(𝑎).) Naively, we could use Theorem 4.12 to computeeach 𝑔𝑖 in 𝑂(2𝑘) lines, but then the total cost is 𝑂(2𝑛−𝑘 ⋅ 2𝑘) = 𝑂(2𝑛)which does not save us anything. However, the crucial observationis that there are only 22𝑘 distinct functions mapping 0, 1𝑘 to 0, 1.For example, if 𝑔17 is an identical function to 𝑔67 that means that ifwe already computed 𝑔17(𝑎) then we can compute 𝑔67(𝑎) using onlya constant number of operations: simply copy the same value! Ingeneral, if you have a collection of 𝑁 functions 𝑔0, 
 , 𝑔𝑁−1 mapping0, 1𝑘 to 0, 1, of which at most 𝑆 are distinct then for every value𝑎 ∈ 0, 1𝑘 we can compute the 𝑁 values 𝑔0(𝑎), 
 , 𝑔𝑁−1(𝑎) using atmost 𝑂(𝑆 ⋅ 2𝑘 + 𝑁) operations (see Fig. 4.9).

In our case, because there are at most 22𝑘 distinct functions map-ping 0, 1𝑘 to 0, 1, we can compute the function 𝑔 (and hence by(4.5) also 𝑓) using at most𝑂(22𝑘 ⋅ 2𝑘 + 2𝑛−𝑘) (4.7)operations. Now all that is left is to plug into (4.7) our choice of 𝑘 =log(𝑛 − 2 log𝑛). By definition, 2𝑘 = 𝑛 − 2 log𝑛, which means that (4.7)can be bounded𝑂 (2𝑛−2 log𝑛 ⋅ (𝑛 − 2 log𝑛) + 2𝑛−log(𝑛−2 log𝑛)) ≀ (4.8)

𝑂 ( 2𝑛𝑛2 ⋅ 𝑛 + 2𝑛𝑛−2 log𝑛 ) ≀ 𝑂 ( 2𝑛𝑛 + 2𝑛0.5𝑛 ) = 𝑂 ( 2𝑛𝑛 ) (4.9)which is what we wanted to prove. (We used above the fact that 𝑛 −2 log𝑛 ≄ 0.5 log𝑛 for sufficiently large 𝑛.)

Using the connection between NAND-CIRC programs and Booleancircuits, an immediate corollary of Theorem 4.15 is the followingimprovement to Theorem 4.13:

Theorem 4.16 — Universality of Boolean circuits, improved bound. Thereexists some constant 𝑐 > 0 such that for every 𝑛, 𝑚 > 0 and func-tion 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚, there is a Boolean circuit with at most𝑐 ⋅ 𝑚2𝑛/𝑛 gates that computes the function 𝑓 .

4.5 COMPUTING EVERY FUNCTION: AN ALTERNATIVE PROOF

Theorem 4.13 is a fundamental result in the theory (and practice!) ofcomputation. In this section we present an alternative proof of thisbasic fact that Boolean circuits can compute every finite function. Thisalternative proof gives a somewhat worse quantitative bound on thenumber of gates but it has the advantage of being simpler, working

Page 176: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

176 introduction to theoretical computer science

directly with circuits and avoiding the usage of all the syntactic sugarmachinery. (However, that machinery is useful in its own right, andwill find other applications later on.)

Theorem 4.17 — Universality of Boolean circuits (alternative phrasing). Thereexists some constant 𝑐 > 0 such that for every 𝑛, 𝑚 > 0 and func-tion 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚, there is a Boolean circuit with at most𝑐 ⋅ 𝑚 ⋅ 𝑛2𝑛 gates that computes the function 𝑓 .

Figure 4.10: Given a function 𝑓 ∶ 0, 1𝑛 → 0, 1,we let đ‘„0, đ‘„1, 
 , đ‘„đ‘âˆ’1 ⊆ 0, 1𝑛 be the set ofinputs such that 𝑓(đ‘„đ‘–) = 1, and note that 𝑁 ≀ 2𝑛.We can express 𝑓 as the OR of đ›żđ‘„đ‘– for 𝑖 ∈ [𝑁] wherethe function đ›żđ›Œ ∶ 0, 1𝑛 → 0, 1 (for đ›Œ ∈ 0, 1𝑛)is defined as follows: đ›żđ›Œ(đ‘„) = 1 iff đ‘„ = đ›Œ. We cancompute the OR of 𝑁 values using 𝑁 two-input ORgates. Therefore if we have a circuit of size 𝑂(𝑛) tocompute đ›żđ›Œ for every đ›Œ ∈ 0, 1𝑛, we can compute 𝑓using a circuit of size 𝑂(𝑛 ⋅ 𝑁) = 𝑂(𝑛 ⋅ 2𝑛).

Proof Idea:

The idea of the proof is illustrated in Fig. 4.10. As before, it isenough to focus on the case that 𝑚 = 1 (the function 𝑓 has a sin-gle output), since we can always extend this to the case of 𝑚 > 1by looking at the composition of 𝑚 circuits each computing a differ-ent output bit of the function 𝑓 . We start by showing that for everyđ›Œ ∈ 0, 1𝑛, there is an 𝑂(𝑛) sized circuit that computes the functionđ›żđ›Œ ∶ 0, 1𝑛 → 0, 1 defined as follows: đ›żđ›Œ(đ‘„) = 1 iff đ‘„ = đ›Œ (that is,đ›żđ›Œ outputs 0 on all inputs except the input đ›Œ). We can then write anyfunction 𝑓 ∶ 0, 1𝑛 → 0, 1 as the OR of at most 2𝑛 functions đ›żđ›Œ forthe đ›Œâ€™s on which 𝑓(đ›Œ) = 1.⋆Proof of Theorem 4.17. We prove the theorem for the case 𝑚 = 1. Theresult can be extended for 𝑚 > 1 as before (see also Exercise 4.9). Let𝑓 ∶ 0, 1𝑛 → 0, 1. We will prove that there is an 𝑂(𝑛 ⋅ 2𝑛)-sizedBoolean circuit to compute 𝑓 in the following steps:

Page 177: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 177

Figure 4.11: For every string đ›Œ ∈ 0, 1𝑛, there is aBoolean circuit of 𝑂(𝑛) gates to compute the functionđ›żđ›Œ ∶ 0, 1𝑛 → 0, 1 such that đ›żđ›Œ(đ‘„) = 1 if andonly if đ‘„ = đ›Œ. The circuit is very simple. Given inputđ‘„0, 
 , đ‘„đ‘›âˆ’1 we compute the AND of 𝑧0, 
 , 𝑧𝑛−1where 𝑧𝑖 = đ‘„đ‘– if đ›Œđ‘– = 1 and 𝑧𝑖 = NOT(đ‘„đ‘–) if đ›Œđ‘– = 0.While formally Boolean circuits only have a gate forcomputing the AND of two inputs, we can implementan AND of 𝑛 inputs by composing 𝑛 two-inputANDs.

1. We show that for every đ›Œ ∈ 0, 1𝑛, there is an 𝑂(𝑛) sized circuitthat computes the function đ›żđ›Œ ∶ 0, 1𝑛 → 0, 1, where đ›żđ›Œ(đ‘„) = 1 iffđ‘„ = đ›Œ.

2. We then show that this implies the existence of an 𝑂(𝑛 ⋅ 2𝑛)-sizedcircuit that computes 𝑓 , by writing 𝑓(đ‘„) as the OR of đ›żđ›Œ(đ‘„) for allđ›Œ ∈ 0, 1𝑛 such that 𝑓(đ›Œ) = 1.We start with Step 1:CLAIM: For đ›Œ ∈ 0, 1𝑛, define đ›żđ›Œ ∶ 0, 1𝑛 as follows:đ›żđ›Œ(đ‘„) = ⎧⎚⎩1 đ‘„ = đ›Œ0 otherwise

. (4.10)

then there is a Boolean circuit using at most 2𝑛 gates that computes đ›żđ›Œ.PROOF OF CLAIM: The proof is illustrated in Fig. 4.11. As an

example, consider the function 𝛿011 ∶ 0, 13 → 0, 1. This functionoutputs 1 on đ‘„ if and only if đ‘„0 = 0, đ‘„1 = 1 and đ‘„2 = 1, and so we canwrite 𝛿011(đ‘„) = đ‘„0 ∧ đ‘„1 ∧ đ‘„2, which translates into a Boolean circuitwith one NOT gate and two AND gates. More generally, for everyđ›Œ ∈ 0, 1𝑛, we can express đ›żđ›Œ(đ‘„) as (đ‘„0 = đ›Œ0)∧(đ‘„1 = đ›Œ1)∧⋯∧(đ‘„đ‘›âˆ’1 =đ›Œđ‘›âˆ’1), where if đ›Œđ‘– = 0 we replace đ‘„đ‘– = đ›Œđ‘– with đ‘„đ‘– and if đ›Œđ‘– = 1 wereplace đ‘„đ‘– = đ›Œđ‘– by simply đ‘„đ‘–. This yields a circuit that computes đ›żđ›Œusing 𝑛 AND gates and at most 𝑛 NOT gates, so a total of at most 2𝑛gates.

Now for every function 𝑓 ∶ 0, 1𝑛 → 0, 1, we can write𝑓(đ‘„) = đ›żđ‘„0(đ‘„) √ đ›żđ‘„1(đ‘„) √ ⋯ √ đ›żđ‘„đ‘âˆ’1(đ‘„) (4.11)where 𝑆 = đ‘„0, 
 , đ‘„đ‘âˆ’1 is the set of inputs on which 𝑓 outputs 1.

(To see this, you can verify that the right-hand side of (4.11) evaluatesto 1 on đ‘„ ∈ 0, 1𝑛 if and only if đ‘„ is in the set 𝑆.)

Therefore we can compute 𝑓 using a Boolean circuit of at most 2𝑛gates for each of the 𝑁 functions đ›żđ‘„đ‘– and combine that with at most 𝑁OR gates, thus obtaining a circuit of at most 2𝑛 ⋅ 𝑁 + 𝑁 gates. Since𝑆 ⊆ 0, 1𝑛, its size 𝑁 is at most 2𝑛 and hence the total number ofgates in this circuit is 𝑂(𝑛 ⋅ 2𝑛).

4.6 THE CLASS SIZE(𝑇 )We have seen that every function 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚 can be com-puted by a circuit of size 𝑂(𝑚 ⋅ 2𝑛), and some functions (such as ad-dition and multiplication) can be computed by much smaller circuits.We define SIZE(𝑠) to be the set of functions that can be computed byNAND circuits of at most 𝑠 gates (or equivalently, by NAND-CIRCprograms of at most 𝑠 lines). Formally, the definition is as follows:

Page 178: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

178 introduction to theoretical computer science

4 The restriction that 𝑚, 𝑛 ≀ 2𝑠 makes no difference;see Exercise 3.11.

Definition 4.18 — Size class of functions. For every 𝑛, 𝑚 ∈ 1, 
 , 2𝑠,we let set SIZE𝑛,𝑚(𝑠) denotes the set of all functions 𝑓 ∶ 0, 1𝑛 →0, 1𝑚 such that 𝑓 ∈ SIZE(𝑠). 4 We denote by SIZE𝑛(𝑠) the setSIZE𝑛,1(𝑠). For every integer 𝑠 ≄ 1, we let SIZE(𝑠) = âˆȘ𝑛,đ‘šâ‰€2𝑠SIZE𝑛,𝑚(𝑠)be the set of all functions 𝑓 for which there exists a NAND circuitof at most 𝑠 gates that compute 𝑓 .Fig. 4.12 depicts the set SIZE𝑛,1(𝑠). Note that SIZE𝑛,𝑚(𝑠) is a set of

functions, not of programs! (Asking if a program or a circuit is a mem-ber of SIZE𝑛,𝑚(𝑠) is a category error as in the sense of Fig. 4.13.) Aswe discussed in Section 3.6.2 (and Section 2.6.1), the distinction be-tween programs and functions is absolutely crucial. You should alwaysremember that while a program computes a function, it is not equal toa function. In particular, as we’ve seen, there can be more than oneprogram to compute the same function.

Figure 4.12: There are 22𝑛 functions mapping 0, 1𝑛to 0, 1, and an infinite number of circuits with 𝑛 bitinputs and a single bit of output. Every circuit com-putes one function, but every function can be com-puted by many circuits. We say that 𝑓 ∈ SIZE𝑛,1(𝑠)if the smallest circuit that computes 𝑓 has 𝑠 or fewergates. For example XOR𝑛 ∈ SIZE𝑛,1(4𝑛). Theo-rem 4.12 shows that every function 𝑔 is computableby some circuit of at most 𝑐 ⋅ 2𝑛/𝑛 gates, and henceSIZE𝑛,1(𝑐 ⋅ 2𝑛/𝑛) corresponds to the set of all func-tions from 0, 1𝑛 to 0, 1.

While we defined SIZE(𝑠) with respect to NAND gates, wewould get essentially the same class if we defined it with respect toAND/OR/NOT gates:Lemma 4.19 Let SIZE𝐮𝑂𝑁𝑛,𝑚 (𝑠) denote the set of all functions 𝑓 ∶ 0, 1𝑛 →0, 1𝑚 that can be computed by an AND/OR/NOT Boolean circuit ofat most 𝑠 gates. Then,

SIZE𝑛,𝑚(𝑠/2) ⊆ SIZE𝐮𝑂𝑁𝑛,𝑚 (𝑠) ⊆ SIZE𝑛,𝑚(3𝑠) (4.12)

Proof. If 𝑓 can be computed by a NAND circuit of at most 𝑠/2 gates,then by replacing each NAND with the two gates NOT and AND, wecan obtain an AND/OR/NOT Boolean circuit of at most 𝑠 gates thatcomputes 𝑓 . On the other hand, if 𝑓 can be computed by a Boolean

Page 179: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 179

Figure 4.13: A “category error” is a question such as“is a cucumber even or odd?” which does not evenmake sense. In this book one type of category erroryou should watch out for is confusing functions andprograms (i.e., confusing specifications and implemen-tations). If đ¶ is a circuit or program, then asking ifđ¶ ∈ SIZE𝑛,1(𝑠) is a category error, since SIZE𝑛,1(𝑠) isa set of functions and not programs or circuits.

AND/OR/NOT circuit of at most 𝑠 gates, then by Theorem 3.12 it canbe computed by a NAND circuit of at most 3𝑠 gates.

The results we have seen in this chapter can be phrased as showingthat ADD𝑛 ∈ SIZE2𝑛,𝑛+1(100𝑛) and MULT𝑛 ∈ SIZE2𝑛,2𝑛(10000𝑛log2 3).Theorem 4.12 shows that for some constant 𝑐, SIZE𝑛,𝑚(𝑐𝑚2𝑛) is equalto the set of all functions from 0, 1𝑛 to 0, 1𝑚.

RRemark 4.20 — Finite vs infinite functions. A NAND-CIRC program 𝑃 can only compute a function witha certain number 𝑛 of inputs and a certain number𝑚 of outputs. Hence, for example, there is no singleNAND-CIRC program that can compute the incre-ment function INC ∶ 0, 1∗ → 0, 1∗ that maps astring đ‘„ (which we identify with a number via thebinary representation) to the string that representsđ‘„ + 1. Rather for every 𝑛 > 0, there is a NAND-CIRCprogram 𝑃𝑛 that computes the restriction INC𝑛 ofthe function INC to inputs of length 𝑛. Since it can beshown that for every 𝑛 > 0 such a program 𝑃𝑛 existsof length at most 10𝑛, INC𝑛 ∈ SIZE(10𝑛) for every𝑛 > 0.If 𝑇 ∶ ℕ → ℕ and đč ∶ 0, 1∗ → 0, 1∗, we willwrite đč ∈ SIZE∗(𝑇 (𝑛)) (or sometimes slightly abusenotation and write simply đč ∈ SIZE(𝑇 (𝑛))) to in-dicate that for every 𝑛 the restriction đč𝑛 of đč toinputs in 0, 1𝑛 is in SIZE(𝑇 (𝑛)). Hence we can writeINC ∈ SIZE∗(10𝑛). We will come back to this issue offinite vs infinite functions later in this course.

Solved Exercise 4.1 — đ‘†đŒđ‘đž closed under complement.. In this exercise weprove a certain “closure property” of the class SIZE𝑛(𝑠). That is, weshow that if 𝑓 is in this class then (up to some small additive term) sois the complement of 𝑓 , which is the function 𝑔(đ‘„) = 1 − 𝑓(đ‘„).

Prove that there is a constant 𝑐 such that for every 𝑓 ∶ 0, 1𝑛 →0, 1 and 𝑠 ∈ ℕ, if 𝑓 ∈ SIZE𝑛(𝑠) then 1 − 𝑓 ∈ SIZE𝑛(𝑠 + 𝑐).

Solution:

If 𝑓 ∈ SIZE(𝑠) then there is an 𝑠-line NAND-CIRC program𝑃 that computes 𝑓 . We can rename the variable Y[0] in 𝑃 to avariable temp and add the line

Y[0] = NAND(temp,temp)

at the very end to obtain a program 𝑃 â€Č that computes 1 − 𝑓 .

Page 180: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

180 introduction to theoretical computer science

Chapter Recap

‱ We can define the notion of computing a functionvia a simplified “programming language”, wherecomputing a function đč in 𝑇 steps would corre-spond to having a 𝑇 -line NAND-CIRC programthat computes đč .

‱ While the NAND-CIRC programming only has oneoperation, other operations such as functions andconditional execution can be implemented using it.

‱ Every function 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚 can be com-puted by a circuit of at most 𝑂(𝑚2𝑛) gates (and infact at most 𝑂(𝑚2𝑛/𝑛) gates).

‱ Sometimes (or maybe always?) we can translate anefficient algorithm to compute 𝑓 into a circuit thatcomputes 𝑓 with a number of gates comparable tothe number of steps in this algorithm.

4.7 EXERCISES

Exercise 4.1 — Pairing. This exercise asks you to give a one-to-one mapfrom ℕ2 to ℕ. This can be useful to implement two-dimensional arraysas “syntactic sugar” in programming languages that only have one-dimensional array.

1. Prove that the map đč(đ‘„, 𝑩) = 2đ‘„3𝑩 is a one-to-one map from ℕ2 toℕ.

2. Show that there is a one-to-one map đč ∶ ℕ2 → ℕ such that for everyđ‘„, 𝑩, đč(đ‘„, 𝑩) ≀ 100 ⋅ maxđ‘„, 𝑩2 + 100.3. For every 𝑘, show that there is a one-to-one map đč ∶ ℕ𝑘 → ℕ such

that for every đ‘„0, 
 , đ‘„đ‘˜âˆ’1 ∈ ℕ, đč(đ‘„0, 
 , đ‘„đ‘˜âˆ’1) ≀ 100 ⋅ (đ‘„0 + đ‘„1 + 
 +đ‘„đ‘˜âˆ’1 + 100𝑘)𝑘.

Exercise 4.2 — Computing MUX. Prove that the NAND-CIRC program be-low computes the function MUX (or LOOKUP1) where MUX(𝑎, 𝑏, 𝑐)equals 𝑎 if 𝑐 = 0 and equals 𝑏 if 𝑐 = 1:t = NAND(X[2],X[2])u = NAND(X[0],t)v = NAND(X[1],X[2])Y[0] = NAND(u,v)

Exercise 4.3 — At least two / Majority. Give a NAND-CIRC program of atmost 6 lines to compute the function MAJ ∶ 0, 13 → 0, 1 whereMAJ(𝑎, 𝑏, 𝑐) = 1 iff 𝑎 + 𝑏 + 𝑐 ≄ 2.

Page 181: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 181

5 You can start by transforming 𝑃 into a NAND-CIRC-PROC program that uses procedure statements, andthen use the code of Fig. 4.3 to transform the latterinto a “sugar free” NAND-CIRC program.

6 Use a “cascade” of adding the bits one after theother, starting with the least significant digit, just likein the elementary-school algorithm.

Exercise 4.4 — Conditional statements. In this exercise we will explore The-orem 4.6: transforming NAND-CIRC-IF programs that use code suchas if .. then .. else .. to standard NAND-CIRC programs.

1. Give a “proof by code” of Theorem 4.6: a program in a program-ming language of your choice that transforms a NAND-CIRC-IFprogram 𝑃 into a “sugar free” NAND-CIRC program 𝑃 â€Č that com-putes the same function. See footnote for hint.5

2. Prove the following statement, which is the heart of Theorem 4.6:suppose that there exists an 𝑠-line NAND-CIRC program to com-pute 𝑓 ∶ 0, 1𝑛 → 0, 1 and an 𝑠â€Č-line NAND-CIRC programto compute 𝑔 ∶ 0, 1𝑛 → 0, 1. Prove that there exist a NAND-CIRC program of at most 𝑠 + 𝑠â€Č + 10 lines to compute the func-tion ℎ ∶ 0, 1𝑛+1 → 0, 1 where ℎ(đ‘„0, 
 , đ‘„đ‘›âˆ’1, đ‘„đ‘›) equals𝑓(đ‘„0, 
 , đ‘„đ‘›âˆ’1) if đ‘„đ‘› = 0 and equals 𝑔(đ‘„0, 
 , đ‘„đ‘›âˆ’1) otherwise.(All programs in this item are standard “sugar-free” NAND-CIRCprograms.)

Exercise 4.5 — Half and full adders. 1. A half adder is the function HA ∶0, 12 ∶→ 0, 12 that corresponds to adding two binary bits. Thatis, for every 𝑎, 𝑏 ∈ 0, 1, HA(𝑎, 𝑏) = (𝑒, 𝑓) where 2𝑒 + 𝑓 = 𝑎 + 𝑏.Prove that there is a NAND circuit of at most five NAND gates thatcomputes HA.

2. A full adder is the function FA ∶ 0, 13 → 0, 12 that takes intwo bits and a “carry” bit and outputs their sum. That is, for every𝑎, 𝑏, 𝑐 ∈ 0, 1, FA(𝑎, 𝑏, 𝑐) = (𝑒, 𝑓) such that 2𝑒 + 𝑓 = 𝑎 + 𝑏 + 𝑐.Prove that there is a NAND circuit of at most nine NAND gates thatcomputes FA.

3. Prove that if there is a NAND circuit of 𝑐 gates that computes FA,then there is a circuit of 𝑐𝑛 gates that computes ADD𝑛 where (asin Theorem 4.7) ADD𝑛 ∶ 0, 12𝑛 → 0, 1𝑛+1 is the function thatoutputs the addition of two input 𝑛-bit numbers. See footnote forhint.6

4. Show that for every 𝑛 there is a NAND-CIRC program to computeADD𝑛 with at most 9𝑛 lines.

Exercise 4.6 — Addition. Write a program using your favorite program-ming language that on input of an integer 𝑛, outputs a NAND-CIRCprogram that computes ADD𝑛. Can you ensure that the program itoutputs for ADD𝑛 has fewer than 10𝑛 lines?

Page 182: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

182 introduction to theoretical computer science

7 Hint: Use Karatsuba’s algorithm.

Exercise 4.7 — Multiplication. Write a program using your favorite pro-gramming language that on input of an integer 𝑛, outputs a NAND-CIRC program that computes MULT𝑛. Can you ensure that the pro-gram it outputs for MULT𝑛 has fewer than 1000 ⋅ 𝑛2 lines?

Exercise 4.8 — Efficient multiplication (challenge). Write a program usingyour favorite programming language that on input of an integer 𝑛,outputs a NAND-CIRC program that computes MULT𝑛 and has atmost 10000𝑛1.9 lines.7 What is the smallest number of lines you canuse to multiply two 2048 bit numbers?

Exercise 4.9 — Multibit function. In the text Theorem 4.12 is only provenfor the case 𝑚 = 1. In this exercise you will extend the proof for every𝑚.

Prove that

1. If there is an 𝑠-line NAND-CIRC program to compute𝑓 ∶ 0, 1𝑛 → 0, 1 and an 𝑠â€Č-line NAND-CIRC programto compute 𝑓 â€Č ∶ 0, 1𝑛 → 0, 1 then there is an 𝑠 + 𝑠â€Č-lineprogram to compute the function 𝑔 ∶ 0, 1𝑛 → 0, 12 such that𝑔(đ‘„) = (𝑓(đ‘„), 𝑓 â€Č(đ‘„)).

2. For every function 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚, there is a NAND-CIRCprogram of at most 10𝑚 ⋅ 2𝑛 lines that computes 𝑓 . (You can use the𝑚 = 1 case of Theorem 4.12, as well as Item 1.)

Exercise 4.10 — Simplifying using syntactic sugar. Let 𝑃 be the followingNAND-CIRC program:

Temp[0] = NAND(X[0],X[0])Temp[1] = NAND(X[1],X[1])Temp[2] = NAND(Temp[0],Temp[1])Temp[3] = NAND(X[2],X[2])Temp[4] = NAND(X[3],X[3])Temp[5] = NAND(Temp[3],Temp[4])Temp[6] = NAND(Temp[2],Temp[2])Temp[7] = NAND(Temp[5],Temp[5])Y[0] = NAND(Temp[6],Temp[7])

1. Write a program 𝑃 â€Č with at most three lines of code that uses bothNAND as well as the syntactic sugar OR that computes the same func-tion as 𝑃 .

Page 183: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

syntactic sugar, and computing every function 183

8 You can use the fact that (𝑎+𝑏)+𝑐 mod 2 = 𝑎+𝑏+𝑐mod 2. In particular it means that if you have thelines d = XOR(a,b) and e = XOR(d,c) then e gets thesum modulo 2 of the variable a, b and c.

2. Draw a circuit that computes the same function as 𝑃 and uses onlyAND and NOT gates.

In the following exercises you are asked to compare the power ofpairs of programming languages. By “comparing the power” of twoprogramming languages 𝑋 and 𝑌 we mean determining the relationbetween the set of functions that are computable using programs in 𝑋and 𝑌 respectively. That is, to answer such a question you need to doboth of the following:

1. Either prove that for every program 𝑃 in 𝑋 there is a program 𝑃 â€Čin 𝑌 that computes the same function as 𝑃 , or give an example fora function that is computable by an 𝑋-program but not computableby a 𝑌 -program.

and

2. Either prove that for every program 𝑃 in 𝑌 there is a program 𝑃 â€Čin 𝑋 that computes the same function as 𝑃 , or give an example for afunction that is computable by a 𝑌 -program but not computable byan 𝑋-program.

When you give an example as above of a function that is com-putable in one programming language but not the other, you needto prove that the function you showed is (1) computable in the firstprogramming language and (2) not computable in the second program-ming language.Exercise 4.11 — Compare IF and NAND. Let IF-CIRC be the programminglanguage where we have the following operations foo = 0, foo = 1,foo = IF(cond,yes,no) (that is, we can use the constants 0 and 1,and the IF ∶ 0, 13 → 0, 1 function such that IF(𝑎, 𝑏, 𝑐) equals 𝑏 if𝑎 = 1 and equals 𝑐 if 𝑎 = 0). Compare the power of the NAND-CIRCprogramming language and the IF-CIRC programming language.

Exercise 4.12 — Compare XOR and NAND. Let XOR-CIRC be the pro-gramming language where we have the following operations foo= XOR(bar,blah), foo = 1 and bar = 0 (that is, we can use theconstants 0, 1 and the XOR function that maps 𝑎, 𝑏 ∈ 0, 12 to 𝑎 + 𝑏mod 2). Compare the power of the NAND-CIRC programminglanguage and the XOR-CIRC programming language. See footnote forhint.8

Exercise 4.13 — Circuits for majority. Prove that there is some constant 𝑐such that for every 𝑛 > 1, MAJ𝑛 ∈ SIZE(𝑐𝑛) where MAJ𝑛 ∶ 0, 1𝑛 →

Page 184: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

184 introduction to theoretical computer science

9 One approach to solve this is using recursion and theso-called Master Theorem.

0, 1 is the majority function on 𝑛 input bits. That is MAJ𝑛(đ‘„) = 1 iff∑𝑛−1𝑖=0 đ‘„đ‘– > 𝑛/2. See footnote for hint.9

Exercise 4.14 — Circuits for threshold. Prove that there is some constant 𝑐such that for every 𝑛 > 1, and integers 𝑎0, 
 , 𝑎𝑛−1, 𝑏 ∈ −2𝑛, −2𝑛 +1, 
 , −1, 0, +1, 
 , 2𝑛, there is a NAND circuit with at most 𝑛𝑐 gatesthat computes the threshold function 𝑓𝑎0,
,𝑎𝑛−1,𝑏 ∶ 0, 1𝑛 → 0, 1 thaton input đ‘„ ∈ 0, 1𝑛 outputs 1 if and only if ∑𝑛−1𝑖=0 đ‘Žđ‘–đ‘„đ‘– > 𝑏.

4.8 BIBLIOGRAPHICAL NOTES

See Jukna’s and Wegener’s books [Juk12; Weg87] for much moreextensive discussion on circuits. Shannon showed that every Booleanfunction can be computed by a circuit of exponential size [Sha38]. Theimproved bound of 𝑐 ⋅ 2𝑛/𝑛 (with the optimal value of 𝑐 for manybases) is due to Lupanov [Lup58]. An exposition of this for the caseof NAND (where 𝑐 = 1) is given in Chapter 4 of his book [Lup84].(Thanks to Sasha Golovnev for tracking down this reference!)

The concept of “syntactic sugar” is also known as “macros” or“meta-programming” and is sometimes implemented via a prepro-cessor or macro language in a programming language or a text editor.One modern example is the Babel JavaScript syntax transformer, thatconverts JavaScript programs written using the latest features intoa format that older Browsers can accept. It even has a plug-in ar-chitecture, that allows users to add their own syntactic sugar to thelanguage.

Page 185: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

5Code as data, data as code

“The term code script is, of course, too narrow. The chromosomal structuresare at the same time instrumental in bringing about the development theyforeshadow. They are law-code and executive power - or, to use another simile,they are architect’s plan and builder’s craft - in one.” , Erwin Schrödinger,1944.

“A mathematician would hardly call a correspondence between the set of 64triples of four units and a set of twenty other units,”universal“, while suchcorrespondence is, probably, the most fundamental general feature of life onEarth”, Misha Gromov, 2013

A program is simply a sequence of symbols, each of which can beencoded as a string of 0’s and 1’s using (for example) the ASCII stan-dard. Therefore we can represent every NAND-CIRC program (andhence also every Boolean circuit) as a binary string. This statementseems obvious but it is actually quite profound. It means that we cantreat circuits or NAND-CIRC programs both as instructions to car-rying computation and also as data that could potentially be used asinputs to other computations.

Big Idea 6 A program is a piece of text, and so it can be fed as inputto other programs.

This correspondence between code and data is one of the most fun-damental aspects of computing. It underlies the notion of generalpurpose computers, that are not pre-wired to compute only one task,and also forms the basis of our hope for obtaining general artificialintelligence. This concept finds immense use in all areas of comput-ing, from scripting languages to machine learning, but it is fair to saythat we haven’t yet fully mastered it. Many security exploits involvecases such as “buffer overflows” when attackers manage to inject codewhere the system expected only “passive” data (see Fig. 5.1). The re-lation between code and data reaches beyond the realm of electronic

Compiled on 8.26.2020 18:10

Learning Objectives:‱ See one of the most important concepts in

computing: duality between code and data.‱ Build up comfort in moving between

different representations of programs.‱ Follow the construction of a “universal circuit

evaluator” that can evaluate other circuitsgiven their representation.

‱ See major result that complements the resultof the last chapter: some functions require anexponential number of gates to compute.

‱ Discussion of Physical extendedChurch-Turing thesis stating that Booleancircuits capture all feasible computation inthe physical world, and its physical andphilosophical implications.

Page 186: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

186 introduction to theoretical computer science

Figure 5.1: As illustrated in this xkcd cartoon, manyexploits, including buffer overflow, SQL injections,and more, utilize the blurry line between “activeprograms” and “static strings”.

computers. For example, DNA can be thought of as both a programand data (in the words of Schrödinger, who wrote before the discov-ery of DNA’s structure a book that inspired Watson and Crick, DNA isboth “architect’s plan and builder’s craft”).

This chapter: A non-mathy overviewIn this chapter, we will begin to explore some of the manyapplications of the correspondence between code and data.We start by using the representation of programs/circuitsas strings to count the number of programs/circuits up to acertain size, and use that to obtain a counterpart to the resultwe proved in Chapter 4. There we proved that every functioncan be computed by a circuit, but that circuit could be expo-nentially large (see Theorem 4.16 for the precise bound) Inthis chapter we will prove that there are some functions forwhich we cannot do better: the smallest circuit that computesthem is exponentially large.We will also use the notion of representing programs/cir-cuits as strings to show the existence of a “universal circuit”- a circuit that can evaluate other circuits. In programminglanguages, this is known as a “meta circular evaluator” - aprogram in a certain programming language that can eval-uate other programs in the same language. These resultsdo have an important restriction: the universal circuit willhave to be of bigger size than the circuits it evaluates. We willshow how to get around this restriction in Chapter 7 wherewe introduce loops and Turing Machines.See Fig. 5.2 for an overview of the results of this chapter.

Figure 5.2: Overview of the results in this chapter.We use the representation of programs/circuits asstrings to derive two main results. First we showthe existence of a universal program/circuit, andin fact (with more work) the existence of such aprogram/circuit whose size is at most polynomial inthe size of the program/circuit it evaluates. We thenuse the string representation to count the numberof programs/circuits of a given size, and use that toestablish that some functions require an exponentialnumber of lines/gates to compute.

Page 187: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 187

5.1 REPRESENTING PROGRAMS AS STRINGS

We can represent programs or circuits as strings in a myriad of ways.For example, since Boolean circuits are labeled directed acyclic graphs,we can use the adjacency matrix or adjacency list representations forthem. However, since the code of a program is ultimately just a se-quence of letters and symbols, arguably the conceptually simplestrepresentation of a program is as such a sequence. For example, thefollowing NAND-CIRC program 𝑃temp_0 = NAND(X[0],X[1])temp_1 = NAND(X[0],temp_0)temp_2 = NAND(X[1],temp_0)Y[0] = NAND(temp_1,temp_2)

is simply a string of 107 symbols which include lower and uppercase letters, digits, the underscore character _ and equality sign =,punctuation marks such as “(”,“)”,“,”, spaces, and “new line” mark-ers (often denoted as “\n” or “↔”). Each such symbol can be encodedas a string of 7 bits using the ASCII encoding, and hence the program𝑃 can be encoded as a string of length 7 ⋅ 107 = 749 bits.

Nothing in the above discussion was specific to the program 𝑃 , andhence we can use the same reasoning to prove that every NAND-CIRCprogram can be represented as a string in 0, 1∗. In fact, we can do abit better. Since the names of the working variables of a NAND-CIRCprogram do not affect its functionality, we can always transform a pro-gram to have the form of 𝑃 â€Č where all variables apart from the inputsand outputs have the form temp_0, temp_1, temp_2, etc.. Moreover,if the program has 𝑠 lines, then we will never need to use an indexlarger than 3𝑠 (since each line involves at most three variables), andsimilarly the indices of the input and output variables will all be atmost 3𝑠. Since a number between 0 and 3𝑠 can be expressed usingat most ⌈log10(3𝑠 + 1)⌉ = 𝑂(log 𝑠) digits, each line in the program(which has the form foo = NAND(bar,blah)), can be representedusing 𝑂(1) + 𝑂(log 𝑠) = 𝑂(log 𝑠) symbols, each of which can be rep-resented by 7 bits. Hence an 𝑠 line program can be represented as astring of 𝑂(𝑠 log 𝑠) bits, resulting in the following theorem:

Theorem 5.1 — Representing programs as strings. There is a constant 𝑐such that for 𝑓 ∈ SIZE(𝑠), there exists a program 𝑃 computing 𝑓whose string representation has length at most 𝑐𝑠 log 𝑠.

P

Page 188: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

188 introduction to theoretical computer science

1 The implicit constant in the 𝑂(⋅) notation is smallerthan 10. That is, for all sufficiently large 𝑠, |SIZE(𝑠)| <210𝑠 log 𝑠, see Remark 5.4. As discussed in Section 1.7,we use the bound 10 simply because it is a roundnumber.

2 “Astronomical” here is an understatement: there aremuch fewer than 2210 stars, or even particles, in theobservable universe.

We omit the formal proof of Theorem 5.1 but pleasemake sure that you understand why it follows fromthe reasoning above.

5.2 COUNTING PROGRAMS, AND LOWER BOUNDS ON THE SIZEOF NAND-CIRC PROGRAMS

One consequence of the representation of programs as strings is thatthe number of programs of certain length is bounded by the numberof strings that represent them. This has consequences for the setsSIZE(𝑠) that we defined in Section 4.6.

Theorem 5.2 — Counting programs. For every 𝑠 ∈ ℕ,|SIZE(𝑠)| ≀ 2𝑂(𝑠 log 𝑠). (5.1)

That is, there are at most 2𝑂(𝑠 log 𝑠) functions computed by NAND-CIRC programs of at most 𝑠 lines. 1

Proof. We will show a one-to-one map 𝐾 from SIZE(𝑠) to the set ofstrings of length 𝑐𝑠 log 𝑠 for some constant 𝑐. This will conclude theproof, since it implies that |SIZE(𝑠)| is smaller than the size of the setof all strings of length at most ℓ, which equals 1+2+4+⋯+2ℓ = 2ℓ+1−1by the formula for sums of geometric progressions.

The map 𝐾 will simply map 𝑓 to the representation of the programcomputing 𝑓 . Specifically, we let 𝐾(𝑓) be the representation of theprogram 𝑃 computing 𝑓 given by Theorem 5.1. This representationhas size at most 𝑐𝑠 log 𝑠, and moreover the map 𝐾 is one to one, sinceif 𝑓 ≠ 𝑓 â€Č then every two programs computing 𝑓 and 𝑓 â€Č respectivelymust have different representations.

A function mapping 0, 12 to 0, 1 can be identified with thetable of its four values on the inputs 00, 01, 10, 11. A function mapping0, 13 to 0, 1 can be identified with the table of its eight values onthe inputs 000, 001, 010, 011, 100, 101, 110, 111. More generally, everyfunction đč ∶ 0, 1𝑛 → 0, 1 can be identified with the table of its 2𝑛values on the inputs 0, 1𝑛. Hence the number of functions mapping0, 1𝑛 to 0, 1 is equal to the number of such tables which (sincewe can choose either 0 or 1 for every row) is exactly 22𝑛 . Note thatthis is double exponential in 𝑛, and hence even for small values of 𝑛(e.g., 𝑛 = 10) the number of functions from 0, 1𝑛 to 0, 1 is trulyastronomical.2 This has the following important corollary:

Page 189: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 189

3 The constant 𝛿 is at least 0.1 and in fact, can be im-proved to be arbitrarily close to 1/2, see Exercise 5.7.

Theorem 5.3 — Counting argument lower bound. There is a constant𝛿 > 0, such that for every sufficiently large 𝑛, there is a function𝑓 ∶ 0, 1𝑛 → 0, 1 such that 𝑓 ∉ SIZE ( 𝛿2𝑛𝑛 ). That is, the shortestNAND-CIRC program to compute 𝑓 requires more than 𝛿 ⋅ 2𝑛/𝑛lines. 3

Proof. The proof is simple. If we let 𝑐 be the constant such that|SIZE(𝑠)| ≀ 2𝑐𝑠 log 𝑠 and 𝛿 = 1/𝑐, then setting 𝑠 = 𝛿2𝑛/𝑛 we see that|SIZE( 𝛿2𝑛𝑛 )| ≀ 2𝑐 𝛿2𝑛𝑛 log 𝑠 < 2𝑐𝛿2𝑛 = 22𝑛 (5.2)

using the fact that since 𝑠 < 2𝑛, log 𝑠 < 𝑛 and 𝛿 = 1/𝑐. But since|SIZE(𝑠)| is smaller than the total number of functions mapping 𝑛 bitsto 1 bit, there must be at least one such function not in SIZE(𝑠), whichis what we needed to prove.

We have seen before that every function mapping 0, 1𝑛 to 0, 1can be computed by an 𝑂(2𝑛/𝑛) line program. Theorem 5.3 showsthat this is tight in the sense that some functions do require such anastronomical number of lines to compute.

Big Idea 7 Some functions 𝑓 ∶ 0, 1𝑛 → 0, 1 cannot be computedby a Boolean circuit using fewer than exponential (in 𝑛) number ofgates.

In fact, as we explore in the exercises, this is the case for most func-tions. Hence functions that can be computed in a small number oflines (such as addition, multiplication, finding short paths in graphs,or even the EVAL function) are the exception, rather than the rule.

RRemark 5.4 — More efficient representation (advanced,optional). The ASCII representation is not the shortestrepresentation for NAND-CIRC programs. NAND-CIRC programs are equivalent to circuits with NANDgates, which means that a NAND-CIRC program of 𝑠lines, 𝑛 inputs, and 𝑚 outputs can be represented bya labeled directed graph of 𝑠 + 𝑛 vertices, of which 𝑛have in-degree zero, and the 𝑠 others have in-degreeat most two. Using the adjacency matrix represen-tation for such graphs, we can reduce the implicitconstant in Theorem 5.2 to be arbitrarily close to 5, seeExercise 5.6.

Page 190: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

190 introduction to theoretical computer science

Figure 5.4: We prove Theorem 5.5 by coming upwith a list 𝑓0, 
 , 𝑓2𝑛 of functions such that 𝑓0 is theall zero function, 𝑓2𝑛 is a function (obtained fromTheorem 5.3) outside of SIZE(0.1 ⋅ 2𝑛/𝑛) and suchthat 𝑓𝑖−1 and 𝑓𝑖 differ by one another on at most oneinput. We can show that for every 𝑖, the number ofgates to compute 𝑓𝑖 is at most 10𝑛 larger than thenumber of gates to compute 𝑓𝑖−1 and so if we let 𝑖be the smallest number such that 𝑓𝑖 ∉ SIZE(𝑠), then𝑓𝑖 ∈ SIZE(𝑠 + 10𝑛).

5.2.1 Size hierarchy theorem (optional)By Theorem 4.15 the class SIZE𝑛(10 ⋅ 2𝑛/𝑛) contains all functionsfrom 0, 1𝑛 to 0, 1, while by Theorem 5.3, there is some function𝑓 ∶ 0, 1𝑛 → 0, 1 that is not contained in SIZE𝑛(0.1 ⋅ 2𝑛/𝑛). In otherwords, for every sufficiently large 𝑛,

SIZE𝑛 (0.1 2𝑛𝑛 ) ⊊ SIZE𝑛 (10 2𝑛𝑛 ) . (5.3)

It turns out that we can use Theorem 5.3 to show a more general re-sult: whenever we increase our “budget” of gates we can computenew functions.

Theorem 5.5 — Size Hierarchy Theorem. For every sufficiently large 𝑛and 10𝑛 < 𝑠 < 0.1 ⋅ 2𝑛/𝑛,

SIZE𝑛(𝑠) ⊊ SIZE𝑛(𝑠 + 10𝑛) . (5.4)

Proof Idea:

To prove the theorem we need to find a function 𝑓 ∶ 0, 1𝑛 → 0, 1such that 𝑓 can be computed by a circuit of 𝑠 + 10𝑛 gates but it cannotbe computed by a circuit of 𝑠 gates. We will do so by coming up witha sequence of functions 𝑓0, 𝑓1, 𝑓2, 
 , 𝑓𝑁 with the following properties:(1) 𝑓0 can be computed by a circuit of at most 10𝑛 gates, (2) 𝑓𝑁 cannotbe computed by a circuit of 0.1 ⋅ 2𝑛/𝑛 gates, and (3) for every 𝑖 ∈0, 
 , 𝑁, if 𝑓𝑖 can be computed by a circuit of size 𝑠, then 𝑓𝑖+1 can becomputed by a circuit of size at most 𝑠+10𝑛. Together these propertiesimply that if we let 𝑖 be the smallest number such that 𝑓𝑖 ∉ SIZE𝑛(𝑠),then since 𝑓𝑖−1 ∈ SIZE(𝑠) it must hold that 𝑓𝑖 ∈ SIZE(𝑠 + 10𝑛) which iswhat we need to prove. See Fig. 5.4 for an illustration.⋆Proof of Theorem 5.5. Let 𝑓∗ ∶ 0, 1𝑛 → 0, 1 be the function(whose existence we are guaranteed by Theorem 5.3) such that𝑓∗ ∉ SIZE𝑛(0.1 ⋅ 2𝑛/𝑛). We define the functions 𝑓0, 𝑓1, 
 , 𝑓2𝑛 map-ping 0, 1𝑛 to 0, 1 as follows. For every đ‘„ ∈ 0, 1𝑛, if đ‘™đ‘’đ‘„(đ‘„) ∈0, 1, 
 , 2𝑛 − 1 is đ‘„â€™s order in the lexicographical order then

𝑓𝑖(đ‘„) = âŽ§âŽšâŽ©đ‘“âˆ—(đ‘„) đ‘™đ‘’đ‘„(đ‘„) < 𝑖0 otherwise. (5.5)

The function 𝑓0 is simply the constant zero function, while thefunction 𝑓2𝑛 is equal to 𝑓∗. Moreover, for every 𝑖 ∈ [2𝑛], the functions𝑓𝑖 and 𝑓𝑖+1 differ on at most one input (i.e., the input đ‘„ ∈ 0, 1𝑛 suchthat đ‘™đ‘’đ‘„(đ‘„) = 𝑖). Let 10𝑛 < 𝑠 < 0.1 ⋅ 2𝑛/𝑛, and let 𝑖 be the first indexsuch that 𝑓𝑖 ∉ SIZE𝑛(𝑠). Since 𝑓2𝑛 = 𝑓∗ ∉ SIZE(0.1 ⋅ 2𝑛/𝑛) there

Page 191: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 191

must exist such an index 𝑖, and moreover 𝑖 > 0 since the constant zerofunction is a member of SIZE𝑛(10𝑛).

By our choice of 𝑖, 𝑓𝑖−1 is a member of SIZE𝑛(𝑠). To complete theproof, we need to show that 𝑓𝑖 ∈ SIZE𝑛(𝑠 + 10𝑛). Let đ‘„âˆ— be the stringsuch that đ‘™đ‘’đ‘„(đ‘„âˆ—) = 𝑖 𝑏 ∈ 0, 1 is the value of 𝑓∗(đ‘„âˆ—). Then we candefine 𝑓𝑖 also as follows

𝑓𝑖(đ‘„) = âŽ§âŽšâŽ©đ‘ đ‘„ = đ‘„âˆ—đ‘“đ‘–(đ‘„) đ‘„ ≠ đ‘„âˆ— (5.6)

or in other words𝑓𝑖(đ‘„) = 𝑓𝑖−1(đ‘„) ∧ EQUAL(đ‘„âˆ—, đ‘„) √ 𝑏 ∧ ÂŹEQUAL(đ‘„âˆ—, đ‘„) (5.7)

where EQUAL ∶ 0, 12𝑛 → 0, 1 is the function that maps đ‘„, đ‘„â€Č ∈0, 1𝑛 to 1 if they are equal and to 0 otherwise. Since (by our choiceof 𝑖), 𝑓𝑖−1 can be computed using at most 𝑠 gates and (as can be easilyverified) that EQUAL ∈ SIZE𝑛(9𝑛), we can compute 𝑓𝑖 using at most𝑠 + 9𝑛 + 𝑂(1) ≀ 𝑠 + 10𝑛 gates which is what we wanted to prove.

Figure 5.5: An illustration of some of what we knowabout the size complexity classes (not to scale!). Thisfigure depicts classes of the form SIZE𝑛,𝑛(𝑠) but thestate of affairs for other size complexity classes suchas SIZE𝑛,1(𝑠) is similar. We know by Theorem 4.12(with the improvement of Section 4.4.2) that allfunctions mapping 𝑛 bits to 𝑛 bits can be computedby a circuit of size 𝑐 ⋅ 2𝑛 for 𝑐 ≀ 10, while on theother hand the counting lower bound (Theorem 5.3,see also Exercise 5.4) shows that some such functionswill require 0.1 ⋅ 2𝑛, and the size hierarchy theorem(Theorem 5.5) shows the existence of functions inSIZE(𝑆) ⧔ SIZE(𝑠) whenever 𝑠 = 𝑜(𝑆), see alsoExercise 5.5. We also consider some specific examples:addition of two 𝑛/2 bit numbers can be done in 𝑂(𝑛)lines, while we don’t know of such a program formultiplying two 𝑛 bit numbers, though we do knowit can be done in 𝑂(𝑛2) and in fact even better size.In the above, FACTOR𝑛 corresponds to the inverseproblem of multiplying- finding the prime factorizationof a given number. At the moment we do not knowof any circuit a polynomial (or even sub-exponential)number of lines that can compute FACTOR𝑛.R

Remark 5.6 — Explicit functions. While the size hierar-chy theorem guarantees that there exists some functionthat can be computed using, for example, 𝑛2 gates, butnot using 100𝑛 gates, we do not know of any explicitexample of such a function. While we suspect thatinteger multiplication is such an example, we do nothave any proof that this is the case.

Page 192: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

192 introduction to theoretical computer science

5.3 THE TUPLES REPRESENTATION

ASCII is a fine presentation of programs, but for some applicationsit is useful to have a more concrete representation of NAND-CIRCprograms. In this section we describe a particular choice, that willbe convenient for us later on. A NAND-CIRC program is simply asequence of lines of the form

blah = NAND(baz,boo)

There is of course nothing special about the particular names weuse for variables. Although they would be harder to read, we couldwrite all our programs using only working variables such as temp_0,temp_1 etc. Therefore, our representation for NAND-CIRC programsignores the actual names of the variables, and just associate a numberwith each variable. We encode a line of the program as a triple ofnumbers. If the line has the form foo = NAND(bar,blah) then weencode it with the triple (𝑖, 𝑗, 𝑘) where 𝑖 is the number correspondingto the variable foo and 𝑗 and 𝑘 are the numbers corresponding to barand blah respectively.

More concretely, we will associate every variable with a numberin the set [𝑡] = 0, 1, 
 , 𝑡 − 1. The first 𝑛 numbers 0, 
 , 𝑛 − 1correspond to the input variables, the last 𝑚 numbers 𝑡 − 𝑚, 
 , 𝑡 − 1correspond to the output variables, and the intermediate numbers𝑛, 
 , 𝑡 − 𝑚 − 1 correspond to the remaining “workspace” variables.Formally, we define our representation as follows:

Definition 5.7 — List of tuples representation. Let 𝑃 be a NAND-CIRCprogram of 𝑛 inputs, 𝑚 outputs, and 𝑠 lines, and let 𝑡 be the num-ber of distinct variables used by 𝑃 . The list of tuples representationof 𝑃 is the triple (𝑛, 𝑚, 𝐿) where 𝐿 is a list of triples of the form(𝑖, 𝑗, 𝑘) for 𝑖, 𝑗, 𝑘 ∈ [𝑡].

We assign a number for variable of 𝑃 as follows:

‱ For every 𝑖 ∈ [𝑛], the variable X[𝑖] is assigned the number 𝑖.‱ For every 𝑗 ∈ [𝑚], the variable Y[𝑗] is assigned the number𝑡 − 𝑚 + 𝑗.‱ Every other variable is assigned a number in 𝑛, 𝑛+1, 
 , 𝑡−𝑚−1 in the order in which the variable appears in the program 𝑃 .

The list of tuples representation is our default choice for represent-ing NAND-CIRC programs. Since “list of tuples representation” is abit of a mouthful, we will often call it simply “the representation” fora program 𝑃 . Sometimes, when the number 𝑛 of inputs and number

Page 193: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 193

4 If you’re curious what these few lines are, see ourGitHub repository.

𝑚 of outputs are known from the context, we will simply represent aprogram as the list 𝐿 instead of the triple (𝑛, 𝑚, 𝐿).

Example 5.8 — Representing the XOR program. Our favorite NAND-CIRC program, the program

u = NAND(X[0],X[1])v = NAND(X[0],u)w = NAND(X[1],u)Y[0] = NAND(v,w)

computing the XOR function is represented as the tuple (2, 1, 𝐿)where 𝐿 = ((2, 0, 1), (3, 0, 2), (4, 1, 2), (5, 3, 4)). That is, the variablesX[0] and X[1] are given the indices 0 and 1 respectively, the vari-ables u,v,w are given the indices 2, 3, 4 respectively, and the variableY[0] is given the index 5.Transforming a NAND-CIRC program from its representation as

code to the representation as a list of tuples is a fairly straightforwardprogramming exercise, and in particular can be done in a few lines ofPython.4 The list-of-tuples representation loses information such as theparticular names we used for the variables, but this is OK since thesenames do not make a difference to the functionality of the program.

5.3.1 From tuples to stringsIf 𝑃 is a program of size 𝑠, then the number 𝑡 of variables is at most 3𝑠(as every line touches at most three variables). Hence we can encodeevery variable index in [𝑡] as a string of length ℓ = ⌈log(3𝑠)⌉, by addingleading zeroes as needed. Since this is a fixed-length encoding, it isprefix free, and so we can encode the list 𝐿 of 𝑠 triples (correspondingto the encoding of the 𝑠 lines of the program) as simply the string oflength 3ℓ𝑠 obtained by concatenating all of these encodings.

We define 𝑆(𝑠) to be the length of the string representing the list 𝐿corresponding to a size 𝑠 program. By the above we see that𝑆(𝑠) = 3𝑠⌈log(3𝑠)⌉ . (5.8)

We can represent 𝑃 = (𝑛, 𝑚, 𝐿) as a string by prepending a prefixfree representation of 𝑛 and 𝑚 to the list 𝐿. Since 𝑛, 𝑚 ≀ 3𝑠 (a pro-gram must touch at least once all its input and output variables), thoseprefix free representations can be encoded using strings of length𝑂(log 𝑠). In particular, every program 𝑃 of at most 𝑠 lines can be rep-resented by a string of length 𝑂(𝑠 log 𝑠). Similarly, every circuit đ¶ ofat most 𝑠 gates can be represented by a string of length 𝑂(𝑠 log 𝑠) (forexample by translating đ¶ to the equivalent program 𝑃 ).

Page 194: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

194 introduction to theoretical computer science

5.4 A NAND-CIRC INTERPRETER IN NAND-CIRC

Since we can represent programs as strings, we can also think of aprogram as an input to a function. In particular, for every naturalnumber 𝑠, 𝑛, 𝑚 > 0 we define the function EVAL𝑠,𝑛,𝑚 ∶ 0, 1𝑆(𝑠)+𝑛 →0, 1𝑚 as follows:

EVAL𝑠,𝑛,𝑚(đ‘đ‘„) = âŽ§âŽšâŽ©đ‘ƒ(đ‘„) 𝑝 ∈ 0, 1𝑆(𝑠) represents a size-𝑠 program 𝑃 with 𝑛 inputs and 𝑚 outputs0𝑚 otherwise(5.9)

where 𝑆(𝑠) is defined as in (5.8) and we use the concrete representa-tion scheme described in Section 5.1.

That is, EVAL𝑠,𝑛,𝑚 takes as input the concatenation of two strings:a string 𝑝 ∈ 0, 1𝑆(𝑠) and a string đ‘„ ∈ 0, 1𝑛. If 𝑝 is a string thatrepresents a list of triples 𝐿 such that (𝑛, 𝑚, 𝐿) is a list-of-tuples rep-resentation of a size-𝑠 NAND-CIRC program 𝑃 , then EVAL𝑠,𝑛,𝑚(đ‘đ‘„)is equal to the evaluation 𝑃(đ‘„) of the program 𝑃 on the input đ‘„. Oth-erwise, EVAL𝑠,𝑛,𝑚(đ‘đ‘„) equals 0𝑚 (this case is not very important: youcan simply think of 0𝑚 as some “junk value” that indicates an error).

Take-away points. The fine details of EVAL𝑠,𝑛,𝑚’s definition are notvery crucial. Rather, what you need to remember about EVAL𝑠,𝑛,𝑚 isthat:

‱ EVAL𝑠,𝑛,𝑚 is a finite function taking a string of fixed length as inputand outputting a string of fixed length as output.

‱ EVAL𝑠,𝑛,𝑚 is a single function, such that computing EVAL𝑠,𝑛,𝑚allows to evaluate arbitrary NAND-CIRC programs of a certainlength on arbitrary inputs of the appropriate length.

‱ EVAL𝑠,𝑛,𝑚 is a function, not a program (recall the discussion in Sec-tion 3.6.2). That is, EVAL𝑠,𝑛,𝑚 is a specification of what output is as-sociated with what input. The existence of a program that computesEVAL𝑠,𝑛,𝑚 (i.e., an implementation for EVAL𝑠,𝑛,𝑚) is a separatefact, which needs to be established (and which we will do in Theo-rem 5.9, with a more efficient program shown in Theorem 5.10).

One of the first examples of self circularity we will see in this book isthe following theorem, which we can think of as showing a “NAND-CIRC interpreter in NAND-CIRC”:

Theorem 5.9 — Bounded Universality of NAND-CIRC programs. For every𝑠, 𝑛, 𝑚 ∈ ℕ with 𝑠 ≄ 𝑚 there is a NAND-CIRC program 𝑈𝑠,𝑛,𝑚 thatcomputes the function EVAL𝑠,𝑛,𝑚.

That is, the NAND-CIRC program 𝑈𝑠,𝑛,𝑚 takes the descriptionof any other NAND-CIRC program 𝑃 (of the right length and input-

Page 195: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 195

Figure 5.6: A universal circuit 𝑈 is a circuit that gets asinput the description of an arbitrary (smaller) circuit𝑃 as a binary string, and an input đ‘„, and outputs thestring 𝑃(đ‘„) which is the evaluation of 𝑃 on đ‘„. We canalso think of 𝑈 as a straight-line program that gets asinput the code of a straight-line program 𝑃 and aninput đ‘„, and outputs 𝑃(đ‘„).

s/outputs) and any input đ‘„, and computes the result of evaluating theprogram 𝑃 on the input đ‘„. Given the equivalence between NAND-CIRC programs and Boolean circuits, we can also think of 𝑈𝑠,𝑛,𝑚 asa circuit that takes as input the description of other circuits and theirinputs, and returns their evaluation, see Fig. 5.6. We call this NAND-CIRC program 𝑈𝑠,𝑛,𝑚 that computes EVAL𝑠,𝑛,𝑚 a bounded universalprogram (or a universal circuit, see Fig. 5.6). “Universal” stands forthe fact that this is a single program that can evaluate arbitrary code,where “bounded” stands for the fact that 𝑈𝑠,𝑛,𝑚 only evaluates pro-grams of bounded size. Of course this limitation is inherent for theNAND-CIRC programming language, since a program of 𝑠 lines (or,equivalently, a circuit of 𝑠 gates) can take at most 2𝑠 inputs. Later, inChapter 7, we will introduce the concept of loops (and the model ofTuring Machines), that allow to escape this limitation.

Proof. Theorem 5.9 is an important result, but it is actually not hard toprove. Specifically, since EVAL𝑠,𝑛,𝑚 is a finite function Theorem 5.9 isan immediate corollary of Theorem 4.12, which states that every finitefunction can be computed by some NAND-CIRC program.

PTheorem 5.9 is simple but important. Make sure youunderstand what this theorem means, and why it is acorollary of Theorem 4.12.

5.4.1 Efficient universal programsTheorem 5.9 establishes the existence of a NAND-CIRC programfor computing EVAL𝑠,𝑛,𝑚, but it provides no explicit bound on thesize of this program. Theorem 4.12, which we used to prove Theo-rem 5.9, guarantees the existence of a NAND-CIRC program whosesize can be as large as exponential in the length of its input. This wouldmean that even for moderately small values of 𝑠, 𝑛, 𝑚 (for example𝑛 = 100, 𝑠 = 300, 𝑚 = 1), computing EVAL𝑠,𝑛,𝑚 might require aNAND program with more lines than there are atoms in the observ-able universe! Fortunately, we can do much better than that. In fact,for every 𝑠, 𝑛, 𝑚 there exists a NAND-CIRC program for comput-ing EVAL𝑠,𝑛,𝑚 with size that is polynomial in its input length. This isshown in the following theorem.

Theorem 5.10 — Efficient bounded universality of NAND-CIRC programs.

For every 𝑠, 𝑛, 𝑚 ∈ ℕ there is a NAND-CIRC program of atmost 𝑂(𝑠2 log 𝑠) lines that computes the function EVAL𝑠,𝑛,𝑚 ∶

Page 196: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

196 introduction to theoretical computer science

0, 1𝑆+𝑛 → 0, 1𝑚 defined above (where 𝑆 is the number of bitsneeded to represent programs of 𝑠 lines).

PIf you haven’t done so already, now might be a goodtime to review 𝑂 notation in Section 1.4.8. In particu-lar, an equivalent way to state Theorem 5.10 is that itsays that there exists some number 𝑐 > 0 such that forevery 𝑠, 𝑛, 𝑚 ∈ ℕ, there exists a NAND-CIRC program𝑃 of at most 𝑐𝑠2 log 𝑠 lines that computes the functionEVAL𝑠,𝑛,𝑚.

Unlike Theorem 5.9, Theorem 5.10 is not a trivial corollary of thefact that every finite function can be computed by some circuit. Prov-ing Theorem 5.9 requires us to present a concrete NAND-CIRC pro-gram for computing the function EVAL𝑠,𝑛,𝑚. We will do so in severalstages.1. First, we will describe the algorithm to evaluate EVAL𝑠,𝑛,𝑚 in

“pseudo code”.

2. Then, we will show how we can write a program to computeEVAL𝑠,𝑛,𝑚 in Python. We will not use much about Python, anda reader that has familiarity with programming in any languageshould be able to follow along.

3. Finally, we will show how we can transform this Python programinto a NAND-CIRC program.This approach yields much more than just proving Theorem 5.10:

we will see that it is in fact always possible to transform (loop free)code in high level languages such as Python to NAND-CIRC pro-grams (and hence to Boolean circuits as well).

5.4.2 A NAND-CIRC interpeter in “pseudocode”To prove Theorem 5.10 it suffices to give a NAND-CIRC program of𝑂(𝑠2 log 𝑠) lines that can evaluate NAND-CIRC programs of 𝑠 lines.Let us start by thinking how we would evaluate such programs if weweren’t restricted to only performing NAND operations. That is, let usdescribe informally an algorithm that on input 𝑛, 𝑚, 𝑠, a list of triples𝐿, and a string đ‘„ ∈ 0, 1𝑛, evaluates the program represented by(𝑛, 𝑚, 𝐿) on the string đ‘„.

PIt would be highly worthwhile for you to stop hereand try to solve this problem yourself. For example,you can try thinking how you would write a program

Page 197: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 197

NANDEVAL(n,m,s,L,x) that computes this function inthe programming language of your choice.

We will now describe such an algorithm. We assume that we haveaccess to a bit array data structure that can store for every 𝑖 ∈ [𝑡] abit 𝑇𝑖 ∈ 0, 1. Specifically, if Table is a variable holding this datastructure, then we assume we can perform the operations:

‱ GET(Table,i)which retrieves the bit corresponding to i in Table.The value of i is assumed to be an integer in [𝑡].

‱ Table = UPDATE(Table,i,b)which updates Table so the the bitcorresponding to i is now set to b. The value of i is assumed to bean integer in [𝑡] and b is a bit in 0, 1.Algorithm 5.11 — Eval NAND-CIRC programs.

Input: Numbers 𝑛, 𝑚, 𝑠 and 𝑡 ≀ 3𝑠, as well as a list 𝐿 of 𝑠triples of numbers in [𝑡], and a string đ‘„ ∈ 0, 1𝑛.

Output: Evaluation of the program represented by(𝑛, 𝑚, 𝐿) on theInput: đ‘„ ∈ 0, 1𝑛.1: Let Vartable be table of size 𝑡2: for 𝑖 in [𝑛] do3: Vartable = UPDATE(Vartable,𝑖,đ‘„đ‘–)4: end for5: for (𝑖, 𝑗, 𝑘) in 𝐿 do6: 𝑎 ← GET(Vartable,𝑗)7: 𝑏 ← GET(Vartable,𝑘)8: Vartable = UPDATE(Vartable,𝑖,NAND(𝑎,𝑏))9: end for

10: for 𝑗 in [𝑚] do11: 𝑩𝑗 ← GET(Vartable,𝑡 − 𝑚 + 𝑗)12: end for13: return 𝑩0, 
 , 𝑩𝑚−1

Algorithm 5.11 evaluates the program given to it as input one lineat a time, updating the Vartable table to contain the value of eachvariable. At the end of the execution it outputs the variables at posi-tions 𝑡 − 𝑚, 𝑡 − 𝑚 + 1, 
 , 𝑡 − 1 which correspond to the input variables.

5.4.3 A NAND interpreter in PythonTo make things more concrete, let us see how we implement Algo-rithm 5.11 in the Python programming language. (There is nothingspecial about Python. We could have easily presented a corresponding

Page 198: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

198 introduction to theoretical computer science

5 Python does not distinguish between lists andarrays, but allows constant time random access to anindexed elements to both of them. One could arguethat if we allowed programs of truly unboundedlength (e.g., larger than 264) then the price wouldnot be constant but logarithmic in the length of thearray/lists, but the difference between 𝑂(𝑠) and𝑂(𝑠 log 𝑠) will not be important for our discussions.

function in JavaScript, C, OCaml, or any other programming lan-guage.) We will construct a function NANDEVAL that on input 𝑛, 𝑚, 𝐿, đ‘„will output the result of evaluating the program represented by(𝑛, 𝑚, 𝐿) on đ‘„. To keep things simple, we will not worry about the casethat 𝐿 does not represent a valid program of 𝑛 inputs and 𝑚 outputs.The code is presented in Fig. 5.7.

Accessing an element of the array Vartable at a given index takesa constant number of basic operations. Hence (since 𝑛, 𝑚 ≀ 𝑠 and𝑡 ≀ 3𝑠), the program above will use 𝑂(𝑠) basic operations.5

5.4.4 Constructing the NAND-CIRC interpreter in NAND-CIRCWe now turn to describing the proof of Theorem 5.10. To prove thetheorem it is not enough to give a Python program. Rather, we need toshow how we compute the function EVAL𝑠,𝑛,𝑚 using a NAND-CIRCprogram. In other words, our job is to transform, for every 𝑠, 𝑛, 𝑚, thePython code of Section 5.4.3 to a NAND-CIRC program 𝑈𝑠,𝑛,𝑚 thatcomputes the function EVAL𝑠,𝑛,𝑚.

PBefore reading further, try to think how you could givea “constructive proof” of Theorem 5.10. That is, thinkof how you would write, in the programming lan-guage of your choice, a function universal(s,n,m)that on input 𝑠, 𝑛, 𝑚 outputs the code for the NAND-CIRC program 𝑈𝑠,𝑛,𝑚 such that 𝑈𝑠,𝑛,𝑚 computesEVAL𝑠,𝑛,𝑚. There is a subtle but crucial differencebetween this function and the Python NANDEVAL pro-gram described above. Rather than actually evaluatinga given program 𝑃 on some input đ‘€, the functionuniversal should output the code of a NAND-CIRCprogram that computes the map (𝑃 , đ‘„) ↩ 𝑃(đ‘„).

Our construction will follow very closely the Python implementa-tion of EVAL above. We will use variables Vartable[0],
,Vartable[2ℓ−1], where ℓ = ⌈log 3𝑠⌉ to store our variables. However, NAND doesn’thave integer-valued variables, so we cannot write code such asVartable[i] for some variable i. However, we can implement thefunction GET(Vartable,i) that outputs the i-th bit of the arrayVartable. Indeed, this is nothing but the function LOOKUPℓ that wehave seen in Theorem 4.10!

PPlease make sure that you understand why GET andLOOKUPℓ are the same function.

We saw that we can compute LOOKUPℓ in time 𝑂(2ℓ) = 𝑂(𝑠) forour choice of ℓ.

Page 199: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 199

Figure 5.7: Code for evaluating a NAND-CIRC program given in the list-of-tuples representation

def NANDEVAL(n,m,L,X):# Evaluate a NAND-CIRC program from list of tuple representation.s = len(L) # num of linest = max(max(a,b,c) for (a,b,c) in L)+1 # max index in L + 1Vartable = [0] * t # initialize array

# helper functionsdef GET(V,i): return V[i]def UPDATE(V,i,b):

V[i]=breturn V

# load input values to Vartable:for i in range(n):

Vartable = UPDATE(Vartable,i,X[i])

# Run the programfor (i,j,k) in L:

a = GET(Vartable,j)b = GET(Vartable,k)c = NAND(a,b)Vartable = UPDATE(Vartable,i,c)

# Return outputs Vartable[t-m], Vartable[t-m+1],....,Vartable[t-1]return [GET(Vartable,t-m+j) for j in range(m)]

# Test on XOR (2 inputs, 1 output)L = ((2, 0, 1), (3, 0, 2), (4, 1, 2), (5, 3, 4))print(NANDEVAL(2,1,L,(0,1))) # XOR(0,1)# [1]print(NANDEVAL(2,1,L,(1,1))) # XOR(1,1)# [0]

Page 200: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

200 introduction to theoretical computer science

For every ℓ, let UPDATEℓ ∶ 0, 12ℓ+ℓ+1 → 0, 12ℓ correspond to theUPDATE function for arrays of length 2ℓ. That is, on input 𝑉 ∈ 0, 12ℓ ,𝑖 ∈ 0, 1ℓ, 𝑏 ∈ 0, 1, UPDATEℓ(𝑉 , 𝑏, 𝑖) is equal to 𝑉 â€Č ∈ 0, 12ℓ suchthat 𝑉 â€Č𝑗 = âŽ§âŽšâŽ©đ‘‰đ‘— 𝑗 ≠ 𝑖𝑏 𝑗 = 1 (5.10)

where we identify the string 𝑖 ∈ 0, 1ℓ with a number in 0, 
 , 2ℓ − 1using the binary representation. We can compute UPDATEℓ using an𝑂(2ℓℓ) = (𝑠 log 𝑠) line NAND-CIRC program as as follows:

1. For every 𝑗 ∈ [2ℓ], there is an 𝑂(ℓ) line NAND-CIRC program tocompute the function EQUALS𝑗 ∶ 0, 1ℓ → 0, 1 that on input 𝑖outputs 1 if and only if 𝑖 is equal to (the binary representation of) 𝑗.(We leave verifying this as Exercise 5.2 and Exercise 5.3.)

2. We have seen that we can compute the function IF ∶ 0, 13 → 0, 1such that IF(𝑎, 𝑏, 𝑐) equals 𝑏 if 𝑎 = 1 and 𝑐 if 𝑎 = 0.Together, this means that we can compute UPDATE (using some

“syntactic sugar” for bounded length loops) as follows:

def UPDATE_ell(V,i,b):# Get V[0]...V[2^ell-1], i in 0,1^ell, b in 0,1# Return NewV[0],...,NewV[2^ell-1]# updated array with NewV[i]=b and all# else same as Vfor j in range(2**ell): # j = 0,1,2,....,2^ell -1

a = EQUALS_j(i)NewV[j] = IF(a,b,V[j])

return NewV

Since the loop over j in UPDATE is run 2ℓ times, and computingEQUALS_j takes 𝑂(ℓ) lines, the total number of lines to compute UP-DATE is 𝑂(2ℓ ⋅ ℓ) = 𝑂(𝑠 log 𝑠). Once we can compute GET and UPDATE,the rest of the implementation amounts to “book keeping” that needsto be done carefully, but is not too insightful, and hence we omit thefull details. Since we run GET and UPDATE 𝑠 times, the total number oflines for computing EVAL𝑠,𝑛,𝑚 is 𝑂(𝑠2) + 𝑂(𝑠2 log 𝑠) = 𝑂(𝑠2 log 𝑠).This completes (up to the omitted details) the proof of Theorem 5.10.

RRemark 5.12 — Improving to quasilinear overhead (ad-vanced optional note). The NAND-CIRC programabove is less efficient than its Python counterpart,since NAND does not offer arrays with efficient ran-dom access. Hence for example the LOOKUP operation

Page 201: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 201

6 ARM stands for “Advanced RISC Machine” whereRISC in turn stands for “Reduced instruction setcomputer”.

on an array of 𝑠 bits takes Ω(𝑠) lines in NAND eventhough it takes 𝑂(1) steps (or maybe 𝑂(log 𝑠) steps,depending on how we count) in Python.It turns out that it is possible to improve the boundof Theorem 5.10, and evaluate 𝑠 line NAND-CIRCprograms using a NAND-CIRC program of 𝑂(𝑠 log 𝑠)lines. The key is to consider the description of NAND-CIRC programs as circuits, and in particular as di-rected acyclic graphs (DAGs) of bounded in-degree.A universal NAND-CIRC program 𝑈𝑠 for 𝑠 line pro-grams will correspond to a universal graph đ»đ‘  for such𝑠 vertex DAGs. We can think of such a graph 𝑈𝑠 asfixed “wiring” for a communication network, thatshould be able to accommodate any arbitrary patternof communication between 𝑠 vertices (where this pat-tern corresponds to an 𝑠 line NAND-CIRC program).It turns out that such efficient routing networks existthat allow embedding any 𝑠 vertex circuit inside a uni-versal graph of size 𝑂(𝑠 log 𝑠), see the bibliographicalnotes Section 5.9 for more on this issue.

5.5 A PYTHON INTERPRETER IN NAND-CIRC (DISCUSSION)

To prove Theorem 5.10 we essentially translated every line of thePython program for EVAL into an equivalent NAND-CIRC snip-pet. However none of our reasoning was specific to the particu-lar function EVAL. It is possible to translate every Python programinto an equivalent NAND-CIRC program of comparable efficiency.(More concretely, if the Python program takes 𝑇 (𝑛) operations oninputs of length at most 𝑛 then there exists NAND-CIRC program of𝑂(𝑇 (𝑛) log𝑇 (𝑛)) lines that agrees with the Python program on inputsof length 𝑛.) Actually doing so requires taking care of many detailsand is beyond the scope of this book, but let me try to convince youwhy you should believe it is possible in principle.

For starters, one can use CPython (the reference implementationfor Python), to evaluate every Python program using a C program. Wecan combine this with a C compiler to transform a Python programto various flavors of “machine language”. So, to transform a Pythonprogram into an equivalent NAND-CIRC program, it is enough toshow how to transform a machine language program into an equiva-lent NAND-CIRC program. One minimalistic (and hence convenient)family of machine languages is known as the ARM architecture whichpowers many mobile devices including essentially all Android de-vices.6 There are even simpler machine languages, such as the LEGarchitecture for which a backend for the LLVM compiler was imple-mented (and hence can be the target of compiling any of the largeand growing list of languages that this compiler supports). Other ex-

Page 202: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

202 introduction to theoretical computer science

amples include the TinyRAM architecture (motivated by interactiveproof systems that we will discuss in Chapter 22) and the teaching-oriented Ridiculously Simple Computer architecture. Going one byone over the instruction sets of such computers and translating themto NAND snippets is no fun, but it is a feasible thing to do. In fact,ultimately this is very similar to the transformation that takes placein converting our high level code to actual silicon gates that are notso different from the operations of a NAND-CIRC program. Indeed,tools such as MyHDL that transform “Python to Silicon” can be usedto convert a Python program to a NAND-CIRC program.

The NAND-CIRC programming language is just a teaching tool,and by no means do I suggest that writing NAND-CIRC programs, orcompilers to NAND-CIRC, is a practical, useful, or enjoyable activity.What I do want is to make sure you understand why it can be done,and to have the confidence that if your life (or at least your grade)depended on it, then you would be able to do this. Understandinghow programs in high level languages such as Python are eventuallytransformed into concrete low-level representation such as NAND isfundamental to computer science.

The astute reader might notice that the above paragraphs onlyoutlined why it should be possible to find for every particular Python-computable function 𝑓 , a particular comparably efficient NAND-CIRCprogram 𝑃 that computes 𝑓 . But this still seems to fall short of ourgoal of writing a “Python interpreter in NAND” which would meanthat for every parameter 𝑛, we come up with a single NAND-CIRCprogram UNIV𝑠 such that given a description of a Python program𝑃 , a particular input đ‘„, and a bound 𝑇 on the number of operations(where the lengths of 𝑃 and đ‘„ and the value of 𝑇 are all at most 𝑠)returns the result of executing 𝑃 on đ‘„ for at most 𝑇 steps. After all,the transformation above takes every Python program into a differentNAND-CIRC program, and so does not yield “one NAND-CIRC pro-gram to rule them all” that can evaluate every Python program up tosome given complexity. However, we can in fact obtain one NAND-CIRC program to evaluate arbitrary Python programs. The reason isthat there exists a Python interpreter in Python: a Python program 𝑈that takes a bit string, interprets it as Python code, and then runs thatcode. Hence, we only need to show a NAND-CIRC program 𝑈 ∗ thatcomputes the same function as the particular Python program 𝑈 , andthis will give us a way to evaluate all Python programs.

What we are seeing time and again is the notion of universality orself reference of computation, which is the sense that all reasonably richmodels of computation are expressive enough that they can “simulatethemselves”. The importance of this phenomenon to both the theoryand practice of computing, as well as far beyond it, including the

Page 203: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 203

foundations of mathematics and basic questions in science, cannot beoverstated.

5.6 THE PHYSICAL EXTENDED CHURCH-TURING THESIS (DISCUS-SION)

We’ve seen that NAND gates (and other Boolean operations) can beimplemented using very different systems in the physical world. Whatabout the reverse direction? Can NAND-CIRC programs simulate anyphysical computer?

We can take a leap of faith and stipulate that Boolean circuits (orequivalently NAND-CIRC programs) do actually encapsulate everycomputation that we can think of. Such a statement (in the realm ofinfinite functions, which we’ll encounter in Chapter 7) is typicallyattributed to Alonzo Church and Alan Turing, and in that contextis known as the Church Turing Thesis. As we will discuss in futurelectures, the Church-Turing Thesis is not a mathematical theorem orconjecture. Rather, like theories in physics, the Church-Turing Thesisis about mathematically modeling the real world. In the context offinite functions, we can make the following informal hypothesis orprediction:

“Physical Extended Church-Turing Thesis” (PECTT): If a functionđč ∶ 0, 1𝑛 → 0, 1𝑚 can be computed in the physical world using 𝑠 amountof “physical resources” then it can be computed by a Boolean circuit program ofroughly 𝑠 gates.

A priori it might seem rather extreme to hypothesize that our mea-ger model of NAND-CIRC programs or Boolean circuits captures allpossible physical computation. But yet, in more than a century ofcomputing technologies, no one has yet built any scalable computingdevice that challenges this hypothesis.

We now discuss the “fine print” of the PECTT in more detail, aswell as the (so far unsuccessful) challenges that have been raisedagainst it. There is no single universally-agreed-upon formalizationof “roughly 𝑠 physical resources”, but we can approximate this notionby considering the size of any physical computing device and thetime it takes to compute the output, and ask that any such device canbe simulated by a Boolean circuit with a number of gates that is apolynomial (with not too large exponent) in the size of the system andthe time it takes it to operate.

In other words, we can phrase the PECTT as stipulating that anyfunction that can be computed by a device that takes a certain volume𝑉 of space and requires 𝑡 time to complete the computation, must becomputable by a Boolean circuit with a number of gates 𝑝(𝑉 , 𝑡) that ispolynomial in 𝑉 and 𝑡.

Page 204: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

204 introduction to theoretical computer science

The exact form of the function 𝑝(𝑉 , 𝑡) is not universally agreedupon but it is generally accepted that if 𝑓 ∶ 0, 1𝑛 → 0, 1 is anexponentially hard function, in the sense that it has no NAND-CIRCprogram of fewer than, say, 2𝑛/2 lines, then a demonstration of a phys-ical device that can compute in the real world 𝑓 for moderate inputlengths (e.g., 𝑛 = 500) would be a violation of the PECTT.

RRemark 5.13 — Advanced note: making PECTT concrete(advanced, optional). We can attempt a more exactphrasing of the PECTT as follows. Suppose that 𝑍 isa physical system that accepts 𝑛 binary stimuli andhas a binary output, and can be enclosed in a sphereof volume 𝑉 . We say that the system 𝑍 computes afunction 𝑓 ∶ 0, 1𝑛 → 0, 1 within 𝑡 seconds if when-ever we set the stimuli to some value đ‘„ ∈ 0, 1𝑛, ifwe measure the output after 𝑡 seconds then we obtain𝑓(đ‘„).One can then phrase the PECTT as stipulating that ifthere exists such a system 𝑍 that computes đč within𝑡 seconds, then there exists a NAND-CIRC programthat computes đč and has at most đ›Œ(𝑉 𝑡)2 lines, wheređ›Œ is some normalization constant. (We can also con-sider variants where we use surface area insteadof volume, or take (𝑉 𝑡) to a different power than 2.However, none of these choices makes a qualitativedifference to the discussion below.) In particular,suppose that 𝑓 ∶ 0, 1𝑛 → 0, 1 is a function thatrequires 2𝑛/(100𝑛) > 20.8𝑛 lines for any NAND-CIRCprogram (such a function exists by Theorem 5.3).Then the PECTT would imply that either the volumeor the time of a system that computes đč will have tobe at least 20.2𝑛/âˆšđ›Œ. Since this quantity grows expo-nentially in 𝑛, it is not hard to set parameters so thateven for moderately large values of 𝑛, such a systemcould not fit in our universe.To fully make the PECTT concrete, we need to decideon the units for measuring time and volume, and thenormalization constant đ›Œ. One conservative choice isto assume that we could squeeze computation to theabsolute physical limits (which are many orders ofmagnitude beyond current technology). This corre-sponds to setting đ›Œ = 1 and using the Planck unitsfor volume and time. The Planck length ℓ𝑃 (which is,roughly speaking, the shortest distance that can the-oretically be measured) is roughly 2−120 meters. ThePlanck time 𝑡𝑃 (which is the time it takes for light totravel one Planck length) is about 2−150 seconds. In theabove setting, if a function đč takes, say, 1KB of input(e.g., roughly 104 bits, which can encode a 100 by 100bitmap image), and requires at least 20.8𝑛 = 20.8⋅104NAND lines to compute, then any physical systemthat computes it would require either volume of

Page 205: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 205

20.2⋅104 Planck length cubed, which is more than 21500meters cubed or take at least 20.2⋅104 Planck Time units,which is larger than 21500 seconds. To get a sense ofhow big that number is, note that the universe is onlyabout 260 seconds old, and its observable radius isonly roughly 290 meters. The above discussion sug-gests that it is possible to empirically falsify the PECTTby presenting a smaller-than-universe-size system thatcomputes such a function.There are of course several hurdles to refuting thePECTT in this way, one of which is that we can’t actu-ally test the system on all possible inputs. However,it turns out that we can get around this issue usingnotions such as interactive proofs and program checkingthat we might encounter later in this book. Another,perhaps more salient problem, is that while we knowmany hard functions exist, at the moment there is nosingle explicit function đč ∶ 0, 1𝑛 → 0, 1 for whichwe can prove an 𝜔(𝑛) (let alone Ω(2𝑛/𝑛)) lower boundon the number of lines that a NAND-CIRC programneeds to compute it.

5.6.1 Attempts at refuting the PECTTOne of the admirable traits of mankind is the refusal to accept limita-tions. In the best case this is manifested by people achieving long-standing “impossible” challenges such as heavier-than-air flight,putting a person on the moon, circumnavigating the globe, or evenresolving Fermat’s Last Theorem. In the worst case it is manifested bypeople continually following the footsteps of previous failures to try todo proven-impossible tasks such as build a perpetual motion machine,trisect an angle with a compass and straightedge, or refute Bell’s in-equality. The Physical Extended Church Turing thesis (in its variousforms) has attracted both types of people. Here are some physicaldevices that have been speculated to achieve computational tasks thatcannot be done by not-too-large NAND-CIRC programs:

‱ Spaghetti sort: One of the first lower bounds that Computer Sci-ence students encounter is that sorting 𝑛 numbers requires makingΩ(𝑛 log𝑛) comparisons. The “spaghetti sort” is a description of aproposed “mechanical computer” that would do this faster. Theidea is that to sort 𝑛 numbers đ‘„1, 
 , đ‘„đ‘›, we could cut 𝑛 spaghettinoodles into lengths đ‘„1, 
 , đ‘„đ‘›, and then if we simply hold themtogether in our hand and bring them down to a flat surface, theywill emerge in sorted order. There are a great many reasons whythis is not truly a challenge to the PECTT hypothesis, and I will notruin the reader’s fun in finding them out by her or himself.

Page 206: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

206 introduction to theoretical computer science

Figure 5.8: Scott Aaronson tests a candidate device forcomputing Steiner trees using soap bubbles.

7 We were extremely conservative in the suggestedparameters for the PECTT, having assumed that asmany as ℓ−2𝑃 10−6 ∌ 1061 bits could potentially bestored in a millimeter radius region.

‱ Soap bubbles: One function đč ∶ 0, 1𝑛 → 0, 1 that is conjecturedto require a large number of NAND lines to solve is the EuclideanSteiner Tree problem. This is the problem where one is given 𝑚points in the plane (đ‘„1, 𝑩1), 
 , (đ‘„đ‘š, 𝑩𝑚) (say with integer coordi-nates ranging from 1 till 𝑚, and hence the list can be representedas a string of 𝑛 = 𝑂(𝑚 log𝑚) size) and some number đŸ. The goalis to figure out whether it is possible to connect all the points byline segments of total length at most đŸ. This function is conjec-tured to be hard because it is NP complete - a concept that we’ll en-counter later in this course - and it is in fact reasonable to conjecturethat as 𝑚 grows, the number of NAND lines required to computethis function grows exponentially in 𝑚, meaning that the PECTTwould predict that if 𝑚 is sufficiently large (such as few hundredsor so) then no physical device could compute đč . Yet, some peopleclaimed that there is in fact a very simple physical device that couldsolve this problem, that can be constructed using some woodenpegs and soap. The idea is that if we take two glass plates, and put𝑚 wooden pegs between them in the locations (đ‘„1, 𝑩1), 
 , (đ‘„đ‘š, 𝑩𝑚)then bubbles will form whose edges touch those pegs in a way thatwill minimize the total energy which turns out to be a function ofthe total length of the line segments. The problem with this deviceis that nature, just like people, often gets stuck in “local optima”.That is, the resulting configuration will not be one that achievesthe absolute minimum of the total energy but rather one that can’tbe improved with local changes. Aaronson has carried out actualexperiments (see Fig. 5.8), and saw that while this device oftenis successful for three or four pegs, it starts yielding suboptimalresults once the number of pegs grows beyond that.

‱ DNA computing. People have suggested using the properties ofDNA to do hard computational problems. The main advantage ofDNA is the ability to potentially encode a lot of information in arelatively small physical space, as well as compute on this infor-mation in a highly parallel manner. At the time of this writing, itwas demonstrated that one can use DNA to store about 1016 bitsof information in a region of radius about a millimeter, as opposedto about 1010 bits with the best known hard disk technology. Thisdoes not posit a real challenge to the PECTT but does suggest thatone should be conservative about the choice of constant and not as-sume that current hard disk + silicon technologies are the absolutebest possible.7

‱ Continuous/real computers. The physical world is often describedusing continuous quantities such as time and space, and people

Page 207: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 207

have suggested that analog devices might have direct access tocomputing with real-valued quantities and would be inherentlymore powerful than discrete models such as NAND machines.Whether the “true” physical world is continuous or discrete is anopen question. In fact, we do not even know how to precisely phrasethis question, let alone answer it. Yet, regardless of the answer, itseems clear that the effort to measure a continuous quantity growswith the level of accuracy desired, and so there is no “free lunch”or way to bypass the PECTT using such machines (see also thispaper). Related to that are proposals known as “hypercomputing”or “Zeno’s computers” which attempt to use the continuity of timeby doing the first operation in one second, the second one in half asecond, the third operation in a quarter second and so on.. Thesefail for a similar reason to the one guaranteeing that Achilles willeventually catch the tortoise despite the original Zeno’s paradox.

‱ Relativity computer and time travel. The formulation above as-sumed the notion of time, but under the theory of relativity time isin the eye of the observer. One approach to solve hard problems isto leave the computer to run for a lot of time from his perspective,but to ensure that this is actually a short while from our perspective.One approach to do so is for the user to start the computer and thengo for a quick jog at close to the speed of light before checking onits status. Depending on how fast one goes, few seconds from thepoint of view of the user might correspond to centuries in com-puter time (it might even finish updating its Windows operatingsystem!). Of course the catch here is that the energy required fromthe user is proportional to how close one needs to get to the speedof light. A more interesting proposal is to use time travel via closedtimelike curves (CTCs). In this case we could run an arbitrarily longcomputation by doing some calculations, remembering the currentstate, and then travelling back in time to continue where we left off.Indeed, if CTCs exist then we’d probably have to revise the PECTT(though in this case I will simply travel back in time and edit thesenotes, so I can claim I never conjectured it in the first place
)

‱ Humans. Another computing system that has been proposed asa counterexample to the PECTT is a 3 pound computer of about0.1m radius, namely the human brain. Humans can walk around,talk, feel, and do other things that are not commonly done byNAND-CIRC programs, but can they compute partial functionsthat NAND-CIRC programs cannot? There are certainly compu-tational tasks that at the moment humans do better than computers(e.g., play some video games, at the moment), but based on ourcurrent understanding of the brain, humans (or other animals)

Page 208: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

208 introduction to theoretical computer science

8 This is a very rough approximation that couldbe wrong to a few orders of magnitude in eitherdirection. For one, there are other structures in thebrain apart from neurons that one might need tosimulate, hence requiring higher overhead. On theother hand, it is by no mean clear that we need tofully clone the brain in order to achieve the samecomputational tasks that it does.

9 There are some well known scientists that haveadvocated that humans have inherent computationaladvantages over computers. See also this.

have no inherent computational advantage over computers. Thebrain has about 1011 neurons, each operating at a speed of about1000 operations per seconds. Hence a rough first approximation isthat a Boolean circuit of about 1014 gates could simulate one secondof a brain’s activity.8 Note that the fact that such a circuit (likely)exists does not mean it is easy to find it. After all, constructing thiscircuit took evolution billions of years. Much of the recent effortsin artificial intelligence research is focused on finding programsthat replicate some of the brain’s capabilities and they take massivecomputational effort to discover, these programs often turn out tobe much smaller than the pessimistic estimates above. For example,at the time of this writing, Google’s neural network for machinetranslation has about 104 nodes (and can be simulated by a NAND-CIRC program of comparable size). Philosophers, priests and manyothers have since time immemorial argued that there is somethingabout humans that cannot be captured by mechanical devices suchas computers; whether or not that is the case, the evidence is thinthat humans can perform computational tasks that are inherentlyimpossible to achieve by computers of similar complexity.9

‱ Quantum computation. The most compelling attack on the Physi-cal Extended Church Turing Thesis comes from the notion of quan-tum computing. The idea was initiated by the observation that sys-tems with strong quantum effects are very hard to simulate on acomputer. Turning this observation on its head, people have pro-posed using such systems to perform computations that we do notknow how to do otherwise. At the time of this writing, scalablequantum computers have not yet been built, but it is a fascinatingpossibility, and one that does not seem to contradict any known lawof nature. We will discuss quantum computing in much more detailin Chapter 23. Modeling quantum computation involves extendingthe model of Boolean circuits into Quantum circuits that have onemore (very special) gate. However, the main takeaway is that whilequantum computing does suggest we need to amend the PECTT,it does not require a complete revision of our worldview. Indeed,almost all of the content of this book remains the same regardless ofwhether the underlying computational model is Boolean circuits orquantum circuits.

RRemark 5.14 — Physical Extended Church-Turing Thesisand Cryptography. While even the precise phrasing ofthe PECTT, let alone understanding its correctness, isstill a subject of active research, some variants of it are

Page 209: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 209

already implicitly assumed in practice. Governments,companies, and individuals currently rely on cryptog-raphy to protect some of their most precious assets,including state secrets, control of weapon systemsand critical infrastructure, securing commerce, andprotecting the confidentiality of personal information.In applied cryptography, one often encounters state-ments such as “cryptosystem 𝑋 provides 128 bits ofsecurity”. What such a statement really means is that(a) it is conjectured that there is no Boolean circuit(or, equivalently, a NAND-CIRC program) of sizemuch smaller than 2128 that can break 𝑋, and (b) weassume that no other physical mechanism can do bet-ter, and hence it would take roughly a 2128 amount of“resources” to break 𝑋. We say “conjectured” and not“proved” because, while we can phrase the statementthat breaking the system cannot be done by an 𝑠-gatecircuit as a precise mathematical conjecture, at themoment we are unable to prove such a statement forany non-trivial cryptosystem. This is related to the Pvs NP question we will discuss in future chapters. Wewill explore Cryptography in Chapter 21.

Chapter Recap

‱ We can think of programs both as describing a pro-cess, as well as simply a list of symbols that can beconsidered as data that can be fed as input to otherprograms.

‱ We can write a NAND-CIRC program that evalu-ates arbitrary NAND-CIRC programs (or equiv-alently a circuit that evaluates other circuits).Moreover, the efficiency loss in doing so is not toolarge.

‱ We can even write a NAND-CIRC program thatevaluates programs in other programming lan-guages such as Python, C, Lisp, Java, Go, etc.

‱ By a leap of faith, we could hypothesize that thenumber of gates in the smallest circuit that com-putes a function 𝑓 captures roughly the amountof physical resources required to compute 𝑓 . Thisstatement is known as the Physical Extended Church-Turing Thesis (PECTT).

‱ Boolean circuits (or equivalently AON-CIRC orNAND-CIRC programs) capture a surprisinglywide array of computational models. The strongestcurrently known challenge to the PECTT comesfrom the potential for using quantum mechanicaleffects to speed-up computation, a model known asquantum computers.

Page 210: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

210 introduction to theoretical computer science

Figure 5.9: A finite computational task is specified bya function 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚. We can modela computational process using Boolean circuits (ofvarying gate sets) or straight-line program. Everyfunction can be computed by many programs. Wesay that 𝑓 ∈ SIZE𝑛,𝑚(𝑠) if there exists a NANDcircuit of at most 𝑠 gates (equivalently a NAND-CIRCprogram of at most 𝑠 lines) that computes 𝑓. Everyfunction 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚 can be computed bya circuit of 𝑂(𝑚 ⋅ 2𝑛/𝑛) gates. Many functions suchas multiplication, addition, solving linear equations,computing the shortest path in a graph, and others,can be computed by circuits of much fewer gates.In particular there is an 𝑂(𝑠2 log 𝑠)-size circuitthat computes the map đ¶, đ‘„ ↩ đ¶(đ‘„) where đ¶ isa string describing a circuit of 𝑠 gates. However,the counting argument shows there do exist somefunctions 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚 that requireΩ(𝑚 ⋅ 2𝑛/𝑛) gates to compute.

5.7 RECAP OF PART I: FINITE COMPUTATION

This chapter concludes the first part of this book that deals with finitecomputation (computing functions that map a fixed number of Booleaninputs to a fixed number of Boolean outputs). The main take-awaysfrom Chapter 3, Chapter 4, and Chapter 5 are as follows (see alsoFig. 5.9):

‱ We can formally define the notion of a function 𝑓 ∶ 0, 1𝑛 →0, 1𝑚 being computable using 𝑠 basic operations. Whether theseoperations are AND/OR/NOT, NAND, or some other universalbasis does not make much difference. We can describe such a com-putation either using a circuit or using a straight-line program.

‱ We define SIZE𝑛,𝑚(𝑠) to be the set of functions that are computableby NAND circuits of at most 𝑠 gates. This set is equal to the set offunctions computable by a NAND-CIRC program of at most 𝑠 linesand up to a constant factor in 𝑠 (which we will not care about);this is also the same as the set of functions that are computableby a Boolean circuit of at most 𝑠 AND/OR/NOT gates. The classSIZE𝑛,𝑚(𝑠) is a set of functions, not of programs/circuits.

‱ Every function 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚 can be computed using acircuit of at most 𝑂(𝑚 ⋅ 2𝑛/𝑛) gates. Some functions require at leastΩ(𝑚 ⋅ 2𝑛/𝑛) gates. We define SIZE𝑛,𝑚(𝑠) to be the set of functionsfrom 0, 1𝑛 to 0, 1𝑚 that can be computed using at most 𝑠 gates.

‱ We can describe a circuit/program 𝑃 as a string. For every 𝑠, thereis a universal circuit/program 𝑈𝑠 that can evaluate programs oflength 𝑠 given their description as strings. We can use this repre-sentation also to count the number of circuits of at most 𝑠 gates and

Page 211: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 211

hence prove that some functions cannot be computed by circuits ofsmaller-than-exponential size.

‱ If there is a circuit of 𝑠 gates that computes a function 𝑓 , then wecan build a physical device to compute 𝑓 using 𝑠 basic components(such as transistors). The “Physical Extended Church-Turing The-sis” postulates that the reverse direction is true as well: if 𝑓 is afunction for which every circuit requires at least 𝑠 gates then thatevery physical device to compute 𝑓 will require about 𝑠 “physicalresources”. The main challenge to the PECTT is quantum computing,which we will discuss in Chapter 23.

Sneak preview: In the next part we will discuss how to model compu-tational tasks on unbounded inputs, which are specified using functionsđč ∶ 0, 1∗ → 0, 1∗ (or đč ∶ 0, 1∗ → 0, 1) that can take anunbounded number of Boolean inputs.

5.8 EXERCISES

Exercise 5.1 Which one of the following statements is false:

a. There is an 𝑂(𝑠3) line NAND-CIRC program that given as inputprogram 𝑃 of 𝑠 lines in the list-of-tuples representation computesthe output of 𝑃 when all its input are equal to 1.

b. There is an 𝑂(𝑠3) line NAND-CIRC program that given as inputprogram 𝑃 of 𝑠 characters encoded as a string of 7𝑠 bits using theASCII encoding, computes the output of 𝑃 when all its input areequal to 1.

c. There is an 𝑂(√𝑠) line NAND-CIRC program that given as inputprogram 𝑃 of 𝑠 lines in the list-of-tuples representation computesthe output of 𝑃 when all its input are equal to 1.

Exercise 5.2 — Equals function. For every 𝑘 ∈ ℕ, show that there is an 𝑂(𝑘)line NAND-CIRC program that computes the function EQUALS𝑘 ∶0, 12𝑘 → 0, 1 where EQUALS(đ‘„, đ‘„â€Č) = 1 if and only if đ‘„ = đ‘„â€Č.

Exercise 5.3 — Equal to constant function. For every 𝑘 ∈ ℕ and đ‘„â€Č ∈ 0, 1𝑘,show that there is an 𝑂(𝑘) line NAND-CIRC program that computesthe function EQUALSđ‘„â€Č ∶ 0, 1𝑘 → 0, 1 that on input đ‘„ ∈ 0, 1𝑘outputs 1 if and only if đ‘„ = đ‘„â€Č.

Exercise 5.4 — Counting lower bound for multibit functions. Prove that thereexists a number 𝛿 > 0 such that for every 𝑛, 𝑚 there exists a function

Page 212: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

212 introduction to theoretical computer science

10 How many functions from 0, 1𝑛 to 0, 1𝑚 exist?

11 Follow the proof of Theorem 5.5, replacing the useof the counting argument with Exercise 5.4.

12 Using the adjacency list representation, a graphwith 𝑛 in-degree zero vertices and 𝑠 in-degree twovertices can be represented using roughly 2𝑠 log(𝑠 +𝑛) ≀ 2𝑠(log 𝑠 + 𝑂(1)) bits. The labeling of the 𝑛 inputand 𝑚 output vertices can be specified by a list of 𝑛labels in [𝑛] and 𝑚 labels in [𝑚].13 Hint: Use the results of Exercise 5.6 and the fact thatin this regime 𝑚 = 1 and 𝑛 â‰Ș 𝑠.

14 Hint: An equivalent way to say this is that youneed to prove that the set of functions that can becomputed using at most 2𝑛/(1000𝑛) lines has fewerthan 2−10022𝑛 elements. Can you see why?

15 Note that if 𝑛 is big enough, then it is easy torepresent such a pair using 𝑛2 bits, since we canrepresent the program using 𝑂(𝑛1.1 log𝑛) bits, andwe can always pad our representation to have exactly𝑛2 length.

𝑓 ∶ 0, 1𝑛 → 0, 1𝑚 that requires at least 𝛿𝑚 ⋅ 2𝑛/𝑛 NAND gates tocompute. See footnote for hint.10

Exercise 5.5 — Size hierarchy theorem for multibit functions. Prove that thereexists a number đ¶ such that for every 𝑛, 𝑚 and 𝑛+𝑚 < 𝑠 < 𝑚⋅2𝑛/(đ¶đ‘›)there exists a function 𝑓 ∈ SIZE𝑛,𝑚(đ¶ ⋅ 𝑠) ⧔ SIZE𝑛,𝑚(𝑠). See footnote forhint.11

Exercise 5.6 — Efficient representation of circuits and a tighter counting upper

bound. Use the ideas of Remark 5.4 to show that for every 𝜖 > 0 andsufficiently large 𝑠, 𝑛, 𝑚,|SIZE𝑛,𝑚(𝑠)| < 2(2+𝜖)𝑠 log 𝑠+𝑛 log𝑛+𝑚 log 𝑠 . (5.11)

Conclude that the implicit constant in Theorem 5.2 can be made arbi-trarily close to 5. See footnote for hint.12

Exercise 5.7 — Tighter counting lower bound. Prove that for every 𝛿 < 1/2, if𝑛 is sufficiently large then there exists a function 𝑓 ∶ 0, 1𝑛 → 0, 1such that 𝑓 ∉ SIZE𝑛,1 ( 𝛿2𝑛𝑛 ). See footnote for hint.13

Exercise 5.8 — Random functions are hard. Suppose 𝑛 > 1000 and that wechoose a function đč ∶ 0, 1𝑛 → 0, 1 at random, choosing for everyđ‘„ ∈ 0, 1𝑛 the value đč(đ‘„) to be the result of tossing an independentunbiased coin. Prove that the probability that there is a 2𝑛/(1000𝑛)line program that computes đč is at most 2−100.14

Exercise 5.9 The following is a tuple representing a NAND program:(3, 1, ((3, 2, 2), (4, 1, 1), (5, 3, 4), (6, 2, 1), (7, 6, 6), (8, 0, 0), (9, 7, 8), (10, 5, 0), (11, 9, 10))).1. Write a table with the eight values 𝑃(000), 𝑃(001), 𝑃(010), 𝑃(011),𝑃(100), 𝑃(101), 𝑃(110), 𝑃(111) in this order.

2. Describe what the programs does in words.

Exercise 5.10 — EVAL with XOR. For every sufficiently large 𝑛, let 𝐾𝑛 ∶0, 1𝑛2 → 0, 1 be the function that takes an 𝑛2-length string thatencodes a pair (𝑃 , đ‘„) where đ‘„ ∈ 0, 1𝑛 and 𝑃 is a NAND programof 𝑛 inputs, a single output, and at most 𝑛1.1 lines, and returns theoutput of 𝑃 on đ‘„.15 That is, 𝐾𝑛(𝑃 , đ‘„) = 𝑃(đ‘„).

Prove that for every sufficiently large 𝑛, there does not exist an XORcircuit đ¶ that computes the function 𝐾𝑛, where a XOR circuit has theXOR gate as well as the constants 0 and 1 (see Exercise 3.5). That is,

Page 213: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

code as data, data as code 213

16 Hint: Use our bound on the number of program-s/circuits of size 𝑠 (Theorem 5.2), as well as theChernoff Bound ( Theorem 18.12) and the unionbound.

prove that there is some constant 𝑛0 such that for every 𝑛 > 𝑛0 andXOR circuit đ¶ of 𝑛2 inputs and a single output, there exists a pair(𝑃 , đ‘„) such that đ¶(𝑃 , đ‘„) ≠ 𝐾𝑛(𝑃 , đ‘„).

Exercise 5.11 — Learning circuits (challenge, optional, assumes more background).

(This exercise assumes background in probability theory and/ormachine learning that you might not have at this point. Feel freeto come back to it at a later point and in particular after going overChapter 18.) In this exercise we will use our bound on the number ofcircuits of size 𝑠 to show that (if we ignore the cost of computation)every such circuit can be learned from not too many training samples.Specifically, if we find a size-𝑠 circuit that classifies correctly a trainingset of 𝑂(𝑠 log 𝑠) samples from some distribution đ·, then it is guaran-teed to do well on the whole distribution đ·. Since Boolean circuitsmodel very many physical processes (maybe even all of them, if the(controversial) physical extended Church-Turing thesis is true), thisshows that all such processes could be learned as well (again, ignor-ing the computation cost of finding a classifier that does well on thetraining data).

Let đ· be any probability distribution over 0, 1𝑛 and let đ¶ be aNAND circuit with 𝑛 inputs, one output, and size 𝑠 ≄ 𝑛. Prove thatthere is some constant 𝑐 such that with probability at least 0.999 thefollowing holds: if 𝑚 = 𝑐𝑠 log 𝑠 and đ‘„0, 
 , đ‘„đ‘šâˆ’1 are chosen indepen-dently from đ·, then for every circuit đ¶â€Č such that đ¶â€Č(đ‘„đ‘–) = đ¶(đ‘„đ‘–) onevery 𝑖 ∈ [𝑚], Prđ‘„âˆŒđ·[đ¶â€Č(đ‘„) ≀ đ¶(đ‘„)] ≀ 0.99.

In other words, if đ¶â€Č is a so called “empirical risk minimizer” thatagrees with đ¶ on all the training examples đ‘„0, 
 , đ‘„đ‘›âˆ’1, then it willalso agree with đ¶ with high probability for samples drawn from thedistribution đ· (i.e., it “generalizes”, to use Machine-Learning lingo).See footnote for hint.16

5.9 BIBLIOGRAPHICAL NOTES

The EVAL function is usually known as a universal circuit. The imple-mentation we describe is not the most efficient known. Valiant [Val76]first showed a universal circuit of 𝑂(𝑛 log𝑛) size where 𝑛 is the size ofthe input. Universal circuits have seen in recent years new motivationsdue to their applications for cryptography, see [LMS16; GKS17] .

While we’ve seen that “most” functions mapping 𝑛 bits to one bitrequire circuits of exponential size Ω(2𝑛/𝑛), we actually do not knowof any explicit function for which we can prove that it requires, say, atleast 𝑛100 or even 100𝑛 size. At the moment, the strongest such lowerbound we know is that there are quite simple and explicit 𝑛-variable

Page 214: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

214 introduction to theoretical computer science

functions that require at least (5 − 𝑜(1))𝑛 lines to compute, see thispaper of Iwama et al as well as this more recent work of Kulikov et al.Proving lower bounds for restricted models of circuits is an extremelyinteresting research area, for which Jukna’s book [Juk12] (see alsoWegener [Weg87]) provides a very good introduction and overview. Ilearned of the proof of the size hierarchy theorem (Theorem 5.5) fromSasha Golovnev.

Scott Aaronson’s blog post on how information is physical is a gooddiscussion on issues related to the physical extended Church-TuringPhysics. Aaronson’s survey on NP complete problems and physicalreality [Aar05] discusses these issues as well, though it might beeasier to read after we reach Chapter 15 on NP and NP-completeness.

Page 215: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

IIUNIFORM COMPUTATION

Page 216: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 217: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Figure 6.1: Once you know how to multiply multi-digit numbers, you can do so for every number 𝑛of digits, but if you had to describe multiplicationusing Boolean circuits or NAND-CIRC programs,you would need a different program/circuit for everylength 𝑛 of the input.

6Functions with Infinite domains, Automata, and Regular ex-pressions

“An algorithm is a finite answer to an infinite number of questions.”, At-tributed to Stephen Kleene.

The model of Boolean circuits (or equivalently, the NAND-CIRCprogramming language) has one very significant drawback: a Booleancircuit can only compute a finite function 𝑓 , and in particular sinceevery gate has two inputs, a size 𝑠 circuit can compute on an inputof length at most 2𝑠. This does not capture our intuitive notion of analgorithm as a single recipe to compute a potentially infinite function.For example, the standard elementary school multiplication algorithmis a single algorithm that multiplies numbers of all lengths, but yetwe cannot express this algorithm as a single circuit, but rather need adifferent circuit (or equivalently, a NAND-CIRC program) for everyinput length (see Fig. 6.1).

In this chapter we extend our definition of computational tasks toconsider functions with the unbounded domain of 0, 1∗. We focuson the question of defining what tasks to compute, mostly leavingthe question of how to do so to later chapters, where we will seeTuring Machines and other computational models for computing onunbounded inputs. In this chapter we will see however one examplefor a simple and restricted model of computation - deterministic finiteautomata (DFAs).

This chapter: A non-mathy overviewIn this chapter we discuss functions that as input strings ofarbitary length. Such functions could have outputs that arelong strings as well, but the case of Boolean functions, wherethe output is a single bit, is of particular importance. The taskof computing a Boolean function is equivalent to the task

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Define functions on unbounded length inputs,

that cannot be described by a finite size tableof inputs and outputs.

‱ Equivalence with the task of decidingmembership in a language.

‱ Deterministic finite automatons (optional): Asimple example for a model for unboundedcomputation

‱ Equivalence with regular expressions.

Page 218: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

218 introduction to theoretical computer science

Figure 6.2: The NAND circuit and NAND-CIRCprogram for computing the XOR of 5 bits. Note howthe circuit for XOR5 merely repeats four times thecircuit to compute the XOR of 2 bits.

of deciding a language. We will also define the restriction ofa function over unbounded length strings to a finite length,and how this restriction can be computed by Boolean circuits.In the second half of this chapter we discuss finite automata,which is a model for computing functions of unboundedlength. This model is not as powerful as Python or othergeneral-purpose programming languages, but can serveas an introduction to these more general models. We alsoshow a beautiful result - the functions computable by finiteautomata are exactly the ones that correspond to regularexpressions. However, the reader can also feel free to skipautomata and go straight to our discussion of Turing Machinesin Chapter 7.

6.1 FUNCTIONS WITH INPUTS OF UNBOUNDED LENGTH

Up until now, we considered the computational task of mappingsome string of length 𝑛 into a string of length 𝑚. However, in gen-eral computational tasks can involve inputs of unbounded length.For example, the following Python function computes the functionXOR ∶ 0, 1∗ → 0, 1, where XOR(đ‘„) equals 1 iff the number of 1’sin đ‘„ is odd. (In other words, XOR(đ‘„) = ∑|đ‘„|−1𝑖=0 đ‘„đ‘– mod 2 for everyđ‘„ ∈ 0, 1∗.) As simple as it is, the XOR function cannot be com-puted by a Boolean circuit. Rather, for every 𝑛, we can compute XOR𝑛(the restriction of XOR to 0, 1𝑛) using a different circuit (e.g., seeFig. 6.2).

def XOR(X):'''Takes list X of 0's and 1's

Outputs 1 if the number of 1's is odd and outputs 0otherwise'''result = 0for i in range(len(X)):

result += X[i] % 2return result

Previously in this book we studied the computation of finite func-tions 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚. Such a function 𝑓 can always be describedby listing all the 2𝑛 values it takes on inputs đ‘„ ∈ 0, 1𝑛. In this chap-ter we consider functions such as XOR that take inputs of unboundedsize. While we can describe XOR using a finite number of symbols(in fact we just did so above), it takes infinitely many possible inputsand so we cannot just write down all of its values. The same is truefor many other functions capturing important computational tasks

Page 219: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 219

including addition, multiplication, sorting, finding paths in graphs,fitting curves to points, and so on and so forth. To contrast with thefinite case, we will sometimes call a function đč ∶ 0, 1∗ → 0, 1 (orđč ∶ 0, 1∗ → 0, 1∗) infinite. However, this does not mean that đčtaks as input strings of infinite length! It just means that đč can take asinput a string of that can be arbitrarily long, and so we cannot simplywrite down a table of all the outputs of đč on different inputs.

Big Idea 8 A function đč ∶ 0, 1∗ → 0, 1∗ specifies the computa-tional task mapping an input đ‘„ ∈ 0, 1∗ into the output đč(đ‘„).

As we’ve seen before, restricting attention to functions that usebinary strings as inputs and outputs does not detract from our gener-ality, since other objects, including numbers, lists, matrices, images,videos, and more, can be encoded as binary strings.

As before, it is important to differentiate between specification andimplementation. For example, consider the following function:

TWINP(đ‘„) = ⎧⎚⎩1 ∃𝑝∈ℕ s.t.𝑝, 𝑝 + 2 are primes and 𝑝 > |đ‘„|0 otherwise(6.1)

This is a mathematically well-defined function. For every đ‘„,TWINP(đ‘„) has a unique value which is either 0 or 1. However, atthe moment no one knows of a Python program that computes thisfunction. The Twin prime conjecture posits that for every 𝑛 thereexists 𝑝 > 𝑛 such that both 𝑝 and 𝑝 + 2 are primes. If this conjectureis true, then 𝑇 is easy to compute indeed - the program def T(x):return 1 will do the trick. However, mathematicians have triedunsuccesfully to prove this conjecture since 1849. That said, whetheror not we know how to implement the function TWINP, the definitionabove provides its specification.

6.1.1 Varying inputs and outputsMany of the functions we are interested in take more than one input.For example the function

MULT(đ‘„, 𝑩) = đ‘„ ⋅ 𝑩 (6.2)that takes the binary representation of a pair of integers đ‘„, 𝑩 ∈ ℕ

and outputs the binary representation of their product đ‘„ ⋅ 𝑩. How-ever, since we can represent a pair of strings as a single string, we willconsider functions such as MULT as mapping 0, 1∗ to 0, 1∗. Wewill typically not be concerned with low-level details such as the pre-cise way to represent a pair of integers as a string, since essentially allchoices will be equivalent for our purposes.

Page 220: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

220 introduction to theoretical computer science

Another example for a function we want to compute is

PALINDROME(đ‘„) = ⎧⎚⎩1 ∀𝑖∈[|đ‘„|]đ‘„đ‘– = đ‘„|đ‘„|−𝑖0 otherwise(6.3)

PALINDROME has a single bit as output. Functions with a singlebit of output are known as Boolean functions. Boolean functions arecentral to the theory of computation, and we will come discuss themoften in this book. Note that even though Boolean functions have asingle bit of output, their input can be of arbitrary length. Thus theyare still infinite functions, that cannot be described via a finite table ofvalues.

“Booleanizing” functions. Sometimes it might be convenient to ob-tain a Boolean variant for a non-Boolean function. For example, thefollowing is a Boolean variant of MULT.

BMULT(đ‘„, 𝑩, 𝑖) = âŽ§âŽšâŽ©đ‘–đ‘Ąâ„Ž bit of đ‘„ ⋅ 𝑩 𝑖 < |đ‘„ ⋅ 𝑩|0 otherwise(6.4)

If we can compute BMULT via any programming language suchas Python, C, Java, etc. then we can compute MULT as well, and viceversa.Solved Exercise 6.1 — Booleanizing general functions. Show that for everyfunction đč ∶ 0, 1∗ → 0, 1∗ there exists a Boolean function BF ∶0, 1∗ → 0, 1 such that a Python program to compute BF can betransformed into a program to compute đč and vice versa.

Solution:

For every đč ∶ 0, 1∗ → 0, 1∗, we can define

BF(đ‘„, 𝑖, 𝑏) = ⎧⎚⎩đč(đ‘„)𝑖 𝑖 < |đč(đ‘„)|, 𝑏 = 01 𝑖 < |đč(đ‘„)|, 𝑏 = 10 𝑖 ≄ |đ‘„| (6.5)

to be the function that on input đ‘„ ∈ 0, 1∗, 𝑖 ∈ ℕ, 𝑏 ∈ 0, 1 out-puts the 𝑖𝑡ℎ bit of đč(đ‘„) if 𝑏 = 0 and 𝑖 < |đ‘„|. If 𝑏 = 1 then BF(đ‘„, 𝑖, 𝑏)outputs 1 iff 𝑖 < |đč(đ‘„)| and hence this allows to compute the lengthof đč(đ‘„).

Computing BF from đč is straightforward. For the other direc-tion, given a Python function BF that computes BF, we can computeđč as follows:

def F(x):res = []

Page 221: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 221

i = 0while BF(x,i,1):

res.apppend(BF(x,i,0))i += 1

return res

6.1.2 Formal LanguagesFor every Boolean function đč ∶ 0, 1∗ → 0, 1, we can define theset 𝐿đč = đ‘„|đč(đ‘„) = 1 of strings on which đč outputs 1. Such setsare known as languages. This name is rooted in formal language theoryas pursued by linguists such as Noam Chomsky. A formal languageis a subset 𝐿 ⊆ 0, 1∗ (or more generally 𝐿 ⊆ Σ∗ for some finitealphabet ÎŁ). The membership or decision problem for a language 𝐿, isthe task of determining, given đ‘„ ∈ 0, 1∗, whether or not đ‘„ ∈ 𝐿. Ifwe can compute the function đč then we can decide membership in thelanguage 𝐿đč and vice versa. Hence, many texts such as [Sip97] referto the task of computing a Boolean function as “deciding a language”.In this book we mostly describe computational task using the functionnotation, which is easier to generalize to computation with more thanone bit of output. However, since the language terminology is sopopular in the literature, we will sometimes mention it.

6.1.3 Restrictions of functionsIf đč ∶ 0, 1∗ → 0, 1 is a Boolean function and 𝑛 ∈ ℕ then the re-striction of đč to inputs of length 𝑛, denoted as đč𝑛, is the finite function𝑓 ∶ 0, 1𝑛 → 0, 1 such that 𝑓(đ‘„) = đč(đ‘„) for every đ‘„ ∈ 0, 1𝑛. Thatis, đč𝑛 is the finite function that is only defined on inputs in 0, 1𝑛, butagrees with đč on those inputs. Since đč𝑛 is a finite function, it can becomputed by a Boolean circuit, implying the following theorem:

Theorem 6.1 — Circuit collection for every infinite function. Let đč ∶ 0, 1∗ →0, 1. Then there is a collection đ¶đ‘›đ‘›âˆˆ1,2,
 of circuits such thatfor every 𝑛 > 0, đ¶đ‘› computes the restriction đč𝑛 of đč to inputs oflength 𝑛.

Proof. This is an immediate corollary of the universality of Booleancircuits. Indeed, since đč𝑛 maps 0, 1𝑛 to 0, 1, Theorem 4.15 impliesthat there exists a Boolean circuit đ¶đ‘› to compute it. In fact. the size ofthis circuit is at most 𝑐 ⋅ 2𝑛/𝑛 gates for some constant 𝑐 ≀ 10.

In particular, Theorem 6.1 implies that there exists such as circuitcollection đ¶đ‘› even for the TWINP function we described before,

Page 222: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

222 introduction to theoretical computer science

despite the fact that we don’t know of any program to compute it. In-deed, this is not that surprising: for every particular 𝑛 ∈ ℕ, TWINP𝑛is either the constant zero function or the constant one function, bothof which can be computed by very simple Boolean circuits. Hencea collection of circuits đ¶đ‘› that computes TWINP certainly exists.The difficulty in computing TWINP using Python or any other pro-gramming language arises from the fact that we don’t know for eachparticular 𝑛 what is the circuit đ¶đ‘› in this collection.

6.2 DETERMINISTIC FINITE AUTOMATA (OPTIONAL)

All our computational models so far - Boolean circuits and straight-line programs - were only applicable for finite functions. In Chapter 7we will present Turing Machines, which are the central models of com-putation for functions of unbounded input length. However, in thissection we will present the more basic model of deterministic finiteautomata (DFA). Automata can serve as a good stepping-stone forTuring machines, though they will not be used much in later parts ofthis book, and so the reader can feel free to skip ahead fo Chapter 7.DFAs turn out to be equivalent in power to regular expressions, whichare a powerful mechanism to specify patterns that is widely used inpractice. Our treatment of automata is quite brief. There are plenty ofresources that help you get more comfortable with DFA’s. In particu-lar, Chapter 1 of Sipser’s book [Sip97] contains an excellent expositionof this material. There are also many websites with online simula-tors for automata, as well as translators from regular expressions toautomata and vice versa (see for example here and here).

At a high level, an algorithm is a recipe for computing an outputfrom an input via a combination of the following steps:

1. Read a bit from the input2. Update the state (working memory)3. Stop and produce an output

For example, recall the Python program that computes the XORfunction:

def XOR(X):'''Takes list X of 0's and 1's

Outputs 1 if the number of 1's is odd and outputs 0otherwise'''result = 0for i in range(len(X)):

result += X[i] % 2return result

Page 223: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 223

Figure 6.3: A deterministic finite automaton thatcomputes the XOR function. It has two states 0 and 1,and when it observes 𝜎 it transitions from 𝑣 to 𝑣 ⊕ 𝜎.

In each step, this program reads a single bit X[i] and updatesits state result based on that bit (flipping result if X[i] is 1 andkeeping it the same otherwise). When its done transversing the input,the program outputs result. In computer science, such a program iscalled a single-pass constant-memory algorithm since it makes a singlepass over the input and its working memory is of finite size. (Indeedin this case result can either be 0 or 1.) Such an algorithm is alsoknown as a Deterministic Finite Automaton or DFA (another name forDFA’s is a finite state machine). We can think of such an algorithm asa “machine” that can be in one of đ¶ states, for some constant đ¶. Themachine starts in some initial state, and then reads its input đ‘„ ∈ 0, 1∗one bit at a time. Whenever the machine reads a bit 𝜎 ∈ 0, 1, ittransitions into a new state based on 𝜎 and its prior state. The outputof the machine is based on the final state. Every single-pass constant-memory algorithm corresponds to such a machine. If an algorithmuses 𝑐 bits of memory, then the contents of its memory are a string oflength 𝑐. Since there are 2𝑐 such strings, at any point in the execution,such an algorithm can be in one of 2𝑐 states.

We can specify a DFA of đ¶ states by a list of đ¶ ⋅ 2 rules. Each rulewill be of the form “If the DFA is in state 𝑣 and the bit read from theinput is 𝜎 then the new state is 𝑣â€Č”. At the end of the computationwe will also have a rule of the form “If the final state is one of thefollowing 
 then output 1, otherwise output 0”. For example, thePython program above can be represented by a two state automata forcomputing XOR of the following form:

‱ Initialize in state 0‱ For every state 𝑠 ∈ 0, 1 and input bit 𝜎 read, if 𝜎 = 1 then change

to state 1 − 𝑠, otherwise stay in state 𝑠.‱ At the end output 1 iff 𝑠 = 1.

We can also describe a đ¶-state DFA as a labeled graph of đ¶ vertices.For every state 𝑠 and bit 𝜎, we add a directed edge labeled with 𝜎between 𝑠 and the state 𝑠â€Č such that if the DFA is at state 𝑠 and reads 𝜎then it transitions to 𝑠â€Č. (If the state stays the same then this edge willbe a self loop; similarly, if 𝑠 transitions to 𝑠â€Č in both the case 𝜎 = 0 and𝜎 = 1 then the graph will contain two parallel edges.) We also labelthe set 𝒼 of states on which the automate will output 1 at the end ofthe computation. This set is known as the set of accepting states. SeeFig. 6.3 for the graphical representation of the XOR automaton.

Formally, a DFA is specified by (1) the table of the đ¶ ⋅ 2 rules, whichcan be represented as a transition function 𝑇 that maps a state 𝑠 ∈ [đ¶]and bit 𝜎 ∈ 0, 1 to the state 𝑠â€Č ∈ [đ¶] which the DFA will transition tofrom state 𝑐 on input 𝜎 and (2) the set 𝒼 of accepting states. This leadsto the following definition.

Page 224: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

224 introduction to theoretical computer science

Definition 6.2 — Deterministic Finite Automaton. A deterministic finiteautomaton (DFA) with đ¶ states over 0, 1 is a pair (𝑇 , 𝒼) with𝑇 ∶ [đ¶] × 0, 1 → [đ¶] and 𝒼 ⊆ [đ¶]. The finite function 𝑇 is knownas the transition function of the DFA and the set 𝒼 is known as theset of accepting states.

Let đč ∶ 0, 1∗ → 0, 1 be a Boolean function with the infinitedomain 0, 1∗. We say that (𝑇 , 𝒼) computes a function đč ∶ 0, 1∗ →0, 1 if for every 𝑛 ∈ ℕ and đ‘„ ∈ 0, 1𝑛, if we define 𝑠0 = 0 and𝑠𝑖+1 = 𝑇 (𝑠𝑖, đ‘„đ‘–) for every 𝑖 ∈ [𝑛], then𝑠𝑛 ∈ 𝒼 ⇔ đč(đ‘„) = 1 (6.6)

PMake sure not to confuse the transition function ofan automaton (𝑇 in Definition 6.2), which is a finitefunction specifying the table of “rules” which it fol-lows, with the function the automaton computes (đč inDefinition 6.2) which is an infinite function.

RRemark 6.3 — Definitions in other texts. Deterministicfinite automata can be defined in several equivalentways. In particular Sipser [Sip97] defines a DFAs as afive-tuple (𝑄, ÎŁ, 𝛿, 𝑞0, đč ) where 𝑄 is the set of states,ÎŁ is the alphabet, 𝛿 is the transition function, 𝑞0 isthe initial state, and đč is the set of accepting states.In this book the set of states is always of the form𝑄 = 0, 
 , đ¶ − 1 and the initial state is always 𝑞0 = 0,but this makes no difference to the computationalpower of these models. Also, we restrict our attentionto the case that the alphabet ÎŁ is equal to 0, 1.

Solved Exercise 6.2 — DFA for (010)∗. Prove that there is a DFA that com-putes the following function đč :

đč(đ‘„) = ⎧⎚⎩1 3 divides |đ‘„| and ∀𝑖∈[|đ‘„|/3]đ‘„đ‘–đ‘„đ‘–+1đ‘„đ‘–+2 = 0100 otherwise(6.7)

Solution:

When asked to construct a deterministic finite automaton, ithelps to start by thinking of it a single-pass constant-memory al-

Page 225: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 225

Figure 6.4: A DFA that outputs 1 only on inputsđ‘„ ∈ 0, 1∗ that are a concatenation of zero or morecopies of 010. The state 0 is both the starting stateand the only accepting state. The table denotes thetransition function of 𝑇 , which maps the current stateand symbol read to the new symbol.

gorithm (for example, a Python program) and then translate thisprogram into a DFA. Here is a simple Python program for comput-ing đč :

def F(X):'''Return 1 iff X is a concatenation of zero/more

copies of [0,1,0]'''if len(X) % 3 != 0:

return Falseultimate = 0penultimate = 1antepenultimate = 0for idx, b in enumerate(X):

antepenultimate = penultimatepenultimate = ultimateultimate = bif idx % 3 == 2 and ((antepenultimate,

penultimate, ultimate) != (0,1,0)):return False

return True

Since we keep three Boolean variables, the working memory canbe in one of 23 = 8 configurations, and so the program above canbe directly translated into an 8 state DFA. While this is not neededto solve the question, by examining the resulting DFA, we can seethat we can merge some states together and obtain a 4 state au-tomaton, described in Fig. 6.4. See also Fig. 6.5, which depicts theexecution of this DFA on a particular input.

6.2.1 Anatomy of an automaton (finite vs. unbounded)Now that we consider computational tasks with unbounded inputsizes, it is crucially important to distinguish between the componentsof our algorithm that are fixed in size, and the components that growwith the size of the input. For the case of DFAs these are the follow-ing:

Constant size components: Given a DFA 𝐮, the following quantities arefixed independent of the input size:

‱ The number of states đ¶ in 𝐮.

‱ The transition function 𝑇 (which has 2đ¶ inputs, and so can be speci-fied by a table of 2đ¶ rows, each entry in which is a number in [đ¶]).

Page 226: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

226 introduction to theoretical computer science

‱ The set 𝒼 ⊆ [đ¶] of accepting states. There are at most 2đ¶ such states,each of which can be described by a string in 0, 1đ¶ specifiyingwhich state is in 𝒼 and which isn’t

Together the above means that we can fully describe an automatonusing finitely many symbols. This is a property we require out of anynotion of “algorithm”: we should be able to write down a completelyspecification of how it produces an output from an input.

Components of unbounded size: The following quantities relating to aDFA are not bounded by any constant. We stress that these are stillfinite for any given input.

‱ The length of the input đ‘„ ∈ 0, 1∗ that the DFA is provided with. Itis always finite, but not bounded.

‱ The number of steps that the DFA takes can grow with the length ofthe input. Indeed, a DFA makes a single pass on the input and so ittakes exactly |đ‘„| steps on an input đ‘„ ∈ 0, 1∗.

Figure 6.5: Execution of the DFA of Fig. 6.4. The num-ber of states and the size of the transition functionare bounded, but the input can be arbitrarily long. Ifthe DFA is at state 𝑠 and observes the value 𝜎 then itmoves to the state 𝑇 (𝑠, 𝜎). At the end of the executionthe DFA accepts iff the final state is in 𝒼.

6.2.2 DFA-computable functionsWe say that a function đč ∶ 0, 1∗ → 0, 1 is DFA computable if thereexists some DFA that computes đč . In Chapter 4 we saw that everyfinite function is computable by some Boolean circuit. Thus, at thispoint you might expect that every infinite function is computable bysome DFA. However, this is very much not the case. We will soon seesome simple examples of infinite functions that are not computable byDFAs, but for starters, let’s prove that such functions exist.

Page 227: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 227

Theorem 6.4 — DFA-computable functions are countable. Let DFACOMP bethe set of all Boolean functions đč ∶ 0, 1∗ → 0, 1 such that thereexists a DFA computing đč . Then DFACOMP is countable.

Proof Idea:

Every DFA can be described by a finite length string, which yieldsan onto map from 0, 1∗ to DFACOMP: namely the function thatmaps a string describing an automaton 𝐮 to the function that it com-putes.⋆Proof of Theorem 6.4. Every DFA can be described by a finite string,representing the transition function 𝑇 and the set of accepting states,and every DFA 𝐮 computes some function đč ∶ 0, 1∗ → 0, 1. Thuswe can define the following function đ‘†đ‘Ąđ·đ¶ ∶ 0, 1∗ → DFACOMP:

đ‘†đ‘Ąđ·đ¶(𝑎) = ⎧⎚⎩đč 𝑎 represents automaton 𝐮 and đč is the function 𝐮 computesONE otherwise

(6.8)where ONE ∶ 0, 1∗ → 0, 1 is the constant function that outputs1 on all inputs (and is a member of DFACOMP). Since by definition,every function đč in DFACOMP is computable by some automaton,đ‘†đ‘Ąđ·đ¶ is an onto function from 0, 1∗ to DFACOMP, which meansthat DFACOMP is countable (see Section 2.4.2).

Since the set of all Boolean functions is uncountable, we get thefollowing corollary:

Theorem 6.5 — Existence of DFA-uncomputable functions. There exists aBoolean function đč ∶ 0, 1∗ → 0, 1 that is not computable by anyDFA.

Proof. If every Boolean function đč is computable by some DFA thenDFACOMP equals the set ALL of all Boolean functions, but by Theo-rem 2.12, the latter set is uncountable, contradicting Theorem 6.4.

6.3 REGULAR EXPRESSIONS

Searching for a piece of text is a common task in computing. At itsheart, the search problem is quite simple. We have a collection 𝑋 =đ‘„0, 
 , đ‘„đ‘˜ of strings (e.g., files on a hard-drive, or student records ina database), and the user wants to find out the subset of all the đ‘„ ∈ 𝑋

Page 228: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

228 introduction to theoretical computer science

that are matched by some pattern (e.g., all files whose names end withthe string .txt). In full generality, we can allow the user to specify thepattern by specifying a (computable) function đč ∶ 0, 1∗ → 0, 1,where đč(đ‘„) = 1 corresponds to the pattern matching đ‘„. That is, theuser provides a program 𝑃 in some Turing-complete programminglanguage such as Python, and the system will return all the đ‘„ ∈ 𝑋such that 𝑃(đ‘„) = 1. For example, one could search for all text filesthat contain the string important document or perhaps (letting 𝑃correspond to a neural-network based classifier) all images that con-tain a cat. However, we don’t want our system to get into an infiniteloop just trying to evaluate the program 𝑃 ! For this reason, typicalsystems for searching files or databases do not allow users to specifythe patterns using full-fledged programming languages. Rather, suchsystems use restricted computational models that on the one hand arerich enough to capture many of the queries needed in practice (e.g., allfilenames ending with .txt, or all phone numbers of the form (617)xxx-xxxx), but on the other hand are restricted enough so the queriescan be evaluated very efficiently on huge files and in particular cannotresult in an infinite loop.

One of the most popular such computational models is regularexpressions. If you ever used an advanced text editor, a command lineshell, or have done any kind of manipulation of text files, then youhave probably come across regular expressions.

A regular expression over some alphabet ÎŁ is obtained by combin-ing elements of ÎŁ with the operation of concatenation, as well as |(corresponding to or) and ∗ (corresponding to repetition zero ormore times). (Common implementations of regular expressions inprogramming languages and shells typically include some extra oper-ations on top of | and ∗, but these operations can be implemented as“syntactic sugar” using the operators | and ∗.) For example, the fol-lowing regular expression over the alphabet 0, 1 corresponds to theset of all strings đ‘„ ∈ 0, 1∗ where every digit is repeated at least twice:(00(0∗)|11(1∗))∗ . (6.9)

The following regular expression over the alphabet 𝑎, 
 , 𝑧, 0, 
 , 9corresponds to the set of all strings that consist of a sequence of oneor more of the letters 𝑎-𝑑 followed by a sequence of one or more digits(without a leading zero):

(𝑎|𝑏|𝑐|𝑑)(𝑎|𝑏|𝑐|𝑑)∗(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)∗ . (6.10)

Formally, regular expressions are defined by the following recursivedefinition:

Page 229: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 229

Definition 6.6 — Regular expression. A regular expression 𝑒 over an al-phabet ÎŁ is a string over ÎŁ âˆȘ (, ), |, ∗,∅, "" that has one of thefollowing forms:

1. 𝑒 = 𝜎 where 𝜎 ∈ ÎŁ2. 𝑒 = (𝑒â€Č|𝑒″) where 𝑒â€Č, 𝑒″ are regular expressions.

3. 𝑒 = (𝑒â€Č)(𝑒″) where 𝑒â€Č, 𝑒″ are regular expressions. (We oftendrop the parentheses when there is no danger of confusion andso write this as 𝑒â€Č 𝑒″.)

4. 𝑒 = (𝑒â€Č)∗ where 𝑒â€Č is a regular expression.

Finally we also allow the following “edge cases”: 𝑒 = ∅ and𝑒 = "". These are the regular expressions corresponding to accept-ing no strings, and accepting only the empty string respectively.

We will drop parenthesis when they can be inferred from thecontext. We also use the convention that OR and concatenation areleft-associative, and we give highest precedence to ∗, then concate-nation, and then OR. Thus for example we write 00∗|11 instead of((0)(0∗))|((1)(1)).

Every regular expression 𝑒 corresponds to a function Ω𝑒 ∶ Σ∗ →0, 1 where Ω𝑒(đ‘„) = 1 if đ‘„ matches the regular expression. For exam-ple, if 𝑒 = (00|11)∗ then Ω𝑒(110011) = 1 but Ω𝑒(101) = 0 (can you seewhy?).

PThe formal definition of Ω𝑒 is one of those definitionsthat is more cumbersome to write than to grasp. Thusit might be easier for you to first work it out on yourown and then check that your definition matches whatis written below.

Definition 6.7 — Matching a regular expression. Let 𝑒 be a regular expres-sion over the alphabet ÎŁ. The function Ω𝑒 ∶ Σ∗ → 0, 1 is definedas follows:

1. If 𝑒 = 𝜎 then Ω𝑒(đ‘„) = 1 iff đ‘„ = 𝜎.2. If 𝑒 = (𝑒â€Č|𝑒″) then Ω𝑒(đ‘„) = Ω𝑒â€Č(đ‘„)∹Ω𝑒″(đ‘„) where √ is the OR op-

erator.

Page 230: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

230 introduction to theoretical computer science

3. If 𝑒 = (𝑒â€Č)(𝑒″) then Ω𝑒(đ‘„) = 1 iff there is some đ‘„â€Č, đ‘„â€ł ∈ Σ∗ suchthat đ‘„ is the concatenation of đ‘„â€Č and đ‘„â€ł and Ω𝑒â€Č(đ‘„â€Č) = Ω𝑒″(đ‘„â€ł) =1.

4. If 𝑒 = (𝑒â€Č)∗ then Ω𝑒(đ‘„) = 1 iff there is some 𝑘 ∈ ℕ and someđ‘„0, 
 , đ‘„đ‘˜âˆ’1 ∈ Σ∗ such that đ‘„ is the concatenation đ‘„0 ⋯ đ‘„đ‘˜âˆ’1 andΩ𝑒â€Č(đ‘„đ‘–) = 1 for every 𝑖 ∈ [𝑘].5. Finally, for the edge cases Ω∅ is the constant zero function, andΊ"" is the function that only outputs 1 on the empty string "".

We say that a regular expression 𝑒 over ÎŁ matches a string đ‘„ ∈ Σ∗if Ω𝑒(đ‘„) = 1.

PThe definitions above are not inherently difficult, butare a bit cumbersome. So you should pause here andgo over it again until you understand why it corre-sponds to our intuitive notion of regular expressions.This is important not just for understanding regularexpressions themselves (which are used time andagain in a great many applications) but also for get-ting better at understanding recursive definitions ingeneral.

A Boolean function is called “regular” if it outputs 1 on preciselythe set of strings that are matched by some regular expression. That is,

Definition 6.8 — Regular functions / languages. Let ÎŁ be a finite set andđč ∶ Σ∗ → 0, 1 be a Boolean function. We say that đč is regular ifđč = Ω𝑒 for some regular expression 𝑒.Similarly, for every formal language 𝐿 ⊆ Σ∗, we say that 𝐿 is reg-

ular if and only if there is a regular expression 𝑒 such that đ‘„ ∈ 𝐿 iff𝑒 matches đ‘„. Example 6.9 — A regular function. Let ÎŁ = 𝑎, 𝑏, 𝑐, 𝑑, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9and đč ∶ Σ∗ → 0, 1 be the function such that đč(đ‘„) outputs 1 iffđ‘„ consists of one or more of the letters 𝑎-𝑑 followed by a sequenceof one or more digits (without a leading zero). Then đč is a regularfunction, since đč = Ω𝑒 where𝑒 = (𝑎|𝑏|𝑐|𝑑)(𝑎|𝑏|𝑐|𝑑)∗(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)∗

(6.11)is the expression we saw in (6.10).

Page 231: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 231

If we wanted to verify, for example, that Ω𝑒(𝑎𝑏𝑐12078) = 1,we can do so by noticing that the expression (𝑎|𝑏|𝑐|𝑑) matchesthe string 𝑎, (𝑎|𝑏|𝑐|𝑑)∗ matches 𝑏𝑐, (0|1|2|3|4|5|6|7|8|9) matches thestring 1, and the expression (0|1|2|3|4|5|6|7|8|9)∗ matches the string2078. Each one of those boils down to a simpler expression. For ex-ample, the expression (𝑎|𝑏|𝑐|𝑑)∗ matches the string 𝑏𝑐 because bothof the one-character strings 𝑏 and 𝑐 are matched by the expression𝑎|𝑏|𝑐|𝑑.Regular expression can be defined over any finite alphabet Σ, but

as usual, we will mostly focus our attention on the binary case, whereÎŁ = 0, 1. Most (if not all) of the theoretical and practical generalinsights about regular expressions can be gleaned from studying thebinary case.

6.3.1 Algorithms for matching regular expressionsRegular expressions would not be very useful for search if we couldnot actually evaulate, given a regular expression 𝑒, whether a string đ‘„is matched by 𝑒. Luckily, there is an algorithm to do so. Specifically,there is an algorithm (think “Python program” though later we willformalize the notion of algorithms using Turing machines) that oninput a regular expression 𝑒 over the alphabet 0, 1 and a string đ‘„ ∈0, 1∗, outputs 1 iff 𝑒 matches đ‘„ (i.e., outputs Ω𝑒(đ‘„)).

Indeed, Definition 6.7 actually specifies a recursive algorithm forcomputing Ω𝑒. Specifically, each one of our operations -concatenation,OR, and star- can be thought of as reducing the task of testing whetheran expression 𝑒 matches a string đ‘„ to testing whether some sub-expressions of 𝑒 match substrings of đ‘„. Since these sub-expressionsare always shorter than the original expression, this yields a recursivealgorithm for checking if 𝑒 matches đ‘„ which will eventually terminateat the base cases of the expressions that correspond to a single symbolor the empty string.

Page 232: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

232 introduction to theoretical computer science

Algorithm 6.10 — Regular expression matching.

Input: Regular expression 𝑒 over Σ∗, đ‘„ ∈ Σ∗Output: Ω𝑒(đ‘„)1: procedure Match(𝑒,đ‘„)2: if 𝑒 = ∅ then return 0 ;3: if đ‘„ = "" then return MatchEmpty(()𝑒) ;4: if 𝑒 ∈ ÎŁ then return 1 iff đ‘„ = 𝑒 ;5: if 𝑒 = (𝑒â€Č|𝑒″) then return Match(𝑒â€Č, đ‘„) or Match(𝑒″, đ‘„)

;6: if 𝑒 = (𝑒â€Č)(𝑒″) then7: for 𝑖 ∈ [|đ‘„| + 1] do8: if Match(𝑒â€Č, đ‘„0 ⋯ đ‘„đ‘–âˆ’1) and Match(𝑒″, đ‘„đ‘– ⋯ đ‘„|đ‘„|−1)

then return 1 ;9: end for

10: end if11: if 𝑒 = (𝑒â€Č)∗ then12: if 𝑒â€Č = "" then return Match("", đ‘„) ;13: # ("")∗ is the same as ""14: for 𝑖 ∈ [|đ‘„|] do15: # đ‘„0 ⋯ đ‘„đ‘–âˆ’1 is shorter than đ‘„16: if Match(𝑒, đ‘„0 ⋯ đ‘„đ‘–âˆ’1) and Match(𝑒â€Č, đ‘„đ‘– ⋯ đ‘„|đ‘„|−1)

then return 1 ;17: end for18: end if19: return 020: end procedure

We assume above that we have a procedure MatchEmpty thaton input a regular expression 𝑒 outputs 1 if and only if 𝑒 matches theempty string "".

The key observation is that in our recursive definition of regular ex-pressions, whenever 𝑒 is made up of one or two expressions 𝑒â€Č, 𝑒″ thenthese two regular expressions are smaller than 𝑒. Eventually (whenthey have size 1) then they must correspond to the non-recursivecase of a single alphabet symbol. Correspondingly, the recursive callsmade in Algorithm 6.10 always correspond to a shorter expression or(in the case of an expression of the form (𝑒â€Č)∗) a shorter input string.Thus, we can prove the correctness of Algorithm 6.10 on inputs ofthe form (𝑒, đ‘„) by induction over min|𝑒|, |đ‘„|. The base case is wheneither đ‘„ = "" or 𝑒 is a single alphabet symbol, "" or ∅. In the casethe expression is of the forrm 𝑒 = (𝑒â€Č|𝑒″) or 𝑒 = (𝑒â€Č)(𝑒″) then wemake recursive calls with the shorter expressions 𝑒â€Č, 𝑒″. In the casethe expression is of the form 𝑒 = (𝑒â€Č)∗ we make recursive calls with

Page 233: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 233

either a shorter string đ‘„ and the same expression, or with the shorterexpression 𝑒â€Č and a string đ‘„â€Č that is equal in length or shorter than đ‘„.Solved Exercise 6.3 — Match the empty string. Give an algorithm that oninput a regular expression 𝑒, outputs 1 if and only if Ω𝑒("") = 1.

Solution:

We can obtain such a recursive algorithm by using the followingobservations:

1. An expression of the form "" or (𝑒â€Č)∗ always matches the emptystring.

2. An expression of the form 𝜎, where 𝜎 ∈ Σ is an alphabet sym-bol, never matches the empty string.

3. The regular expression ∅ does not match the empty string.

4. An expression of the form 𝑒â€Č|𝑒″ matches the empty string if andonly if one of 𝑒â€Č or 𝑒″ matches it.

5. An expression of the form (𝑒â€Č)(𝑒″) matches the empty string ifand only if both 𝑒â€Č and 𝑒″ match it.

Given the above observations, we see that the following algo-rithm will check if 𝑒 matches the empty string:

procedureMatchEmpty𝑒 lIf 𝑒 = ∅ return 0 lendif lIf𝑒 = "" return 1 lendif lIf 𝑒 = ∅ or 𝑒 ∈ ÎŁ return 0 lendif lIf𝑒 = (𝑒â€Č|𝑒″) return 𝑀𝑎𝑡𝑐ℎ𝐾𝑚𝑝𝑡𝑩(𝑒â€Č) or 𝑀𝑎𝑡𝑐ℎ𝐾𝑚𝑝𝑡𝑩(𝑒″) lendifLIf 𝑒 = (𝑒â€Č)(𝑟â€Č) return 𝑀𝑎𝑡𝑐ℎ𝐾𝑚𝑝𝑡𝑩(𝑒â€Č) or 𝑀𝑎𝑡𝑐ℎ𝐾𝑚𝑝𝑡𝑩(𝑒″)lendif lIf 𝑒 = (𝑒â€Č)∗ return 1 lendif endprocedure

6.4 EFFICIENT MATCHING OF REGULAR EXPRESSIONS (OP-TIONAL)

Algorithm 6.10 is not very efficient. For example, given an expressioninvolving concatenation or the “star” operation and a string of length𝑛, it can make 𝑛 recursive calls, and hence it can be shown that in theworst case Algorithm 6.10 can take time exponential in the length ofthe input string đ‘„. Fortunately, it turns out that there is a much moreefficient algorithm that can match regular expressions in linear (i.e.,𝑂(𝑛)) time. Since we have not yet covered the topics of time and spacecomplexity, we describe this algorithm in high level terms, withoutmaking the computational model precise, using the colloquial no-tion of 𝑂(𝑛) running time as is used in introduction to programming

Page 234: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

234 introduction to theoretical computer science

courses and whiteboard coding interviews. We will see a formal defi-nition of time complexity in Chapter 13.

Theorem 6.11 — Matching regular expressions in linear time. Let 𝑒 be aregular expression. Then there is an 𝑂(𝑛) time algorithm thatcomputes Ω𝑒.The implicit constant in the 𝑂(𝑛) term of Theorem 6.11 depends

on the expression 𝑒. Thus, another way to state Theorem 6.11 is thatfor every expression 𝑒, there is some constant 𝑐 and an algorithm 𝐮that computes Ω𝑒 on 𝑛-bit inputs using at most 𝑐 ⋅ 𝑛 steps. This makessense, since in practice we often want to compute Ω𝑒(đ‘„) for a smallregular expression 𝑒 and a large document đ‘„. Theorem 6.11 tells usthat we can do so with running time that scales linearly with the sizeof the document, even if it has (potentially) worse dependence on thesize of the regular expression.

We prove Theorem 6.11 by obtaining more efficient recursive al-gorithm, that determines whether 𝑒 matches a string đ‘„ ∈ 0, 1𝑛 byreducing this task to determining whether a related expression 𝑒â€Čmatches đ‘„0, 
 , đ‘„đ‘›âˆ’2. This will result in an expression for the runningtime of the form 𝑇 (𝑛) = 𝑇 (𝑛 − 1) + 𝑂(1) which solves to 𝑇 (𝑛) = 𝑂(𝑛).

Restrictions of regular expressions. The central definition for the algo-rithm behind Theorem 6.11 is the notion of a restriction of a regularexpression. The idea is that for every regular expression 𝑒 and symbol𝜎 in its alphabet, it is possible to define a regular expression 𝑒[𝜎] suchthat 𝑒[𝜎] matches a string đ‘„ if and only if 𝑒 matches the string đ‘„đœŽ. Forexample, if 𝑒 is the regular expression 01|(01) ∗ (01) (i.e., one or moreoccurrences of 01) then 𝑒[1] is equal to 0|(01) ∗ 0 and 𝑒[0] will be ∅.(Can you see why?)

Algorithm 6.12 computes the resriction 𝑒[𝜎] given a regular ex-pression 𝑒 and an alphabet symbol 𝜎. It always terminates, since therecursive calls it makes are always on expressions smaller than theinput expression. Its correctness can be proven by induction on thelength of the regular expression 𝑒, with the base cases being when 𝑒 is"", ∅, or a single alphabet symbol 𝜏 .

Page 235: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 235

Algorithm 6.12 — Restricting regular expression.

Input: Regular expression 𝑒 over ÎŁ, symbol 𝜎 ∈ ÎŁOutput: Regular expression 𝑒â€Č = 𝑒[𝜎] such that Ω𝑒â€Č(đ‘„) =Ω𝑒(đ‘„đœŽ) for every đ‘„ ∈ Σ∗1: procedure Restrict(𝑒,𝜎)2: if 𝑒 = "" or 𝑒 = ∅ then return ∅ ;3: if 𝑒 = 𝜏 for 𝜏 ∈ ÎŁ then return "" if 𝜏 = 𝜎 and return∅ otherwise ;4: if 𝑒 = (𝑒â€Č|𝑒″) then return (Restrict(𝑒â€Č, 𝜎)|Restrict(𝑒″, 𝜎))

;5: if 𝑒 = (𝑒â€Č)∗ then return (𝑒â€Č)∗(Restrict(𝑒â€Č, 𝜎)) ;6: if 𝑒 = (𝑒â€Č)(𝑒″) and Ω𝑒″("") = 0 then return(𝑒â€Č)(Restrict(𝑒″, 𝜎)) ;7: if 𝑒 = (𝑒â€Č)(𝑒″) and Ω𝑒″("") = 1 then return(𝑒â€Č)(Restrict(𝑒″, 𝜎) | Restrict(𝑒â€Č, 𝜎)) ;8: end procedure

Using this notion of restriction, we can define the following recur-sive algorithm for regular expression matching:

Algorithm 6.13 — Regular expression matching in linear time.

Input: Regular expression 𝑒 over Σ∗, đ‘„ ∈ Σ𝑛 where 𝑛 ∈ ℕOutput: Ω𝑒(đ‘„)1: procedure FMatch(𝑒,đ‘„)2: if đ‘„ = "" then return MatchEmpty(()𝑒) ;3: Let 𝑒â€Č ← Restrict(𝑒, đ‘„đ‘›âˆ’2)4: return FMatch(𝑒â€Č, đ‘„0 ⋯ đ‘„đ‘›âˆ’1)5: end procedure

By the definition of a restriction, for every 𝜎 ∈ ÎŁ and đ‘„â€Č ∈ Σ∗,the expression 𝑒 matches đ‘„â€Č𝜎 if and only if 𝑒[𝜎] matches đ‘„â€Č. Hence forevery 𝑒 and đ‘„ ∈ Σ𝑛, Ω𝑒[đ‘„đ‘›âˆ’1](đ‘„0 ⋯ đ‘„đ‘›âˆ’2) = Ω𝑒(đ‘„) and Algorithm 6.13does return the correct answer. The only remaining task is to analyzeits running time. Note that Algorithm 6.13 uses the MatchEmptyprocedure of Solved Exercise 6.3 in the base case that đ‘„ = "". However,this is OK since the running time of this procedure depends only on 𝑒and is independent of the length of the original input.

For simplicity, let us restrict our attention to the case that the al-phabet ÎŁ is equal to 0, 1. Define đ¶(ℓ) to be the maximum numberof operations that Algorithm 6.12 takes when given as input a regularexpression 𝑒 over 0, 1 of at most ℓ symbols. The value đ¶(ℓ) can beshown to be polynomial in ℓ, though this is not important for this the-orem, since we only care about the dependence of the time to compute

Page 236: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

236 introduction to theoretical computer science

Ω𝑒(đ‘„) on the length of đ‘„ and not about the dependence of this time onthe length of 𝑒.

Algorithm 6.13 is a recursive algorithm that input an expression𝑒 and a string đ‘„ ∈ 0, 1𝑛, does computation of at most đ¶(|𝑒|) stepsand then calls itself with input some expression 𝑒â€Č and a string đ‘„â€Č oflength 𝑛 − 1. It will terminate after 𝑛 steps when it reaches a string oflength 0. So, the running time 𝑇 (𝑒, 𝑛) that it takes for Algorithm 6.13to compute Ω𝑒 for inputs of length 𝑛 satisfies the recursive equation:

𝑇 (𝑒, 𝑛) = max𝑇 (𝑒[0], 𝑛 − 1), 𝑇 (𝑒[1], 𝑛 − 1) + đ¶(|𝑒|) (6.12)

(In the base case 𝑛 = 0, 𝑇 (𝑒, 0) is equal to some constant dependingonly on 𝑒.) To get some intuition for the expression Eq. (6.12), let usopen up the recursion for one level, writing 𝑇 (𝑒, 𝑛) as𝑇 (𝑒, 𝑛) = max𝑇 (𝑒[0][0], 𝑛 − 2) + đ¶(|𝑒[0]|),𝑇 (𝑒[0][1], 𝑛 − 2) + đ¶(|𝑒[0]|),𝑇 (𝑒[1][0], 𝑛 − 2) + đ¶(|𝑒[1]|),𝑇 (𝑒[1][1], 𝑛 − 2) + đ¶(|𝑒[1]|) + đ¶(|𝑒|) . (6.13)

Continuing this way, we can see that 𝑇 (𝑒, 𝑛) ≀ 𝑛 ⋅ đ¶(𝐿) + 𝑂(1)where 𝐿 is the largest length of any expression 𝑒â€Č that we encounteralong the way. Therefore, the following claim suffices to show thatAlgorithm 6.13 runs in 𝑂(𝑛) time:

Claim: Let 𝑒 be a regular expression over 0, 1, then there is a num-ber 𝐿(𝑒) ∈ ℕ, such that for every sequence of symbols đ›Œ0, 
 , đ›Œđ‘›âˆ’1, ifwe define 𝑒â€Č = 𝑒[đ›Œ0][đ›Œ1] ⋯ [đ›Œđ‘›âˆ’1] (i.e., restricting 𝑒 to đ›Œ0, and then đ›Œ1and so on and so forth), then |𝑒â€Č| ≀ 𝐿(𝑒).

Proof of claim: For a regular expression 𝑒 over 0, 1 and đ›Œ ∈ 0, 1𝑚,we denote by 𝑒[đ›Œ] the expression 𝑒[đ›Œ0][đ›Œ1] ⋯ [đ›Œđ‘šâˆ’1] obtained by restrict-ing 𝑒 to đ›Œ0 and then to đ›Œ1 and so on. We let 𝑆(𝑒) = 𝑒[đ›Œ]|đ›Œ ∈ 0, 1∗.We will prove the claim by showing that for every 𝑒, the set 𝑆(𝑒) is fi-nite, and hence so is the number 𝐿(𝑒) which is the maximum length of𝑒â€Č for 𝑒â€Č ∈ 𝑆(𝑒).We prove this by induction on the structure of 𝑒. If 𝑒 is a symbol, theempty string, or the empty set, then this is straightforward to showas the most expressions 𝑆(𝑒) can contain are the expression itself, "",and ∅. Otherwise we split to the two cases (i) 𝑒 = 𝑒â€Č∗ and (ii) 𝑒 =𝑒â€Č𝑒″, where 𝑒â€Č, 𝑒″ are smaller expressions (and hence by the inductionhypothesis 𝑆(𝑒â€Č) and 𝑆(𝑒″) are finite). In the case (i), if 𝑒 = (𝑒â€Č)∗ then𝑒[đ›Œ] is either equal to (𝑒â€Č)∗𝑒â€Č[đ›Œ] or it is simply the empty set if 𝑒â€Č[đ›Œ] = ∅.Since 𝑒â€Č[đ›Œ] is in the set 𝑆(𝑒â€Č), the number of distinct expressions in𝑆(𝑒) is at most |𝑆(𝑒â€Č)| + 1. In the case (ii), if 𝑒 = 𝑒â€Č𝑒″ then all therestrictions of 𝑒 to strings đ›Œ will either have the form 𝑒â€Č𝑒″[đ›Œ] or the form𝑒â€Č𝑒″[đ›Œ]|𝑒â€Č[đ›Œâ€Č] where đ›Œâ€Č is some string such that đ›Œ = đ›Œâ€Čđ›Œâ€ł and 𝑒″[đ›Œâ€ł]

Page 237: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 237

matches the empty string. Since 𝑒″[đ›Œ] ∈ 𝑆(𝑒″) and 𝑒â€Č[đ›Œâ€Č] ∈ 𝑆(𝑒â€Č), thenumber of the possible distinct expressions of the form 𝑒[đ›Œ] is at most|𝑆(𝑒″)| + |𝑆(𝑒″)| ⋅ |𝑆(𝑒â€Č)|. This completes the proof of the claim.

The bottom line is that while running Algorithm 6.13 on a regularexpression 𝑒, all the expressions we ever encounter are in the finite set𝑆(𝑒), no matter how large the input đ‘„ is, and so the running time ofAlgorithm 6.13 satisfies the equation 𝑇 (𝑛) = 𝑇 (𝑛 − 1) + đ¶â€Č for someconstant đ¶â€Č depending on 𝑒. This solves to 𝑂(𝑛) where the implicitconstant in the O notation can (and will) depend on 𝑒 but crucially,not on the length of the input đ‘„.6.4.1 Matching regular expressions using DFAsTheorem 6.11 is already quite impressive, but we can do even better.Specifically, no matter how long the string đ‘„ is, we can compute Ω𝑒(đ‘„)by maintaining only a constant amount of memory and moreovermaking a single pass over đ‘„. That is, the algorithm will scan the inputđ‘„ once from start to finish, and then determine whether or not đ‘„ ismatched by the expression 𝑒. This is important in the common caseof trying to match a short regular expression over a huge file or docu-ment that might not even fit in our computer’s memory. Of course, aswe have seen before, a single-pass constant-memory algorithm is sim-ply a deterministic finite automaton. As we will see in Theorem 6.16, afunction is can be computed by regular expression if and only if it canbe computed by a DFA. We start with showing the “only if” direction:

Theorem 6.14 — DFA for regular expression matching. Let 𝑒 be a regularexpression. Then there is an algorithm that on input đ‘„ ∈ 0, 1∗computes Ω𝑒(đ‘„) while making a single pass over đ‘„ and maintaininga constant amount of memory.

Proof Idea:

The single-pass constant-memory for checking if a string matchesa regular expression is presented in Algorithm 6.15. The idea is toreplace the recursive algorithm of Algorithm 6.13 with a dynamic pro-gram, using the technique of memoization. If you haven’t taken yet analgorithms course, you might not know these techniques. This is OK;while this more efficient algorithm is crucial for the many practicalapplications of regular expressions, it is not of great importance forthis book.⋆

Page 238: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

238 introduction to theoretical computer science

Algorithm 6.15 — Regular expression matching by a DFA.

Input: Regular expression 𝑒 over Σ∗, đ‘„ ∈ Σ𝑛 where 𝑛 ∈ ℕOutput: Ω𝑒(đ‘„)1: procedure DFAMatch(𝑒,đ‘„)2: Let 𝑆 ← 𝑆(𝑒) be the set 𝑒[đ›Œ]|đ›Œ ∈ 0, 1∗ as defined

in the proof of [reglintimethm]().ref.3: for 𝑒â€Č ∈ 𝑆 do4: Let 𝑣𝑒â€Č ← 1 if Ω𝑒â€Č("") = 1 and 𝑣𝑒â€Č ← 0 otherwise5: end for6: for 𝑖 ∈ [𝑛] do7: Let 𝑙𝑎𝑠𝑡𝑒â€Č ← 𝑣𝑒â€Č for all 𝑒â€Č ∈ 𝑆8: Let 𝑣𝑒â€Č ← 𝑙𝑎𝑠𝑡𝑒â€Č[đ‘„đ‘–] for all 𝑒â€Č ∈ 𝑆9: end for

10: return 𝑣𝑒11: end procedure

Proof of Theorem 6.14. Algorithm 6.15 checks if a given string đ‘„ ∈ Σ∗is matched by the regular expression 𝑒. For every regular expres-sion 𝑒, this algorithm has a constant number 2|𝑆(𝑒)| Boolean vari-ables (𝑣𝑒â€Č , 𝑙𝑎𝑠𝑡𝑒â€Č for 𝑒â€Č ∈ 𝑆(𝑒)), and it makes a single pass overthe input string. Hence it corresponds to a DFA. We prove its cor-rectness by induction on the length 𝑛 of the input. Specifically, wewill argue that before reading the 𝑖-th bit of đ‘„, the variable 𝑣𝑒â€Č isequal to Ω𝑒â€Č(đ‘„0 ⋯ đ‘„đ‘–âˆ’1) for every 𝑒â€Č ∈ 𝑆(𝑒). In the case 𝑖 = 0 thisholds since we initialize 𝑣𝑒â€Č = Ω𝑒â€Č("") for all 𝑒â€Č ∈ 𝑆(𝑒). For 𝑖 > 0this holds by induction since the inductive hypothesis implies that𝑙𝑎𝑠𝑡â€Č𝑒 = Ω𝑒â€Č(đ‘„0 ⋯ đ‘„đ‘–âˆ’2) for all 𝑒â€Č ∈ 𝑆(𝑒) and by the definition of the set𝑆(𝑒â€Č), for every 𝑒â€Č ∈ 𝑆(𝑒) and đ‘„đ‘–âˆ’1 ∈ ÎŁ, 𝑒″ = 𝑒â€Č[đ‘„đ‘–âˆ’1] is in 𝑆(𝑒) andΩ𝑒â€Č(đ‘„0 ⋯ đ‘„đ‘–âˆ’1) = Ω𝑒″(đ‘„0 ⋯ đ‘„đ‘–).

6.4.2 Equivalence of regular expressions and automataRecall that a Boolean function đč ∶ 0, 1∗ → 0, 1 is defined to beregular if it is equal to Ω𝑒 for some regular expression 𝑒. (Equivalently,a language 𝐿 ⊆ 0, 1∗ is defined to be regular if there is a regularexpression 𝑒 such that 𝑒 matches đ‘„ iff đ‘„ ∈ 𝐿.) The following theorem isthe central result of automata theory:

Theorem 6.16 — DFA and regular expression equivalency. Let đč ∶ 0, 1∗ →0, 1. Then đč is regular if and only if there exists a DFA (𝑇 , 𝒼) thatcomputes đč .

Proof Idea:

Page 239: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 239

Figure 6.6: A deterministic finite automaton thatcomputes the function Ω(01)∗ .

Figure 6.7: Given a DFA of đ¶ states, for every 𝑣, đ‘€ ∈[đ¶] and number 𝑡 ∈ 0, 
 , đ¶ we define the functionđč 𝑡𝑣,đ‘€ ∶ 0, 1∗ → 0, 1 to output one on inputđ‘„ ∈ 0, 1∗ if and only if when the DFA is initializedin the state 𝑣 and is given the input đ‘„, it will reach thestate đ‘€ while going only through the intermediatestates 0, 
 , 𝑡 − 1.

One direction follows from Theorem 6.14, which shows that forevery regular expression 𝑒, the function Ω𝑒 can be computed by a DFA(see for example Fig. 6.6). For the other direction, we show that givena DFA (𝑇 , 𝒼) for every 𝑣, đ‘€ ∈ [đ¶] we can find a regular expression thatwould match đ‘„ ∈ 0, 1∗ if and only if the DFA starting in state 𝑣, willend up in state đ‘€ after reading đ‘„.⋆Proof of Theorem 6.16. Since Theorem 6.14 proves the “only if” direc-tion, we only need to show the “if” direction. Let 𝐮 = (𝑇 , 𝒼) be a DFAwith đ¶ states that computes the function đč . We need to show that đč isregular.

For every 𝑣, đ‘€ ∈ [đ¶], we let đč𝑣,đ‘€ ∶ 0, 1∗ → 0, 1 be the functionthat maps đ‘„ ∈ 0, 1∗ to 1 if and only if the DFA 𝐮, starting at thestate 𝑣, will reach the state đ‘€ if it reads the input đ‘„. We will prove thatđč𝑣,đ‘€ is regular for every 𝑣, đ‘€. This will prove the theorem, since byDefinition 6.2, đč(đ‘„) is equal to the OR of đč0,đ‘€(đ‘„) for every đ‘€ ∈ 𝒼.Hence if we have a regular expression for every function of the formđč𝑣,đ‘€ then (using the | operation) we can obtain a regular expressionfor đč as well.

To give regular expressions for the functions đč𝑣,đ‘€, we start bydefining the following functions đč 𝑡𝑣,đ‘€: for every 𝑣, đ‘€ ∈ [đ¶] and0 ≀ 𝑡 ≀ đ¶, đč 𝑡𝑣,đ‘€(đ‘„) = 1 if and only if starting from 𝑣 and observ-ing đ‘„, the automata reaches đ‘€ with all intermediate states being in the set[𝑡] = 0, 
 , 𝑡 − 1 (see Fig. 6.7). That is, while 𝑣, đ‘€ themselves mightbe outside [𝑡], đč 𝑡𝑣,đ‘€(đ‘„) = 1 if and only if throughout the execution ofthe automaton on the input đ‘„ (when initiated at 𝑣) it never enters anyof the states outside [𝑡] and still ends up at đ‘€. If 𝑡 = 0 then [𝑡] is theempty set, and hence đč 0𝑣,đ‘€(đ‘„) = 1 if and only if the automaton reachesđ‘€ from 𝑣 directly on đ‘„, without any intermediate state. If 𝑡 = đ¶ thenall states are in [𝑡], and hence đč 𝑡𝑣,đ‘€ = đč𝑣,đ‘€.

We will prove the theorem by induction on 𝑡, showing that đč 𝑡𝑣,đ‘€ isregular for every 𝑣, đ‘€ and 𝑡. For the base case of 𝑡 = 0, đč 0𝑣,đ‘€ is regularfor every 𝑣, đ‘€ since it can be described as one of the expressions "", ∅,0, 1 or 0|1. Specifically, if 𝑣 = đ‘€ then đč 0𝑣,đ‘€(đ‘„) = 1 if and only if đ‘„ isthe empty string. If 𝑣 ≠ đ‘€ then đč 0𝑣,đ‘€(đ‘„) = 1 if and only if đ‘„ consistsof a single symbol 𝜎 ∈ 0, 1 and 𝑇 (𝑣, 𝜎) = đ‘€. Therefore in this caseđč 0𝑣,đ‘€ corresponds to one of the four regular expressions 0|1, 0, 1 or ∅,depending on whether 𝐮 transitions to đ‘€ from 𝑣 when it reads either 0or 1, only one of these symbols, or neither.

Inductive step: Now that we’ve seen the base case, let’s prove thegeneral case by induction. Assume, via the induction hypothesis, thatfor every 𝑣â€Č, đ‘€â€Č ∈ [đ¶], we have a regular expression 𝑅𝑡𝑣,đ‘€ that computesđč 𝑡𝑣â€Č,đ‘€â€Č . We need to prove that đč 𝑡+1𝑣,đ‘€ is regular for every 𝑣, đ‘€. If the

Page 240: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

240 introduction to theoretical computer science

automaton arrives from 𝑣 to đ‘€ using the intermediate states [𝑡 + 1],then it visits the 𝑡-th state zero or more times. If the path labeled by đ‘„causes the automaton to get from 𝑣 to đ‘€ without visiting the 𝑡-th stateat all, then đ‘„ is matched by the regular expression 𝑅𝑡𝑣,đ‘€. If the pathlabeled by đ‘„ causes the automaton to get from 𝑣 to đ‘€ while visiting the𝑡-th state 𝑘 > 0 times then we can think of this path as:‱ First travel from 𝑣 to 𝑡 using only intermediate states in [𝑡 − 1].‱ Then go from 𝑡 back to itself 𝑘 − 1 times using only intermediate

states in [𝑡 − 1]‱ Then go from 𝑡 to đ‘€ using only intermediate states in [𝑡 − 1].

Therefore in this case the string đ‘„ is matched by the regular expres-sion 𝑅𝑡𝑣,𝑡(𝑅𝑡𝑡,𝑡)∗𝑅𝑡𝑡,đ‘€. (See also Fig. 6.8.)

Therefore we can compute đč 𝑡+1𝑣,đ‘€ using the regular expression𝑅𝑡𝑣,đ‘€ | 𝑅𝑡𝑣,𝑡(𝑅𝑡𝑡,𝑡)∗𝑅𝑡𝑡,đ‘€ . (6.14)This completes the proof of the inductive step and hence of the theo-rem.

Figure 6.8: If we have regular expressions 𝑅𝑡𝑣â€Č,đ‘€â€Čcorresponding to đč 𝑡𝑣â€Č,đ‘€â€Č for every 𝑣â€Č, đ‘€â€Č ∈ [đ¶], we canobtain a regular expression 𝑅𝑡+1𝑣,đ‘€ corresponding tođč 𝑡+1𝑣,đ‘€ . The key observation is that a path from 𝑣 to đ‘€using 0, 
 , 𝑡 either does not touch 𝑡 at all, in whichcase it is captured by the expression 𝑅𝑡𝑣,đ‘€, or it goesfrom 𝑣 to 𝑡, comes back to 𝑡 zero or more times, andthen goes from 𝑡 to đ‘€, in which case it is captured bythe expression 𝑅𝑡𝑣,𝑡(𝑅𝑡𝑡,𝑡)∗𝑅𝑡𝑡,đ‘€.

6.4.3 Closure properties of regular expressionsIf đč and đș are regular functions computed by the expressions 𝑒 and 𝑓respectively, then the expression 𝑒|𝑓 computes the function đ» = đč √ đșdefined as đ»(đ‘„) = đč(đ‘„) √ đș(đ‘„). Another way to say this is that the setof regular functions is closed under the OR operation. That is, if đč and đșare regular then so is đč √ đș. An important corollary of Theorem 6.16is that this set is also closed under the NOT operation:

Page 241: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 241

Lemma 6.17 — Regular expressions closed under complement. If đč ∶ 0, 1∗ →0, 1 is regular then so is the function đč , where đč(đ‘„) = 1 − đč(đ‘„) forevery đ‘„ ∈ 0, 1∗.Proof. If đč is regular then by Theorem 6.11 it can be computed by aDFA 𝐮 = (𝑇 , 𝒜) with some đ¶ states. But then the DFA 𝐮 = (𝑇 , [đ¶]â§”đ’œ)which does the same computation but where flips the set of acceptedstates will compute đč . By Theorem 6.16 this implies that đč is regularas well.

Since 𝑎 ∧ 𝑏 = 𝑎 ∹ 𝑏, Lemma 6.17 implies that the set of regularfunctions is closed under the AND operation as well. Moreover, sinceOR, NOT and AND are a universal basis, this set is also closed un-der NAND, XOR, and any other finite function. That is, we have thefollowing corollary:

Theorem 6.18 — Closure of regular expressions. Let 𝑓 ∶ 0, 1𝑘 → 0, 1 beany finite Boolean function, and let đč0, 
 , đč𝑘−1 ∶ 0, 1∗ → 0, 1 beregular functions. Then the function đș(đ‘„) = 𝑓(đč0(đ‘„), đč1(đ‘„), 
 , đč𝑘−1(đ‘„))is regular.

Proof. This is a direct consequence of the closure of regular functionsunder OR and NOT (and hence AND) and Theorem 4.13, that statesthat every 𝑓 can be computed by a Boolean circuit (which is simply acombination of the AND, OR, and NOT operations).

6.5 LIMITATIONS OF REGULAR EXPRESSIONS AND THE PUMPINGLEMMA

The efficiency of regular expression matching makes them very useful.This is the reason why operating systems and text editors often restricttheir search interface to regular expressions and don’t allow searchingby specifying an arbitrary function. But this efficiency comes at a cost.As we have seen, regular expressions cannot compute every function.In fact there are some very simple (and useful!) functions that theycannot compute. Here is one example:Lemma 6.19 — Matching parenthesis. Let ÎŁ = ⟹, ⟩ and MATCHPAREN âˆ¶ÎŁâˆ— → 0, 1 be the function that given a string of parentheses, out-puts 1 if and only if every opening parenthesis is matched by a corre-sponding closed one. Then there is no regular expression over ÎŁ thatcomputes MATCHPAREN.

Lemma 6.19 is a consequence of the following result, which isknown as the pumping lemma:

Page 242: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

242 introduction to theoretical computer science

Theorem 6.20 — Pumping Lemma. Let 𝑒 be a regular expression oversome alphabet ÎŁ. Then there is some number 𝑛0 such that for ev-ery đ‘€ ∈ Σ∗ with |đ‘€| > 𝑛0 and Ω𝑒(đ‘€) = 1, we can write đ‘€ = đ‘„đ‘Šđ‘§ forstrings đ‘„, 𝑩, 𝑧 ∈ Σ∗ satisfying the following conditions:

1. |𝑩| ≄ 1.2. |đ‘„đ‘Š| ≀ 𝑛0.3. Ω𝑒(đ‘„đ‘Šđ‘˜đ‘§) = 1 for every 𝑘 ∈ ℕ.

Figure 6.9: To prove the “pumping lemma” we lookat a word đ‘€ that is much larger than the regularexpression 𝑒 that matches it. In such a case, part ofđ‘€ must be matched by some sub-expression of theform (𝑒â€Č)∗, since this is the only operator that allowsmatching words longer than the expression. If welook at the “leftmost” such sub-expression and define𝑩𝑘 to be the string that is matched by it, we obtain thepartition needed for the pumping lemma.

Proof Idea:

The idea behind the proof the following. Let 𝑛0 be twice the num-ber of symbols that are used in the expression 𝑒, then the only waythat there is some đ‘€ with |đ‘€| > 𝑛0 and Ω𝑒(đ‘€) = 1 is that 𝑒 containsthe ∗ (i.e. star) operator and that there is a nonempty substring 𝑩 ofđ‘€ that was matched by (𝑒â€Č)∗ for some sub-expression 𝑒â€Č of 𝑒. We cannow repeat 𝑩 any number of times and still get a matching string. Seealso Fig. 6.9.⋆

PThe pumping lemma is a bit cumbersome to state,but one way to remember it is that it simply says thefollowing: “if a string matching a regular expression islong enough, one of its substrings must be matched usingthe ∗ operator”.

Page 243: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 243

Proof of Theorem 6.20. To prove the lemma formally, we use inductionon the length of the expression. Like all induction proofs, this is goingto be somewhat lengthy, but at the end of the day it directly followsthe intuition above that somewhere we must have used the star oper-ation. Reading this proof, and in particular understanding how theformal proof below corresponds to the intuitive idea above, is a verygood way to get more comfortable with inductive proofs of this form.

Our inductive hypothesis is that for an 𝑛 length expression, 𝑛0 =2𝑛 satisfies the conditions of the lemma. The base case is when theexpression is a single symbol 𝜎 ∈ ÎŁ or that the expression is ∅ or"". In all these cases the conditions of the lemma are satisfied simplybecause there 𝑛0 = 2 and there is no string đ‘„ of length larger than 𝑛0that is matched by the expression.

We now prove the inductive step. Let 𝑒 be a regular expressionwith 𝑛 > 1 symbols. We set 𝑛0 = 2𝑛 and let đ‘€ ∈ Σ∗ be a stringsatisfying |đ‘€| > 𝑛0. Since 𝑒 has more than one symbol, it has one ofthe the forms (a) 𝑒â€Č|𝑒″, (b), (𝑒â€Č)(𝑒″), or (c) (𝑒â€Č)∗ where in all thesecases the subexpressions 𝑒â€Č and 𝑒″ have fewer symbols than 𝑒 andhence satisfy the induction hypothesis.

In the case (a), every string đ‘€ matched by 𝑒 must be matched byeither 𝑒â€Č or 𝑒″. If 𝑒â€Č matches đ‘€ then, since |đ‘€| > 2|𝑒â€Č|, by the inductionhypothesis there exist đ‘„, 𝑩, 𝑧 with |𝑩| ≄ 1 and |đ‘„đ‘Š| ≀ 2|𝑒â€Č| < 𝑛0 suchthat 𝑒â€Č (and therefore also 𝑒 = 𝑒â€Č|𝑒″) matches đ‘„đ‘Šđ‘˜đ‘§ for every 𝑘. Thesame arguments works in the case that 𝑒″ matches đ‘€.

In the case (b), if đ‘€ is matched by (𝑒â€Č)(𝑒″) then we can write đ‘€ =đ‘€â€Čđ‘€â€ł where 𝑒â€Č matches đ‘€â€Č and 𝑒″ matches đ‘€â€ł. We split to subcases. If|đ‘€â€Č| > 2|𝑒â€Č| then by the induction hypothesis there exist đ‘„, 𝑩, 𝑧â€Č with|𝑩| ≀ 1, |đ‘„đ‘Š| ≀ 2|𝑒â€Č| < 𝑛0 such that đ‘€â€Č = đ‘„đ‘Šđ‘§â€Č and 𝑒â€Č matches đ‘„đ‘Šđ‘˜đ‘§â€Čfor every 𝑘 ∈ ℕ. This completes the proof since if we set 𝑧 = 𝑧â€Čđ‘€â€łthen we see that đ‘€ = đ‘€â€Čđ‘€â€ł = đ‘„đ‘Šđ‘§ and 𝑒 = (𝑒â€Č)(𝑒″) matches đ‘„đ‘Šđ‘˜đ‘§ forevery 𝑘 ∈ ℕ. Otherwise, if |đ‘€â€Č| ≀ 2|𝑒â€Č| then since |đ‘€| = |đ‘€â€Č| + |đ‘€â€ł| >𝑛0 = 2(|𝑒â€Č| + |𝑒″|), it must be that |đ‘€â€ł| > 2|𝑒″|. Hence by the inductionhypothesis there exist đ‘„â€Č, 𝑩, 𝑧 such that |𝑩| ≄ 1, |đ‘„â€Č𝑩| ≀ 2|𝑒″| and 𝑒″matches đ‘„â€Č𝑩𝑘𝑧 for every 𝑘 ∈ ℕ. But now if we set đ‘„ = đ‘€â€Čđ‘„â€Č we see that|đ‘„đ‘Š| ≀ |đ‘€â€Č| + |đ‘„â€Č𝑩| ≀ 2|𝑒â€Č| + 2|𝑒″| = 𝑛0 and on the other hand theexpression 𝑒 = (𝑒â€Č)(𝑒″) matches đ‘„đ‘Šđ‘˜đ‘§ = đ‘€â€Čđ‘„â€Č𝑩𝑘𝑧 for every 𝑘 ∈ ℕ.

In case (c), if đ‘€ is matched by (𝑒â€Č)∗ then đ‘€ = đ‘€0 ⋯ đ‘€đ‘Ą where forevery 𝑖 ∈ [𝑡], đ‘€đ‘– is a nonempty string matched by 𝑒â€Č. If |đ‘€0| > 2|𝑒â€Č|then we can use the same approach as in the concatenation case above.Otherwise, we simply note that if đ‘„ is the empty string, 𝑩 = đ‘€0, and𝑧 = đ‘€1 ⋯ đ‘€đ‘Ą then |đ‘„đ‘Š| ≀ 𝑛0 and đ‘„đ‘Šđ‘˜đ‘§ is matched by (𝑒â€Č)∗ for every𝑘 ∈ ℕ.

Page 244: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

244 introduction to theoretical computer science

RRemark 6.21 — Recursive definitions and inductiveproofs. When an object is recursively defined (as in thecase of regular expressions) then it is natural to proveproperties of such objects by induction. That is, if wewant to prove that all objects of this type have prop-erty 𝑃 , then it is natural to use an inductive steps thatsays that if 𝑜â€Č, 𝑜″, 𝑜‮ etc have property 𝑃 then so is anobject 𝑜 that is obtained by composing them.

Using the pumping lemma, we can easily prove Lemma 6.19 (i.e.,the non-regularity of the “matching parenthesis” function):

Proof of Lemma 6.19. Suppose, towards the sake of contradiction, thatthere is an expression 𝑒 such that Ω𝑒 = MATCHPAREN. Let 𝑛0 bethe number obtained from Theorem 6.20 and let đ‘€ = ⟹𝑛0âŸ©đ‘›0 (i.e.,𝑛0 left parenthesis followed by 𝑛0 right parenthesis). Then we seethat if we write đ‘€ = đ‘„đ‘Šđ‘§ as in Lemma 6.19, the condition |đ‘„đ‘Š| ≀ 𝑛0implies that 𝑩 consists solely of left parenthesis. Hence the stringđ‘„đ‘Š2𝑧 will contain more left parenthesis than right parenthesis. HenceMATCHPAREN(đ‘„đ‘Š2𝑧) = 0 but by the pumping lemma Ω𝑒(đ‘„đ‘Š2𝑧) = 1,contradicting our assumption that Ω𝑒 = MATCHPAREN.

The pumping lemma is a very useful tool to show that certain func-tions are not computable by a regular expression. However, it is notan “if and only if” condition for regularity: there are non regularfunctions that still satisfy the conditions of the pumping lemma. Tounderstand the pumping lemma, it is important to follow the order ofquantifiers in Theorem 6.20. In particular, the number 𝑛0 in the state-ment of Theorem 6.20 depends on the regular expression (in the proofwe chose 𝑛0 to be twice the number of symbols in the expression). So,if we want to use the pumping lemma to rule out the existence of aregular expression 𝑒 computing some function đč , we need to be ableto choose an appropriate input đ‘€ ∈ 0, 1∗ that can be arbitrarily largeand satisfies đč(đ‘€) = 1. This makes sense if you think about the intu-ition behind the pumping lemma: we need đ‘€ to be large enough as toforce the use of the star operator.Solved Exercise 6.4 — Palindromes is not regular. Prove that the followingfunction over the alphabet 0, 1, ; is not regular: PAL(đ‘€) = 1 if andonly if đ‘€ = 𝑱; 𝑱𝑅 where 𝑱 ∈ 0, 1∗ and 𝑱𝑅 denotes 𝑱 “reversed”:the string 𝑱|𝑱|−1 ⋯ 𝑱0. (The Palindrome function is most often definedwithout an explicit separator character ;, but the version with such aseparator is a bit cleaner and so we use it here. This does not make

Page 245: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 245

Figure 6.10: A cartoon of a proof using the pumping lemma that a function đč is not regular. The pumping lemma states that if đč is regular then thereexists a number 𝑛0 such that for every large enough đ‘€ with đč(đ‘€) = 1, there exists a partition of đ‘€ to đ‘€ = đ‘„đ‘Šđ‘§ satisfying certain conditions suchthat for every 𝑘 ∈ ℕ, đč(đ‘„đ‘Šđ‘˜đ‘§) = 1. You can imagine a pumping-lemma based proof as a game between you and the adversary. Every there existsquantifier corresponds to an object you are free to choose on your own (and base your choice on previously chosen objects). Every for every quantifiercorresponds to an object the adversary can choose arbitrarily (and again based on prior choices) as long as it satisfies the conditions. A valid proofcorresponds to a strategy by which no matter what the adversary does, you can win the game by obtaining a contradiction which would be a choiceof 𝑘 that would result in đč(đ‘„đ‘Šđ‘˜đ‘§) = 0, hence violating the conclusion of the pumping lemma.

Page 246: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

246 introduction to theoretical computer science

much difference, as one can easily encode the separator as a specialbinary string instead.)

Solution:

We use the pumping lemma. Suppose towards the sake of con-tradiction that there is a regular expression 𝑒 computing PAL,and let 𝑛0 be the number obtained by the pumping lemma (The-orem 6.20). Consider the string đ‘€ = 0𝑛0 ; 0𝑛0 . Since the reverseof the all zero string is the all zero string, PAL(đ‘€) = 1. Now, bythe pumping lemma, if PAL is computed by 𝑒, then we can writeđ‘€ = đ‘„đ‘Šđ‘§ such that |đ‘„đ‘Š| ≀ 𝑛0, |𝑩| ≄ 1 and PAL(đ‘„đ‘Šđ‘˜đ‘§) = 1 forevery 𝑘 ∈ ℕ. In particular, it must hold that PAL(đ‘„đ‘§) = 1, but thisis a contradiction, since đ‘„đ‘§ = 0𝑛0−|𝑩|; 0𝑛0 and so its two parts arenot of the same length and in particular are not the reverse of oneanother.

For yet another example of a pumping-lemma based proof, seeFig. 6.10 which illustrates a cartoon of the proof of the non-regularityof the function đč ∶ 0, 1∗ → 0, 1 which is defined as đč(đ‘„) = 1 iffđ‘„ = 0𝑛1𝑛 for some 𝑛 ∈ ℕ (i.e., đ‘„ consists of a string of consecutivezeroes, followed by a string of consecutive ones of the same length).

6.6 ANSWERING SEMANTIC QUESTIONS ABOUT REGULAR EX-PRESSIONS

Regular expressions have applications beyond search. For example,regular expressions are often used to define tokens (such as what is avalid variable identifier, or keyword) in the design of parsers, compilersand interpreters for programming languages. There other applicationstoo: for example, in recent years, the world of networking moved fromfixed topologies to “software defined networks”. Such networks arerouted by programmable switches that can implement policies suchas “if packet is secured by SSL then forward it to A, otherwise for-ward it to B”. To represent such policies we need a language that ison one hand sufficiently expressive to capture the policies we wantto implement, but on the other hand sufficiently restrictive so that wecan quickly execute them at network speed and also be able to answerquestions such as “can C see the packets moved from A to B?”. TheNetKAT network programming language uses a variant of regularexpressions to achieve precisely that. For this application, it is im-portant that we are not able to merely answer whether an expression𝑒 matches a string đ‘„ but also answer semantic questions about regu-lar expressions such as “do expressions 𝑒 and 𝑒â€Č compute the same

Page 247: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 247

function?” and “does there exist a string đ‘„ that is matched by the ex-pression 𝑒?”. The following theorem shows that we can answer thelatter question:

Theorem 6.22 — Emptiness of regular languages is computable. There is analgorithm that given a regular expression 𝑒, outputs 1 if and only ifΩ𝑒 is the constant zero function.

Proof Idea:

The idea is that we can directly observe this from the structureof the expression. The only way a regular expression 𝑒 computesthe constant zero function is if 𝑒 has the form ∅ or is obtained byconcatenating ∅ with other expressions.⋆Proof of Theorem 6.22. Define a regular expression to be “empty” if itcomputes the constant zero function. Given a regular expression 𝑒, wecan determine if 𝑒 is empty using the following rules:

‱ If 𝑒 has the form 𝜎 or "" then it is not empty.

‱ If 𝑒 is not empty then 𝑒|𝑒â€Č is not empty for every 𝑒â€Č.‱ If 𝑒 is not empty then 𝑒∗ is not empty.

‱ If 𝑒 and 𝑒â€Č are both not empty then 𝑒 𝑒â€Č is not empty.

‱ ∅ is empty.

Using these rules it is straightforward to come up with a recursivealgorithm to determine emptiness.

Using Theorem 6.22, we can obtain an algorithm that determineswhether or not two regular expressions 𝑒 and 𝑒â€Č are equivalent, in thesense that they compute the same function.

Theorem 6.23 — Equivalence of regular expressions is computable. LetREGEQ ∶ 0, 1∗ → 0, 1 be the function that on input (a stringrepresenting) a pair of regular expressions 𝑒, 𝑒â€Č, REGEQ(𝑒, 𝑒â€Č) = 1if and only if Ω𝑒 = Ω𝑒â€Č . Then there is an algorithm that computesREGEQ.

Proof Idea:

The idea is to show that given a pair of regular expressions 𝑒 and𝑒â€Č we can find an expression 𝑒″ such that Ω𝑒″(đ‘„) = 1 if and only ifΩ𝑒(đ‘„) ≠ Ω𝑒â€Č(đ‘„). Therefore Ω𝑒″ is the constant zero function if and only

Page 248: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

248 introduction to theoretical computer science

if 𝑒 and 𝑒â€Č are equivalent, and thus we can test for emptiness of 𝑒″ todetermine equivalence of 𝑒 and 𝑒â€Č.⋆Proof of Theorem 6.23. We will prove Theorem 6.23 from Theorem 6.22.(The two theorems are in fact equivalent: it is easy to prove Theo-rem 6.22 from Theorem 6.23, since checking for emptiness is the sameas checking equivalence with the expression ∅.) Given two regu-lar expressions 𝑒 and 𝑒â€Č, we will compute an expression 𝑒″ such thatΩ𝑒″(đ‘„) = 1 if and only if Ω𝑒(đ‘„) ≠ Ω𝑒â€Č(đ‘„). One can see that 𝑒 is equiva-lent to 𝑒â€Č if and only if 𝑒″ is empty.

We start with the observation that for every bit 𝑎, 𝑏 ∈ 0, 1, 𝑎 ≠ 𝑏 ifand only if (𝑎 ∧ 𝑏) ∹ (𝑎 ∧ 𝑏) . (6.15)

Hence we need to construct 𝑒″ such that for every đ‘„,Ω𝑒″(đ‘„) = (Ω𝑒(đ‘„) ∧ Ω𝑒â€Č(đ‘„)) √ (Ω𝑒(đ‘„) ∧ Ω𝑒â€Č(đ‘„)) . (6.16)To construct the expression 𝑒″, we will show how given any pair of

expressions 𝑒 and 𝑒â€Č, we can construct expressions 𝑒 ∧ 𝑒â€Č and 𝑒 thatcompute the functions Ω𝑒 ∧ Ω𝑒â€Č and Ω𝑒 respectively. (Computing theexpression for 𝑒 √ 𝑒â€Č is straightforward using the | operation of regularexpressions.)

Specifically, by Lemma 6.17, regular functions are closed undernegation, which means that for every regular expression 𝑒, there is anexpression 𝑒 such that Ω𝑒(đ‘„) = 1 − Ω𝑒(đ‘„) for every đ‘„ ∈ 0, 1∗. Now,for every two expression 𝑒 and 𝑒â€Č, the expression𝑒 ∧ 𝑒â€Č = (𝑒|𝑒â€Č) (6.17)

computes the AND of the two expressions. Given these two transfor-mations, we see that for every regular expressions 𝑒 and 𝑒â€Č we can finda regular expression 𝑒″ satisfying (6.16) such that 𝑒″ is empty if andonly if 𝑒 and 𝑒â€Č are equivalent.

Chapter Recap

‱ We model computational tasks on arbitrarily largeinputs using infinite functions đč ∶ 0, 1∗ → 0, 1∗.

‱ Such functions take an arbitrarily long (but stillfinite!) string as input, and cannot be described bya finite table of inputs and ouptuts.

‱ A function with a single bit of output is known asa Boolean function, and the tasks of computing it isequivalent to deciding a language 𝐿 ⊆ 0, 1∗.

Page 249: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

functions with infinite domains, automata, and regular expressions 249

‱ Deterministic finite automata (DFAs) are one simplemodel for computing (infinite) Boolean functions.

‱ There are some functions that cannot be computedby DFAs.

‱ The set of functions computable by DFAs is thesame as the set of languages that can be recognizedby regular expressions.

6.7 EXERCISES

Exercise 6.1 — Closure properties of regular functions. Suppose that đč, đș ∶0, 1∗ → 0, 1 are regular. For each one of the following defini-tions of the function đ» , either prove that đ» is always regular or give acounterexample for regular đč, đș that would make đ» not regular.

1. đ»(đ‘„) = đč(đ‘„) √ đș(đ‘„).2. đ»(đ‘„) = đč(đ‘„) ∧ đș(đ‘„)3. đ»(đ‘„) = NAND(đč(đ‘„), đș(đ‘„)).4. đ»(đ‘„) = đč(đ‘„đ‘…) where đ‘„đ‘… is the reverse of đ‘„: đ‘„đ‘… = đ‘„đ‘›âˆ’1đ‘„đ‘›âˆ’2 ⋯ đ‘„đ‘œ for𝑛 = |đ‘„|.5. đ»(đ‘„) = ⎧⎚⎩1 đ‘„ = 𝑱𝑣 s.t. đč(𝑱) = đș(𝑣) = 10 otherwise

6. đ»(đ‘„) = ⎧⎚⎩1 đ‘„ = 𝑱𝑱 s.t. đč(𝑱) = đș(𝑱) = 10 otherwise

7. đ»(đ‘„) = ⎧⎚⎩1 đ‘„ = 𝑱𝑱𝑅 s.t. đč(𝑱) = đș(𝑱) = 10 otherwise

Exercise 6.2 One among the following two functions that map 0, 1∗to 0, 1 can be computed by a regular expression, and the other onecannot. For the one that can be computed by a regular expression,write the expression that does it. For the one that cannot, prove thatthis cannot be done using the pumping lemma.

‱ đč(đ‘„) = 1 if 4 divides ∑|đ‘„|−1𝑖=0 đ‘„đ‘– and đč(đ‘„) = 0 otherwise.

‱ đș(đ‘„) = 1 if and only if ∑|đ‘„|−1𝑖=0 đ‘„đ‘– ≄ |đ‘„|/4 and đș(đ‘„) = 0 otherwise.

Exercise 6.3 — Non regularity. 1. Prove that the following function đč ∶0, 1∗ → 0, 1 is not regular. For every đ‘„ ∈ 0, 1∗, đč(đ‘„) = 1 iff đ‘„ isof the form đ‘„ = 13𝑖 for some 𝑖 > 0.

Page 250: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

250 introduction to theoretical computer science

2. Prove that the following function đč ∶ 0, 1∗ → 0, 1 is not regular.For every đ‘„ ∈ 0, 1∗, đč(đ‘„) = 1 iff ∑𝑗 đ‘„đ‘— = 3𝑖 for some 𝑖 > 0.

6.8 BIBLIOGRAPHICAL NOTES

The relation of regular expressions with finite automata is a beautifultopic, on which we only touch upon in this text. It is covered moreextensively in [Sip97; HMU14; Koz97]. These texts also discuss top-ics such as non deterministic finite automata (NFA) and the relationbetween context-free grammars and pushdown automata.

The automaton of Fig. 6.4 was generated using the FSM simulatorof Ivan Zuzak and Vedrana Jankovic. Our proof of Theorem 6.11 isclosely related to the Myhill-Nerode Theorem. One direction of theMyhill-Nerode theorem can be stated as saying that if 𝑒 is a regularexpression then there is at most a finite number of strings 𝑧0, 
 , 𝑧𝑘−1such that Ω𝑒[𝑧𝑖] ≠ Ω𝑒[𝑧𝑗] for every 0 ≀ 𝑖 ≠ 𝑗 < 𝑘.

Page 251: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Figure 7.1: An algorithm is a finite recipe to computeon arbitrarily long inputs. The components of analgorithm include the instructions to be performed,finite state or “local variables”, the memory to storethe input and intermediate computations, as well asmechanisms to decide which part of the memory toaccess, and when to repeat instructions and when tohalt.

7Loops and infinity

“The bounds of arithmetic were however outstepped the moment the idea ofapplying the [punched] cards had occurred; and the Analytical Engine doesnot occupy common ground with mere ‘calculating machines.’ 
 In enablingmechanism to combine together general symbols, in successions of unlim-ited variety and extent, a uniting link is established between the operations ofmatter and the abstract mental processes of the most abstract branch of mathe-matical science.”, Ada Augusta, countess of Lovelace, 1843

As the quote of Chapter 6 says, an algorithm is “a finite answer toan infinite number of questions”. To express an algorithm we need towrite down a finite set of instructions that will enable us to computeon arbitrarily long inputs. To describe and execute an algorithm weneed the following components (see Fig. 7.1):

‱ The finite set of instructions to be performed.

‱ Some “local variables” or finite state used in the execution.

‱ A potentially unbounded working memory to store the input aswell as any other values we may require later.

‱ While the memory is unbounded, at every single step we can onlyread and write to a finite part of it, and we need a way to addresswhich are the parts we want to read from and write to.

‱ If we only have a finite set of instructions but our input can bearbitrarily long, we will need to repeat instructions (i.e., loop back).We need a mechanism to decide when we will loop and when wewill halt.

This chapter: A non-mathy overviewIn this chapter we give a general model of an algorithm,which (unlike Boolean circuits) is not restricted to a fixedinput lengths, and (unlike finite automata) is not restricted to

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Learn the model of Turing machines, which

can compute functions of arbitrary inputlengths.

‱ See a programming-language description ofTuring machines, using NAND-TM programs,which add loops and arrays to NAND-CIRC.

‱ See some basic syntactic sugar andequivalence of variants of Turing machinesand NAND-TM programs.

Page 252: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

252 introduction to theoretical computer science

a finite amount of working memory. We will see two ways tomodel algorithms:

‱ Turing machines, invented by Alan Turing in 1936, are anhypothetical abstract device that yields a finite descriptionof an algorithm that can handle arbitrarily long inputs.

‱ The NAND-TM Programming language extends NAND-CIRC with the notion of loops and arrays to obtain finiteprograms that can compute a function with arbitrarilylong inputs.

It turns out that these two models are equivalent, and in factthey are equivalent to many other computational modelsincluding programming languages such as C, Lisp, Python,JavaScript, etc. This notion, known as Turing equivalenceor Turing completeness, will be discussed in Chapter 8. SeeFig. 7.2 for an overview of the models presented in this chap-ter and Chapter 8.

Figure 7.2: Overview of our models for finite andunbounded computation. In the previous chapterswe study the computation of finite functions, whichare functions 𝑓 ∶ 0, 1𝑛 → 0, 1𝑚 for some fixed𝑛, 𝑚, and modeled computing these functions usingcircuits or straightline programs. In this chapter westudy computing unbounded functions of the formđč ∶ 0, 1∗ → 0, 1𝑚 or đč ∶ 0, 1∗ → 0, 1∗.We model computing these functions using TuringMachines or (equivalently) NAND-TM programswhich add the notion of loops to the NAND-CIRCprogramming language. In Chapter 8 we will showthat these models are equivalent to many othermodels, including RAM machines, the 𝜆 calculus, andall the common programming languages including C,Python, Java, JavaScript, etc.

7.1 TURING MACHINES“Computing is normally done by writing certain symbols on paper. We maysuppose that this paper is divided into squares like a child’s arithmetic book..The behavior of the [human] computer at any moment is determined by thesymbols which he is observing, and of his ‘state of mind’ at that moment
 Wemay suppose that in a simple operation not more than one symbol is altered.”,“We compare a man in the process of computing 
 to a machine which is onlycapable of a finite number of configurations
 The machine is supplied with a‘tape’ (the analogue of paper) 
 divided into sections (called ‘squares’) eachcapable of bearing a ‘symbol’ ”, Alan Turing, 1936

Page 253: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 253

Figure 7.3: Aside from his many other achievements,Alan Turing was an excellent long distance runnerwho just fell shy of making England’s olympic team.A fellow runner once asked him why he punishedhimself so much in training. Alan said “I have sucha stressful job that the only way I can get it out of mymind is by running hard; it’s the only way I can getsome release.”

Figure 7.4: Until the advent of electronic computers,the word “computer” was used to describe a personthat performed calculations. Most of these “humancomputers” were women, and they were absolutelyessential to many achievements including mappingthe stars, breaking the Enigma cipher, and the NASAspace mission; see also the bibliographical notes.Photo from National Photo Company Collection; seealso [Sob17].

Figure 7.5: Steam-powered Turing Machine mural,painted by CSE grad students at the University ofWashington on the night before spring qualifyingexaminations, 1987. Image from https://www.cs.washington.edu/building/art/SPTM.

“What is the difference between a Turing machine and the modern computer?It’s the same as that between Hillary’s ascent of Everest and the establishmentof a Hilton hotel on its peak.” , Alan Perlis, 1982.

The “granddaddy” of all models of computation is the Turing Ma-chine. Turing machines were defined in 1936 by Alan Turing in anattempt to formally capture all the functions that can be computedby human “computers” (see Fig. 7.4) that follow a well-defined set ofrules, such as the standard algorithms for addition or multiplication.

Turing thought of such a person as having access to as much“scratch paper” as they need. For simplicity we can think of thisscratch paper as a one dimensional piece of graph paper (or tape, asit is commonly referred to), which is divided to “cells”, where each“cell” can hold a single symbol (e.g., one digit or letter, and moregenerally some element of a finite alphabet). At any point in time, theperson can read from and write to a single cell of the paper, and basedon the contents can update his/her finite mental state, and/or move tothe cell immediately to the left or right of the current one.

Turing modeled such a computation by a “machine” that maintainsone of 𝑘 states. At each point in time the machine reads from its “worktape” a single symbol from a finite alphabet ÎŁ and uses that to up-date its state, write to tape, and possibly move to an adjacent cell (seeFig. 7.7). To compute a function đč using this machine, we initialize thetape with the input đ‘„ ∈ 0, 1∗ and our goal is to ensure that the tapewill contain the value đč(đ‘„) at the end of the computation. Specifically,a computation of a Turing Machine 𝑀 with 𝑘 states and alphabet ÎŁ oninput đ‘„ ∈ 0, 1∗ proceeds as follows:

‱ Initially the machine is at state 0 (known as the “starting state”)and the tape is initialized to ▷, đ‘„0, 
 , đ‘„đ‘›âˆ’1,∅,∅, 
. We use thesymbol ▷ to denote the beginning of the tape, and the symbol ∅ todenote an empty cell. We will always assume that the alphabet ÎŁ isa (potentially strict) superset of ▷,∅, 0, 1.

‱ The location 𝑖 to which the machine points to is set to 0.‱ At each step, the machine reads the symbol 𝜎 = 𝑇 [𝑖] that is in the𝑖𝑡ℎ location of the tape, and based on this symbol and its state 𝑠

decides on:

– What symbol 𝜎â€Č to write on the tape– Whether to move Left (i.e., 𝑖 ← 𝑖 − 1), Right (i.e., 𝑖 ← 𝑖 + 1), Stay

in place, or Halt the computation.– What is going to be the new state 𝑠 ∈ [𝑘]

‱ The set of rules the Turing machine follows is known as its transi-tion function.

Page 254: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

254 introduction to theoretical computer science

Figure 7.6: The components of a Turing Machine. Notehow they correspond to the general components ofalgorithms as described in Fig. 7.1.

‱ When the machine halts then its output is the binary string ob-tained by reading the tape from the beginning until the head posi-tion, dropping all symbols such as ▷, ∅, etc. that are not either 0 or1.

7.1.1 Extended example: A Turing machine for palindromesLet PAL (for palindromes) be the function that on input đ‘„ ∈ 0, 1∗,outputs 1 if and only if đ‘„ is an (even length) palindrome, in the sensethat đ‘„ = đ‘€0 ⋯ đ‘€đ‘›âˆ’1đ‘€đ‘›âˆ’1đ‘€đ‘›âˆ’2 ⋯ đ‘€0 for some 𝑛 ∈ ℕ and đ‘€ ∈ 0, 1𝑛.

We now show a Turing Machine 𝑀 that computes PAL. To specify𝑀 we need to specify (i) 𝑀 ’s tape alphabet ÎŁ which should contain atleast the symbols 0,1, ▷ and ∅, and (ii) 𝑀 ’s transition function whichdetermines what action 𝑀 takes when it reads a given symbol while itis in a particular state.

In our case, 𝑀 will use the alphabet 0, 1, ▷,∅, × and will have𝑘 = 14 states. Though the states are simply numbers between 0 and𝑘 − 1, for convenience we will give them the following labels:

State Label0 START1 RIGHT_02 RIGHT_13 LOOK_FOR_04 LOOK_FOR_15 RETURN6 REJECT7 ACCEPT8 OUTPUT_09 OUTPUT_110 0_AND_BLANK11 1_AND_BLANK12 BLANK_AND_STOP

We describe the operation of our Turing Machine 𝑀 in words:

‱ 𝑀 starts in state START and will go right, looking for the first sym-bol that is 0 or 1. If we find ∅ before we hit such a symbol then wewill move to the OUTPUT_1 state that we describe below.

‱ Once 𝑀 finds such a symbol 𝑏 ∈ 0, 1, 𝑀 deletes 𝑏 from the tapeby writing the × symbol, it enters either the RIGHT_0 or RIGHT_1mode according to the value of 𝑏 and starts moving rightwardsuntil it hits the first ∅ or × symbol.

Page 255: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 255

‱ Once we find this symbol we go into the state LOOK_FOR_0 orLOOK_FOR_1 depending on whether we were in the state RIGHT_0or RIGHT_1 and make one left move.

‱ In the state LOOK_FOR_𝑏, we check whether the value on the tape is𝑏. If it is, then we delete it by changing its value to ×, and move tothe state RETURN. Otherwise, we change to the OUTPUT_0 state.

‱ The RETURN state means we go back to the beginning. Specifically,we move leftward until we hit the first symbol that is not 0 or 1, inwhich case we change our state to START.

‱ The OUTPUT_𝑏 states mean that we are going to output the value 𝑏.In both these states we go left until we hit ▷. Once we do so, wemake a right step, and change to the 1_AND_BLANK or 0_AND_BLANKstates respectively. In the latter states, we write the correspondingvalue, and then move right and change to the BLANK_AND_STOPstate, in which we write ∅ to the tape and halt.

The above description can be turned into a table describing for eachone of the 13 ⋅ 5 combination of state and symbol, what the Turingmachine will do when it is in that state and it reads that symbol. Thistable is known as the transition function of the Turing machine.

7.1.2 Turing machines: a formal definition

Figure 7.7: A Turing machine has access to a tape ofunbounded length. At each point in the execution,the machine can read a single symbol of the tape,and based on that and its current state, write a newsymbol, update the tape, decide whether to move left,right, stay, or halt.

The formal definition of Turing machines is as follows:

Definition 7.1 — Turing Machine. A (one tape) Turing machine with 𝑘states and alphabet ÎŁ ⊇ 0, 1, ▷,∅ is represented by a transitionfunction 𝛿𝑀 ∶ [𝑘] × ÎŁ → [𝑘] × ÎŁ × L, R, S, H.

Page 256: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

256 introduction to theoretical computer science

For every đ‘„ ∈ 0, 1∗, the output of 𝑀 on input đ‘„, denoted by𝑀(đ‘„), is the result of the following process:

‱ We initialize 𝑇 to be the sequence ▷, đ‘„0, đ‘„1, 
 , đ‘„đ‘›âˆ’1,∅,∅, 
,where 𝑛 = |đ‘„|. (That is, 𝑇 [0] = ▷, 𝑇 [𝑖 + 1] = đ‘„đ‘– for 𝑖 ∈ [𝑛], and𝑇 [𝑖] = ∅ for 𝑖 > 𝑛.)

‱ We also initialize 𝑖 = 0 and 𝑠 = 0.‱ We then repeat the following process:

1. Let (𝑠â€Č, 𝜎â€Č, đ·) = 𝛿𝑀(𝑠, 𝑇 [𝑖]).2. Set 𝑠 → 𝑠â€Č, 𝑇 [𝑖] → 𝜎â€Č.3. If đ· = R then set 𝑖 → 𝑖+1, if đ· = L then set 𝑖 → max𝑖−1, 0.

(If đ· = S then we keep 𝑖 the same.)4. If đ· = H then halt.

‱ If the process above halts, then 𝑀 ’s output, denoted by 𝑀(đ‘„),is the string 𝑩 ∈ 0, 1∗ obtained by concatenating all the sym-bols in 0, 1 in positions 𝑇 [0], 
 , 𝑇 [𝑖] where 𝑖 is the final headposition.

‱ If The Turing machine does not halt then we denote 𝑀(đ‘„) = ⊄.

PYou should make sure you see why this formal def-inition corresponds to our informal description ofa Turing Machine. To get more intuition on TuringMachines, you can explore some of the online avail-able simulators such as Martin Ugarte’s, AnthonyMorphett’s, or Paul Rendell’s.

One should not confuse the transition function 𝛿𝑀 of a Turing ma-chine 𝑀 with the function that the machine computes. The transitionfunction 𝛿𝑀 is a finite function, with 𝑘|ÎŁ| inputs and 4𝑘|ÎŁ| outputs.(Can you see why?) The machine can compute an infinite function đčthat takes as input a string đ‘„ ∈ 0, 1∗ of arbitrary length and mightalso produce an arbitrary length string as output.

In our formal definition, we identified the machine 𝑀 with its tran-sition function 𝛿𝑀 since the transition function tells us everythingwe need to know about the Turing machine, and hence serves as agood mathematical representation of it. This choice of representa-tion is somewhat arbitrary, and is based on our convention that thestate space is always the numbers 0, 
 , 𝑘 − 1 with 0 as the startingstate. Other texts use different conventions and so their mathematical

Page 257: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 257

definition of a Turing machine might look superficially different, butthese definitions describe the same computational process and hasthe same computational powers. See Section 7.7 for a comparison be-tween Definition 7.1 and the way Turing Machines are defined in textssuch as Sipser [Sip97]. These definitions are equivalent despite theirsuperficial differences.

7.1.3 Computable functionsWe now turn to making one of the most important definitions in thisbook, that of computable functions.

Definition 7.2 — Computable functions. Let đč ∶ 0, 1∗ → 0, 1∗ bea (total) function and let 𝑀 be a Turing machine. We say that 𝑀computes đč if for every đ‘„ ∈ 0, 1∗, 𝑀(đ‘„) = đč(đ‘„).

We say that a function đč is computable if there exists a Turingmachine 𝑀 that computes it.

Defining a function “computable” if and only if it can be computedby a Turing machine might seem “reckless” but, as we’ll see in Chap-ter 8, it turns out that being computable in the sense of Definition 7.2is equivalent to being computable in essentially any reasonable modelof computation. This is known as the Church-Turing Thesis. (Unlikethe extended Church-Turing Thesis which we discussed in Section 5.6,the Church-Turing thesis itself is widely believed and there are nocandidate devices that attack it.)

Big Idea 9 We can precisely define what it means for a function tobe computable by any possible algorithm.

This is a good point to remind the reader that functions are not thesame as programs:

Functions ≠ Programs . (7.1)A Turing machine (or program) 𝑀 can compute some functionđč , but it is not the same as đč . In particular there can be more than

one program to compute the same function. Being computable is aproperty of functions, not of machines.

We will often pay special attention to functions đč ∶ 0, 1∗ → 0, 1that have a single bit of output. Hence we give a special name for theset of functions of this form that are computable.

Definition 7.3 — The class R. We define R be the set of all computablefunctions đč ∶ 0, 1∗ → 0, 1.

Page 258: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

258 introduction to theoretical computer science

1 A partial function đč from a set 𝐮 to a set đ” is afunction that is only defined on a subset of 𝐮, (seeSection 1.4.3). We can also think of such a function asmapping 𝐮 to đ” âˆȘ ⊄ where ⊄ is a special “failure”symbol such that đč(𝑎) = ⊄ indicates the function đčis not defined on 𝑎.

RRemark 7.4 — Functions vs. languages. As discussedin Section 6.1.2, many texts use the terminology of“languages” rather than functions to refer to compu-tational tasks. A Turing machine 𝑀 decides a language𝐿 if for every input đ‘„ ∈ 0, 1∗, 𝑀(đ‘„) outputs 1 ifand only if đ‘„ ∈ 𝐿. This is equivalent to computingthe Boolean function đč ∶ 0, 1∗ → 0, 1 defined asđč(đ‘„) = 1 iff đ‘„ ∈ 𝐿. A language 𝐿 is decidable if thereis a Turing machine 𝑀 that decides it. For historicalreasons, some texts also call such a language recursive(which is the reason that the letter R is often usedto denote the set of computable Boolean functions /decidable languages defined in Definition 7.3).In this book we stick to the terminology of functionsrather than languages, but all definitions and resultscan be easily translated back and forth by using theequivalence between the function đč ∶ 0, 1∗ → 0, 1and the language 𝐿 = đ‘„ ∈ 0, 1∗ | đč (đ‘„) = 1.

7.1.4 Infinite loops and partial functionsOne crucial difference between circuits/straight-line programs andTuring machines is the following. Looking at a NAND-CIRC program𝑃 , we can always tell how many inputs and how many outputs it has(by simply looking at the X and Y variables). Furthermore, we areguaranteed that if we invoke 𝑃 on any input then some output will beproduced.

In contrast, given any Turing machine 𝑀 , we cannot determinea priori the length of the output. In fact, we don’t even know if anoutput would be produced at all! For example, it is very easy to comeup with a Turing machine whose transition function never outputs Hand hence never halts.

If a machine 𝑀 fails to stop and produce an output on some aninput đ‘„, then it cannot compute any total function đč , since clearly oninput đ‘„, 𝑀 will fail to output đč(đ‘„). However, 𝑀 can still compute apartial function.1

For example, consider the partial function DIV that on input a pair(𝑎, 𝑏) of natural numbers, outputs ⌈𝑎/𝑏⌉ if 𝑏 > 0, and is undefinedotherwise. We can define a Turing machine 𝑀 that computes DIV oninput 𝑎, 𝑏 by outputting the first 𝑐 = 0, 1, 2, 
 such that 𝑐𝑏 ≄ 𝑎. If 𝑎 > 0and 𝑏 = 0 then the machine 𝑀 will never halt, but this is OK, sinceDIV is undefined on such inputs. If 𝑎 = 0 and 𝑏 = 0, the machine 𝑀will output 0, which is also OK, since we don’t care about what theprogram outputs on inputs on which DIV is undefined. Formally, wedefine computability of partial functions as follows:

Page 259: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 259

Definition 7.5 — Computable (partial or total) functions. Let đč be either atotal or partial function mapping 0, 1∗ to 0, 1∗ and let 𝑀 be aTuring machine. We say that 𝑀 computes đč if for every đ‘„ ∈ 0, 1∗on which đč is defined, 𝑀(đ‘„) = đč(đ‘„). We say that a (partial ortotal) function đč is computable if there is a Turing machine thatcomputes it.

Note that if đč is a total function, then it is defined on every đ‘„ ∈0, 1∗ and hence in this case, Definition 7.5 is identical to Defini-tion 7.2.

RRemark 7.6 — Bot symbol. We often use ⊄ as our spe-cial “failure symbol”. If a Turing machine 𝑀 fails tohalt on some input đ‘„ ∈ 0, 1∗ then we denote this by𝑀(đ‘„) = ⊄. This does not mean that 𝑀 outputs someencoding of the symbol ⊄ but rather that 𝑀 entersinto an infinite loop when given đ‘„ as input.If a partial function đč is undefined on đ‘„ then we canalso write đč(đ‘„) = ⊄. Therefore one might thinkthat Definition 7.5 can be simplified to requiring that𝑀(đ‘„) = đč(đ‘„) for every đ‘„ ∈ 0, 1∗, which would implythat for every đ‘„, 𝑀 halts on đ‘„ if and only if đč is de-fined on đ‘„. However this is not the case: for a TuringMachine 𝑀 to compute a partial function đč it is notnecessary for 𝑀 to enter an infinite loop on inputs đ‘„on which đč is not defined. All that is needed is for 𝑀to output đč(đ‘„) on đ‘„â€™s on which đč is defined: on otherinputs it is OK for 𝑀 to output an arbitrary value suchas 0, 1, or anything else, or not to halt at all. To borrowa term from the C programming language, on inputs đ‘„on which đč is not defined, what 𝑀 does is “undefinedbehavior”.

7.2 TURING MACHINES AS PROGRAMMING LANGUAGES

The name “Turing machine”, with its “tape” and “head” evokes aphysical object, while in contrast we think of a program as a pieceof text. But we can think of a Turing machine as a program as well.For example, consider the Turing Machine 𝑀 of Section 7.1.1 thatcomputes the function PAL such that PAL(đ‘„) = 1 iff đ‘„ is a palindrome.We can also describe this machine as a program using the Python-likepseudocode of the form below

# Gets an array Tape initialized to# [">", x_0 , x_1 , .... , x_(n-1), "", "", ...]# At the end of the execution, Tape[1] is equal to 1# if x is a palindrome and is equal to 0 otherwise

Page 260: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

260 introduction to theoretical computer science

2 Most programming languages use arrays of fixedsize, while a Turing machine’s tape is unbounded. Butof course there is no need to store an infinite numberof ∅ symbols. If you want, you can think of the tapeas a list that starts off just long enough to store theinput, but is dynamically grown in size as the Turingmachine’s head explores new positions.

def PAL(Tape):head = 0state = 0 # STARTwhile (state != 12):

if (state == 0 && Tape[head]=='0'):state = 3 # LOOK_FOR_0Tape[head] = 'x'head += 1 # move right

if (state==0 && Tape[head]=='1')state = 4 # LOOK_FOR_1Tape[head] = 'x'head += 1 # move right

... # more if statements here

The particular details of this program are not important. What mat-ters is that we can describe Turing machines as programs. Moreover,note that when translating a Turing machine into a program, the tapebecomes a list or array that can hold values from the finite set Σ.2 Thehead position can be thought of as an integer valued variable that canhold integers of unbounded size. The state is a local register that canhold one of a fixed number of values in [𝑘].

More generally we can think of every Turing Machine 𝑀 as equiva-lent to a program similar to the following:

# Gets an array Tape initialized to# [">", x_0 , x_1 , .... , x_(n-1), "", "", ...]def M(Tape):

state = 0i = 0 # holds head locationwhile (True):

# Move head, modify state, write to tape# based on current state and cell at head# below are just examples for how program looks

for a particular transition functionif Tape[i]=="0" and state==7: #

ÎŽ_M(7,"0")=(19,"1","R")i += 1Tape[i]="1"state = 19

elif Tape[i]==">" and state == 13: #ÎŽ_M(13,">")=(15,"0","S")Tape[i]="0"state = 15

elif ......

Page 261: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 261

elif Tape[i]==">" and state == 29: #ÎŽ_M(29,">")=(.,.,"H")break # Halt

If we wanted to use only Boolean (i.e., 0/1-valued) variables thenwe can encode the state variables using ⌈log 𝑘⌉ bits. Similarly, wecan represent each element of the alphabet Σ using ℓ = ⌈log |Σ|⌉ bitsand hence we can replace the Σ-valued array Tape[] with ℓ Boolean-valued arrays Tape0[],
, Tape(ℓ − 1)[].7.2.1 The NAND-TM Programming languageWe now introduce the NAND-TM programming language, which aimsto capture the power of a Turing machine in a programming languageformalism. Just like the difference between Boolean circuits and Tur-ing Machines, the main difference between NAND-TM and NAND-CIRC is that NAND-TM models a single uniform algorithm that cancompute a function that takes inputs of arbitrary lengths. To do so, weextend the NAND-CIRC programming language with two constructs:

‱ Loops: NAND-CIRC is a straight-line programming language- aNAND-CIRC program of 𝑠 lines takes exactly 𝑠 steps of computa-tion and hence in particular cannot even touch more than 3𝑠 vari-ables. Loops allow us to capture in a short program the instructionsfor a computation that can take an arbitrary amount of time.

‱ Arrays: A NAND-CIRC program of 𝑠 lines touches at most 3𝑠 vari-ables. While we can use variables with names such as Foo_17 orBar[22], they are not true arrays, since the number in the identifieris a constant that is “hardwired” into the program.

Figure 7.8: A NAND-TM program has scalar variablesthat can take a Boolean value, array variables thathold a sequence of Boolean values, and a specialindex variable i that can be used to index the arrayvariables. We refer to the i-th value of the arrayvariable Spam using Spam[i]. At each iteration ofthe program the index variable can be incrementedor decremented by one step using the MODANDJMPoperation.

Thus a good way to remember NAND-TM is using the followinginformal equation:

NAND-TM = NAND-CIRC + loops + arrays (7.2)

Page 262: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

262 introduction to theoretical computer science

RRemark 7.7 — NAND-CIRC + loops + arrays = every-thing.. As we will see, adding loops and arrays toNAND-CIRC is enough to capture the full power ofall programming languages! Hence we could replace“NAND-TM” with any of Python, C, Javascript, OCaml,etc. in the lefthand side of (7.2). But we’re gettingahead of ourselves: this issue will be discussed inChapter 8.

Concretely, the NAND-TM programming language adds the fol-lowing features on top of NAND-CIRC (see Fig. 7.8):

‱ We add a special integer valued variable i. All other variables inNAND-TM are Boolean valued (as in NAND-CIRC).

‱ Apart from i NAND-TM has two kinds of variables: scalars andarrays. Scalar variables hold one bit (just as in NAND-CIRC). Arrayvariables hold an unbounded number of bits. At any point in thecomputation we can access the array variables at the location in-dexed by i using Foo[i]. We cannot access the arrays at locationsother than the one pointed to by i.

‱ We use the convention that arrays always start with a capital letter,and scalar variables (which are never indexed with i) start withlowercase letters. Hence Foo is an array and bar is a scalar variable.

‱ The input and output X and Y are now considered arrays with val-ues of zeroes and ones. (There are also two other special arraysX_nonblank and Y_nonblank, see below.)

‱ We add a special MODANDJUMP instruction that takes two booleanvariables 𝑎, 𝑏 as input and does the following:

– If 𝑎 = 1 and 𝑏 = 1 then MODANDJUMP(𝑎, 𝑏) increments i by oneand jumps to the first line of the program.

– If 𝑎 = 0 and 𝑏 = 1 then MODANDJUMP(𝑎, 𝑏) decrements i by oneand jumps to the first line of the program. (If i is already equalto 0 then it stays at 0.)

– If 𝑎 = 1 and 𝑏 = 0 then MODANDJUMP(𝑎, 𝑏) jumps to the first line ofthe program without modifying i.

– If 𝑎 = 𝑏 = 0 then MODANDJUMP(𝑎, 𝑏) halts execution of theprogram.

‱ The MODANDJUMP instruction always appears in the last line of aNAND-TM program and nowhere else.

Page 263: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 263

Default values. We need one more convention to handle “default val-ues”. Turing machines have the special symbol ∅ to indicate that tapelocation is “blank” or “uninitialized”. In NAND-TM there is no suchsymbol, and all variables are Boolean, containing either 0 or 1. Allvariables and locations of arrays are default to 0 if they have not beeninitialized to another value. To keep track of whether a 0 in an arraycorresponds to a true zero or to an uninitialized cell, a programmercan always add to an array Foo a “companion array” Foo_nonblankand set Foo_nonblank[i] to 1 whenever the i’th location is initial-ized. In particular we will use this convention for the input and out-put arrays X and Y. A NAND-TM program has four special arrays X,X_nonblank, Y, and Y_nonblank. When a NAND-TM program is exe-cuted on input đ‘„ ∈ 0, 1∗ of length 𝑛, the first 𝑛 cells of the array X areinitialized to đ‘„0, 
 , đ‘„đ‘›âˆ’1 and the first 𝑛 cells of the array X_nonblankare initialized to 1. (All uninitialized cells default to 0.) The output ofa NAND-TM program is the string Y[0], 
, Y[𝑚 − 1] where 𝑚 is thesmallest integer such that Y_nonblank[𝑚]= 0. A NAND-TM programgets called with X and X_nonblank initialized to contain the input, andwrites to Y and Y_nonblank to produce the output.

Formally, NAND-TM programs are defined as follows:

Definition 7.8 — NAND-TM programs. A NAND-TM program consists ofa sequence of lines of the form foo = NAND(bar,blah) endingwith a line of the form MODANDJMP(foo,bar), where foo,bar,blahare either scalar variables (sequences of letters, digits, and under-scores) or array variables of the form Foo[i] (starting with capitalletter and indexed by i). The program has the array variables X,X_nonblank, Y, Y_nonblank and the index variable i built in, andcan use additional array and scalar variables.

If 𝑃 is a NAND-TM program and đ‘„ ∈ 0, 1∗ is an input then anexecution of 𝑃 on đ‘„ is the following process:

1. The arrays X and X_nonblank are initialized by X[𝑖]= đ‘„đ‘– andX_nonblank[𝑖]= 1 for all 𝑖 ∈ [|đ‘„|]. All other variables and cellsare initialized to 0. The index variable i is also initialized to 0.

2. The program is executed line by line, when the last line MODAND-JMP(foo,bar) is executed then we do as follows:

a. If foo= 1 and bar= 0 then jump to the first line without mod-ifying the value of i.

b. If foo= 1 and bar= 1 then increment i by one and jump tothe first line.

Page 264: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

264 introduction to theoretical computer science

c. If foo= 0 and bar= 1 then decrement i by one (unless it is al-ready zero) and jump to the first line.

d. If foo= 0 and bar= 0 then halt and output Y[0], 
, Y[𝑚 − 1]where 𝑚 is the smallest integer such that Y_nonblank[𝑚]= 0.

7.2.2 Sneak peak: NAND-TM vs Turing machinesAs the name implies, NAND-TM programs are a direct implemen-tation of Turing machines in programming language form. We willshow the equivalence below but you can already see how the compo-nents of Turing machines and NAND-TM programs correspond to oneanother:

Table 7.2: Turing Machine and NAND-TM analogs

Turing Machine NAND-TM programState: single register thattakes values in [𝑘] Scalar variables: Several variables

such as foo, bar etc.. each takingvalues in 0, 1.

Tape: One tape containingvalues in a finite set Σ.Potentially infinite but 𝑇 [𝑡]defaults to ∅ for all locations𝑡 that have not beenaccessed.

Arrays: Several arrays such as Foo,Bar etc.. for each such array Arr andindex 𝑗, the value of Arr at position 𝑗is either 0 or 1. The value defaults to0 for position that have not beenwritten to.

Head location: A number𝑖 ∈ ℕ that encodes theposition of the head.

Index variable: The variable i that canbe used to access the arrays.

Accessing memory: At everystep the Turing machine hasaccess to its local state, butcan only access the tape atthe position of the currenthead location.

Accessing memory: At every step aNAND-TM program has access to allthe scalar variables, but can onlyaccess the arrays at the location i ofthe index variable

Control of location: In eachstep the machine can movethe head location by at mostone position.

Control of index variable: In eachiteration of its main loop theprogram can modify the index i byat most one.

7.2.3 ExamplesWe now present some examples of NAND-TM programs.

Page 265: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 265

Example 7.9 — Increment in NAND-TM. The following is a NAND-TMprogram to compute the increment function. That is, INC ∶ 0, 1∗ →0, 1∗ such that for every đ‘„ ∈ 0, 1𝑛, INC(đ‘„) is the 𝑛 + 1 bit longstring 𝑩 such that if 𝑋 = ∑𝑛−1𝑖=0 đ‘„đ‘– ⋅ 2𝑖 is the number represented byđ‘„, then 𝑩 is the (least-significant digit first) binary representation ofthe number 𝑋 + 1.

We start by showing the program using the “syntactic sugar”we’ve seen before of using shorthand for some NAND-CIRC pro-grams we have seen before to compute simple functions such asIF, XOR and AND (as well as the constant one function as well as thefunction COPY that just maps a bit to itself).

carry = IF(started,carry,one(started))started = one(started)Y[i] = XOR(X[i],carry)carry = AND(X[i],carry)Y_nonblank[i] = one(started)MODANDJUMP(X_nonblank[i],X_nonblank[i])

The above is not, strictly speaking, a valid NAND-TM program.If we “open up” all of the syntactic sugar, we get the following“sugar free” valid program to compute the same function.

temp_0 = NAND(started,started)temp_1 = NAND(started,temp_0)temp_2 = NAND(started,started)temp_3 = NAND(temp_1,temp_2)temp_4 = NAND(carry,started)carry = NAND(temp_3,temp_4)temp_6 = NAND(started,started)started = NAND(started,temp_6)temp_8 = NAND(X[i],carry)temp_9 = NAND(X[i],temp_8)temp_10 = NAND(carry,temp_8)Y[i] = NAND(temp_9,temp_10)temp_12 = NAND(X[i],carry)carry = NAND(temp_12,temp_12)temp_14 = NAND(started,started)Y_nonblank[i] = NAND(started,temp_14)MODANDJUMP(X_nonblank[i],X_nonblank[i])

Page 266: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

266 introduction to theoretical computer science

Example 7.10 — XOR in NAND-TM. The following is a NAND-TM pro-gram to compute the XOR function on inputs of arbitrary length.That is XOR ∶ 0, 1∗ → 0, 1 such that XOR(đ‘„) = ∑|đ‘„|−1𝑖=0 đ‘„đ‘–mod 2 for every đ‘„ ∈ 0, 1∗. Once again, we use a certain “syn-tactic sugar”. Specifically, we access the arrays X and Y at theirzero-th entry, while NAND-TM only allows access to arrays in thecoordinate of the variable i.

temp_0 = NAND(X[0],X[0])Y_nonblank[0] = NAND(X[0],temp_0)temp_2 = NAND(X[i],Y[0])temp_3 = NAND(X[i],temp_2)temp_4 = NAND(Y[0],temp_2)Y[0] = NAND(temp_3,temp_4)MODANDJUMP(X_nonblank[i],X_nonblank[i])

To transform the program above to a valid NAND-TM program,we can transform references such as X[0] and Y[0] to scalar vari-ables x_0 and y_0 (similarly we can transform any reference of theform Foo[17] or Bar[15] to scalars such as foo_17 and bar_15).We then need to add code to load the value of X[0] to x_0 andsimilarly to write to Y[0] the value of y_0, but this is not hard todo. Using the fact that variables are initialized to zero by default,we can create a variable init which will be set to 1 at the end ofthe first iteration and not changed since then. We can then add anarray Atzero and code that will modify Atzero[i] to 1 if init is0 and otherwise leave it as it is. This will ensure that Atzero[i] isequal to 1 if and only if i is set to zero, and allow the program toknow when we are at the zero-th location. Thus we can add codeto read and write to the corresponding scalars x_0, y_0 when weare at the zero-th location, and also code to move i to zero andthen halt at the end. Working this out fully is somewhat tedious,but can be a good exercise.

PWorking out the above two examples can go a longway towards understanding the NAND-TM language.See our GitHub repository for a full specification ofthe NAND-TM language.

Page 267: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 267

7.3 EQUIVALENCE OF TURING MACHINES AND NAND-TM PRO-GRAMS

Given the above discussion, it might not be surprising that Turingmachines turn out to be equivalent to NAND-TM programs. Indeed,we designed the NAND-TM language to have this property. Never-theless, this is an important result, and the first of many other suchequivalence results we will see in this book.

Theorem 7.11 — Turing machines and NAND-TM programs are equivalent. Forevery đč ∶ 0, 1∗ → 0, 1∗, đč is computable by a NAND-TM pro-gram 𝑃 if and only if there is a Turing Machine 𝑀 that computesđč .

Proof Idea:

To prove such an equivalence theorem, we need to show two di-rections. We need to be able to (1) transform a Turing machine 𝑀 toa NAND-TM program 𝑃 that computes the same function as 𝑀 and(2) transform a NAND-TM program 𝑃 into a Turing machine 𝑀 thatcomputes the same function as 𝑃 .

The idea of the proof is illustrated in Fig. 7.9. To show (1), givena Turing machine 𝑀 , we will create a NAND-TM program 𝑃 thatwill have an array Tape for the tape of 𝑀 and scalar (i.e., non array)variable(s) state for the state of 𝑀 . Specifically, since the state of aTuring machine is not in 0, 1 but rather in a larger set [𝑘], we will use⌈log 𝑘⌉ variables state_0 , 
, state_⌈log 𝑘⌉ − 1 variables to store therepresentation of the state. Similarly, to encode the larger alphabet Σof the tape, we will use ⌈log |Σ|⌉ arrays Tape_0 , 
, Tape_⌈log |Σ|⌉ − 1,such that the 𝑖𝑡ℎ location of these arrays encodes the 𝑖𝑡ℎ symbol in thetape for every tape. Using the fact that every function can be computedby a NAND-CIRC program, we will be able to compute the transitionfunction of 𝑀 , replacing moving left and right by decrementing andincrementing i respectively.

We show (2) using very similar ideas. Given a program 𝑃 thatuses 𝑎 array variables and 𝑏 scalar variables, we will create a Turingmachine with about 2𝑏 states to encode the values of scalar variables,and an alphabet of about 2𝑎 so we can encode the arrays using ourtape. (The reason the sizes are only “about” 2𝑎 and 2𝑏 is that we willneed to add some symbols and steps for bookkeeping purposes.) TheTuring Machine 𝑀 will simulate each iteration of the program 𝑃 byupdating its state and tape accordingly.⋆Proof of Theorem 7.11. We start by proving the “if” direction of The-orem 7.11. Namely we show that given a Turing machine 𝑀 , we can

Page 268: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

268 introduction to theoretical computer science

Figure 7.9: Comparing a Turing Machine to a NAND-TM program. Both have an unbounded memorycomponent (the tape for a Turing machine, and the ar-rays for a NAND-TM program), as well as a constantlocal memory (state for a Turing machine, and scalarvariables for a NAND-TM program). Both can onlyaccess at each step one location of the unboundedmemory, this is the “head” location for a Turingmachine, and the value of the index variable i for aNAND-TM program.

find a NAND-TM program 𝑃𝑀 such that for every input đ‘„, if 𝑀 haltson input đ‘„ with output 𝑩 then 𝑃𝑀(đ‘„) = 𝑩. Since our goal is just toshow such a program 𝑃𝑀 exists, we don’t need to write out the fullcode of 𝑃𝑀 line by line, and can take advantage of our various “syn-tactic sugar” in describing it.

The key observation is that by Theorem 4.12 we can compute everyfinite function using a NAND-CIRC program. In particular, considerthe transition function 𝛿𝑀 ∶ [𝑘] × ÎŁ → [𝑘] × ÎŁ × L, R of our TuringMachine. We can encode the its components as follows:

‱ We encode [𝑘] using 0, 1ℓ and ÎŁ using 0, 1ℓâ€Č , where ℓ = ⌈log 𝑘⌉and ℓâ€Č = ⌈log |ÎŁ|⌉.

‱ We encode the set L, R, S, H using 0, 12. We will choose theencode L ↩ 01, R ↩ 11, S ↩ 10, H ↩ 00. (This convenientlycorresponds to the semantics of the MODANDJUMP operation.)

Hence we can identify 𝛿𝑀 with a function 𝑀 ∶ 0, 1ℓ+ℓâ€Č →0, 1ℓ+ℓâ€Č+2, mapping strings of length ℓ + ℓâ€Č to strings of lengthℓ + ℓâ€Č + 2. By Theorem 4.12 there exists a finite length NAND-CIRCprogram ComputeM that computes this function 𝑀 . The NAND-TMprogram to simulate 𝑀 will essentially be the following:

Page 269: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 269

Algorithm 7.12 — NAND-TM program to simulate TM 𝑀 .

Input: đ‘„ ∈ 0, 1∗Output: 𝑀(đ‘„) if 𝑀 halts on đ‘„. Otherwise go into infinite

loop1: # We use variables state_0 
 state_ℓ − 1 to encode 𝑀 ’s

state2: # We use arrays Tape_0[] 
 Tape_ℓâ€Č − 1[] to encode 𝑀 ’s

tape3: # We omit the initial and final ”book keeping” to copy

Input: to Tape and copyOutput: from Tape4: # Use the fact that transition is finite and computable by

NAND-CIRC program:5: state_0 
 state_ℓ − 1, Tape_0[i]
 Tape_ℓâ€Č − 1[i],

dir0,dir1 ← TRANSITION( state_0 
 state_ℓ − 1,Tape_0[i]
 Tape_ℓâ€Č − 1[i], dir0,dir1 )

6: MODANDJMP(dir0,dir1)

Every step of the main loop of the above program perfectly mimicsthe computation of the Turing Machine 𝑀 and so the program carriesout exactly the definition of computation by a Turing Machine as perDefinition 7.1.

For the other direction, suppose that 𝑃 is a NAND-TM programwith 𝑠 lines, ℓ scalar variables, and ℓâ€Č array variables. We will showthat there exists a Turing machine 𝑀𝑃 with 2ℓ + đ¶ states and alphabetÎŁ of size đ¶â€Č + 2ℓâ€Č that computes the same functions as 𝑃 (where đ¶, đ¶â€Čare some constants to be determined later).

Specifically, consider the function 𝑃 ∶ 0, 1ℓ × 0, 1ℓâ€Č → 0, 1ℓ ×0, 1ℓâ€Č that on input the contents of 𝑃 ’s scalar variables and the con-tents of the array variables at location i in the beginning of an itera-tion, outputs all the new values of these variables at the last line of theiteration, right before the MODANDJUMP instruction is executed.

If foo and bar are the two variables that are used as input to theMODANDJUMP instruction, then this means that based on the values ofthese variables we can compute whether i will increase, decrease orstay the same, and whether the program will halt or jump back to thebeginning. Hence a Turing machine can simulate an execution of 𝑃 inone iteration using a finite function applied to its alphabet. The overalloperation of the Turing machine will be as follows:

1. The machine 𝑀𝑃 encodes the contents of the array variables of 𝑃in its tape, and the contents of the scalar variables in (part of) itsstate. Specifically, if 𝑃 has ℓ local variables and 𝑡 arrays, then thestate space of 𝑀 will be large enough to encode all 2ℓ assignments

Page 270: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

270 introduction to theoretical computer science

to the local variables and the alphabet Σ of 𝑀 will be large enoughto encode all 2𝑡 assignments for the array variables at each location.The head location corresponds to the index variable i.

2. Recall that every line of the program 𝑃 corresponds to reading andwriting either a scalar variable, or an array variable at the locationi. In one iteration of 𝑃 the value of i remains fixed, and so themachine 𝑀 can simulate this iteration by reading the values ofall array variables at i (which are encoded by the single symbolin the alphabet Σ located at the i-th cell of the tape) , reading thevalues of all scalar variables (which are encoded by the state), andupdating both. The transition function of 𝑀 can output L, S, Rdepending on whether the values given to the MODANDJMP operationare 01, 10 or 11 respectively.

3. When the program halts (i.e., MODANDJMP gets 00) then the Turingmachine will enter into a special loop to copy the results of the Yarray into the output and then halt. We can achieve this by adding afew more states.

The above is not a full formal description of a Turing Machine, butour goal is just to show that such a machine exists. One can see that𝑀𝑃 simulates every step of 𝑃 , and hence computes the same functionas 𝑃 .

RRemark 7.13 — Running time equivalence (optional). Ifwe examine the proof of Theorem 7.11 then we can seethat every iteration of the loop of a NAND-TM pro-gram corresponds to one step in the execution of theTuring machine. We will come back to this questionof measuring number of computation steps later inthis course. For now the main take away point is thatNAND-TM programs and Turing Machines are essen-tially equivalent in power even when taking runningtime into account.

7.3.1 Specification vs implementation (again)Once you understand the definitions of both NAND-TM programsand Turing Machines, Theorem 7.11 is fairly straightforward. Indeed,NAND-TM programs are not as much a different model from TuringMachines as they are simply a reformulation of the same model usingprogramming language notation. You can think of the difference be-tween a Turing machine and a NAND-TM program as the differencebetween representing a number using decimal or binary notation. In

Page 271: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 271

contrast, the difference between a function đč and a Turing machinethat computes đč is much more profound: it is like the difference be-tween the equation đ‘„2 + đ‘„ = 12 and the number 3 that is a solutionfor this equation. For this reason, while we take special care in distin-guishing functions from programs or machines, we will often identifythe two latter concepts. We will move freely between describing analgorithm as a Turing machine or as a NAND-TM program (as wellas some of the other equivalent computational models we will see inChapter 8 and beyond).

Table 7.3: Specification vs Implementation formalisms

Setting Specification ImplementationFinite com-putation

Functions mapping 0, 1𝑛 to0, 1𝑚 Circuits, Straightlineprograms

Infinitecomputa-tion

Functions mapping 0, 1∗ to0, 1 or to 0, 1∗. Algorithms, TuringMachines, Programs

7.4 NAND-TM SYNTACTIC SUGAR

Just like we did with NAND-CIRC in Chapter 4, we can use “syntacticsugar” to make NAND-TM programs easier to write. For starters, wecan use all of the syntactic sugar of NAND-CIRC, and so have accessto macro definitions and conditionals (i.e., if/then). But we can gobeyond this and achieve for example:

‱ Inner loops such as the while and for operations common to manyprogramming language.

‱ Multiple index variables (e.g., not just i but we can add j, k, etc.).

‱ Arrays with more than one dimension (e.g., Foo[i][j],Bar[i][j][k] etc.)

In all of these cases (and many others) we can implement the newfeature as mere “syntactic sugar” on top of standard NAND-TM,which means that the set of functions computable by NAND-TMwith this feature is the same as the set of functions computable bystandard NAND-TM. Similarly, we can show that the set of functionscomputable by Turing Machines that have more than one tape, ortapes of more dimensions than one, is the same as the set of functionscomputable by standard Turing machines.

Page 272: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

272 introduction to theoretical computer science

7.4.1 “GOTO” and inner loopsWe can implement more advanced looping constructs than the simpleMODANDJUMP. For example, we can implement GOTO. A GOTO statementcorresponds to jumping to a certain line in the execution. For example,if we have code of the form

"start": do fooGOTO("end")

"skip": do bar"end": do blah

then the program will only do foo and blah as when it reaches theline GOTO("end") it will jump to the line labeled with "end". We canachieve the effect of GOTO in NAND-TM using conditionals. In thecode below, we assume that we have a variable pc that can take stringsof some constant length. This can be encoded using a finite numberof Boolean variables pc_0, pc_1, 
, pc_𝑘 − 1, and so when we writebelow pc = "label" what we mean is something like pc_0 = 0,pc_1= 1, 
 (where the bits 0, 1, 
 correspond to the encoding of the finitestring "label" as a string of length 𝑘). We also assume that we haveaccess to conditional (i.e., if statements), which we can emulate usingsyntactic sugar in the same way as we did in NAND-CIRC.

To emulate a GOTO statement, we will first modify a program P ofthe form

do foodo bardo blah

to have the following form (using syntactic sugar for if):

pc = "line1"if (pc=="line1"):

do foopc = "line2"

if (pc=="line2"):do barpc = "line3"

if (pc=="line3"):do blah

These two programs do the same thing. The variable pc cor-responds to the “program counter” and tells the program whichline to execute next. We can see that if we wanted to emulate aGOTO("line3") then we could simply modify the instruction pc ="line2" to be pc = "line3".

Page 273: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 273

In NAND-CIRC we could only have GOTOs that go forward in thecode, but since in NAND-TM everything is encompassed within alarge outer loop, we can use the same ideas to implement GOTO’s thatcan go backwards, as well as conditional loops.

Other loops. Once we have GOTO, we can emulate all the standard loopconstructs such as while, do .. until or for in NAND-TM as well.For example, we can replace the code

while foo:do blah

do bar

with

"loop":if NOT(foo): GOTO("next")do blahGOTO("loop")

"next":do bar

RRemark 7.14 — GOTO’s in programming languages. TheGOTO statement was a staple of most early program-ming languages, but has largely fallen out of favor andis not included in many modern languages such asPython, Java, Javascript. In 1968, Edsger Dijsktra wrote afamous letter titled “Go to statement considered harm-ful.” (see also Fig. 7.10). The main trouble with GOTOis that it makes analysis of programs more difficultby making it harder to argue about invariants of theprogram.When a program contains a loop of the form:

for j in range(100):do something

do blah

you know that the line of code do blah can only bereached if the loop ended, in which case you knowthat j is equal to 100, and might also be able to argueother properties of the state of the program. In con-trast, if the program might jump to do blah from anyother point in the code, then it’s very hard for you asthe programmer to know what you can rely upon inthis code. As Dijkstra said, such invariants are impor-tant because “our intellectual powers are rather gearedto master static relations and .. our powers to visualizeprocesses evolving in time are relatively poorly developed”

Page 274: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

274 introduction to theoretical computer science

Figure 7.10: XKCD’s take on the GOTO statement.

and so “we should 
 do 
our utmost best to shorten theconceptual gap between the static program and the dynamicprocess.”That said, GOTO is still a major part of lower level lan-guages where it is used to implement higher levellooping constructs such as while and for loops.For example, even though Java doesn’t have a GOTOstatement, the Java Bytecode (which is a lower levelrepresentation of Java) does have such a statement.Similarly, Python bytecode has instructions such asPOP_JUMP_IF_TRUE that implement the GOTO function-ality, and similar instructions are included in manyassembly languages. The way we use GOTO to imple-ment a higher level functionality in NAND-TM isreminiscent of the way these various jump instructionsare used to implement higher level looping constructs.

7.5 UNIFORMITY, AND NAND VS NAND-TM (DISCUSSION)

While NAND-TM adds extra operations over NAND-CIRC, it is notexactly accurate to say that NAND-TM programs or Turing machinesare “more powerful” than NAND-CIRC programs or Boolean circuits.NAND-CIRC programs, having no loops, are simply not applicablefor computing functions with an unbounded number of inputs. Thus,to compute a function đč ∶ 0, 1∗ ∶→ 0, 1∗ using NAND-CIRC (orequivalently, Boolean circuits) we need a collection of programs/cir-cuits: one for every input length.

The key difference between NAND-CIRC and NAND-TM is thatNAND-TM allows us to express the fact that the algorithm for com-puting parities of length-100 strings is really the same one as the al-gorithm for computing parities of length-5 strings (or similarly thefact that the algorithm for adding 𝑛-bit numbers is the same for every𝑛, etc.). That is, one can think of the NAND-TM program for generalparity as the “seed” out of which we can grow NAND-CIRC programsfor length 10, length 100, or length 1000 parities as needed.

This notion of a single algorithm that can compute functions ofall input lengths is known as uniformity of computation and hencewe think of Turing machines / NAND-TM as uniform model of com-putation, as opposed to Boolean circuits or NAND-CIRC which is anonuniform model, where we have to specify a different program forevery input length.

Looking ahead, we will see that this uniformity leads to anothercrucial difference between Turing machines and circuits. Turing ma-chines can have inputs and outputs that are longer than the descrip-tion of the machine as a string and in particular there exists a Turingmachine that can “self replicate” in the sense that it can print its own

Page 275: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 275

code. This notion of “self replication”, and the related notion of “selfreference” is crucial to many aspects of computation, as well of courseto life itself, whether in the form of digital or biological programs.

For now, what you ought to remember is the following differencesbetween uniform and non uniform computational models:

‱ Non uniform computational models: Examples are NAND-CIRCprograms and Boolean circuits. These are models where each indi-vidual program/circuit can compute a finite function 𝑓 ∶ 0, 1𝑛 →0, 1𝑚. We have seen that every finite function can be computed bysome program/circuit. To discuss computation of an infinite func-tion đč ∶ 0, 1∗ → 0, 1∗ we need to allow a sequence 𝑃𝑛𝑛∈ℕ ofprograms/circuits (one for every input length), but this does notcapture the notion of a single algorithm to compute the function đč .

‱ Uniform computational models: Examples are Turing machines andNAND-TM programs. These are models where a single program/-machine can take inputs of arbitrary length and hence compute aninfinite function đč ∶ 0, 1∗ → 0, 1∗. The number of steps thata program/machine takes on some input is not a priori boundedin advance and in particular there is a chance that it will enter intoan infinite loop. Unlike the nonuniform case, we have not shownthat every infinite function can be computed by some NAND-TMprogram/Turing Machine. We will come back to this point in Chap-ter 9.

Chapter Recap

‱ Turing machines capture the notion of a single al-gorithm that can evaluate functions of every inputlength.

‱ They are equivalent to NAND-TM programs, whichadd loops and arrays to NAND-CIRC.

‱ Unlike NAND-CIRC or Boolean circuits, the num-ber of steps that a Turing machine takes on a giveninput is not fixed in advance. In fact, a Turing ma-chine or a NAND-TM program can enter into aninfinite loop on certain inputs, and not halt at all.

7.6 EXERCISES

Exercise 7.1 — Explicit NAND TM programming. Produce the code of a(syntactic-sugar free) NAND-TM program 𝑃 that computes the (un-bounded input length) Majority function 𝑀𝑎𝑗 ∶ 0, 1∗ → 0, 1 wherefor every đ‘„ ∈ 0, 1∗, 𝑀𝑎𝑗(đ‘„) = 1 if and only if ∑|đ‘„|𝑖=0 đ‘„đ‘– > |đ‘„|/2. Wesay “produce” rather than “write” because you do not have to write

Page 276: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

276 introduction to theoretical computer science

the code of 𝑃 by hand, but rather can use the programming languageof your choice to compute this code.

Exercise 7.2 — Computable functions examples. Prove that the followingfunctions are computable. For all of these functions, you do not haveto fully specify the Turing Machine or the NAND-TM program thatcomputes the function, but rather only prove that such a machine orprogram exists:

1. INC ∶ 0, 1∗ → 0, 1∗ which takes as input a representation of anatural number 𝑛 and outputs the representation of 𝑛 + 1.

2. ADD ∶ 0, 1∗ → 0, 1∗ which takes as input a representation ofa pair of natural numbers (𝑛, 𝑚) and outputs the representation of𝑛 + 𝑚.

3. MULT ∶ 0, 1∗ → 0, 1∗, which takes a representation of a pair ofnatural numbers (𝑛, 𝑚) and outputs the representation of 𝑛.

4. SORT ∶ 0, 1∗ → 0, 1∗ which takes as input the representation ofa list of natural numbers (𝑎0, 
 , 𝑎𝑛−1) and returns its sorted version(𝑏0, 
 , 𝑏𝑛−1) such that for every 𝑖 ∈ [𝑛] there is some 𝑗 ∈ [𝑛] with𝑏𝑖 = 𝑎𝑗 and 𝑏0 ≀ 𝑏1 ≀ ⋯ ≀ 𝑏𝑛−1.

Exercise 7.3 — Two index NAND-TM. Define NAND-TM’ to be the variant ofNAND-TM where there are two index variables i and j. Arrays can beindexed by either i or j. The operation MODANDJMP takes four variables𝑎, 𝑏, 𝑐, 𝑑 and uses the values of 𝑐, 𝑑 to decide whether to increment j,decrement j or keep it in the same value (corresponding to 01, 10, and00 respectively). Prove that for every function đč ∶ 0, 1∗ → 0, 1∗, đčis computable by a NAND-TM program if and only if đč is computableby a NAND-TM’ program.

Exercise 7.4 — Two tape Turing machines. Define a two tape Turing machineto be a Turing machine which has two separate tapes and two separateheads. At every step, the transition function gets as input the locationof the cells in the two tapes, and can decide whether to move eachhead independently. Prove that for every function đč ∶ 0, 1∗ →0, 1∗, đč is computable by a standard Turing Machine if and only if đčis computable by a two-tape Turing machine.

Exercise 7.5 — Two dimensional arrays. Define NAND-TM’ ’ to be the vari-ant of NAND-TM where just like NAND-TM’ defined in Exercise 7.3

Page 277: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 277

3 You can use the sequence R, L,R, R, L, L, R,R,R, L, L, L,
.

there are two index variables i and j, but now the arrays are two di-mensional and so we index an array Foo by Foo[i][j]. Prove that forevery function đč ∶ 0, 1∗ → 0, 1∗, đč is computable by a NAND-TMprogram if and only if đč is computable by a NAND-TM’ ’ program.

Exercise 7.6 — Two dimensional Turing machines. Define a two-dimensionalTuring machine to be a Turing machine in which the tape is two dimen-sional. At every step the machine can move Up, Down, Left, Right, orStay. Prove that for every function đč ∶ 0, 1∗ → 0, 1∗, đč is com-putable by a standard Turing Machine if and only if đč is computableby a two-dimensional Turing machine.

Exercise 7.7 Prove the following closure properties of the set R definedin Definition 7.3:

1. If đč ∈ R then the function đș(đ‘„) = 1 − đč(đ‘„) is in R.

2. If đč, đș ∈ R then the function đ»(đ‘„) = đč(đ‘„) √ đș(đ‘„) is in R.

3. If đč ∈ R then the function đč ∗ in in R where đč ∗ is defined as fol-lows: đč ∗(đ‘„) = 1 iff there exist some strings đ‘€0, 
 , đ‘€đ‘˜âˆ’1 such thatđ‘„ = đ‘€0đ‘€1 ⋯ đ‘€đ‘˜âˆ’1 and đč(đ‘€đ‘–) = 1 for every 𝑖 ∈ [𝑘].

4. If đč ∈ R then the function

đș(đ‘„) = âŽ§âŽšâŽ©âˆƒđ‘Šâˆˆ0,1|đ‘„|đč(đ‘„đ‘Š) = 10 otherwise(7.3)

is in R.

Exercise 7.8 — Oblivious Turing Machines (challenging). Define a Turing Ma-chine 𝑀 to be oblivious if its head movements are independent of itsinput. That is, we say that 𝑀 is oblivious if there exists an infinitesequence MOVE ∈ L, R, S∞ such that for every đ‘„ ∈ 0, 1∗, themovements of 𝑀 when given input đ‘„ (up until the point it halts, ifsuch point exists) are given by MOVE0,MOVE1,MOVE2, 
.

Prove that for every function đč ∶ 0, 1∗ → 0, 1∗, if đč is com-putable then it is computable by an oblivious Turing machine. Seefootnote for hint.3

Exercise 7.9 — Single vs multiple bit. Prove that for every đč ∶ 0, 1∗ →0, 1∗, the function đč is computable if and only if the following func-

Page 278: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

278 introduction to theoretical computer science

tion đș ∶ 0, 1∗ → 0, 1 is computable, where đș is defined as follows:đș(đ‘„, 𝑖, 𝜎) = ⎧⎚⎩đč(đ‘„)𝑖 𝑖 < |đč(đ‘„)|, 𝜎 = 01 𝑖 < |đč(đ‘„)|, 𝜎 = 10 𝑖 ≄ |đč(đ‘„)|

Exercise 7.10 — Uncomputability via counting. Recall that R is the set of alltotal functions from 0, 1∗ to 0, 1 that are computable by a Turingmachine (see Definition 7.3). Prove that R is countable. That is, provethat there exists a one-to-one map đ·đ‘Ąđ‘ ∶ R → ℕ. You can use theequivalence between Turing machines and NAND-TM programs.

Exercise 7.11 — Not every function is computable. Prove that the set of alltotal functions from 0, 1∗ → 0, 1 is not countable. You can use theresults of Section 2.4. (We will see an explicit uncomputable functionin Chapter 9.)

7.7 BIBLIOGRAPHICAL NOTES

Augusta Ada Byron, countess of Lovelace (1815-1852) lived a shortbut turbulent life, though is today most well known for her collabo-ration with Charles Babbage (see [Ste87] for a biography). Ada tookan immense interest in Babbage’s analytical engine, which we men-tioned in Chapter 3. In 1842-3, she translated from Italian a paper ofMenabrea on the engine, adding copious notes (longer than the paperitself). The quote in the chapter’s beginning is taken from Nota A inthis text. Lovelace’s notes contain several examples of programs for theanalytical engine, and because of this she has been called “the world’sfirst computer programmer” though it is not clear whether they werewritten by Lovelace or Babbage himself [Hol01]. Regardless, Ada wasclearly one of very few people (perhaps the only one outside of Bab-bage himself) to fully appreciate how significant and revolutionarythe idea of mechanizing computation truly is.

The books of Shetterly [She16] and Sobel [Sob17] discuss the his-tory of human computers (who were female, more often than not)and their important contributions to scientific discoveries in astron-omy and space exploration.

Alan Turing was one of the intellectual giants of the 20th century.He was not only the first person to define the notion of computation,but also invented and used some of the world’s earliest computationaldevices as part of the effort to break the Enigma cipher during WorldWar II, saving millions of lives. Tragically, Turing committed suicidein 1954, following his conviction in 1952 for homosexual acts and acourt-mandated hormonal treatment. In 2009, British prime minister

Page 279: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

loops and infinity 279

Gordon Brown made an official public apology to Turing, and in 2013Queen Elizabeth II granted Turing a posthumous pardon. Turing’s lifeis the subject of a great book and a mediocre movie.

Sipser’s text [Sip97] defines a Turing machine as a seven tuple con-sisting of the state space, input alphabet, tape alphabet, transitionfunction, starting state, accepting state, and rejecting state. Superfi-cially this looks like a very different definition than Definition 7.1 butit is simply a different representation of the same concept, just as agraph can be represented in either adjacency list or adjacency matrixform.

One difference is that Sipser considers a general set of states 𝑄 thatis not necessarily of the form 𝑄 = 0, 1, 2, 
 , 𝑘 − 1 for some naturalnumber 𝑘 > 0. Sipser also restricts his attention to Turing machinesthat output only a single bit and therefore designates two special halt-ing states: the “0 halting state” (often known as the rejecting state) andthe other as the “1 halting state” (often known as the accepting state).Thus instead of writing 0 or 1 on an output tape, the machine will en-ter into one of these states and halt. This again makes no differenceto the computational power, though we prefer to consider the moregeneral model of multi-bit outputs. (Sipser presents the basic task of aTuring machine as that of deciding a language as opposed to computinga function, but these are equivalent, see Remark 7.4.)

Sipser considers also functions with input in Σ∗ for an arbitraryalphabet Σ (and hence distinguishes between the input alphabet whichhe denotes as Σ and the tape alphabet which he denotes as Γ), while werestrict attention to functions with binary strings as input. Again thisis not a major issue, since we can always encode an element of Σ usinga binary string of length log⌈|Σ|⌉. Finally (and this is a very minorpoint) Sipser requires the machine to either move left or right in everystep, without the Stay operation, though staying in place is very easyto emulate by simply moving right and then back left.

Another definition used in the literature is that a Turing machine𝑀 recognizes a language 𝐿 if for every đ‘„ ∈ 𝐿, 𝑀(đ‘„) = 1 and forevery đ‘„ ∉ 𝐿, 𝑀(đ‘„) ∈ 0, ⊄. A language 𝐿 is recursively enumerable ifthere exists a Turing machine 𝑀 that recognizes it, and the set of allrecursively enumerable languages is often denoted by RE. We will notuse this terminology in this book.

One of the first programming-language formulations of Turingmachines was given by Wang [Wan57]. Our formulation of NAND-TM is aimed at making the connection with circuits more direct, withthe eventual goal of using it for the Cook-Levin Theorem, as well asresults such as P ⊆ P/poly and BPP ⊆ P/poly. The website esolangs.orgfeatures a large variety of esoteric Turing-complete programminglanguages. One of the most famous of them is Brainf*ck.

Page 280: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 281: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

8Equivalent models of computation

“All problems in computer science can be solved by another level of indirec-tion”, attributed to David Wheeler.

“Because we shall later compute with expressions for functions, we need adistinction between functions and forms and a notation for expressing thisdistinction. This distinction and a notation for describing it, from which wedeviate trivially, is given by Church.”, John McCarthy, 1960 (in paperdescribing the LISP programming language)

So far we have defined the notion of computing a function usingTuring machines, which are not a close match to the way computationis done in practice. In this chapter we justify this choice by showingthat the definition of computable functions will remain the sameunder a wide variety of computational models. This notion is knownas Turing completeness or Turing equivalence and is one of the mostfundamental facts of computer science. In fact, a widely believedclaim known as the Church-Turing Thesis holds that every “reasonable”definition of computable function is equivalent to being computableby a Turing machine. We discuss the Church-Turing Thesis and thepotential definitions of “reasonable” in Section 8.8.

Some of the main computational models we discuss in this chapterinclude:

‱ RAM Machines: Turing Machines do not correspond to standardcomputing architectures that have Random Access Memory (RAM).The mathematical model of RAM machines is much closer to actualcomputers, but we will see that it is equivalent in power to TuringMachines. We also discuss a programming language variant ofRAM machines, which we call NAND-RAM. The equivalence ofTuring Machines and RAM machines enables demonstrating theTuring Equivalence of many popular programming languages, in-cluding all general-purpose languages used in practice such as C,Python, JavaScript, etc.

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Learn about RAM machines and the λ

calculus.‱ Equivalence between these and other models

and Turing machines.‱ Cellular automata and configurations of

Turing machines.‱ Understand the Church-Turing thesis.

Page 282: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

282 introduction to theoretical computer science

‱ Cellular Automata: Many natural and artificial systems can bemodeled as collections of simple components, each evolving ac-cording to simple rules based on its state and the state of its imme-diate neighbors. One well-known such example is Conway’s Gameof Life. To prove that cellular automata are equivalent to Turingmachines we introduce the tool of configurations of Turing Ma-chines. These have other applications, and in particular are used inChapter 11 to prove Gödel’s Incompleteness Theorem: a central resultin mathematics.

‱ 𝜆 calculus: The 𝜆 calculus is a model for expressing computationthat originates from the 1930’s, though it is closely connected tofunctional programming languages widely used today. Showingthe equivalence of 𝜆 calculus to Turing Machines involves a beauti-ful technique to eliminate recursion known as the “Y Combinator”.

This chapter: A non-mathy overviewIn this chapter we study equivalence between models. Twocomputational models are equivalent (also known as Turingequivalent) if they can compute the same set of functions. Forexample, we have seen that Turing Machines and NAND-TMprograms are equivalent since we can transform every Tur-ing Machine into a NAND-TM program that computes thesame function, and similarly can transform every NAND-TM program into a Turing Machine that computes the samefunction.In this chapter we show this extends far beyond Turing Ma-chines. The techniques we develop allow us to show thatall general-purpose programming languages (i.e., Python,C, Java, etc.) are Turing Complete, in the sense that they cansimulate Turing Machines and hence compute all functionsthat can be computed by a TM. We will also show the otherdirection- Turing Machines can be used to simulate a pro-gram in any of these languages and hence compute anyfunction computable by them. This means that all these pro-gramming language are Turing equivalent: they are equivalentin power to Turing Machines and to each other. This is apowerful principle, which underlies behind the vast reach ofComputer Science. Moreover, it enables us to “have our cakeand eat it too”- since all these models are equivalent, we canchoose the model of our convenience for the task at hand.To achieve this equivalence, we define a new computationalmodel known as RAM machines. RAM Machines capture the

Page 283: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 283

architecture of modern computers more closely than TuringMachines, but are still computationally equivalent to Turingmachines.Finally, we will show that Turing equivalence extends farbeyond traditional programming languages. We will seethat cellular automata which are a mathematical model of ex-tremely simple natural systems is also Turing equivalent, andalso see the Turing equivalence of the 𝜆 calculus - a logicalsystem for expressing functions that is the basis for functionalprogramming languages such as Lisp, OCaml, and more.See Fig. 8.1 for an overview of the results of this chapter.

Figure 8.1: Some Turing-equivalent models. All ofthese are equivalent in power to Turing Machines(or equivalently NAND-TM programs) in the sensethat they can compute exactly the same class offunctions. All of these are models for computinginfinite functions that take inputs of unboundedlength. In contrast, Boolean circuits / NAND-CIRCprograms can only compute finite functions and henceare not Turing complete.

8.1 RAM MACHINES AND NAND-RAM

One of the limitations of Turing Machines (and NAND-TM programs)is that we can only access one location of our arrays/tape at a time. Ifthe head is at position 22 in the tape and we want to access the 957-thposition then it will take us at least 923 steps to get there. In contrast,almost every programming language has a formalism for directlyaccessing memory locations. Actual physical computers also provideso called Random Access Memory (RAM) which can be thought of as alarge array Memory, such that given an index 𝑝 (i.e., memory address,or a pointer), we can read from and write to the 𝑝𝑡ℎ location of Memory.(“Random access memory” is quite a misnomer since it has nothing todo with probability, but since it is a standard term in both the theoryand practice of computing, we will use it as well.)

The computational model that models access to such a memory isthe RAM machine (sometimes also known as the Word RAM model),as depicted in Fig. 8.2. The memory of a RAM machine is an arrayof unbounded size where each cell can store a single word, whichwe think of as a string in 0, 1đ‘€ and also (equivalently) as a num-ber in [2đ‘€]. For example, many modern computing architectures

Page 284: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

284 introduction to theoretical computer science

Figure 8.2: A RAMMachine contains a finite number oflocal registers, each of which holds an integer, and anunbounded memory array. It can perform arithmeticoperations on its register as well as load to a register 𝑟the contents of the memory at the address indexed bythe number in register 𝑟â€Č.

Figure 8.3: Different aspects of RAM machines andTuring machines. RAM machines can store integersin their local registers, and can read and write totheir memory at a location specified by a register.In contrast, Turing machines can only access theirmemory in the head location, which moves at mostone position to the right or left in each step.

use 64 bit words, in which every memory location holds a string in0, 164 which can also be thought of as a number between 0 and264 − 1 = 18, 446, 744, 073, 709, 551, 615. The parameter đ‘€ is knownas the word size. In practice often đ‘€ is a fixed number such as 64, butwhen doing theory we model đ‘€ as a parameter that can depend onthe input length or number of steps. (You can think of 2đ‘€ as roughlycorresponding to the largest memory address that we use in the com-putation.) In addition to the memory array, a RAM machine alsocontains a constant number of registers 𝑟0, 
 , 𝑟𝑘−1, each of which canalso contain a single word.

The operations a RAM machine can carry out include:‱ Data movement: Load data from a certain cell in memory into

a register or store the contents of a register into a certain cell ofmemory. RAM machine can directly access any cell of memorywithout having to move the “head” (as Turing machines do) to thatlocation. That is, in one step a RAM machine can load into register𝑟𝑖 the contents of the memory cell indexed by register 𝑟𝑗, or storeinto the memory cell indexed by register 𝑟𝑗 the contents of register𝑟𝑖.

‱ Computation: RAM machines can carry out computation on regis-ters such as arithmetic operations, logical operations, and compar-isons.

‱ Control flow: As in the case of Turing machines, the choice of whatinstruction to perform next can depend on the state of the RAMmachine, which is captured by the contents of its register.We will not give a formal definition of RAM Machines, though the

bibliographical notes section (Section 8.10) contains sources for suchdefinitions. Just as the NAND-TM programming language modelsTuring machines, we can also define a NAND-RAM programming lan-guage that models RAM machines. The NAND-RAM programminglanguage extends NAND-TM by adding the following features:‱ The variables of NAND-RAM are allowed to be (non negative)

integer valued rather than only Boolean as is the case in NAND-TM. That is, a scalar variable foo holds a non negative integer in ℕ(rather than only a bit in 0, 1), and an array variable Bar holdsan array of integers. As in the case of RAM machines, we will notallow integers of unbounded size. Concretely, each variable holdsa number between 0 and 𝑇 − 1, where 𝑇 is the number of stepsthat have been executed by the program so far. (You can ignorethis restriction for now: if we want to hold larger numbers, wecan simply execute dummy instructions; it will be useful in laterchapters.)

Page 285: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 285

Figure 8.4: Overview of the steps in the proof of The-orem 8.1 simulating NANDRAM with NANDTM.We first use the inner loop syntactic sugar of Sec-tion 7.4.1 to enable loading an integer from an arrayto the index variable i of NANDTM. Once we can dothat, we can simulate indexed access in NANDTM. Wethen use an embedding of ℕ2 in ℕ to simulate twodimensional bit arrays in NANDTM. Finally, we usethe binary representation to encode one-dimensionalarrays of integers as two dimensional arrays of bitshence completing the simulation of NANDRAM withNANDTM.

‱ We allow indexed access to arrays. If foo is a scalar and Bar is anarray, then Bar[foo] refers to the location of Bar indexed by thevalue of foo. (Note that this means we don’t need to have a specialindex variable i anymore.)

‱ As is often the case in programming languages, we will assumethat for Boolean operations such as NAND, a zero valued integer isconsidered as false, and a nonzero valued integer is considered astrue.

‱ In addition to NAND, NAND-RAM also includes all the basic arith-metic operations of addition, subtraction, multiplication, (integer)division, as well as comparisons (equal, greater than, less than,etc..).

‱ NAND-RAM includes conditional statements if/then as part ofthe language.

‱ NAND-RAM contains looping constructs such as while and do aspart of the language.

A full description of the NAND-RAM programming language isin the appendix. However, the most important fact you need to knowabout NAND-RAM is that you actually don’t need to know muchabout NAND-RAM at all, since it is equivalent in power to Turingmachines:

Theorem 8.1 — Turing Machines (aka NAND-TM programs) and RAM ma-

chines (aka NAND-RAM programs) are equivalent. For every functionđč ∶ 0, 1∗ → 0, 1∗, đč is computable by a NAND-TM program ifand only if đč is computable by a NAND-RAM program.

Since NAND-TM programs are equivalent to Turing machines, andNAND-RAM programs are equivalent to RAM machines, Theorem 8.1shows that all these four models are equivalent to one another.

Proof Idea:

Clearly NAND-RAM is only more powerful than NAND-TM, andso if a function đč is computable by a NAND-TM program then it canbe computed by a NAND-RAM program. The challenging direction isto transform a NAND-RAM program 𝑃 to an equivalent NAND-TMprogram 𝑄. To describe the proof in full we will need to cover the fullformal specification of the NAND-RAM language, and show how wecan implement every one of its features as syntactic sugar on top ofNAND-TM.

This can be done but going over all the operations in detail is rathertedious. Hence we will focus on describing the main ideas behind this

Page 286: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

286 introduction to theoretical computer science

transformation. (See also Fig. 8.4.) NAND-RAM generalizes NAND-TM in two main ways: (a) adding indexed access to the arrays (ie..,Foo[bar] syntax) and (b) moving from Boolean valued variables tointeger valued ones. The transformation has two steps:

1. Indexed access of bit arrays: We start by showing how to handle (a).Namely, we show how we can implement in NAND-TM the op-eration Setindex(Bar) such that if Bar is an array that encodessome integer 𝑗, then after executing Setindex(Bar) the value ofi will equal to 𝑗. This will allow us to simulate syntax of the formFoo[Bar] by Setindex(Bar) followed by Foo[i].

2. Two dimensional bit arrays: We then show how we can use “syntacticsugar” to augment NAND-TM with two dimensional arrays. That is,have two indices i and j and two dimensional arrays, such that we canuse the syntax Foo[i][j] to access the (i,j)-th location of Foo.

3. Arrays of integers: Finally we will encode a one dimensional arrayArr of integers by a two dimensional Arrbin of bits. The idea issimple: if 𝑎𝑖,0, 
 , 𝑎𝑖,ℓ is a binary (prefix-free) representation ofArr[𝑖], then Arrbin[𝑖][𝑗] will be equal to 𝑎𝑖,𝑗.Once we have arrays of integers, we can use our usual syntactic

sugar for functions, GOTO etc. to implement the arithmetic and controlflow operations of NAND-RAM.⋆

The above approach is not the only way to obtain a proof of Theo-rem 8.1, see for example Exercise 8.1

RRemark 8.2 — RAM machines / NAND-RAM and assemblylanguage (optional). RAM machines correspond quiteclosely to actual microprocessors such as those in theIntel x86 series that also contains a large primary mem-ory and a constant number of small registers. This is ofcourse no accident: RAM machines aim at modelingmore closely than Turing machines the architecture ofactual computing systems, which largely follows theso called von Neumann architecture as described inthe report [Neu45]. As a result, NAND-RAM is sim-ilar in its general outline to assembly languages suchas x86 or NIPS. These assembly languages all haveinstructions to (1) move data from registers to mem-ory, (2) perform arithmetic or logical computationson registers, and (3) conditional execution and loops(“if” and “goto”, commonly known as “branches” and“jumps” in the context of assembly languages).The main difference between RAM machines andactual microprocessors (and correspondingly between

Page 287: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 287

NAND-RAM and assembly languages) is that actualmicroprocessors have a fixed word size đ‘€ so that allregisters and memory cells hold numbers in [2đ‘€] (orequivalently strings in 0, 1đ‘€). This number đ‘€ canvary among different processors, but common valuesare either 32 or 64. As a theoretical model, RAM ma-chines do not have this limitation, but we rather let đ‘€be the logarithm of our running time (which roughlycorresponds to its value in practice as well). Actualmicroprocessors also have a fixed number of registers(e.g., 14 general purpose registers in x86-64) but thisdoes not make a big difference with RAM machines.It can be shown that RAM machines with as few astwo registers are as powerful as full-fledged RAM ma-chines that have an arbitrarily large constant numberof registers.Of course actual microprocessors have many featuresnot shared with RAM machines as well, includingparallelism, memory hierarchies, and many others.However, RAM machines do capture actual comput-ers to a first approximation and so (as we will see), therunning time of an algorithm on a RAM machine (e.g.,𝑂(𝑛) vs 𝑂(𝑛2)) is strongly correlated with its practicalefficiency.

8.2 THE GORY DETAILS (OPTIONAL)

We do not show the full formal proof of Theorem 8.1 but focus on themost important parts: implementing indexed access, and simulatingtwo dimensional arrays with one dimensional ones. Even these arealready quite tedious to describe, as will not be surprising to anyonethat has ever written a compiler. Hence you can feel free to merelyskim this section. The important point is not for you to know all de-tails by heart but to be convinced that in principle it is possible totransform a NAND-RAM program to an equivalent NAND-TM pro-gram, and even be convinced that, with sufficient time and effort, youcould do it if you wanted to.

8.2.1 Indexed access in NAND-TMIn NAND-TM we can only access our arrays in the position of the in-dex variable i, while NAND-RAM has integer-valued variables andcan use them for indexed access to arrays, of the form Foo[bar]. To im-plement indexed access in NAND-TM, we will encode integers in ourarrays using some prefix-free representation (see Section 2.5.2)), andthen have a procedure Setindex(Bar) that sets i to the value encodedby Bar. We can simulate the effect of Foo[Bar] using Setindex(Bar)followed by Foo[i].

Implementing Setindex(Bar) can be achieved as follows:

Page 288: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

288 introduction to theoretical computer science

1. We initialize an array Arzero such that Atzero[0]= 1 andAtzero[𝑗]= 0 for all 𝑗 > 0. (This can be easily done in NAND-TMas all uninitialized variables default to zero.)

2. Set i to zero, by decrementing it until we reach the point whereAtzero[i]= 1.

3. Let Temp be an array encoding the number 0.4. We use GOTO to simulate an inner loop of of the form: while Temp ≠

Bar, increment Temp.5. At the end of the loop, i is equal to the value encoded by Bar.

In NAND-TM code (using some syntactic sugar), we can imple-ment the above operations as follows:# assume Atzero is an array such that Atzero[0]=1# and Atzero[j]=0 for all j>0

# set i to 0.LABEL("zero_idx")dir0 = zerodir1 = one# corresponds to i <- i-1GOTO("zero_idx",NOT(Atzero[i]))...# zero out temp#(code below assumes a specific prefix-free encoding in

which 10 is the "end marker")Temp[0] = 1Temp[1] = 0# set i to Bar, assume we know how to increment, compareLABEL("increment_temp")cond = EQUAL(Temp,Bar)dir0 = onedir1 = one# corresponds to i <- i+1INC(Temp)GOTO("increment_temp",cond)# if we reach this point, i is number encoded by Bar...# final instruction of programMODANDJUMP(dir0,dir1)

8.2.2 Two dimensional arrays in NAND-TMTo implement two dimensional arrays, we want to embed them in aone dimensional array. The idea is that we come up with a one to one

Page 289: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 289

Figure 8.5: Illustration of the map 𝑒𝑚𝑏𝑒𝑑(đ‘„, 𝑩) =12 (đ‘„ + 𝑩)(đ‘„ + 𝑩 + 1) + đ‘„ for đ‘„, 𝑩 ∈ [10], one cansee that for every distinct pairs (đ‘„, 𝑩) and (đ‘„â€Č, 𝑩â€Č),𝑒𝑚𝑏𝑒𝑑(đ‘„, 𝑩) ≠ 𝑒𝑚𝑏𝑒𝑑(đ‘„â€Č, 𝑩â€Č).

function 𝑒𝑚𝑏𝑒𝑑 ∶ ℕ × ℕ → ℕ, and so embed the location (𝑖, 𝑗) of thetwo dimensional array Two in the location 𝑒𝑚𝑏𝑒𝑑(𝑖, 𝑗) of the array One.

Since the set ℕ × ℕ seems “much bigger” than the set ℕ, a priori itmight not be clear that such a one to one mapping exists. However,once you think about it more, it is not that hard to construct. For ex-ample, you could ask a child to use scissors and glue to transform a10” by 10” piece of paper into a 1” by 100” strip. This is essentiallya one to one map from [10] × [10] to [100]. We can generalize this toobtain a one to one map from [𝑛] × [𝑛] to [𝑛2] and more generally a oneto one map from ℕ × ℕ to ℕ. Specifically, the following map 𝑒𝑚𝑏𝑒𝑑would do (see Fig. 8.5):𝑒𝑚𝑏𝑒𝑑(đ‘„, 𝑩) = 12 (đ‘„ + 𝑩)(đ‘„ + 𝑩 + 1) + đ‘„ . (8.1)

Exercise 8.3 asks you to prove that 𝑒𝑚𝑏𝑒𝑑 is indeed one to one, aswell as computable by a NAND-TM program. (The latter can be doneby simply following the grade-school algorithms for multiplication,addition, and division.) This means that we can replace code of theform Two[Foo][Bar] = something (i.e., access the two dimensionalarray Two at the integers encoded by the one dimensional arrays Fooand Bar) by code of the form:

Blah = embed(Foo,Bar)Setindex(Blah)Two[i] = something

8.2.3 All the restOnce we have two dimensional arrays and indexed access, simulatingNAND-RAM with NAND-TM is just a matter of implementing thestandard algorithms for arithmetic operations and comparisons inNAND-TM. While this is cumbersome, it is not difficult, and the endresult is to show that every NAND-RAM program 𝑃 can be simulatedby an equivalent NAND-TM program 𝑄, thus completing the proof ofTheorem 8.1.

RRemark 8.3 — Recursion in NAND-RAM (advanced). Oneconcept that appears in many programming languagesbut we did not include in NAND-RAM programs isrecursion. However, recursion (and function calls ingeneral) can be implemented in NAND-RAM usingthe stack data structure. A stack is a data structure con-taining a sequence of elements, where we can “push”elements into it and “pop” them from it in “first in lastout” order.We can implement a stack using an array of integersStack and a scalar variable stackpointer that will

Page 290: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

290 introduction to theoretical computer science

Figure 8.6: A punched card corresponding to a Fortranstatement.

1 Some programming language have fixed (even ifextremely large) bounds on the amount of memorythey can access, which formally prevent them frombeing applicable to computing infinite functions andhence simulating Turing machines. We ignore suchissues in this discussion and assume access to somestorage device without a fixed upper bound on itscapacity.

be the number of items in the stack. We implementpush(foo) by

Stack[stackpointer]=foostackpointer += one

and implement bar = pop() by

bar = Stack[stackpointer]stackpointer -= one

We implement a function call to đč by pushing thearguments for đč into the stack. The code of đč will“pop” the arguments from the stack, perform the com-putation (which might involve making recursive ornon recursive calls) and then “push” its return valueinto the stack. Because of the “first in last out” na-ture of a stack, we do not return control to the callingprocedure until all the recursive calls are done.The fact that we can implement recursion using a non-recursive language is not surprising. Indeed, machinelanguages typically do not have recursion (or functioncalls in general), and hence a compiler implementsfunction calls using a stack and GOTO. You can findonline tutorials on how recursion is implementedvia stack in your favorite programming language,whether it’s Python , JavaScript, or Lisp/Scheme.

8.3 TURING EQUIVALENCE (DISCUSSION)

Any of the standard programming language such as C, Java, Python,Pascal, Fortran have very similar operations to NAND-RAM. (In-deed, ultimately they can all be executed by machines which have afixed number of registers and a large memory array.) Hence usingTheorem 8.1, we can simulate any program in such a programminglanguage by a NAND-TM program. In the other direction, it is a fairlyeasy programming exercise to write an interpreter for NAND-TM inany of the above programming languages. Hence we can also simulateNAND-TM programs (and so by Theorem 7.11, Turing machines) us-ing these programming languages. This property of being equivalentin power to Turing Machines / NAND-TM is called Turing Equivalent(or sometimes Turing Complete). Thus all programming languages weare familiar with are Turing equivalent.1

8.3.1 The “Best of both worlds” paradigmThe equivalence between Turing Machines and RAM machines allowsus to choose the most convenient language for the task at hand:

‱ When we want to prove a theorem about all programs/algorithms,we can use Turing machines (or NAND-TM) since they are sim-

Page 291: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 291

Figure 8.7: By having the two equivalent languagesNAND-TM and NAND-RAM, we can “have our cakeand eat it too”, using NAND-TM when we want toprove that programs can’t do something, and usingNAND-RAM or other high level languages when wewant to prove that programs can do something.

pler and easier to analyze. In particular, if we want to show thata certain function can not be computed, then we will use Turingmachines.

‱ When we want to show that a function can be computed we can useRAM machines or NAND-RAM, because they are easier to pro-gram in and correspond more closely to high level programminglanguages we are used to. In fact, we will often describe NAND-RAM programs in an informal manner, trusting that the readercan fill in the details and translate the high level description to theprecise program. (This is just like the way people typically use in-formal or “pseudocode” descriptions of algorithms, trusting thattheir audience will know to translate these descriptions to code ifneeded.)

Our usage of Turing Machines / NAND-TM and RAM Machines/ NAND-RAM is very similar to the way people use in practice highand low level programming languages. When one wants to producea device that executes programs, it is convenient to do so for verysimple and “low level” programming language. When one wants todescribe an algorithm, it is convenient to use as high level a formalismas possible.

Big Idea 10 Using equivalence results such as those betweenTuring and RAM machines, we can “have our cake and eat it too”.We can use a simpler model such as Turing machines when we wantto prove something can’t be done, and use a feature-rich model such asRAM machines when we want to prove something can be done.

8.3.2 Let’s talk about abstractions“The programmer is in the unique position that 
 he has to be ableto think in terms of conceptual hierarchies that are much deeper thana single mind ever needed to face before.”, Edsger Dijkstra, “On thecruelty of really teaching computing science”, 1988.

At some point in any theory of computation course, the instructorand students need to have the talk. That is, we need to discuss the levelof abstraction in describing algorithms. In algorithms courses, onetypically describes algorithms in English, assuming readers can “fillin the details” and would be able to convert such an algorithm into animplementation if needed. For example, Algorithm 8.4 is a high leveldescription of the breadth first search algorithm.

Page 292: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

292 introduction to theoretical computer science

Algorithm 8.4 — Breadth First Search.

Input: Graph đș, vertices 𝑱, 𝑣Output: ”connected” when 𝑱 is connected to 𝑣 in đș, ”dis-

connected”1: Initialize empty queue 𝑄.2: Put 𝑱 in 𝑄3: while 𝑄 is not empty do4: Remove top vertex đ‘€ from 𝑄5: if đ‘€ = 𝑣 then return ”connected”6: end if7: Mark đ‘€8: Add all unmarked neighbors of đ‘€ to 𝑄.9: end while

10: return ”disconnected”

If we wanted to give more details on how to implement breadthfirst search in a programming language such as Python or C (orNAND-RAM / NAND-TM for that matter), we would describe howwe implement the queue data structure using an array, and similarlyhow we would use arrays to mark vertices. We call such an “interme-diate level” description an implementation level or pseudocode descrip-tion. Finally, if we want to describe the implementation precisely, wewould give the full code of the program (or another fully precise rep-resentation, such as in the form of a list of tuples). We call this a formalor low level description.

Figure 8.8: We can describe an algorithm at differentlevels of granularity/detail and precision. At thehighest level we just write the idea in words, omittingall details on representation and implementation.In the intermediate level (also known as implemen-tation or pseudocode) we give enough details of theimplementation that would allow someone to de-rive it, though we still fall short of providing the fullcode. The lowest level is where the actual code ormathematical description is fully spelled out. Thesedifferent levels of detail all have their uses, and mov-ing between them is one of the most important skillsfor a computer scientist.

While we started off by describing NAND-CIRC, NAND-TM, andNAND-RAM programs at the full formal level, as we progress in this

Page 293: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 293

book we will move to implementation and high level description.After all, our goal is not to use these models for actual computation,but rather to analyze the general phenomenon of computation. Thatsaid, if you don’t understand how the high level description translatesto an actual implementation, going “down to the metal” is often anexcellent exercise. One of the most important skills for a computerscientist is the ability to move up and down hierarchies of abstractions.

A similar distinction applies to the notion of representation of objectsas strings. Sometimes, to be precise, we give a low level specificationof exactly how an object maps into a binary string. For example, wemight describe an encoding of 𝑛 vertex graphs as length 𝑛2 binarystrings, by saying that we map a graph đș over the vertices [𝑛] to astring đ‘„ ∈ 0, 1𝑛2 such that the 𝑛 ⋅ 𝑖 + 𝑗-th coordinate of đ‘„ is 1 if andonly if the edge 𝑖 𝑗 is present in đș. We can also use an intermediate orimplementation level description, by simply saying that we represent agraph using the adjacency matrix representation.

Finally, because we are translating between the various represen-tations of graphs (and objects in general) can be done via a NAND-RAM (and hence a NAND-TM) program, when talking in a high levelwe also suppress discussion of representation altogether. For example,the fact that graph connectivity is a computable function is true re-gardless of whether we represent graphs as adjacency lists, adjacencymatrices, list of edge-pairs, and so on and so forth. Hence, in caseswhere the precise representation doesn’t make a difference, we wouldoften talk about our algorithms as taking as input an object 𝑋 (thatcan be a graph, a vector, a program, etc.) without specifying how 𝑋 isencoded as a string.

Defining ”Algorithms”. Up until now we have used the term “algo-rithm” informally. However, Turing Machines and the range of equiv-alent models yield a way to precisely and formally define algorithms.Hence whenever we refer to an algorithm in this book, we will meanthat it is an instance of one of the Turing equivalent models, such asTuring machines, NAND-TM, RAM machines, etc. Because of theequivalence of all these models, in many contexts, it will not matterwhich of these we use.

8.3.3 Turing completeness and equivalence, a formal definition (optional)A computational model is some way to define what it means for a pro-gram (which is represented by a string) to compute a (partial) func-tion. A computational model ℳ is Turing complete, if we can map ev-ery Turing machine (or equivalently NAND-TM program) 𝑁 into aprogram 𝑃 for ℳ that computes the same function as 𝑄. It is Turingequivalent if the other direction holds as well (i.e., we can map everyprogram in ℳ to a Turing machine that computes the same function).

Page 294: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

294 introduction to theoretical computer science

We can define this notion formally as follows. (This formal definitionis not crucial for the remainder of this book so feel to skip it as longas you understand the general concept of Turing equivalence; Thisnotion is sometimes referred to in the literature as Gödel numberingor admissible numbering.)

Definition 8.5 — Turing completeness and equivalence (optional). Let ℱ bethe set of all partial functions from 0, 1∗ to 0, 1∗. A computa-tional model is a map ℳ ∶ 0, 1∗ → ℱ.

We say that a program 𝑃 ∈ 0, 1∗ ℳ-computes a function đč ∈ ℱif ℳ(𝑃) = đč .

A computational model ℳ is Turing complete if there is a com-putable map ENCODEℳ ∶ 0, 1∗ → 0, 1∗ for every Turingmachine 𝑁 (represented as a string), ℳ(ENCODEℳ(𝑁)) is equalto the partial function computed by 𝑁 .

A computational model ℳ is Turing equivalent if it is Tur-ing complete and there exists a computable map DECODEℳ ∶0, 1∗ → 0, 1∗ such that or every string 𝑃 ∈ 0, 1∗, 𝑁 =DECODEℳ(𝑃 ) is a string representation of a Turing machine thatcomputes the function ℳ(𝑃).Some examples of Turing equivalent models (some of which we

have already seen, and some are discussed below) include:

‱ Turing machines‱ NAND-TM programs‱ NAND-RAM programs‱ λ calculus‱ Game of life (mapping programs and inputs/outputs to starting

and ending configurations)‱ Programming languages such as Python/C/Javascript/OCaml


(allowing for unbounded storage)

8.4 CELLULAR AUTOMATA

Many physical systems can be described as consisting of a large num-ber of elementary components that interact with one another. Oneway to model such systems is using cellular automata. This is a systemthat consists of a large (or even infinite) number of cells. Each cellonly has a constant number of possible states. At each time step, a cellupdates to a new state by applying some simple rule to the state ofitself and its neighbors.

A canonical example of a cellular automaton is Conway’s Gameof Life. In this automata the cells are arranged in an infinite two di-mensional grid. Each cell has only two states: “dead” (which we can

Page 295: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 295

Figure 8.9: Rules for Conway’s Game of Life. Imagefrom this blog post.

encode as 0 and identify with ∅) or “alive” (which we can encodeas 1). The next state of a cell depends on its previous state and thestates of its 8 vertical, horizontal and diagonal neighbors (see Fig. 8.9).A dead cell becomes alive only if exactly three of its neighbors arealive. A live cell continues to live if it has two or three live neighbors.Even though the number of cells is potentially infinite, we can en-code the state using a finite-length string by only keeping track of thelive cells. If we initialize the system in a configuration with a finitenumber of live cells, then the number of live cells will stay finite in allfuture steps. The Wikipedia page for the Game of Life contains somebeautiful figures and animations of configurations that produce veryinteresting evolutions.

Figure 8.10: In a two dimensional cellular automatonevery cell is in position 𝑖, 𝑗 for some integers 𝑖, 𝑗 ∈ â„€.The state of a cell is some value 𝐮𝑖,𝑗 ∈ ÎŁ for somefinite alphabet ÎŁ. At a given time step, the state of thecell is adjusted according to some function applied tothe state of (𝑖, 𝑗) and all its neighbors (𝑖 ± 1, 𝑗 ± 1).In a one dimensional cellular automaton every cell is inposition 𝑖 ∈ â„€ and the state 𝐮𝑖 of 𝑖 at the next timestep depends on its current state and the state of itstwo neighbors 𝑖 − 1 and 𝑖 + 1.

Since the cells in the game of life are are arranged in an infinite two-dimensional grid, it is an example of a two dimensional cellular automa-ton. We can also consider the even simpler setting of a one dimensionalcellular automaton, where the cells are arranged in an infinite line, seeFig. 8.10. It turns out that even this simple model is enough to achieve

Page 296: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

296 introduction to theoretical computer science

Figure 8.11: A Game-of-Life configuration simulatinga Turing Machine. Figure by Paul Rendell.

Turing-completeness. We will now formally define one-dimensionalcellular automata and then prove their Turing completeness.

Definition 8.6 — One dimensional cellular automata. Let ÎŁ be a finite setcontaining the symbol ∅. A one dimensional cellular automation overalphabet ÎŁ is described by a transition rule 𝑟 ∶ ÎŁ3 → ÎŁ, whichsatisfies 𝑟(∅,∅,∅) = ∅.

A configuration of the automaton 𝑟 is a function 𝐮 ∶ â„€ → ÎŁ. Ifan automaton with rule 𝑟 is in configuration 𝐮, then its next config-uration, denoted by 𝐮â€Č = NEXT𝑟(𝐮), is the function 𝐮â€Č such that𝐮â€Č(𝑖) = 𝑟(𝐮(𝑖 − 1), 𝐮(𝑖), 𝐮(𝑖 + 1)) for every 𝑖 ∈ â„€. In other words,the next state of the automaton 𝑟 at point 𝑖 obtained by applyingthe rule 𝑟 to the values of 𝐮 at 𝑖 and its two neighbors.

Finite configuration. We say that a configuration of an automaton 𝑟is finite if there is only some finite number of indices 𝑖0, 
 , 𝑖𝑗−1 in â„€such that 𝐮(𝑖𝑗) ≠ ∅. (That is, for every 𝑖 ∉ 𝑖0, 
 , 𝑖𝑗−1, 𝐮(𝑖) = ∅.)Such a configuration can be represented using a finite string thatencodes the indices 𝑖0, 
 , 𝑖𝑛−1 and the values 𝐮(𝑖0), 
 , 𝐮(𝑖𝑛−1). Since𝑅(∅,∅,∅) = ∅, if 𝐮 is a finite configuration then NEXT𝑟(𝐮) is finiteas well. We will only be interested in studying cellular automata thatare initialized in finite configurations, and hence remain in a finiteconfiguration throughout their evolution.

8.4.1 One dimensional cellular automata are Turing completeWe can write a program (for example using NAND-RAM) that sim-ulates the evolution of any cellular automaton from an initial finiteconfiguration by simply storing the values of the cells with state notequal to ∅ and repeatedly applying the rule 𝑟. Hence cellular au-tomata can be simulated by Turing Machines. What is more surprisingthat the other direction holds as well. For example, as simple as itsrules seem, we can simulate a Turing machine using the game of life(see Fig. 8.11).

In fact, even one dimensional cellular automata can be Turing com-plete:

Theorem 8.7 — One dimensional automata are Turing complete. For everyTuring machine 𝑀 , there is a one dimensional cellular automatonthat can simulate 𝑀 on every input đ‘„.To make the notion of “simulating a Turing machine” more precise

we will need to define configurations of Turing machines. We willdo so in Section 8.4.2 below, but at a high level a configuration of aTuring machine is a string that encodes its full state at a given step in

Page 297: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 297

its computation. That is, the contents of all (non empty) cells of itstape, its current state, as well as the head position.

The key idea in the proof of Theorem 8.7 is that at every point inthe computation of a Turing machine 𝑀 , the only cell in 𝑀 ’s tape thatcan change is the one where the head is located, and the value thiscell changes to is a function of its current state and the finite state of𝑀 . This observation allows us to encode the configuration of a Turingmachine 𝑀 as a finite configuration of a cellular automaton 𝑟, andensure that a one-step evolution of this encoded configuration underthe rules of 𝑟 corresponds to one step in the execution of the Turingmachine 𝑀 .

8.4.2 Configurations of Turing machines and the next-step functionTo turn the above ideas into a rigorous proof (and even statement!)of Theorem 8.7 we will need to precisely define the notion of config-urations of Turing machines. This notion will be useful for us in laterchapters as well.

Figure 8.12: A configuration of a Turing machine 𝑀with alphabet ÎŁ and state space [𝑘] encodes the stateof 𝑀 at a particular step in its execution as a string đ›Œover the alphabet ÎŁ = ÎŁ × (⋅ × [𝑘]). The string isof length 𝑡 where 𝑡 is such that 𝑀’s tape contains ∅ inall positions 𝑡 and larger and 𝑀’s head is in a positionsmaller than 𝑡. If 𝑀’s head is in the 𝑖-th position, thenfor 𝑗 ≠ 𝑖, đ›Œđ‘— encodes the value of the 𝑗-th cell of 𝑀’stape, while đ›Œđ‘– encodes both this value as well as thecurrent state of 𝑀 . If the machine writes the value 𝜏 ,changes state to 𝑡, and moves right, then in the nextconfiguration will contain at position 𝑖 the value (𝜏, ⋅)and at position 𝑖 + 1 the value (đ›Œđ‘–+1, 𝑡).

Definition 8.8 — Configuration of Turing Machines.. Let 𝑀 be a Turing ma-chine with tape alphabet ÎŁ and state space [𝑘]. A configuration of 𝑀is a string đ›Œ ∈ Σ∗ where ÎŁ = ÎŁ × (⋅ âˆȘ [𝑘]) that satisfies that thereis exactly one coordinate 𝑖 for which đ›Œđ‘– = (𝜎, 𝑠) for some 𝜎 ∈ ÎŁ and𝑠 ∈ [𝑘]. For all other coordinates 𝑗, đ›Œđ‘— = (𝜎â€Č, ⋅) for some 𝜎â€Č ∈ ÎŁ.

A configuration đ›Œ ∈ Σ∗ of 𝑀 corresponds to the following stateof its execution:

‱ 𝑀 ’s tape contains đ›Œđ‘—,0 for all 𝑗 < |đ›Œ| and contains ∅ for all po-sitions that are at least |đ›Œ|, where we let đ›Œđ‘—,0 be the value 𝜎 suchthat đ›Œđ‘— = (𝜎, 𝑡) with 𝜎 ∈ ÎŁ and 𝑡 ∈ ⋅ âˆȘ [𝑘]. (In other words,

Page 298: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

298 introduction to theoretical computer science

since đ›Œđ‘— is a pair of an alphabet symbol 𝜎 and either a state in [𝑘]or the symbol ⋅, đ›Œđ‘—,0 is the first component 𝜎 of this pair.)

‱ 𝑀 ’s head is in the unique position 𝑖 for which đ›Œđ‘– has the form(𝜎, 𝑠) for 𝑠 ∈ [𝑘], and 𝑀 ’s state is equal to 𝑠.P

Definition 8.8 below has some technical details, butis not actually that deep or complicated. Try to take amoment to stop and think how you would encode as astring the state of a Turing machine at a given point inan execution.Think what are all the components that you need toknow in order to be able to continue the executionfrom this point onwards, and what is a simple wayto encode them using a list of finite symbols. In par-ticular, with an eye towards our future applications,try to think of an encoding which will make it as sim-ple as possible to map a configuration at step 𝑡 to theconfiguration at step 𝑡 + 1.

Definition 8.8 is a little cumbersome, but ultimately a configurationis simply a string that encodes a snapshot of the Turing machine at agiven point in the execution. (In operating-systems lingo, it is a “coredump”.) Such a snapshot needs to encode the following components:

1. The current head position.

2. The full contents of the large scale memory, that is the tape.

3. The contents of the “local registers”, that is the state of the ma-chine.

The precise details of how we encode a configuration are not impor-tant, but we do want to record the following simple fact:Lemma 8.9 Let 𝑀 be a Turing machine and let NEXT𝑀 ∶ Σ∗ → Σ∗be the function that maps a configuration of 𝑀 to the configurationat the next step of the execution. Then for every 𝑖 ∈ ℕ, the value ofNEXT𝑀(đ›Œ)𝑖 only depends on the coordinates đ›Œđ‘–âˆ’1, đ›Œđ‘–, đ›Œđ‘–+1.

(For simplicity of notation, above we use the convention that if 𝑖is “out of bounds”, such as 𝑖 < 0 or 𝑖 > |đ›Œ|, then we assume thatđ›Œđ‘– = (∅, ⋅).) We leave proving Lemma 8.9 as Exercise 8.7. The ideabehind the proof is simple: if the head is neither in position 𝑖 norpositions 𝑖 − 1 and 𝑖 + 1, then the next-step configuration at 𝑖 will bethe same as it was before. Otherwise, we can “read off” the state of theTuring machine and the value of the tape at the head location from the

Page 299: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 299

Figure 8.13: Evolution of a one dimensional automata.Each row in the figure corresponds to the configura-tion. The initial configuration corresponds to the toprow and contains only a single “live” cell. This figurecorresponds to the “Rule 110” automaton of StephenWolfram which is Turing Complete. Figure takenfrom Wolfram MathWorld.

configuration at 𝑖 or one of its neighbors and use that to update whatthe new state at 𝑖 should be. Completing the full proof is not hard,but doing it is a great way to ensure that you are comfortable with thedefinition of configurations.

Completing the proof of Theorem 8.7. We can now restate Theorem 8.7more formally, and complete its proof:

Theorem 8.10 — One dimensional automata are Turing complete (formal state-

ment). For every Turing Machine 𝑀 , if we denote by ÎŁ the alphabetof its configuration strings, then there is a one-dimensional cellularautomaton 𝑟 over the alphabet Σ∗ such that(NEXT𝑀(đ›Œ)) = NEXT𝑟 (đ›Œ) (8.2)

for every configuration đ›Œ ∈ Σ∗ of 𝑀 (again using the conventionthat we consider đ›Œđ‘– = ∅ if 𝑖 is ”out of bounds).

Proof. We consider the element (∅, ⋅) of Σ to correspond to the ∅element of the automaton 𝑟. In this case, by Lemma 8.9, the functionNEXT𝑀 that maps a configuration of 𝑀 into the next one is in fact avalid rule for a one dimensional automata.

The automaton arising from the proof of Theorem 8.10 has a largealphabet, and furthermore one whose size that depends on the ma-chine 𝑀 that is being simulated. It turns out that one can obtain anautomaton with an alphabet of fixed size that is independent of theprogram being simulated, and in fact the alphabet of the automatoncan be the minimal set 0, 1! See Fig. 8.13 for an example of such anTuring-complete automaton.

RRemark 8.11 — Configurations of NAND-TM programs.We can use the same approach as Definition 8.8 todefine configurations of a NAND-TM program. Such aconfiguration will need to encode:

1. The current value of the variable i.2. For every scalar variable foo, the value of foo.3. For every array variable Bar, the value Bar[𝑗] for

every 𝑗 ∈ 0, 
 , 𝑡 − 1 where 𝑡 − 1 is the largestvalue that the index variable i ever achieved in thecomputation.

Page 300: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

300 introduction to theoretical computer science

8.5 LAMBDA CALCULUS AND FUNCTIONAL PROGRAMMING LAN-GUAGES

The λ calculus is another way to define computable functions. It wasproposed by Alonzo Church in the 1930’s around the same time asAlan Turing’s proposal of the Turing Machine. Interestingly, whileTuring Machines are not used for practical computation, the λ calculushas inspired functional programming languages such as LISP, ML andHaskell, and indirectly the development of many other programminglanguages as well. In this section we will present the λ calculus andshow that its power is equivalent to NAND-TM programs (and hencealso to Turing machines). Our Github repository contains a Jupyternotebook with a Python implementation of the λ calculus that you canexperiment with to get a better feel for this topic.

The λ operator. At the core of the λ calculus is a way to define “anony-mous” functions. For example, instead of giving a name 𝑓 to a func-tion and defining it as 𝑓(đ‘„) = đ‘„ × đ‘„ (8.3)

we can write it as đœ†đ‘„.đ‘„ × đ‘„ (8.4)and so (đœ†đ‘„.đ‘„ × đ‘„)(7) = 49. That is, you can think of đœ†đ‘„.đ‘’đ‘„đ‘(đ‘„),

where đ‘’đ‘„đ‘ is some expression as a way of specifying the anonymousfunction đ‘„ ↩ đ‘’đ‘„đ‘(đ‘„). Anonymous functions, using either đœ†đ‘„.𝑓(đ‘„), đ‘„ ↩𝑓(đ‘„) or other closely related notation, appear in many programminglanguages. For example, in Python we can define the squaring functionusing lambda x: x*x while in JavaScript we can use x => x*x or(x) => x*x. In Scheme we would define it as (lambda (x) (* x x)).Clearly, the name of the argument to a function doesn’t matter, and so𝜆𝑩.𝑩 × 𝑩 is the same as đœ†đ‘„.đ‘„ × đ‘„, as both correspond to the squaringfunction.

Dropping parenthesis. To reduce notational clutter, when writing𝜆 calculus expressions we often drop the parentheses for functionevaluation. Hence instead of writing 𝑓(đ‘„) for the result of applyingthe function 𝑓 to the input đ‘„, we can also write this as simply 𝑓 đ‘„.Therefore we can write (đœ†đ‘„.đ‘„ × đ‘„)7 = 49. In this chapter, we will useboth the 𝑓(đ‘„) and 𝑓 đ‘„ notations for function application. Functionevaluations are associative and bind from left to right, and hence 𝑓 𝑔 ℎis the same as (𝑓𝑔)ℎ.8.5.1 Applying functions to functionsA key feature of the λ calculus is that functions are “first-class objects”in the sense that we can use functions as arguments to other functions.

Page 301: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 301

For example, can you guess what number is the following expressionequal to? (((𝜆𝑓.(𝜆𝑩.(𝑓 (𝑓 𝑩))))(đœ†đ‘„.đ‘„ × đ‘„)) 3) (8.5)

PThe expression (8.5) might seem daunting, but beforeyou look at the solution below, try to break it apartto its components, and evaluate each component at atime. Working out this example would go a long waytoward understanding the λ calculus.

Let’s evaluate (8.5) one step at a time. As nice as it is for the λcalculus to allow anonymous functions, adding names can be veryhelpful for understanding complicated expressions. So, let us writeđč = 𝜆𝑓.(𝜆𝑩.(𝑓(𝑓𝑩))) and 𝑔 = đœ†đ‘„.đ‘„ × đ‘„.

Therefore (8.5) becomes ((đč 𝑔) 3) . (8.6)

On input a function 𝑓 , đč outputs the function 𝜆𝑩.(𝑓(𝑓 𝑩)), or inother words đč𝑓 is the function 𝑩 ↩ 𝑓(𝑓(𝑩)). Our function 𝑔 is simply𝑔(đ‘„) = đ‘„2 and so (đč𝑔) is the function that maps 𝑩 to (𝑩2)2 = 𝑩4. Hence((đč𝑔)3) = 34 = 81.Solved Exercise 8.1 What number does the following expression equalto? ((đœ†đ‘„.(𝜆𝑩.đ‘„)) 2) 9) . (8.7)

Solution:𝜆𝑩.đ‘„ is the function that on input 𝑩 ignores its input and outputsđ‘„. Hence (đœ†đ‘„.(𝜆𝑩.đ‘„))2 yields the function 𝑩 ↩ 2 (or, using 𝜆 nota-tion, the function 𝜆𝑩.2). Hence (8.7) is equivalent to (𝜆𝑩.2)9 = 2.

8.5.2 Obtaining multi-argument functions via CurryingIn a λ expression of the form đœ†đ‘„.𝑒, the expression 𝑒 can itself involvethe λ operator. Thus for example the functionđœ†đ‘„.(𝜆𝑩.đ‘„ + 𝑩) (8.8)

maps đ‘„ to the function 𝑩 ↩ đ‘„ + 𝑩.In particular, if we invoke the function (8.8) on 𝑎 to obtain some

function 𝑓 , and then invoke 𝑓 on 𝑏, we obtain the value 𝑎 + 𝑏. We

Page 302: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

302 introduction to theoretical computer science

Figure 8.14: In the “currying” transformation, we cancreate the effect of a two parameter function 𝑓(đ‘„, 𝑩)with the λ expression đœ†đ‘„.(𝜆𝑩.𝑓(đ‘„, 𝑩)) which on inputđ‘„ outputs a one-parameter function đ‘“đ‘„ that has đ‘„â€œhardwired” into it and such that đ‘“đ‘„(𝑩) = 𝑓(đ‘„, 𝑩).This can be illustrated by a circuit diagram; seeChelsea Voss’s site.

can see that the one-argument function (8.8) corresponding to 𝑎 ↩(𝑏 ↩ 𝑎 + 𝑏) can also be thought of as the two-argument function(𝑎, 𝑏) ↩ 𝑎 + 𝑏. Generally, we can use the λ expression đœ†đ‘„.(𝜆𝑩.𝑓(đ‘„, 𝑩))to simulate the effect of a two argument function (đ‘„, 𝑩) ↩ 𝑓(đ‘„, 𝑩). Thistechnique is known as Currying. We will use the shorthand đœ†đ‘„, 𝑩.𝑒for đœ†đ‘„.(𝜆𝑩.𝑒). If 𝑓 = đœ†đ‘„.(𝜆𝑩.𝑒) then (𝑓𝑎)𝑏 corresponds to applying 𝑓𝑎and then invoking the resulting function on 𝑏, obtaining the result ofreplacing in 𝑒 the occurrences of đ‘„ with 𝑎 and occurrences of 𝑏 with𝑩. By our rules of associativity, this is the same as (𝑓𝑎𝑏) which we’llsometimes also write as 𝑓(𝑎, 𝑏).8.5.3 Formal description of the λ calculusWe now provide a formal description of the λ calculus. We start with“basic expressions” that contain a single variable such as đ‘„ or 𝑩 andbuild more complex expressions of the form (𝑒 𝑒â€Č) and đœ†đ‘„.𝑒 where 𝑒, 𝑒â€Čare expressions and đ‘„ is a variable idenifier. Formally λ expressionsare defined as follows:

Definition 8.12 — λ expression.. A λ expression is either a single variableidentifier or an expression 𝑒 of the one of the following forms:

‱ Application: 𝑒 = (𝑒â€Č 𝑒″), where 𝑒â€Č and 𝑒″ are λ expressions.

‱ Abstraction: 𝑒 = đœ†đ‘„.(𝑒â€Č) where 𝑒â€Č is a λ expression.

Definition 8.12 is a recursive definition since we defined the conceptof λ expressions in terms of itself. This might seem confusing at first,but in fact you have known recursive definitions since you were anelementary school student. Consider how we define an arithmeticexpression: it is an expression that is either just a number, or has one ofthe forms (𝑒 + 𝑒â€Č), (𝑒 − 𝑒â€Č), (𝑒 × 𝑒â€Č), or (𝑒 Ă· 𝑒â€Č), where 𝑒 and 𝑒â€Č are otherarithmetic expressions.

Free and bound variables. Variables in a λ expression can either befree or bound to a 𝜆 operator (in the sense of Section 1.4.7). In a single-variable λ expression 𝑣𝑎𝑟, the variable 𝑣𝑎𝑟 is free. The set of free andbound variables in an application expression 𝑒 = (𝑒â€Č 𝑒″) is the sameas that of the underlying expressions 𝑒â€Č and 𝑒″. In an abstraction ex-pression 𝑒 = 𝜆𝑣𝑎𝑟.(𝑒â€Č), all free occurences of 𝑣𝑎𝑟 in 𝑒â€Č are bound tothe 𝜆 operator of 𝑒. If you find the notion of free and bound variablesconfusing, you can avoid all these issues by using unique identifiersfor all variables.

Precedence and parenthesis. We will use the following rules to allowus to drop some parenthesis. Function application associates fromleft to right, and so 𝑓𝑔ℎ is the same as (𝑓𝑔)ℎ. Function application hasa higher precedence than the λ operator, and so đœ†đ‘„.đ‘“đ‘”đ‘„ is the same

Page 303: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 303

as đœ†đ‘„.((𝑓𝑔)đ‘„). This is similar to how we use the precedence rules inarithmetic operations to allow us to use fewer parenthesis and so writethe expression (7×3)+2 as 7×3+2. As mentioned in Section 8.5.2, wealso use the shorthand đœ†đ‘„, 𝑩.𝑒 for đœ†đ‘„.(𝜆𝑩.𝑒) and the shorthand 𝑓(đ‘„, 𝑩)for (𝑓 đ‘„) 𝑩. This plays nicely with the “Currying” transformation ofsimulating multi-input functions using λ expressions.

Equivalence of λ expressions. As we have seen in Solved Exercise 8.1,the rule that (đœ†đ‘„.đ‘’đ‘„đ‘)đ‘’đ‘„đ‘â€Č is equivalent to đ‘’đ‘„đ‘[đ‘„ → đ‘’đ‘„đ‘â€Č] enables usto modify λ expressions and obtain simpler equivalent form for them.Another rule that we can use is that the parameter does not matterand hence for example 𝜆𝑩.𝑩 is the same as 𝜆𝑧.𝑧. Together these rulesdefine the notion of equivalence of λ expressions:

Definition 8.13 — Equivalence of λ expressions. Two λ expressions areequivalent if they can be made into the same expression by repeatedapplications of the following rules:

1. Evaluation (aka đ›œ reduction): The expression (đœ†đ‘„.đ‘’đ‘„đ‘)đ‘’đ‘„đ‘â€Č isequivalent to đ‘’đ‘„đ‘[đ‘„ → đ‘’đ‘„đ‘â€Č].

2. Variable renaming (aka đ›Œ conversion): The expression đœ†đ‘„.đ‘’đ‘„đ‘is equivalent to 𝜆𝑩.đ‘’đ‘„đ‘[đ‘„ → 𝑩].

If đ‘’đ‘„đ‘ is a λ expression of the form đœ†đ‘„.đ‘’đ‘„đ‘â€Č then it naturally corre-sponds to the function that maps any input 𝑧 to đ‘’đ‘„đ‘â€Č[đ‘„ → 𝑧]. Hencethe λ calculus naturally implies a computational model. Since in the λcalculus the inputs can themselves be functions, we need to decide inwhat order we evaluate an expression such as(đœ†đ‘„.𝑓)(𝜆𝑩.𝑔𝑧) . (8.9)There are two natural conventions for this:

‱ Call by name (aka “lazy evaluation”): We evaluate (8.9) by first plug-ging in the righthand expression (𝜆𝑩.𝑔𝑧) as input to the lefthandside function, obtaining 𝑓[đ‘„ → (𝜆𝑩.𝑔𝑧)] and then continue fromthere.

‱ Call by value (aka “eager evaluation”): We evaluate (8.9) by firstevaluating the righthand side and obtaining ℎ = 𝑔[𝑩 → 𝑧], and thenplugging this into the lefthandside to obtain 𝑓[đ‘„ → ℎ].Because the λ calculus has only pure functions, that do not have

“side effects”, in many cases the order does not matter. In fact, it canbe shown that if we obtain a definite irreducible expression (for ex-ample, a number) in both strategies, then it will be the same one.

Page 304: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

304 introduction to theoretical computer science

However, for concreteness we will always use the “call by name” (i.e.,lazy evaluation) order. (The same choice is made in the programminglanguage Haskell, though many other programming languages useeager evaluation.) Formally, the evaluation of a λ expression using“call by name” is captured by the following process:

Definition 8.14 — Simplification of λ expressions. Let 𝑒 be a λ expres-sion. The simplification of 𝑒 is the result of the following recursiveprocess:

1. If 𝑒 is a single variable đ‘„ then the simplification of 𝑒 is 𝑒.2. If 𝑒 has the form 𝑒 = đœ†đ‘„.𝑒â€Č then the simplification of 𝑒 is đœ†đ‘„.𝑓 â€Č

where 𝑓 â€Č is the simplification of 𝑒â€Č.3. (Evaluation / đ›œ reduction.) If 𝑒 has the form 𝑒 = (đœ†đ‘„.𝑒â€Č 𝑒″) then

the simplification of 𝑒 is the simplification of 𝑒â€Č[đ‘„ → 𝑒″], whichdenotes replacing all copies of đ‘„ in 𝑒â€Č bound to the 𝜆 operatorwith 𝑒″

4. (Renaming / đ›Œ conversion.) The canonical simplification of 𝑒 isobtained by taking the simplification of 𝑒 and renaming the vari-ables so that the first bound variable in the expression is 𝑣0, thesecond one is 𝑣1, and so on and so forth.

We say that two λ expressions 𝑒 and 𝑒â€Č are equivalent, denoted by𝑒 ≅ 𝑒â€Č, if they have the same canonical simplification.

Solved Exercise 8.2 — Equivalence of λ expressions. Prove that the followingtwo expressions 𝑒 and 𝑓 are equivalent:

𝑒 = đœ†đ‘„.đ‘„ (8.10)

𝑓 = (𝜆𝑎.(𝜆𝑏.𝑏))(𝜆𝑧.𝑧𝑧) (8.11)

Solution:

The canonical simplification of 𝑒 is simply 𝜆𝑣0.𝑣0. To do thecanonical simplification of 𝑓 we first use đ›œ reduction to plug in𝜆𝑧.𝑧𝑧 instead of 𝑎 in (𝜆𝑏.𝑏) but since 𝑎 is not used in this function atall, we simply obtained 𝜆𝑏.𝑏 which simplifies to 𝜆𝑣0.𝑣0 as well.

Page 305: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 305

2 In Lisp, the PAIR, HEAD and TAIL functions aretraditionally called cons, car and cdr.

8.5.4 Infinite loops in the λ calculusLike Turing machines and NAND-TM programs, the simplificationprocess in the λ calculus can also enter into an infinite loop. For exam-ple, consider the λ expressionđœ†đ‘„.đ‘„đ‘„ đœ†đ‘„.đ‘„đ‘„ (8.12)

If we try to simplify (8.12) by invoking the lefthand function onthe righthand one, then we get another copy of (8.12) and hence thisnever ends. There are examples where the order of evaluation canmatter for whether or not an expression can be simplified, see Exer-cise 8.9.

8.6 THE “ENHANCED” Λ CALCULUS

We now discuss the λ calculus as a computational model. We willstart by describing an “enhanced” version of the λ calculus that con-tains some “superfluous features” but is easier to wrap your headaround. We will first show how the enhanced λ calculus is equiva-lent to Turing machines in computational power. Then we will showhow all the features of “enhanced λ calculus” can be implemented as“syntactic sugar” on top of the “pure” (i.e., non enhanced) λ calculus.Hence the pure λ calculus is equivalent in power to Turing machines(and hence also to RAM machines and all other Turing-equivalentmodels).

The enhanced λ calculus includes the following set of objects andoperations:

‱ Boolean constants and IF function: There are λ expressions 0, 1and IF that satisfy the following conditions: for every λ expression𝑒 and 𝑓 , IF 1 𝑒 𝑓 = 𝑒 and IF 0 𝑒 𝑓 = 𝑓 . That is, IF is the function thatgiven three arguments 𝑎, 𝑒, 𝑓 outputs 𝑒 if 𝑎 = 1 and 𝑓 if 𝑎 = 0.

‱ Pairs: There is a λ expression PAIR which we will think of as thepairing function. For every λ expressions 𝑒, 𝑓 , PAIR 𝑒 𝑓 is thepair ⟹𝑒, đ‘“âŸ© that contains 𝑒 as its first member and 𝑓 as its secondmember. We also have λ expressions HEAD and TAIL that extractthe first and second member of a pair respectively. Hence, for everyλ expressions 𝑒, 𝑓 , HEAD (PAIR 𝑒 𝑓) = 𝑒 and TAIL (PAIR 𝑒 𝑓) = 𝑓 .2

‱ Lists and strings: There is λ expression NIL that corresponds tothe empty list, which we also denote by ⟚⊄⟩. Using PAIR and NILwe construct lists. The idea is that if 𝐿 is a 𝑘 element list of theform ⟹𝑒1, 𝑒2, 
 , 𝑒𝑘, ⊄⟩ then for every λ expression 𝑒0 we can obtainthe 𝑘 + 1 element list ⟹𝑒0, 𝑒1, 𝑒2, 
 , 𝑒𝑘, ⊄⟩ using the expressionPAIR 𝑒0 𝐿. For example, for every three λ expressions 𝑒, 𝑓, 𝑔, the

Page 306: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

306 introduction to theoretical computer science

following corresponds to the three element list ⟹𝑒, 𝑓, 𝑔, ⊄⟩:PAIR 𝑒 (PAIR 𝑓 (PAIR 𝑔 NIL)) . (8.13)

The λ expression ISEMPTY returns 1 on NIL and returns 0 on everyother list. A string is simply a list of bits.

‱ List operations: The enhanced λ calculus also contains thelist-processing functions MAP, REDUCE, and FILTER. Givena list 𝐿 = âŸšđ‘„0, 
 , đ‘„đ‘›âˆ’1, ⊄⟩ and a function 𝑓 , MAP 𝐿 𝑓 ap-plies 𝑓 on every member of the list to obtain the new list𝐿â€Č = ⟹𝑓(đ‘„0), 
 , 𝑓(đ‘„đ‘›âˆ’1), ⊄⟩. Given a list 𝐿 as above and anexpression 𝑓 whose output is either 0 or 1, FILTER 𝐿 𝑓 returns thelist âŸšđ‘„đ‘–âŸ©đ‘“đ‘„đ‘–=1 containing all the elements of 𝐿 for which 𝑓 outputs1. The function REDUCE applies a “combining” operation to alist. For example, REDUCE 𝐿 + 0 will return the sum of all theelements in the list 𝐿. More generally, REDUCE takes a list 𝐿, anoperation 𝑓 (which we think of as taking two arguments) and a λexpression 𝑧 (which we think of as the “neutral element” for theoperation 𝑓 , such as 0 for addition and 1 for multiplication). Theoutput is defined via

REDUCE 𝐿 𝑓 𝑧 = âŽ§âŽšâŽ©đ‘§ 𝐿 = NIL𝑓 (HEAD 𝐿) (REDUCE (TAIL 𝐿) 𝑓 𝑧) otherwise.

(8.14)See Fig. 8.16 for an illustration of the three list-processing operations.

‱ Recursion: Finally, we want to be able to execute recursive func-tions. Since in λ calculus functions are anonymous, we can’t writea definition of the form 𝑓(đ‘„) = 𝑏𝑙𝑎ℎ where 𝑏𝑙𝑎ℎ includes calls to𝑓 . Instead we use functions 𝑓 that take an additional input 𝑚𝑒 as aparameter. The operator RECURSE will take such a function 𝑓 asinput and return a “recursive version” of 𝑓 where all the calls to 𝑚𝑒are replaced by recursive calls to this function. That is, if we have afunction đč taking two parameters 𝑚𝑒 and đ‘„, then RECURSE đč willbe the function 𝑓 taking one parameter đ‘„ such that 𝑓(đ‘„) = đč(𝑓, đ‘„)for every đ‘„.

Solved Exercise 8.3 — Compute NAND using λ calculus. Give a λ expression𝑁 such that 𝑁 đ‘„ 𝑩 = NAND(đ‘„, 𝑩) for every đ‘„, 𝑩 ∈ 0, 1.

Page 307: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 307

Solution:

The NAND of đ‘„, 𝑩 is equal to 1 unless đ‘„ = 𝑩 = 1. Hence we canwrite 𝑁 = đœ†đ‘„, 𝑩.IF(đ‘„, IF(𝑩, 0, 1), 1) (8.15)

Solved Exercise 8.4 — Compute XOR using λ calculus. Give a λ expressionXOR such that for every list 𝐿 = âŸšđ‘„0, 
 , đ‘„đ‘›âˆ’1, ⊄⟩ where đ‘„đ‘– ∈ 0, 1 for𝑖 ∈ [𝑛], XOR𝐿 evaluates to ∑ đ‘„đ‘– mod 2.

Solution:

First, we note that we can compute XOR of two bits as follows:

NOT = 𝜆𝑎.IF(𝑎, 0, 1) (8.16)

andXOR2 = 𝜆𝑎, 𝑏.IF(𝑏,NOT(𝑎), 𝑎) (8.17)

(We are using here a bit of syntactic sugar to describe the func-tions. To obtain the λ expression for XOR we will simply replacethe expression (8.16) in (8.17).) Now recursively we can define theXOR of a list as follows:

XOR(𝐿) = ⎧⎚⎩0 𝐿 is emptyXOR2(HEAD(𝐿),XOR(TAIL(𝐿))) otherwise

(8.18)This means that XOR is equal to

RECURSE (𝜆𝑚𝑒, 𝐿.IF(ISEMPTY(𝐿), 0,XOR2(HEAD 𝐿 , 𝑚𝑒(TAIL 𝐿)))) .(8.19)

That is, XOR is obtained by applying the RECURSE operatorto the function that on inputs 𝑚𝑒, 𝐿, returns 0 if ISEMPTY(𝐿) andotherwise returns XOR2 applied to HEAD(𝐿) and to 𝑚𝑒(TAIL(𝐿)).

We could have also computed XOR using the REDUCE opera-tion, we leave working this out as an exercise to the reader.

8.6.1 Computing a function in the enhanced λ calculusAn enhanced λ expression is obtained by composing the objects abovewith the application and abstraction rules. The result of simplifying a λ

Page 308: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

308 introduction to theoretical computer science

Figure 8.15: A list âŸšđ‘„0, đ‘„1, đ‘„2⟩ in the λ calculus is con-structed from the tail up, building the pair âŸšđ‘„2,NIL⟩,then the pair âŸšđ‘„1, âŸšđ‘„2,NIL⟩⟩ and finally the pairâŸšđ‘„0, âŸšđ‘„1, âŸšđ‘„2,NIL⟩⟩⟩. That is, a list is a pair wherethe first element of the pair is the first element of thelist and the second element is the rest of the list. Thefigure on the left renders this “pairs inside pairs”construction, though it is often easier to think of a listas a “chain”, as in the figure on the right, where thesecond element of each pair is thought of as a link,pointer or reference to the remainder of the list.

Figure 8.16: Illustration of the MAP, FILTER andREDUCE operations.

expression is an equivalent expression, and hence if two expressionshave the same simplification then they are equivalent.

Definition 8.15 — Computing a function via λ calculus. Let đč ∶ 0, 1∗ →0, 1∗We say that đ‘’đ‘„đ‘ computes đč if for every đ‘„ ∈ 0, 1∗,đ‘’đ‘„đ‘âŸšđ‘„0, 
 , đ‘„đ‘›âˆ’1, ⊄⟩ ≅ ⟹𝑩0, 
 , 𝑩𝑚−1, ⊄⟩ (8.20)where 𝑛 = |đ‘„|, 𝑩 = đč(đ‘„), and 𝑚 = |𝑩|, and the notion of equiva-

lence is defined as per Definition 8.14.

8.6.2 Enhanced λ calculus is Turing-completeThe basic operations of the enhanced λ calculus more or less amountto the Lisp or Scheme programming languages. Given that, it is per-haps not surprising that the enhanced λ-calculus is equivalent toTuring machines:

Theorem 8.16 — Lambda calculus and NAND-TM. For every functionđč ∶ 0, 1∗ → 0, 1∗, đč is computable in the enhanced λ calculus ifand only if it is computable by a Turing machine.

Page 309: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 309

Proof Idea:

To prove the theorem, we need to show that (1) if đč is computableby a λ calculus expression then it is computable by a Turing machine,and (2) if đč is computable by a Turing machine, then it is computableby an enhanced λ calculus expression.

Showing (1) is fairly straightforward. Applying the simplificationrules to a λ expression basically amounts to “search and replace”which we can implement easily in, say, NAND-RAM, or for thatmatter Python (both of which are equivalent to Turing machines inpower). Showing (2) essentially amounts to simulating a Turing ma-chine (or writing a NAND-TM interpreter) in a functional program-ming language such as LISP or Scheme. We give the details below buthow this can be done is a good exercise in mastering some functionalprogramming techniques that are useful in their own right.⋆Proof of Theorem 8.16. We only sketch the proof. The “if” directionis simple. As mentioned above, evaluating λ expressions basicallyamounts to “search and replace”. It is also a fairly straightforwardprogramming exercise to implement all the above basic operations inan imperative language such as Python or C, and using the same ideaswe can do so in NAND-RAM as well, which we can then transform toa NAND-TM program.

For the “only if” direction we need to simulate a Turing machineusing a λ expression. We will do so by first showing that showingfor every Turing machine 𝑀 a λ expression to compute the next-stepfunction NEXT𝑀 ∶ Σ∗ → Σ∗ that maps a configuration of 𝑀 to the nextone (see Section 8.4.2).

A configuration of 𝑀 is a string đ›Œ ∈ Σ∗ for a finite set ÎŁ. We canencode every symbol 𝜎 ∈ ÎŁ by a finite string 0, 1ℓ, and so we willencode a configuration đ›Œ in the λ calculus as a list âŸšđ›Œ0, đ›Œ1, 
 , đ›Œđ‘šâˆ’1, ⊄⟩where đ›Œđ‘– is an ℓ-length string (i.e., an ℓ-length list of 0’s and 1’s) en-coding a symbol in ÎŁ.

By Lemma 8.9, for every đ›Œ ∈ Σ∗, NEXT𝑀(đ›Œ)𝑖 is equal to𝑟(đ›Œđ‘–âˆ’1, đ›Œđ‘–, đ›Œđ‘–+1) for some finite function 𝑟 ∶ ÎŁ3 → ÎŁ. Using ourencoding of ÎŁ as 0, 1ℓ, we can also think of 𝑟 as mapping 0, 13ℓ to0, 1ℓ. By Solved Exercise 8.3, we can compute the NAND function,and hence every finite function, including 𝑟, using the λ calculus.Using this insight, we can compute NEXT𝑀 using the λ calculus asfollows. Given a list 𝐿 encoding the configuration đ›Œ0 ⋯ đ›Œđ‘šâˆ’1, wedefine the lists 𝐿𝑝𝑟𝑒𝑣 and đżđ‘›đ‘’đ‘„đ‘Ą encoding the configuration đ›Œ shiftedby one step to the right and left respectively. The next configurationđ›Œâ€Č is defined as đ›Œâ€Č𝑖 = 𝑟(𝐿𝑝𝑟𝑒𝑣[𝑖], 𝐿[𝑖], đżđ‘›đ‘’đ‘„đ‘Ą[𝑖]) where we let 𝐿â€Č[𝑖] denote

Page 310: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

310 introduction to theoretical computer science

the 𝑖-th element of 𝐿â€Č. This can be computed by recursion (and henceusing the enhanced λ calculus’ RECURSE operator) as follows:

Algorithm 8.17 — 𝑁𝐾𝑋𝑇𝑀 using the λ calculus.

Input: List 𝐿 = âŸšđ›Œ0, đ›Œ1, 
 , đ›Œđ‘šâˆ’1, ⊄⟩ encoding a configura-tion đ›Œ.

Output: List 𝐿â€Č encoding 𝑁𝐾𝑋𝑇𝑀(đ›Œ)1: procedure ComputeNext(𝐿𝑝𝑟𝑒𝑣, 𝐿, đżđ‘›đ‘’đ‘„đ‘Ą)2: if thenđŒđ‘†đžđ‘€đ‘ƒđ‘‡ 𝑌 𝐿𝑝𝑟𝑒𝑣3: return đ‘đŒđż4: end if5: 𝑎 ← đ»đžđŽđ· 𝐿𝑝𝑟𝑒𝑣6: if thenđŒđ‘†đžđ‘€đ‘ƒđ‘‡ 𝑌 𝐿7: 𝑏 ← ∅ # Encoding of ∅ in 0, 1ℓ8: else9: 𝑏 ← đ»đžđŽđ· 𝐿

10: end if11: if thenđŒđ‘†đžđ‘€đ‘ƒđ‘‡ 𝑌 đżđ‘›đ‘’đ‘„đ‘Ą12: 𝑐 ← ∅13: else14: 𝑐 ← đ»đžđŽđ· đżđ‘›đ‘’đ‘„đ‘Ą15: end if16: return đ‘ƒđŽđŒđ‘… 𝑟(𝑎, 𝑏, 𝑐) ComputeNext(𝑇 đŽđŒđż 𝐿𝑝𝑟𝑒𝑣 , 𝑇 đŽđŒđż 𝐿 , 𝑇 đŽđŒđż đżđ‘›đ‘’đ‘„đ‘Ą)17: end procedure18: 𝐿𝑝𝑟𝑒𝑣 ← đ‘ƒđŽđŒđ‘… ∅ 𝐿 # 𝐿𝑝𝑟𝑒𝑣 = ⟹∅, đ›Œ0, 
 , đ›Œđ‘šâˆ’1, ⊄⟩19: đżđ‘›đ‘’đ‘„đ‘Ą ← 𝑇 đŽđŒđż 𝐿 # đżđ‘›đ‘’đ‘„đ‘Ą = âŸšđ›Œ1, 
 , đ›Œđ‘šâˆ’1, ⊄20: return ComputeNext(𝐿𝑝𝑟𝑒𝑣, 𝐿, đżđ‘›đ‘’đ‘„đ‘Ą)

Once we can compute NEXT𝑀 , we can simulate the execution of𝑀 on input đ‘„ using the following recursion. Define FINAL(đ›Œ) to bethe final configuration of 𝑀 when initialized at configuration đ›Œ. Thefunction FINAL can be defined recursively as follows:

FINAL(đ›Œ) = âŽ§âŽšâŽ©đ›Œ đ›Œ is halting configurationNEXT𝑀(đ›Œ) otherwise

. (8.21)

Checking whether a configuration is halting (i.e., whether it isone in which the transition function would output Halt) can be easilyimplemented in the 𝜆 calculus, and hence we can use the RECURSEto compute FINAL. If we let đ›Œ0 be the initial configuration of 𝑀 oninput đ‘„ then we can obtain the output 𝑀(đ‘„) from FINAL(đ›Œ0), hencecompleting the proof.

Page 311: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 311

8.7 FROM ENHANCED TO PURE Λ CALCULUS

While the collection of “basic” functions we allowed for the enhancedλ calculus is smaller than what’s provided by most Lisp dialects, com-ing from NAND-TM it still seems a little “bloated”. Can we make dowith less? In other words, can we find a subset of these basic opera-tions that can implement the rest?

It turns out that there is in fact a proper subset of the operations ofthe enhanced λ calculus that can be used to implement the rest. Thatsubset is the empty set. That is, we can implement all the operationsabove using the λ formalism only, even without using 0’s and 1’s. It’sλ’s all the way down!

PThis is a good point to pause and think howyou would implement these operations your-self. For example, start by thinking how youcould implement MAP using REDUCE, andthen REDUCE using RECURSE combined with0, 1, IF,PAIR,HEAD,TAIL,NIL, ISEMPTY. You canalso PAIR, HEAD and TAIL based on 0, 1, IF. The mostchallenging part is to implement RECURSE using onlythe operations of the pure λ calculus.

Theorem 8.18 — Enhanced λ calculus equivalent to pure λ calculus.. Thereare λ expressions that implement the functions 0,1,IF,PAIR, HEAD,TAIL, NIL, ISEMPTY, MAP, REDUCE, and RECURSE.

The idea behind Theorem 8.18 is that we encode 0 and 1 them-selves as λ expressions, and build things up from there. This is knownas Church encoding, as it was originated by Church in his effort toshow that the λ calculus can be a basis for all computation. We willnot write the full formal proof of Theorem 8.18 but outline the ideasinvolved in it:

‱ We define 0 to be the function that on two inputs đ‘„, 𝑩 outputs 𝑩,and 1 to be the function that on two inputs đ‘„, 𝑩 outputs đ‘„. We useCurrying to achieve the effect of two-input functions and hence0 = đœ†đ‘„.𝜆𝑩.𝑩 and 1 = đœ†đ‘„.𝜆𝑩.đ‘„. (This representation scheme is thecommon convention for representing false and true but there aremany other alternative representations for 0 and 1 that would haveworked just as well.)

‱ The above implementation makes the IF function trivial:IF(𝑐𝑜𝑛𝑑, 𝑎, 𝑏) is simply 𝑐𝑜𝑛𝑑 𝑎 𝑏 since 0𝑎𝑏 = 𝑏 and 1𝑎𝑏 = 𝑎. Wecan write IF = đœ†đ‘„.đ‘„ to achieve IF(𝑐𝑜𝑛𝑑, 𝑎, 𝑏) = (((IF𝑐𝑜𝑛𝑑)𝑎)𝑏) =𝑐𝑜𝑛𝑑 𝑎 𝑏.

Page 312: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

312 introduction to theoretical computer science

‱ To encode a pair (đ‘„, 𝑩) we will produce a function đ‘“đ‘„,𝑩 that has đ‘„and 𝑩 “in its belly” and satisfies đ‘“đ‘„,𝑩𝑔 = đ‘”đ‘„đ‘Š for every function 𝑔.That is, PAIR = đœ†đ‘„, 𝑩. (𝜆𝑔.đ‘”đ‘„đ‘Š). We can extract the first element ofa pair 𝑝 by writing 𝑝1 and the second element by writing 𝑝0, and soHEAD = 𝜆𝑝.𝑝1 and TAIL = 𝜆𝑝.𝑝0.

‱ We define NIL to be the function that ignores its input and alwaysoutputs 1. That is, NIL = đœ†đ‘„.1. The ISEMPTY function checks,given an input 𝑝, whether we get 1 if we apply 𝑝 to the function𝑧𝑒𝑟𝑜 = đœ†đ‘„, 𝑩.0 that ignores both its inputs and always outputs 0. Forevery valid pair of the form 𝑝 = PAIRđ‘„đ‘Š, 𝑝𝑧𝑒𝑟𝑜 = đ‘đ‘„đ‘Š = 0 whileNIL𝑧𝑒𝑟𝑜 = 1. Formally, ISEMPTY = 𝜆𝑝.𝑝(đœ†đ‘„, 𝑩.0).

RRemark 8.19 — Church numerals (optional). There isnothing special about Boolean values. You can usesimilar tricks to implement natural numbers usingλ terms. The standard way to do so is to representthe number 𝑛 by the function ITER𝑛 that on input afunction 𝑓 outputs the function đ‘„ ↩ 𝑓(𝑓(⋯ 𝑓(đ‘„))) (𝑛times). That is, we represent the natural number 1 as𝜆𝑓.𝑓 , the number 2 as 𝜆𝑓.(đœ†đ‘„.𝑓(đ‘“đ‘„)), the number 3 as𝜆𝑓.(đœ†đ‘„.𝑓(𝑓(đ‘“đ‘„))), and so on and so forth. (Note thatthis is not the same representation we used for 1 inthe Boolean context: this is fine; we already know thatthe same object can be represented in more than oneway.) The number 0 is represented by the functionthat maps any function 𝑓 to the identity function đœ†đ‘„.đ‘„.(That is, 0 = 𝜆𝑓.(đœ†đ‘„.đ‘„).)In this representation, we can compute PLUS(𝑛, 𝑚)as 𝜆𝑓.đœ†đ‘„.(𝑛𝑓)((𝑚𝑓)đ‘„) and TIMES(𝑛, 𝑚) as 𝜆𝑓.𝑛(𝑚𝑓).Subtraction and division are trickier, but can beachieved using recursion. (Working this out is a greatexercise.)

8.7.1 List processingNow we come to a bigger hurdle, which is how to implementMAP, FILTER, REDUCE and RECURSE in the pure λ calculus. Itturns out that we can build MAP and FILTER from REDUCE, andREDUCE from RECURSE. For example MAP(𝐿, 𝑓) is the same asREDUCE(𝐿, 𝑔) where 𝑔 is the operation that on input đ‘„ and 𝑩, outputsPAIR(𝑓(đ‘„),NIL) if 𝑩 is NIL and otherwise outputs PAIR(𝑓(đ‘„), 𝑩). (Ileave checking this as a (recommended!) exercise for you, the reader.)

We can define REDUCE(𝐿, 𝑔) recursively, by settingREDUCE(NIL, 𝑔) = NIL and stipulating that given a non-empty list 𝐿, which we can think of as a pair (ℎ𝑒𝑎𝑑, 𝑟𝑒𝑠𝑡),

Page 313: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 313

REDUCE(𝐿, 𝑔) = 𝑔(ℎ𝑒𝑎𝑑,REDUCE(𝑟𝑒𝑠𝑡, 𝑔))). Thus, we mighttry to write a recursive λ expression for REDUCE as follows

REDUCE = 𝜆𝐿, 𝑔.IF(ISEMPTY(𝐿),NIL, 𝑔HEAD(𝐿)REDUCE(TAIL(𝐿), 𝑔)) .(8.22)

The only fly in this ointment is that the λ calculus does not have thenotion of recursion, and so this is an invalid definition. But of coursewe can use our RECURSE operator to solve this problem. We willreplace the recursive call to “REDUCE” with a call to a function 𝑚𝑒that is given as an extra argument, and then apply RECURSE to this.Thus REDUCE = RECURSE đ‘šđ‘Šđ‘…đžđ·đ‘ˆđ¶đž where

đ‘šđ‘Šđ‘…đžđ·đ‘ˆđ¶đž = 𝜆𝑚𝑒, 𝐿, 𝑔.IF(ISEMPTY(𝐿),NIL, 𝑔HEAD(𝐿)𝑚𝑒(TAIL(𝐿), 𝑔)) .(8.23)

8.7.2 The Y combinator, or recursion without recursionEq. (8.23) means that implementing MAP, FILTER, and REDUCE boilsdown to implementing the RECURSE operator in the pure λ calculus.This is what we do now.

How can we implement recursion without recursion? We willillustrate this using a simple example - the XOR function. As shown inSolved Exercise 8.4, we can write the XOR function of a list recursivelyas follows:

XOR(𝐿) = ⎧⎚⎩0 𝐿 is emptyXOR2(HEAD(𝐿),XOR(TAIL(𝐿))) otherwise

(8.24)

where XOR2 ∶ 0, 12 → 0, 1 is the XOR on two bits. In Python wewould write this asdef xor2(a,b): return 1-b if a else bdef head(L): return L[0]def tail(L): return L[1:]

def xor(L): return xor2(head(L),xor(tail(L))) if L else 0

print(xor([0,1,1,0,0,1]))# 1

Now, how could we eliminate this recursive call? The main idea isthat since functions can take other functions as input, it is perfectlylegal in Python (and the λ calculus of course) to give a function itselfas input. So, our idea is to try to come up with a non recursive functiontempxor that takes two inputs: a function and a list, and such thattempxor(tempxor,L)will output the XOR of L!

Page 314: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

314 introduction to theoretical computer science

PAt this point you might want to stop and try to im-plement this on your own in Python or any otherprogramming language of your choice (as long as itallows functions as inputs).

Our first attempt might be to simply use the idea of replacing therecursive call by me. Let’s define this function as myxor

def myxor(me,L): return xor2(head(L),me(tail(L))) if Lelse 0

Let’s test this out:

myxor(myxor,[1,0,1])

If you do this, you will get the following complaint from the inter-preter:

TypeError: myxor() missing 1 required positional argu-ment

The problem is that myxor expects two inputs- a function and alist- while in the call to me we only provided a list. To correct this, wemodify the call to also provide the function itself:

def tempxor(me,L): return xor2(head(L),me(me,tail(L))) ifL else 0

Note the call me(me,..) in the definition of tempxor: given a func-tion me as input, tempxor will actually call the function me with itselfas the first input. If we test this out now, we see that we actually getthe right result!

tempxor(tempxor,[1,0,1])# 0tempxor(tempxor,[1,0,1,1])# 1

and so we can define xor(L) as simply return tem-pxor(tempxor,L).

The approach above is not specific to XOR. Given a recursive func-tion f that takes an input x, we can obtain a non recursive version asfollows:

1. Create the function myf that takes a pair of inputs me and x, andreplaces recursive calls to f with calls to me.

2. Create the function tempf that converts calls in myf of the formme(x) to calls of the form me(me,x).

Page 315: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 315

3 Because of specific issues of Python syntax, in thisimplementation we use f * g for applying f to grather than fg, and use λx(exp) rather than λx.expfor abstraction. We also use _0 and _1 for the λ termsfor 0 and 1 so as not to confuse with the Pythonconstants.

3. The function f(x) will be defined as tempf(tempf,x)

Here is the way we implement the RECURSE operator in Python. Itwill take a function myf as above, and replace it with a function g suchthat g(x)=myf(g,x) for every x.

def RECURSE(myf):def tempf(me,x): return myf(lambda y: me(me,y),x)

return lambda x: tempf(tempf,x)

xor = RECURSE(myxor)

print(xor([0,1,1,0,0,1]))# 1

print(xor([1,1,0,0,1,1,1,1]))# 0

From Python to the calculus. In the λ calculus, a two input function𝑔 that takes a pair of inputs 𝑚𝑒, 𝑩 is written as 𝜆𝑚𝑒.(𝜆𝑩.𝑔). So thefunction 𝑩 ↩ 𝑚𝑒(𝑚𝑒, 𝑩) is simply written as 𝑚𝑒 𝑚𝑒 and similarlythe function đ‘„ ↩ 𝑡𝑒𝑚𝑝𝑓(𝑡𝑒𝑚𝑝𝑓, đ‘„) is simply 𝑡𝑒𝑚𝑝𝑓 𝑡𝑒𝑚𝑝𝑓 . (Canyou see why?) Therefore the function tempf defined above can bewritten as λ me. myf(me me). This means that if we denote the inputof RECURSE by 𝑓 , then RECURSE 𝑚𝑩𝑓 = 𝑡𝑒𝑚𝑝𝑓 𝑡𝑒𝑚𝑝𝑓 where 𝑡𝑒𝑚𝑝𝑓 =𝜆𝑚.𝑓(𝑚 𝑚) or in other words

RECURSE = 𝜆𝑓.((𝜆𝑚.𝑓(𝑚 𝑚)) (𝜆𝑚.𝑓(𝑚 𝑚))) (8.25)

The online appendix contains an implementation of the λ calcu-lus using Python. Here is an implementation of the recursive XORfunction from that appendix:3

# XOR of two bitsXOR2 = λ(a,b)(IF(a,IF(b,_0,_1),b))

# Recursive XOR with recursive calls replaced by mparameter

myXOR = λ(m,l)(IF(ISEMPTY(l),_0,XOR2(HEAD(l),m(TAIL(l)))))

# Recurse operator (aka Y combinator)RECURSE = λf((λm(f(m*m)))(λm(f(m*m))))

# XOR function

Page 316: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

316 introduction to theoretical computer science

XOR = RECURSE(myXOR)

#TESTING:

XOR(PAIR(_1,NIL)) # List [1]# equals 1

XOR(PAIR(_1,PAIR(_0,PAIR(_1,NIL)))) # List [1,0,1]# equals 0

RRemark 8.20 — The Y combinator. The RECURSE opera-tor above is better known as the Y combinator.It is one of a family of a fixed point operators that givena lambda expression đč , find a fixed point 𝑓 of đč suchthat 𝑓 = đč𝑓 . If you think about it, XOR is the fixedpoint of 𝑚𝑩𝑋𝑂𝑅 above. XOR is the function suchthat for every đ‘„, if plug in XOR as the first argumentof 𝑚𝑩𝑋𝑂𝑅 then we get back XOR, or in other wordsXOR = 𝑚𝑩𝑋𝑂𝑅 XOR. Hence finding a fixed point for𝑚𝑩𝑋𝑂𝑅 is the same as applying RECURSE to it.

8.8 THE CHURCH-TURING THESIS (DISCUSSION)“[In 1934], Church had been speculating, and finally definitely proposed, thatthe λ-definable functions are all the effectively calculable functions 
. WhenChurch proposed this thesis, I sat down to disprove it 
 but, quickly realizingthat [my approach failed], I became overnight a supporter of the thesis.”,Stephen Kleene, 1979.

“[The thesis is] not so much a definition or to an axiom but 
 a natural law.”,Emil Post, 1936.

We have defined functions to be computable if they can be computedby a NAND-TM program, and we’ve seen that the definition wouldremain the same if we replaced NAND-TM programs by Python pro-grams, Turing machines, λ calculus, cellular automata, and manyother computational models. The Church-Turing thesis is that this isthe only sensible definition of “computable” functions. Unlike the“Physical Extended Church-Turing Thesis” (PECTT) which we sawbefore, the Church-Turing thesis does not make a concrete physicalprediction that can be experimentally tested, but it certainly motivatespredictions such as the PECTT. One can think of the Church-TuringThesis as either advocating a definitional choice, making some pre-diction about all potential computing devices, or suggesting somelaws of nature that constrain the natural world. In Scott Aaronson’s

Page 317: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 317

words, “whatever it is, the Church-Turing thesis can only be regardedas extremely successful”. No candidate computing device (includingquantum computers, and also much less reasonable models such asthe hypothetical “closed time curve” computers we mentioned before)has so far mounted a serious challenge to the Church-Turing thesis.These devices might potentially make some computations more effi-cient, but they do not change the difference between what is finitelycomputable and what is not. (The extended Church-Turing thesis,which we discuss in Section 13.3, stipulates that Turing machines cap-ture also the limit of what can be efficiently computable. Just like itsphysical version, quantum computing presents the main challenge tothis thesis.)

8.8.1 Different models of computationWe can summarize the models we have seen in the following table:

Table 8.1: Different models for computing finite functions andfunctions with arbitrary input length.

Computationalproblems Type of model ExamplesFinite functions𝑓 ∶ 0, 1𝑛 → 0, 1𝑚 Non uniform

computation(algorithmdepends on inputlength)

Boolean circuits,NAND circuits,straight-line programs(e.g., NAND-CIRC)

Functions withunbounded inputsđč ∶ 0, 1∗ → 0, 1∗

Sequential accessto memory

Turing machines,NAND-TM programs

– Indexed access /RAM

RAM machines,NAND-RAM, modernprogramminglanguages

– Other Lambda calculus,cellular automata

Later on in Chapter 17 we will study memory bounded computa-tion. It turns out that NAND-TM programs with a constant amountof memory are equivalent to the model of finite automata (the adjec-tives “deterministic” or “nondeterministic” are sometimes added aswell, this model is also known as finite state machines) which in turncaptures the notion of regular languages (those that can be described byregular expressions), which is a concept we will see in Chapter 10.

Page 318: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

318 introduction to theoretical computer science

Chapter Recap

‱ While we defined computable functions usingTuring machines, we could just as well have doneso using many other models, including not justNAND-TM programs but also RAM machines,NAND-RAM, the λ-calculus, cellular automata andmany other models.

‱ Very simple models turn out to be “Turing com-plete” in the sense that they can simulate arbitrarilycomplex computation.

8.9 EXERCISES

Exercise 8.1 — Alternative proof for TM/RAM equivalence. Let SEARCH ∶0, 1∗ → 0, 1∗ be the following function. The input is a pair(𝐿, 𝑘) where 𝑘 ∈ 0, 1∗, 𝐿 is an encoding of a list of key value pairs(𝑘0, 𝑣1), 
 , (𝑘𝑚−1, 𝑣𝑚−1) where 𝑘0, 
 , 𝑘𝑚−1, 𝑣0, 
 , 𝑣𝑚−1 are binarystrings. The output is 𝑣𝑖 for the smallest 𝑖 such that 𝑘𝑖 = 𝑘, if such 𝑖exists, and otherwise the empty string.

1. Prove that SEARCH is computable by a Turing machine.

2. Let UPDATE(𝐿, 𝑘, 𝑣) be the function whose input is a list 𝐿 of pairs,and whose output is the list 𝐿â€Č obtained by prepending the pair(𝑘, 𝑣) to the beginning of 𝐿. Prove that UPDATE is computable by aTuring machine.

3. Suppose we encode the configuration of a NAND-RAM programby a list 𝐿 of key/value pairs where the key is either the name ofa scalar variable foo or of the form Bar[<num>] for some num-ber <num> and it contains all the nonzero values of variables. LetNEXT(𝐿) be the function that maps a configuration of a NAND-RAM program at one step to the configuration in the next step.Prove that NEXT is computable by a Turing machine (you don’thave to implement each one of the arithmetic operations: it isenough to implement addition and multiplication).

4. Prove that for every đč ∶ 0, 1∗ → 0, 1∗ that is computable by aNAND-RAM program, đč is computable by a Turing machine.

Exercise 8.2 — NAND-TM lookup. This exercise shows part of the proof thatNAND-TM can simulate NAND-RAM. Produce the code of a NAND-TM program that computes the function LOOKUP ∶ 0, 1∗ → 0, 1that is defined as follows. On input 𝑝𝑓(𝑖)đ‘„, where 𝑝𝑓(𝑖) denotes aprefix-free encoding of an integer 𝑖, LOOKUP(𝑝𝑓(𝑖)đ‘„) = đ‘„đ‘– if 𝑖 < |đ‘„|

Page 319: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 319

4 You don’t have to give a full description of a Turingmachine: use our “have the cake and eat it too”paradigm to show the existence of such a machine byarguing from more powerful equivalent models.

5 Same hint as Exercise 8.5 applies. Note that forshowing that LONGPATH is computable you don’thave to give an efficient algorithm.

and LOOKUP(𝑝𝑓(𝑖)đ‘„) = 0 otherwise. (We don’t care what LOOKUPoutputs on inputs that are not of this form.) You can choose anyprefix-free encoding of your choice, and also can use your favoriteprogramming language to produce this code.

Exercise 8.3 — Pairing. Let 𝑒𝑚𝑏𝑒𝑑 ∶ ℕ2 → ℕ be the function defined as𝑒𝑚𝑏𝑒𝑑(đ‘„0, đ‘„1) = 12 (đ‘„0 + đ‘„1)(đ‘„0 + đ‘„1 + 1) + đ‘„1.1. Prove that for every đ‘„0, đ‘„1 ∈ ℕ, 𝑒𝑚𝑏𝑒𝑑(đ‘„0, đ‘„1) is indeed a natural

number.

2. Prove that 𝑒𝑚𝑏𝑒𝑑 is one-to-one

3. Construct a NAND-TM program 𝑃 such that for every đ‘„0, đ‘„1 ∈ ℕ,𝑃(𝑝𝑓(đ‘„0)𝑝𝑓(đ‘„1)) = 𝑝𝑓(𝑒𝑚𝑏𝑒𝑑(đ‘„0, đ‘„1)), where 𝑝𝑓 is the prefix-freeencoding map defined above. You can use the syntactic sugar forinner loops, conditionals, and incrementing/decrementing thecounter.

4. Construct NAND-TM programs 𝑃0, 𝑃1 such that for for everyđ‘„0, đ‘„1 ∈ ℕ and 𝑖 ∈ 𝑁 , 𝑃𝑖(𝑝𝑓(𝑒𝑚𝑏𝑒𝑑(đ‘„0, đ‘„1))) = 𝑝𝑓(đ‘„đ‘–). You canuse the syntactic sugar for inner loops, conditionals, and increment-ing/decrementing the counter.

Exercise 8.4 — Shortest Path. Let SHORTPATH ∶ 0, 1∗ → 0, 1∗be the function that on input a string encoding a triple (đș, 𝑱, 𝑣) out-puts a string encoding ∞ if 𝑱 and 𝑣 are disconnected in đș or a stringencoding the length 𝑘 of the shortest path from 𝑱 to 𝑣. Prove thatSHORTPATH is computable by a Turing machine. See footnote forhint.4

Exercise 8.5 — Longest Path. Let LONGPATH ∶ 0, 1∗ → 0, 1∗ bethe function that on input a string encoding a triple (đș, 𝑱, 𝑣) outputsa string encoding ∞ if 𝑱 and 𝑣 are disconnected in đș or a string en-coding the length 𝑘 of the longest simple path from 𝑱 to 𝑣. Prove thatLONGPATH is computable by a Turing machine. See footnote forhint.5

Exercise 8.6 — Shortest path λ expression. Let SHORTPATH be as inExercise 8.4. Prove that there exists a 𝜆 expression that computesSHORTPATH. You can use Exercise 8.4

Exercise 8.7 — Next-step function is local. Prove Lemma 8.9 and use it tocomplete the proof of Theorem 8.7.

Page 320: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

320 introduction to theoretical computer science

6 Hint: You can reduce the number of variables afunction takes by “pairing them up”. That is, define aλ expression PAIR such that for every đ‘„, 𝑩 PAIRđ‘„đ‘Š issome function 𝑓 such that 𝑓0 = đ‘„ and 𝑓1 = 𝑩. Thenuse PAIR to iteratively reduce the number of variablesused.

7 Use structural induction on the expression 𝑒.

8 The name 𝑧𝑖𝑝 is a common name for this operation,for example in Python. It should not be confused withthe zip compression file format.

9 Use MAP and REDUCE (and potentially FILTER).You might also find the function 𝑧𝑖𝑝 of Exercise 8.10useful.

10 Try to set up a procedure such that if array Leftcontains an encoding of a λ expression đœ†đ‘„.𝑒 andarray Right contains an encoding of another λ expres-sion 𝑒â€Č, then the array Result will contain 𝑒[đ‘„ → 𝑒â€Č].

Exercise 8.8 — λ calculus requires at most three variables. Prove that for ev-ery λ-expression 𝑒 with no free variables there is an equivalent λ-expression 𝑓 that only uses the variables đ‘„,𝑩, and 𝑧.6

Exercise 8.9 — Evaluation order example in λ calculus. 1. Let 𝑒 =đœ†đ‘„.7 ((đœ†đ‘„.đ‘„đ‘„)(đœ†đ‘„.đ‘„đ‘„)). Prove that the simplification process of 𝑒ends in a definite number if we use the “call by name” evaluationorder while it never ends if we use the “call by value” order.

2. (bonus, challenging) Let 𝑒 be any λ expression. Prove that if thesimplification process ends in a definite number if we use the “callby value” order then it also ends in such a number if we use the“call by name” order. See footnote for hint.7

Exercise 8.10 — Zip function. Give an enhanced λ calculus expression tocompute the function 𝑧𝑖𝑝 that on input a pair of lists đŒ and 𝐿 of thesame length 𝑛, outputs a list of 𝑛 pairs 𝑀 such that the 𝑗-th elementof 𝑀 (which we denote by 𝑀𝑗) is the pair (đŒđ‘—, 𝐿𝑗). Thus 𝑧𝑖𝑝 “zipstogether” these two lists of elements into a single list of pairs.8

Exercise 8.11 — Next-step function without đ‘…đžđ¶đ‘ˆđ‘…đ‘†đž. Let 𝑀 be a Turingmachine. Give an enhanced λ calculus expression to compute thenext-step function NEXT𝑀 of 𝑀 (as in the proof of Theorem 8.16)without using RECURSE. See footnote for hint.9

Exercise 8.12 — λ calculus to NAND-TM compiler (challenging). Give a programin the programming language of your choice that takes as input a λexpression 𝑒 and outputs a NAND-TM program 𝑃 that computes thesame function as 𝑒. For partial credit you can use the GOTO and allNAND-CIRC syntactic sugar in your output program. You can useany encoding of λ expressions as binary string that is convenient foryou. See footnote for hint.10

Exercise 8.13 — At least two in 𝜆 calculus. Let 1 = đœ†đ‘„, 𝑩.đ‘„ and 0 = đœ†đ‘„, 𝑩.𝑩 asbefore. Define

ALT = 𝜆𝑎, 𝑏, 𝑐.(𝑎(𝑏1(𝑐10))(𝑏𝑐0)) (8.26)

Prove that ALT is a 𝜆 expression that computes the at least two func-tion. That is, for every 𝑎, 𝑏, 𝑐 ∈ 0, 1 (as encoded above) ALT𝑎𝑏𝑐 = 1if and only at least two of 𝑎, 𝑏, 𝑐 are equal to 1.

Page 321: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 321

Exercise 8.14 — Locality of next-step function. This question will help youget a better sense of the notion of locality of the next step function of Tur-ing Machines. This locality plays an important role in results such asthe Turing completeness of 𝜆 calculus and one dimensional cellularautomata, as well as results such as Godel’s Incompleteness Theoremand the Cook Levin theorem that we will see later in this course. De-fine STRINGS to be the a programming language that has the followingsemantics:

‱ A STRINGS program 𝑄 has a single string variable str that is boththe input and the output of 𝑄. The program has no loops and noother variables, but rather consists of a sequence of conditionalsearch and replace operations that modify str.

‱ The operations of a STRINGS program are:

– REPLACE(pattern1,pattern2)where pattern1 and pattern2are fixed strings. This replaces the first occurrence of pattern1in str with pattern2

– if search(pattern) code executes code if pattern is asubstring of str. The code code can itself include nested if’s.(One can also add an else ... to execute if pattern is nota substring of condf).

– the returned value is str

‱ A STRING program 𝑄 computes a function đč ∶ 0, 1∗ → 0, 1∗ iffor every đ‘„ ∈ 0, 1∗, if we initialize str to đ‘„ and then execute thesequence of instructions in 𝑄, then at the end of the execution strequals đč(đ‘„).For example, the following is a STRINGS program that computes

the function đč ∶ 0, 1∗ → 0, 1∗ such that for every đ‘„ ∈ 0, 1∗, if đ‘„contains a substring of the form 𝑩 = 11𝑎𝑏11 where 𝑎, 𝑏 ∈ 0, 1, thenđč(đ‘„) = đ‘„â€Č where đ‘„â€Č is obtained by replacing the first occurrence of 𝑩 inđ‘„ with 00.if search('110011')

replace('110011','00') else if search('110111')

replace('110111','00') else if search('111011')

replace('111011','00') else if search('111111')

replace('1111111','00')

Page 322: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

322 introduction to theoretical computer science

Prove that for every Turing Machine program 𝑀 , there exists aSTRINGS program 𝑄 that computes the NEXT𝑀 function that mapsevery string encoding a valid configuration of 𝑀 to the string encodingthe configuration of the next step of 𝑀 ’s computation. (We don’tcare what the function will do on strings that do not encode a validconfiguration.) You don’t have to write the STRINGS program fully,but you do need to give a convincing argument that such a programexists.

8.10 BIBLIOGRAPHICAL NOTES

Chapters 7 in the wonderful book of Moore and Mertens [MM11]contains a great exposition much of this material. .

The RAM model can be very useful in studying the concrete com-plexity of practical algorithms. Its theoretical study was initiated in[CR73]. However, the exact set of operations that are allowed in theRAM model and their costs vary between texts and contexts. Oneneeds to be careful in making such definitions, especially if the wordsize grows, as was already shown by Shamir [Sha79]. Chapter 3 inSavage’s book [Sav98] contains a more formal description of RAMmachines, see also the paper [Hag98]. A study of RAM algorithmsthat are independent of the input size (known as the “transdichoto-mous RAM model”) was initiated by [FW93]

The models of computation we considered so far are inherentlysequential, but these days much computation happens in parallel,whether using multi-core processors or in massively parallel dis-tributed computation in data centers or over the Internet. Parallelcomputing is important in practice, but it does not really make muchdifference for the question of what can and can’t be computed. Afterall, if a computation can be performed using 𝑚 machines in 𝑡 time,then it can be computed by a single machine in time 𝑚𝑡.

The λ-calculus was described by Church in [Chu41]. Pierce’s book[Pie02] is a canonical textbook, see also [Bar84]. The “Currying tech-nique” is named after the logician Haskell Curry (the Haskell pro-gramming language is named after Haskell Curry as well). Curryhimself attributed this concept to Moses Schönfinkel, though for somereason the term “Schönfinkeling” never caught on.

Unlike most programming languages, the pure λ-calculus doesn’thave the notion of types. Every object in the λ calculus can also bethought of as a λ expression and hence as a function that takes oneinput and returns one output. All functions take one input and re-turn one output, and if you feed a function an input of a form it didn’texpect, it still evaluates the λ expression via “search and replace”,replacing all instances of its parameter with copies of the input expres-

Page 323: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

equivalent models of computation 323

sion you fed it. Typed variants of the λ calculus are objects of intenseresearch, and are strongly related to type systems for programminglanguage and computer-verifiable proof systems, see [Pie02]. Some ofthe typed variants of the λ calculus do not have infinite loops, whichmakes them very useful as ways of enabling static analysis of pro-grams as well as computer-verifiable proofs. We will come back to thispoint in Chapter 10 and Chapter 22.

Tao has proposed showing the Turing completeness of fluid dy-namics (a “water computer”) as a way of settling the question of thebehavior of the Navier-Stokes equations, see this popular article.

Page 324: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 325: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

9Universality and uncomputability

“A function of a variable quantity is an analytic expression composed in anyway whatsoever of the variable quantity and numbers or constant quantities.”,Leonhard Euler, 1748.

“The importance of the universal machine is clear. We do not need to have aninfinity of different machines doing different jobs. 
 The engineering problemof producing various machines for various jobs is replaced by the office work of‘programming’ the universal machine”, Alan Turing, 1948

One of the most significant results we showed for Boolean circuits(or equivalently, straight-line programs) is the notion of universality:there is a single circuit that can evaluate all other circuits. However,this result came with a significant caveat. To evaluate a circuit of 𝑠gates, the universal circuit needed to use a number of gates largerthan 𝑠. It turns out that uniform models such as Turing machines orNAND-TM programs allow us to “break out of this cycle” and obtaina truly universal Turing machine 𝑈 that can evaluate all other machines,including machines that are more complex (e.g., more states) than 𝑈itself. (Similarly, there is a Universal NAND-TM program 𝑈 â€Č that canevaluate all NAND-TM programs, including programs that have morelines than 𝑈 â€Č.)

It is no exaggeration to say that the existence of such a universalprogram/machine underlies the information technology revolutionthat began in the latter half of the 20th century (and is still ongoing).Up to that point in history, people have produced various special-purpose calculating devices such as the abacus, the slide ruler, andmachines that compute various trigonometric series. But as Turing(who was perhaps the one to see most clearly the ramifications ofuniversality) observed, a general purpose computer is much more pow-erful. Once we build a device that can compute the single universalfunction, we have the ability, via software, to extend it to do arbitrarycomputations. For example, if we want to simulate a new Turing ma-chine 𝑀 , we do not need to build a new physical machine, but rather

Compiled on 8.26.2020 18:10

Learning Objectives:‱ The universal machine/program - “one

program to rule them all”‱ A fundamental result in computer science and

mathematics: the existence of uncomputablefunctions.

‱ The halting problem: the canonical example ofan uncomputable function.

‱ Introduction to the technique of reductions.‱ Rice’s Theorem: A “meta tool” for

uncomputability results, and a starting pointfor much of the research on compilers,programming languages, and softwareverification.

Page 326: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

326 introduction to theoretical computer science

can represent 𝑀 as a string (i.e., using code) and then input 𝑀 to theuniversal machine 𝑈 .

Beyond the practical applications, the existence of a universal algo-rithm also has surprising theoretical ramifications, and in particularcan be used to show the existence of uncomputable functions, upend-ing the intuitions of mathematicians over the centuries from Eulerto Hilbert. In this chapter we will prove the existence of the univer-sal program, and also show its implications for uncomputability, seeFig. 9.1

This chapter: A non-mathy overviewIn this chapter we will see two of the most important resultsin Computer Science:

1. The existence of a universal Turing machine: a single algo-rithm that can evaluate all other algorithms,

2. The existence of uncomputable functions: functions (includ-ing the famous “Halting problem”) that cannot be computedby any algorithm.

Along the way, we develop the technique of reductions as away to show hardness of computing a function. A reductiongives a way to compute a certain function using “wishfulthinking” and assuming that another function can be com-puted. Reductions are of course widely used in program-ming - we often obtain an algorithm for one task by usinganother task as a “black box” subroutine. However we willuse it in the “contra positive”: rather than using a reductionto show that the former task is “easy”, we use them to showthat the latter task is “hard”. Don’t worry if you find thisconfusing - reductions are initially confusing - but they can bemastered with time and practice.

9.1 UNIVERSALITY OR A META-CIRCULAR EVALUATOR

We start by proving the existence of a universal Turing machine. This isa single Turing machine 𝑈 that can evaluate arbitrary Turing machines𝑀 on arbitrary inputs đ‘„, including machines 𝑀 that can have morestates and larger alphabet than 𝑈 itself. In particular, 𝑈 can even beused to evaluate itself! This notion of self reference will appear time andagain in this book, and as we will see, leads to several counter-intuitivephenomena in computing.

Page 327: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 327

Figure 9.1: In this chapter we will show the existenceof a universal Turing machine and then use this to de-rive first the existence of some uncomputable function.We then use this to derive the uncomputability ofTuring’s famous “halting problem” (i.e., the HALTfunction), from which we a host of other uncom-putability results follow. We also introduce reductions,which allow us to use the uncomputability of afunction đč to derive the uncomputability of a newfunction đș.

Figure 9.2: A Universal Turing Machine is a singleTuring Machine 𝑈 that can evaluate, given input the(description as a string of) arbitrary Turing machine𝑀 and input đ‘„, the output of 𝑀 on đ‘„. In contrast tothe universal circuit depicted in Fig. 5.6, the machine𝑀 can be much more complex (e.g., more states ortape alphabet symbols) than 𝑈 .

Theorem 9.1 — Universal Turing Machine. There exists a Turing machine𝑈 such that on every string 𝑀 which represents a Turing machine,and đ‘„ ∈ 0, 1∗, 𝑈(𝑀, đ‘„) = 𝑀(đ‘„).

That is, if the machine 𝑀 halts on đ‘„ and outputs some 𝑩 ∈0, 1∗ then 𝑈(𝑀, đ‘„) = 𝑩, and if 𝑀 does not halt on đ‘„ (i.e.,𝑀(đ‘„) = ⊄) then 𝑈(𝑀, đ‘„) = ⊄.

Big Idea 11 There is a “universal” algorithm that can evaluatearbitrary algorithms on arbitrary inputs.

Proof Idea:

Once you understand what the theorem says, it is not that hard toprove. The desired program 𝑈 is an interpreter for Turing machines.That is, 𝑈 gets a representation of the machine 𝑀 (think of it as sourcecode), and some input đ‘„, and needs to simulate the execution of 𝑀 onđ‘„.

Think of how you would code 𝑈 in your favorite programminglanguage. First, you would need to decide on some representationscheme for 𝑀 . For example, you can use an array or a dictionaryto encode 𝑀 ’s transition function. Then you would use some datastructure, such as a list, to store the contents of 𝑀 ’s tape. Now you cansimulate 𝑀 step by step, updating the data structure as you go along.The interpreter will continue the simulation until the machine halts.

Once you do that, translating this interpreter from your favoriteprogramming language to a Turing machine can be done just as wehave seen in Chapter 8. The end result is what’s known as a “meta-

Page 328: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

328 introduction to theoretical computer science

circular evaluator”: an interpreter for a programming language in thesame one. This is a concept that has a long history in computer sciencestarting from the original universal Turing machine. See also Fig. 9.3.⋆9.1.1 Proving the existence of a universal Turing MachineTo prove (and even properly state) Theorem 9.1, we need to fix somerepresentation for Turing machines as strings. One potential choicefor such a representation is to use the equivalence between Turingmachines and NAND-TM programs and hence represent a Turingmachine 𝑀 using the ASCII encoding of the source code of the corre-sponding NAND-TM program 𝑃 . However, we will use a more directencoding.

Definition 9.2 — String representation of Turing Machine. Let 𝑀 be a Turingmachine with 𝑘 states and a size ℓ alphabet ÎŁ = 𝜎0, 
 , 𝜎ℓ−1 (weuse the convention 𝜎0 = 0,𝜎1 = 1, 𝜎2 = ∅, 𝜎3 = ▷). We represent𝑀 as the triple (𝑘, ℓ, 𝑇 ) where 𝑇 is the table of values for 𝛿𝑀 :𝑇 = (𝛿𝑀(0, 𝜎0), 𝛿𝑀(0, 𝜎1), 
 , 𝛿𝑀(𝑘 − 1, 𝜎ℓ−1)) , (9.1)

where each value 𝛿𝑀(𝑠, 𝜎) is a triple (𝑠â€Č, 𝜎â€Č, 𝑑) with 𝑠â€Č ∈ [𝑘],𝜎â€Č ∈ ÎŁ and 𝑑 a number 0, 1, 2, 3 encoding one of L, R, S, H. Thussuch a machine 𝑀 is encoded by a list of 2 + 3𝑘 ⋅ ℓ natural num-bers. The string representation of 𝑀 is obtained by concatenatingprefix free representation of all these integers. If a string đ›Œ ∈ 0, 1∗does not represent a list of integers in the form above, then we treatit as representing the trivial Turing machine with one state thatimmediately halts on every input.

RRemark 9.3 — Take away points of representation. Thedetails of the representation scheme of Turing ma-chines as strings are immaterial for almost all applica-tions. What you need to remember are the followingpoints:

1. We can represent every Turing machine as a string.2. Given the string representation of a Turing ma-

chine 𝑀 and an input đ‘„, we can simulate 𝑀 ’sexecution on the input đ‘„. (This is the content ofTheorem 9.1.)

An additional minor issue is that for convenience wemake the assumption that every string represents someTuring machine. This is very easy to ensure by justmapping strings that would otherwise not represent a

Page 329: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 329

Turing machine into some fixed trivial machine. Thisassumption is not very important, but does make afew results (such as Rice’s Theorem: Theorem 9.15) alittle less cumbersome to state.

Using this representation, we can formally prove Theorem 9.1.

Proof of Theorem 9.1. We will only sketch the proof, giving the majorideas. First, we observe that we can easily write a Python programthat, on input a representation (𝑘, ℓ, 𝑇 ) of a Turing machine 𝑀 andan input đ‘„, evaluates 𝑀 on 𝑋. Here is the code of this program forconcreteness, though you can feel free to skip it if you are not familiarwith (or interested in) Python:

# constantsdef EVAL(ÎŽ,x):

'''Evaluate TM given by transition table ÎŽon input x'''Tape = [""] + [a for a in x]i = 0; s = 0 # i = head pos, s = statewhile True:

s, Tape[i], d = Ύ[(s,Tape[i])]if d == "H": breakif d == "L": i = max(i-1,0)if d == "R": i += 1if i>= len(Tape): Tape.append('Ί')

j = 1; Y = [] # produce outputwhile Tape[j] != 'Ί':

Y.append(Tape[j])j += 1

return Y

On input a transition table 𝛿 this program will simulate the cor-responding machine 𝑀 step by step, at each point maintaining theinvariant that the array Tape contains the contents of 𝑀 ’s tape, andthe variable s contains 𝑀 ’s current state.

The above does not prove the theorem as stated, since we needto show a Turing machine that computes EVAL rather than a Pythonprogram. With enough effort, we can translate this Python codeline by line to a Turing machine. However, to prove the theorem wedon’t need to do this, but can use our “eat the cake and have it too”paradigm. That is, while we need to evaluate a Turing machine, inwriting the code for the interpreter we are allowed to use a richermodel such as NAND-RAM since it is equivalent in power to Turingmachines per Theorem 8.1).

Page 330: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

330 introduction to theoretical computer science

Translating the above Python code to NAND-RAM is truly straight-forward. The only issue is that NAND-RAM doesn’t have the dictio-nary data structure built in, which we have used above to store thetransition function ÎŽ. However, we can represent a dictionary đ· ofthe form 𝑘𝑒𝑩0 ∶ 𝑣𝑎𝑙0, 
 , 𝑘𝑒𝑩𝑚−1 ∶ 𝑣𝑎𝑙𝑚−1 as simply a list of pairs.To compute đ·[𝑘] we can scan over all the pairs until we find one ofthe form (𝑘, 𝑣) in which case we return 𝑣. Similarly we scan the listto update the dictionary with a new value, either modifying it or ap-pending the pair (𝑘𝑒𝑩, 𝑣𝑎𝑙) at the end.

RRemark 9.4 — Efficiency of the simulation. The argu-ment in the proof of Theorem 9.1 is a very inefficientway to implement the dictionary data structure inpractice, but it suffices for the purpose of proving thetheorem. Reading and writing to a dictionary of 𝑚values in this implementation takes Ω(𝑚) steps, butit is in fact possible to do this in 𝑂(log𝑚) steps usinga search tree data structure or even 𝑂(1) (for “typical”instances) using a hash table. NAND-RAM and RAMmachines correspond to the architecture of modernelectronic computers, and so we can implement hashtables and search trees in NAND-RAM just as they areimplemented in other programming languages.

The construction above yields a universal Turing Machine with avery large number of states. However, since universal Turing machineshave such a philosophical and technical importance, researchers haveattempted to find the smallest possible universal Turing machines, seeSection 9.7.

9.1.2 Implications of universality (discussion)There is more than one Turing machine 𝑈 that satisfies the condi-tions of Theorem 9.1, but the existence of even a single such machineis already extremely fundamental to both the theory and practice ofcomputer science. Theorem 9.1’s impact reaches beyond the particu-lar model of Turing machines. Because we can simulate every TuringMachine by a NAND-TM program and vice versa, Theorem 9.1 im-mediately implies there exists a universal NAND-TM program 𝑃𝑈such that 𝑃𝑈(𝑃 , đ‘„) = 𝑃(đ‘„) for every NAND-TM program 𝑃 . We canalso “mix and match” models. For example since we can simulateevery NAND-RAM program by a Turing machine, and every TuringMachine by the 𝜆 calculus, Theorem 9.1 implies that there exists a 𝜆expression 𝑒 such that for every NAND-RAM program 𝑃 and input đ‘„on which 𝑃(đ‘„) = 𝑩, if we encode (𝑃 , đ‘„) as a 𝜆-expression 𝑓 (using the

Page 331: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 331

Figure 9.3: a) A particularly elegant example of a“meta-circular evaluator” comes from John Mc-Carthy’s 1960 paper, where he defined the Lispprogramming language and gave a Lisp function thatevaluates an arbitrary Lisp program (see above). Lispwas not initially intended as a practical program-ming language and this example was merely meantas an illustration that the Lisp universal function ismore elegant than the universal Turing machine. Itwas McCarthy’s graduate student Steve Russell whosuggested that it can be implemented. As McCarthylater recalled, “I said to him, ho, ho, you’re confusingtheory with practice, this eval is intended for reading, notfor computing. But he went ahead and did it. That is, hecompiled the eval in my paper into IBM 704 machine code,fixing a bug, and then advertised this as a Lisp interpreter,which it certainly was”. b) A self-replicating C programfrom the classic essay of Thompson [Tho84].

𝜆-calculus encoding of strings as lists of 0’s and 1’s) then (𝑒 𝑓) eval-uates to an encoding of 𝑩. More generally we can say that for every𝒳 and 𝒮 in the set Turing Machines, RAM Machines, NAND-TM,NAND-RAM, 𝜆-calculus, JavaScript, Python, 
 of Turing equivalentmodels, there exists a program/machine in 𝒳 that computes the map(𝑃 , đ‘„) ↩ 𝑃(đ‘„) for every program/machine 𝑃 ∈ 𝒮.

The idea of a “universal program” is of course not limited to theory.For example compilers for programming languages are often used tocompile themselves, as well as programs more complicated than thecompiler. (An extreme example of this is Fabrice Bellard’s ObfuscatedTiny C Compiler which is a C program of 2048 bytes that can compilea large subset of the C programming language, and in particular cancompile itself.) This is also related to the fact that it is possible to writea program that can print its own source code, see Fig. 9.3. There areuniversal Turing machines known that require a very small numberof states or alphabet symbols, and in particular there is a universalTuring machine (with respect to a particular choice of representingTuring machines as strings) whose tape alphabet is ▷,∅, 0, 1 andhas fewer than 25 states (see Section 9.7).

9.2 IS EVERY FUNCTION COMPUTABLE?

In Theorem 4.12, we saw that NAND-CIRC programs can computeevery finite function 𝑓 ∶ 0, 1𝑛 → 0, 1. Therefore a natural guess isthat NAND-TM programs (or equivalently, Turing Machines) couldcompute every infinite function đč ∶ 0, 1∗ → 0, 1. However, thisturns out to be false. That is, there exists a function đč ∶ 0, 1∗ → 0, 1that is uncomputable!

Page 332: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

332 introduction to theoretical computer science

The existence of uncomputable functions is quite surprising. Ourintuitive notion of a “function” (and the notion most mathematicianshad until the 20th century) is that a function 𝑓 defines some implicitor explicit way of computing the output 𝑓(đ‘„) from the input đ‘„. Thenotion of an “uncomputable function” thus seems to be a contradic-tion in terms, but yet the following theorem shows that such creaturesdo exist:

Theorem 9.5 — Uncomputable functions. There exists a function đč ∗ ∶0, 1∗ → 0, 1 that is not computable by any Turing machine.

Proof Idea:

The idea behind the proof follows quite closely Cantor’s proof thatthe reals are uncountable (Theorem 2.5), and in fact the theorem canalso be obtained fairly directly from that result (see Exercise 7.11).However, it is instructive to see the direct proof. The idea is to con-struct đč ∗ in a way that will ensure that every possible machine 𝑀 willin fact fail to compute đč ∗. We do so by defining đč ∗(đ‘„) to equal 0 if đ‘„describes a Turing machine 𝑀 which satisfies 𝑀(đ‘„) = 1 and definingđč ∗(đ‘„) = 1 otherwise. By construction, if 𝑀 is any Turing machine andđ‘„ is the string describing it, then đč ∗(đ‘„) ≠ 𝑀(đ‘„) and therefore 𝑀 doesnot compute đč ∗.⋆Proof of Theorem 9.5. The proof is illustrated in Fig. 9.4. We start bydefining the following function đș ∶ 0, 1∗ → 0, 1:

For every string đ‘„ ∈ 0, 1∗, if đ‘„ satisfies (1) đ‘„ is a valid repre-sentation of some Turing machine 𝑀 (per the representation schemeabove) and (2) when the program 𝑀 is executed on the input đ‘„ ithalts and produces an output, then we define đș(đ‘„) as the first bit ofthis output. Otherwise (i.e., if đ‘„ is not a valid representation of a Tur-ing machine, or the machine đ‘€đ‘„ never halts on đ‘„) we define đș(đ‘„) = 0.We define đč ∗(đ‘„) = 1 − đș(đ‘„).

We claim that there is no Turing machine that computes đč ∗. In-deed, suppose, towards the sake of contradiction, there exists a ma-chine 𝑀 that computes đč ∗, and let đ‘„ be the binary string that rep-resents the machine 𝑀 . On one hand, since by our assumption 𝑀computes đč ∗, on input đ‘„ the machine 𝑀 halts and outputs đč ∗(đ‘„). Onthe other hand, by the definition of đč ∗, since đ‘„ is the representationof the machine 𝑀 , đč ∗(đ‘„) = 1 − đș(đ‘„) = 1 − 𝑀(đ‘„), hence yielding acontradiction.

Page 333: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 333

Figure 9.4: We construct an uncomputable functionby defining for every two strings đ‘„, 𝑩 the value1 − 𝑀𝑩(đ‘„) which equals 0 if the machine describedby 𝑩 outputs 1 on đ‘„, and 1 otherwise. We then defineđč ∗(đ‘„) to be the “diagonal” of this table, namelyđč ∗(đ‘„) = 1 − đ‘€đ‘„(đ‘„) for every đ‘„. The function đč ∗is uncomputable, because if it was computable bysome machine whose string description is đ‘„âˆ— then wewould get that đ‘€đ‘„âˆ— (đ‘„âˆ—) = đč(đ‘„âˆ—) = 1 − đ‘€đ‘„âˆ— (đ‘„âˆ—).

Big Idea 12 There are some functions that can not be computed byany algorithm.

PThe proof of Theorem 9.5 is short but subtle. I suggestthat you pause here and go back to read it again andthink about it - this is a proof that is worth reading atleast twice if not three or four times. It is not often thecase that a few lines of mathematical reasoning estab-lish a deeply profound fact - that there are problemswe simply cannot solve.

The type of argument used to prove Theorem 9.5 is known as di-agonalization since it can be described as defining a function basedon the diagonal entries of a table as in Fig. 9.4. The proof can bethought of as an infinite version of the counting argument we usedfor showing lower bound for NAND-CIRC programs in Theorem 5.3.Namely, we show that it’s not possible to compute all functions from0, 1∗ → 0, 1 by Turing machines simply because there are morefunctions like that then there are Turing machines.

As mentioned in Remark 7.4, many texts use the “language” ter-minology and so will call a set 𝐿 ⊆ 0, 1∗ an undecidable or nonrecursive language if the function đč ∶ 0, 1∗ ∶→ 0, 1 such thatđč(đ‘„) = 1 ↔ đ‘„ ∈ 𝐿 is uncomputable.

Page 334: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

334 introduction to theoretical computer science

9.3 THE HALTING PROBLEM

Theorem 9.5 shows that there is some function that cannot be com-puted. But is this function the equivalent of the “tree that falls in theforest with no one hearing it”? That is, perhaps it is a function thatno one actually wants to compute. It turns out that there are naturaluncomputable functions:

Theorem 9.6 — Uncomputability of Halting function. Let HALT ∶ 0, 1∗ →0, 1 be the function such that for every string 𝑀 ∈ 0, 1∗,HALT(𝑀, đ‘„) = 1 if Turing machine 𝑀 halts on the input đ‘„ andHALT(𝑀, đ‘„) = 0 otherwise. Then HALT is not computable.

Before turning to prove Theorem 9.6, we note that HALT is a verynatural function to want to compute. For example, one can think ofHALT as a special case of the task of managing an “App store”. Thatis, given the code of some application, the gatekeeper for the storeneeds to decide if this code is safe enough to allow in the store or not.At a minimum, it seems that we should verify that the code would notgo into an infinite loop.Proof Idea:

One way to think about this proof is as follows:

Uncomputability of đč ∗ + Universality = Uncomputability of HALT(9.2)

That is, we will use the universal Turing machine that computes EVALto derive the uncomputability of HALT from the uncomputability ofđč ∗ shown in Theorem 9.5. Specifically, the proof will be by contra-diction. That is, we will assume towards a contradiction that HALT iscomputable, and use that assumption, together with the universal Tur-ing machine of Theorem 9.1, to derive that đč ∗ is computable, whichwill contradict Theorem 9.5.⋆

Big Idea 13 If a function đč is uncomputable we can show thatanother function đ» is uncomputable by giving a way to reduce the taskof computing đč to computing đ» .

Proof of Theorem 9.6. The proof will use the previously establishedresult Theorem 9.5. Recall that Theorem 9.5 shows that the followingfunction đč ∗ ∶ 0, 1∗ → 0, 1 is uncomputable:

đč ∗(đ‘„) = ⎧⎚⎩1 đ‘„(đ‘„) = 00 otherwise(9.3)

Page 335: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 335

where đ‘„(đ‘„) denotes the output of the Turing machine described by thestring đ‘„ on the input đ‘„ (with the usual convention that đ‘„(đ‘„) = ⊄ if thiscomputation does not halt).

We will show that the uncomputability of đč ∗ implies the uncom-putability of HALT. Specifically, we will assume, towards a contra-diction, that there exists a Turing machine 𝑀 that can compute theHALT function, and use that to obtain a Turing machine 𝑀 â€Č that com-putes the function đč ∗. (This is known as a proof by reduction, since wereduce the task of computing đč ∗ to the task of computing HALT. Bythe contrapositive, this means the uncomputability of đč ∗ implies theuncomputability of HALT.)

Indeed, suppose that 𝑀 is a Turing machine that computes HALT.Algorithm 9.7 describes a Turing Machine 𝑀 â€Č that computes đč ∗. (Weuse “high level” description of Turing machines, appealing to the“have your cake and eat it too” paradigm, see Big Idea 10.)

Algorithm 9.7 — đč ∗ to đ»đŽđżđ‘‡ reduction.

Input: đ‘„ ∈ 0, 1∗Output: đč ∗(đ‘„)1: # Assume T.M. đ‘€đ»đŽđżđ‘‡ computes đ»đŽđżđ‘‡2: Let 𝑧 ← đ‘€đ»đŽđżđ‘‡ (đ‘„, đ‘„). # Assume 𝑧 = đ»đŽđżđ‘‡ (đ‘„, đ‘„).3: if 𝑧 = 0 then4: return 05: end if6: Let 𝑩 ← 𝑈(đ‘„, đ‘„) # 𝑈 universal TM, i.e., 𝑩 = đ‘„(đ‘„)7: if 𝑩 = 0 then8: return 19: end if

10: return 0We claim that Algorithm 9.7 computes the function đč ∗. In-

deed, suppose that đ‘„(đ‘„) = 0 (and hence đč ∗(đ‘„) = 1). In thiscase, HALT(đ‘„, đ‘„) = 1 and hence, under our assumption that𝑀(đ‘„, đ‘„) = HALT(đ‘„, đ‘„), the value 𝑧 will equal 1, and hence Al-gorithm 9.7 will set 𝑩 = đ‘„(đ‘„) = 0, and output the correct value1.

Suppose otherwise that đ‘„(đ‘„) ≠ 0 (and hence đč ∗(đ‘„) = 0). In thiscase there are two possibilities:

‱ Case 1: The machine described by đ‘„ does not halt on the input đ‘„.In this case, HALT(đ‘„, đ‘„) = 0. Since we assume that 𝑀 computesHALT it means that on input đ‘„, đ‘„, the machine 𝑀 must halt andoutput the value 0. This means that Algorithm 9.7 will set 𝑧 = 0and output 0.

Page 336: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

336 introduction to theoretical computer science

1 This argument has also been connected to theissues of consciousness and free will. I am personallyskeptical of its relevance to these issues. Perhaps thereasoning is that humans have the ability to solve thehalting problem but they exercise their free will andconsciousness by choosing not to do so.

‱ Case 2: The machine described by đ‘„ halts on the input đ‘„ and out-puts some 𝑩â€Č ≠ 0. In this case, since HALT(đ‘„, đ‘„) = 1, under ourassumptions, Algorithm 9.7 will set 𝑩 = 𝑩â€Č ≠ 0 and so output 0.We see that in all cases, 𝑀 â€Č(đ‘„) = đč ∗(đ‘„), which contradicts the

fact that đč ∗ is uncomputable. Hence we reach a contradiction to ouroriginal assumption that 𝑀 computes HALT.

POnce again, this is a proof that’s worth reading morethan once. The uncomputability of the halting prob-lem is one of the fundamental theorems of computerscience, and is the starting point for much of the in-vestigations we will see later. An excellent way to geta better understanding of Theorem 9.6 is to go overSection 9.3.2, which presents an alternative proof ofthe same result.

9.3.1 Is the Halting problem really hard? (discussion)Many people’s first instinct when they see the proof of Theorem 9.6is to not believe it. That is, most people do believe the mathematicalstatement, but intuitively it doesn’t seem that the Halting problem isreally that hard. After all, being uncomputable only means that HALTcannot be computed by a Turing machine.

But programmers seem to solve HALT all the time by informally orformally arguing that their programs halt. It’s true that their programsare written in C or Python, as opposed to Turing machines, but thatmakes no difference: we can easily translate back and forth betweenthis model and any other programming language.

While every programmer encounters at some point an infinite loop,is there really no way to solve the halting problem? Some peopleargue that they personally can, if they think hard enough, determinewhether any concrete program that they are given will halt or not.Some have even argued that humans in general have the ability todo that, and hence humans have inherently superior intelligence tocomputers or anything else modeled by Turing machines.1

The best answer we have so far is that there truly is no way to solveHALT, whether using Macs, PCs, quantum computers, humans, orany other combination of electronic, mechanical, and biological de-vices. Indeed this assertion is the content of the Church-Turing Thesis.This of course does not mean that for every possible program 𝑃 , itis hard to decide if 𝑃 enters an infinite loop. Some programs don’teven have loops at all (and hence trivially halt), and there are manyother far less trivial examples of programs that we can certify to never

Page 337: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 337

Figure 9.5: SMBC’s take on solving the Halting prob-lem.

enter an infinite loop (or programs that we know for sure that willenter such a loop). However, there is no general procedure that woulddetermine for an arbitrary program 𝑃 whether it halts or not. More-over, there are some very simple programs for which no one knowswhether they halt or not. For example, the following Python programwill halt if and only if Goldbach’s conjecture is false:

def isprime(p):return all(p % i for i in range(2,p-1))

def Goldbach(n):return any( (isprime(p) and isprime(n-p))

for p in range(2,n-1))

n = 4while True:

if not Goldbach(n): breakn+= 2

Given that Goldbach’s Conjecture has been open since 1742, it isunclear that humans have any magical ability to say whether this (orother similar programs) will halt or not.

9.3.2 A direct proof of the uncomputability of HALT (optional)It turns out that we can combine the ideas of the proofs of Theo-rem 9.5 and Theorem 9.6 to obtain a short proof of the latter theorem,that does not appeal to the uncomputability of đč ∗. This short proofappeared in print in a 1965 letter to the editor of Christopher Strachey:

To the Editor, The Computer Journal.An Impossible ProgramSir,A well-known piece of folk-lore among programmers holds that it isimpossible to write a program which can examine any other programand tell, in every case, if it will terminate or get into a closed loop whenit is run. I have never actually seen a proof of this in print, and thoughAlan Turing once gave me a verbal proof (in a railway carriage on theway to a Conference at the NPL in 1953), I unfortunately and promptlyforgot the details. This left me with an uneasy feeling that the proofmust be long or complicated, but in fact it is so short and simple that itmay be of interest to casual readers. The version below uses CPL, butnot in any essential way.Suppose T[R] is a Boolean function taking a routine (or program) Rwith no formal or free variables as its arguments and that for all R,T[R] = True if R terminates if run and that T[R] = False if R does notterminate.Consider the routine P defined as follows

Page 338: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

338 introduction to theoretical computer science

rec routine P§L: if T[P] go to LReturn §

If T[P] = True the routine P will loop, and it will only terminate ifT[P] = False. In each case ‘T[P]“ has exactly the wrong value, and thiscontradiction shows that the function T cannot exist.Yours faithfully,C. StracheyChurchill College, Cambridge

PTry to stop and extract the argument for provingTheorem 9.6 from the letter above.

Since CPL is not as common today, let us reproduce this proof. Theidea is the following: suppose for the sake of contradiction that thereexists a program T such that T(f,x) equals True iff f halts on inputx. (Strachey’s letter considers the no-input variant of HALT, but aswe’ll see, this is an immaterial distinction.) Then we can construct aprogram P and an input x such that T(P,x) gives the wrong answer.The idea is that on input x, the program P will do the following: runT(x,x), and if the answer is True then go into an infinite loop, andotherwise halt. Now you can see that T(P,P) will give the wronganswer: if P halts when it gets its own code as input, then T(P,P) issupposed to be True, but then P(P) will go into an infinite loop. Andif P does not halt, then T(P,P) is supposed to be False but then P(P)will halt. We can also code this up in Python:

def CantSolveMe(T):"""Gets function T that claims to solve HALT.Returns a pair (P,x) of code and input on whichT(P,x) ≠ HALT(x)"""def fool(x):

if T(x,x):while True: pass

return "I halted"

return (fool,fool)

For example, consider the following Naive Python program T thatguesses that a given function does not halt if its input contains whileor for

Page 339: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 339

def T(f,x):"""Crude halting tester - decides it doesn't halt if it

contains a loop."""import inspectsource = inspect.getsource(f)if source.find("while"): return Falseif source.find("for"): return Falsereturn True

If we now set (f,x) = CantSolveMe(T), then T(f,x)=False butf(x) does in fact halt. This is of course not specific to this particular T:for every program T, if we run (f,x) = CantSolveMe(T) then we’llget an input on which T gives the wrong answer to HALT.

9.4 REDUCTIONS

The Halting problem turns out to be a linchpin of uncomputability, inthe sense that Theorem 9.6 has been used to show the uncomputabil-ity of a great many interesting functions. We will see several examplesof such results in this chapter and the exercises, but there are manymore such results (see Fig. 9.6).

Figure 9.6: Some uncomputability results. An arrowfrom problem X to problem Y means that we use theuncomputability of X to prove the uncomputabilityof Y by reducing computing X to computing Y.All of these results except for the MRDP Theoremappear in either the text or exercises. The HaltingProblem HALT serves as our starting point for allthese uncomputability results as well as many others.

The idea behind such uncomputability results is conceptually sim-ple but can at first be quite confusing. If we know that HALT is un-computable, and we want to show that some other function BLAH isuncomputable, then we can do so via a contrapositive argument (i.e.,proof by contradiction). That is, we show that if there exists a Turingmachine that computes BLAH then there exists a Turing machine thatcomputes HALT. (Indeed, this is exactly how we showed that HALTitself is uncomputable, by reducing this fact to the uncomputability ofthe function đč ∗ from Theorem 9.5.)

Page 340: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

340 introduction to theoretical computer science

For example, to prove that BLAH is uncomputable, we could showthat there is a computable function 𝑅 ∶ 0, 1∗ → 0, 1∗ such that forevery pair 𝑀 and đ‘„, HALT(𝑀, đ‘„) = BLAH(𝑅(𝑀, đ‘„)). The existence ofsuch a function 𝑅 implies that if BLAH was computable then HALTwould be computable as well, hence leading to a contradiction! Theconfusing part about reductions is that we are assuming somethingwe believe is false (that BLAH has an algorithm) to derive somethingthat we know is false (that HALT has an algorithm). Michael Sipserdescribes such results as having the form “If pigs could whistle thenhorses could fly”.

A reduction-based proof has two components. For starters, sincewe need 𝑅 to be computable, we should describe the algorithm tocompute it. The algorithm to compute 𝑅 is known as a reduction sincethe transformation 𝑅 modifies an input to HALT to an input to BLAH,and hence reduces the task of computing HALT to the task of comput-ing BLAH. The second component of a reduction-based proof is theanalysis of the algorithm 𝑅: namely a proof that 𝑅 does indeed satisfythe desired properties.

Reduction-based proofs are just like other proofs by contradiction,but the fact that they involve hypothetical algorithms that don’t reallyexist tends to make reductions quite confusing. The one silver liningis that at the end of the day the notion of reductions is mathematicallyquite simple, and so it’s not that bad even if you have to go back tofirst principles every time you need to remember what is the directionthat a reduction should go in.

RRemark 9.8 — Reductions are algorithms. A reductionis an algorithm, which means that, as discussed inRemark 0.3, a reduction has three components:

‱ Specification (what): In the case of a reductionfrom HALT to BLAH, the specification is that func-tion 𝑅 ∶ 0, 1∗ → 0, 1∗ should satisfy thatHALT(𝑀, đ‘„) = BLAH(𝑅(𝑀, đ‘„)) for every Tur-ing machine 𝑀 and input đ‘„. In general, to reducea function đč to đș, the reduction should satisfyđč(đ‘€) = đș(𝑅(đ‘€)) for every input đ‘€ to đč .

‱ Implementation (how): The algorithm’s descrip-tion: the precise instructions how to transform aninput đ‘€ to the output 𝑅(đ‘€).

‱ Analysis (why): A proof that the algorithm meetsthe specification. In particular, in a reductionfrom đč to đș this is a proof that for every inputđ‘€, the output 𝑩 of the algorithm satisfies thatđč(đ‘€) = đș(𝑩).

Page 341: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 341

9.4.1 Example: Halting on the zero problemHere is a concrete example for a proof by reduction. We define thefunction HALTONZERO ∶ 0, 1∗ → 0, 1 as follows. Given anystring 𝑀 , HALTONZERO(𝑀) = 1 if and only if 𝑀 describes a Turingmachine that halts when it is given the string 0 as input. A prioriHALTONZERO seems like a potentially easier function to computethan the full-fledged HALT function, and so we could perhaps hopethat it is not uncomputable. Alas, the following theorem shows thatthis is not the case:

Theorem 9.9 — Halting without input. HALTONZERO is uncomputable.

PThe proof of Theorem 9.9 is below, but before readingit you might want to pause for a couple of minutesand think how you would prove it yourself. In partic-ular, try to think of what a reduction from HALT toHALTONZERO would look like. Doing so is an excel-lent way to get some initial comfort with the notionof proofs by reduction, which a technique we will beusing time and again in this book.

Figure 9.7: To prove Theorem 9.9, we show thatHALTONZERO is uncomputable by giving a reductionfrom the task of computing HALT to the task of com-puting HALTONZERO. This shows that if there was ahypothetical algorithm 𝐮 computing HALTONZERO,then there would be an algorithm đ” computingHALT, contradicting Theorem 9.6. Since neither 𝐮 norđ” actually exists, this is an example of an implicationof the form “if pigs could whistle then horses couldfly”.

Proof of Theorem 9.9. The proof is by reduction from HALT, seeFig. 9.7. We will assume, towards the sake of contradiction, thatHALTONZERO is computable by some algorithm 𝐮, and use thishypothetical algorithm 𝐮 to construct an algorithm đ” to computeHALT, hence obtaining a contradiction to Theorem 9.6. (As discussed

Page 342: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

342 introduction to theoretical computer science

in Big Idea 10, following our “have your cake and eat it too” paradigm,we just use the generic name “algorithm” rather than worryingwhether we model them as Turing machines, NAND-TM programs,NAND-RAM, etc.; this makes no difference since all these models areequivalent to one another.)

Since this is our first proof by reduction from the Halting prob-lem, we will spell it out in more details than usual. Such a proof byreduction consists of two steps:

1. Description of the reduction: We will describe the operation of ouralgorithm đ”, and how it makes “function calls” to the hypotheticalalgorithm 𝐮.

2. Analysis of the reduction: We will then prove that under the hypoth-esis that Algorithm 𝐮 computes HALTONZERO, Algorithm đ” willcompute HALT.

Algorithm 9.10 — đ»đŽđżđ‘‡ to đ»đŽđżđ‘‡ 𝑂𝑁𝑍𝐾𝑅𝑂 reduction.

Input: Turing machine 𝑀 and string đ‘„.Output: Turing machine 𝑀 â€Č such that 𝑀 halts on đ‘„ iff 𝑀 â€Č

halts on zero1: procedure 𝑁𝑀,đ‘„(đ‘€) # Description of the T.M. 𝑁𝑀,đ‘„2: return 𝐾𝑉 𝐮𝐿(𝑀, đ‘„) # Ignore the

Input: đ‘€, evaluate 𝑀 on đ‘„.3: end procedure4: return 𝑁𝑀,đ‘„ # We do not execute 𝑁𝑀,đ‘„: only return its

description

Our Algorithm đ” works as follows: on input 𝑀, đ‘„, it runs Algo-rithm 9.10 to obtain a Turing Machine 𝑀 â€Č, and then returns 𝐮(𝑀 â€Č).The machine 𝑀 â€Č ignores its input 𝑧 and simply runs 𝑀 on đ‘„.

In pseudocode, the program 𝑁𝑀,đ‘„ will look something like thefollowing:

def N(z):M = r'.......'# a string constant containing desc. of Mx = r'.......'# a string constant containing xreturn eval(M,x)# note that we ignore the input z

That is, if we think of 𝑁𝑀,đ‘„ as a program, then it is a program thatcontains 𝑀 and đ‘„ as “hardwired constants”, and given any input 𝑧, itsimply ignores the input and always returns the result of evaluating

Page 343: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 343

𝑀 on đ‘„. The algorithm đ” does not actually execute the machine 𝑁𝑀,đ‘„.đ” merely writes down the description of 𝑁𝑀,đ‘„ as a string (just as wedid above) and feeds this string as input to 𝐮.

The above completes the description of the reduction. The analysis isobtained by proving the following claim:

Claim: For every strings 𝑀, đ‘„, 𝑧, the machine 𝑁𝑀,đ‘„ constructed byAlgorithm đ” in Step 1 satisfies that 𝑁𝑀,đ‘„ halts on 𝑧 if and only if theprogram described by 𝑀 halts on the input đ‘„.

Proof of Claim: Since 𝑁𝑀,đ‘„ ignores its input and evaluates 𝑀 on đ‘„using the universal Turing machine, it will halt on 𝑧 if and only if 𝑀halts on đ‘„.

In particular if we instantiate this claim with the input 𝑧 = 0 to𝑁𝑀,đ‘„, we see that HALTONZERO(𝑁𝑀,đ‘„) = HALT(𝑀, đ‘„). Thus ifthe hypothetical algorithm 𝐮 satisfies 𝐮(𝑀) = HALTONZERO(𝑀)for every 𝑀 then the algorithm đ” we construct satisfies đ”(𝑀, đ‘„) =HALT(𝑀, đ‘„) for every 𝑀, đ‘„, contradicting the uncomputability ofHALT.

RRemark 9.11 — The hardwiring technique. In the proof ofTheorem 9.9 we used the technique of “hardwiring”an input đ‘„ to a program/machine 𝑃 . That is, modify-ing a program 𝑃 that it uses “hardwired constants”for some of all of its input. This technique is quitecommon in reductions and elsewhere, and we willoften use it again in this course.

9.5 RICE’S THEOREM AND THE IMPOSSIBILITY OF GENERALSOFTWARE VERIFICATION

The uncomputability of the Halting problem turns out to be a specialcase of a much more general phenomenon. Namely, that we cannotcertify semantic properties of general purpose programs. “Semantic prop-erties” mean properties of the function that the program computes, asopposed to properties that depend on the particular syntax used bythe program.

An example for a semantic property of a program 𝑃 is the propertythat whenever 𝑃 is given an input string with an even number of 1’s,it outputs 0. Another example is the property that 𝑃 will always haltwhenever the input ends with a 1. In contrast, the property that a Cprogram contains a comment before every function declaration is nota semantic property, since it depends on the actual source code asopposed to the input/output relation.

Page 344: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

344 introduction to theoretical computer science

Checking semantic properties of programs is of great interest, as itcorresponds to checking whether a program conforms to a specifica-tion. Alas it turns out that such properties are in general uncomputable.We have already seen some examples of uncomputable semantic func-tions, namely HALT and HALTONZERO, but these are just the “tip ofthe iceberg”. We start by observing one more such example:

Theorem 9.12 — Computing all zero function. Let ZEROFUNC ∶ 0, 1∗ →0, 1 be the function such that for every 𝑀 ∈ 0, 1∗, ZEROFUNC(𝑀) =1 if and only if 𝑀 represents a Turing machine such that 𝑀 outputs0 on every input đ‘„ ∈ 0, 1∗. Then ZEROFUNC is uncomputable.

PDespite the similarity in their names, ZEROFUNC andHALTONZERO are two different functions. For exam-ple, if 𝑀 is a Turing machine that on input đ‘„ ∈ 0, 1∗,halts and outputs the OR of all of đ‘„â€™s coordinates, thenHALTONZERO(𝑀) = 1 (since 𝑀 does halt on theinput 0) but ZEROFUNC(𝑀) = 0 (since 𝑀 does notcompute the constant zero function).

Proof of Theorem 9.12. The proof is by reduction to HALTONZERO.Suppose, towards the sake of contradiction, that there was an algo-rithm 𝐮 such that 𝐮(𝑀) = ZEROFUNC(𝑀) for every 𝑀 ∈ 0, 1∗.Then we will construct an algorithm đ” that solves HALTONZERO,contradicting Theorem 9.9.

Given a Turing machine 𝑁 (which is the input to HALTONZERO),our Algorithm đ” does the following:

1. Construct a Turing Machine 𝑀 which on input đ‘„ ∈ 0, 1∗, firstruns 𝑁(0) and then outputs 0.

2. Return 𝐮(𝑀).Now if 𝑁 halts on the input 0 then the Turing machine 𝑀 com-

putes the constant zero function, and hence under our assumptionthat 𝐮 computes ZEROFUNC, 𝐮(𝑀) = 1. If 𝑁 does not halt on theinput 0, then the Turing machine 𝑀 will not halt on any input, andso in particular will not compute the constant zero function. Henceunder our assumption that 𝐮 computes ZEROFUNC, 𝐮(𝑀) = 0.We see that in both cases, ZEROFUNC(𝑀) = HALTONZERO(𝑁)and hence the value that Algorithm đ” returns in step 2 is equal toHALTONZERO(𝑁) which is what we needed to prove.

Another result along similar lines is the following:

Page 345: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 345

Theorem 9.13 — Uncomputability of verifying parity. The following func-tion is uncomputable

COMPUTES-PARITY(𝑃 ) = ⎧⎚⎩1 𝑃 computes the parity function0 otherwise(9.4)

PWe leave the proof of Theorem 9.13 as an exercise(Exercise 9.6). I strongly encourage you to stop hereand try to solve this exercise.

9.5.1 Rice’s TheoremTheorem 9.13 can be generalized far beyond the parity function. Infact, this generalization rules out verifying any type of semantic spec-ification on programs. We define a semantic specification on programsto be some property that does not depend on the code of the programbut just on the function that the program computes.

For example, consider the following two C programs

int First(int n) if (n<0) return 0;return 2*n;

int Second(int n) int i = 0;int j = 0if (n<0) return 0;while (j<n)

i = i + 2;j= j + 1;

return i;

First and Second are two distinct C programs, but they computethe same function. A semantic property, would be either true for bothprograms or false for both programs, since it depends on the functionthe programs compute and not on their code. An example for a se-mantic property that both First and Second satisfy is the following:“The program 𝑃 computes a function 𝑓 mapping integers to integers satisfy-ing that 𝑓(𝑛) ≄ 𝑛 for every input 𝑛”.

Page 346: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

346 introduction to theoretical computer science

A property is not semantic if it depends on the source code ratherthan the input/output behavior. For example, properties such as “theprogram contains the variable k” or “the program uses the while op-eration” are not semantic. Such properties can be true for one of theprograms and false for others. Formally, we define semantic proper-ties as follows:

Definition 9.14 — Semantic properties. A pair of Turing machines𝑀 and 𝑀 â€Č are functionally equivalent if for every đ‘„ ∈ 0, 1∗,𝑀(đ‘„) = 𝑀 â€Č(đ‘„). (In particular, 𝑀(đ‘„) = ⊄ iff 𝑀 â€Č(đ‘„) = ⊄ for allđ‘„.)A function đč ∶ 0, 1∗ → 0, 1 is semantic if for every pair of

strings 𝑀, 𝑀 â€Č that represent functionally equivalent Turing ma-chines, đč(𝑀) = đč(𝑀 â€Č). (Recall that we assume that every stringrepresents some Turing machine, see Remark 9.3)

There are two trivial examples of semantic functions: the constantone function and the constant zero function. For example, if 𝑍 is theconstant zero function (i.e., 𝑍(𝑀) = 0 for every 𝑀) then clearlyđč(𝑀) = đč(𝑀 â€Č) for every pair of Turing machines 𝑀 and 𝑀 â€Č that arefunctionally equivalent 𝑀 and 𝑀 â€Č. Here is a non-trivial exampleSolved Exercise 9.1 — 𝑍𝐾𝑅𝑂đčđ‘ˆđ‘đ¶ is semantic. Prove that the functionZEROFUNC is semantic.

Solution:

Recall that ZEROFUNC(𝑀) = 1 if and only if 𝑀(đ‘„) = 0 forevery đ‘„ ∈ 0, 1∗. If 𝑀 and 𝑀 â€Č are functionally equivalent, then forevery đ‘„, 𝑀(đ‘„) = 𝑀 â€Č(đ‘„). Hence ZEROFUNC(𝑀) = 1 if and only ifZEROFUNC(𝑀 â€Č) = 1.

Often the properties of programs that we are most interested incomputing are the semantic ones, since we want to understand theprograms’ functionality. Unfortunately, Rice’s Theorem tells us thatthese properties are all uncomputable:

Theorem 9.15 — Rice’s Theorem. Let đč ∶ 0, 1∗ → 0, 1. If đč is seman-tic and non-trivial then it is uncomputable.

Proof Idea:

The idea behind the proof is to show that every semantic non-trivial function đč is at least as hard to compute as HALTONZERO.This will conclude the proof since by Theorem 9.9, HALTONZEROis uncomputable. If a function đč is non trivial then there are two

Page 347: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 347

machines 𝑀0 and 𝑀1 such that đč(𝑀0) = 0 and đč(𝑀1) = 1. So,the goal would be to take a machine 𝑁 and find a way to map it intoa machine 𝑀 = 𝑅(𝑁), such that (i) if 𝑁 halts on zero then 𝑀 isfunctionally equivalent to 𝑀1 and (ii) if 𝑁 does not halt on zero then𝑀 is functionally equivalent 𝑀0.

Because đč is semantic, if we achieved this, then we would be guar-anteed that HALTONZERO(𝑁) = đč(𝑅(𝑁)), and hence would showthat if đč was computable, then HALTONZERO would be computableas well, contradicting Theorem 9.9.⋆Proof of Theorem 9.15. We will not give the proof in full formality, butrather illustrate the proof idea by restricting our attention to a particu-lar semantic function đč . However, the same techniques generalize toall possible semantic functions. Define MONOTONE ∶ 0, 1∗ → 0, 1as follows: MONOTONE(𝑀) = 1 if there does not exist 𝑛 ∈ ℕ andtwo inputs đ‘„, đ‘„â€Č ∈ 0, 1𝑛 such that for every 𝑖 ∈ [𝑛] đ‘„đ‘– ≀ đ‘„â€Č𝑖 but 𝑀(đ‘„)outputs 1 and 𝑀(đ‘„â€Č) = 0. That is, MONOTONE(𝑀) = 1 if it’s notpossible to find an input đ‘„ such that flipping some bits of đ‘„ from 0 to1 will change 𝑀 ’s output in the other direction from 1 to 0. We willprove that MONOTONE is uncomputable, but the proof will easilygeneralize to any semantic function.

We start by noting that MONOTONE is neither the constant zeronor the constant one function:

‱ The machine INF that simply goes into an infinite loop on everyinput satisfies MONOTONE(INF) = 1, since INF is not definedanywhere and so in particular there are no two inputs đ‘„, đ‘„â€Č wheređ‘„đ‘– ≀ đ‘„â€Č𝑖 for every 𝑖 but INF(đ‘„) = 0 and INF(đ‘„â€Č) = 1.

‱ The machine PAR that computes the XOR or parity of its input, isnot monotone (e.g., PAR(1, 1, 0, 0, 
 , 0) = 0 but PAR(1, 0, 0, 
 , 0) =0) and hence MONOTONE(PAR) = 0.(Note that INF and PAR are machines and not functions.)We will now give a reduction from HALTONZERO to

MONOTONE. That is, we assume towards a contradiction thatthere exists an algorithm 𝐮 that computes MONOTONE and we willbuild an algorithm đ” that computes HALTONZERO. Our algorithm đ”will work as follows:

Algorithm đ”:Input: String 𝑁 describing a Turing machine. (Goal: ComputeHALTONZERO(𝑁))Assumption: Access to Algorithm 𝐮 to compute MONOTONE.Operation:

Page 348: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

348 introduction to theoretical computer science

1. Construct the following machine 𝑀 : “On input 𝑧 ∈ 0, 1∗ do: (a)Run 𝑁(0), (b) Return PAR(𝑧)”.

2. Return 1 − 𝐮(𝑀).To complete the proof we need to show that đ” outputs the cor-

rect answer, under our assumption that 𝐮 computes MONOTONE.In other words, we need to show that HALTONZERO(𝑁) = 1 −𝑀𝑂𝑁𝑂𝑇 𝑂𝑁𝐾(𝑀). Suppose that 𝑁 does not halt on zero. In thiscase the program 𝑀 constructed by Algorithm đ” enters into an in-finite loop in step (a) and will never reach step (b). Hence in thiscase 𝑁 is functionally equivalent to INF. (The machine 𝑁 is notthe same machine as INF: its description or code is different. But itdoes have the same input/output behavior (in this case) of neverhalting on any input. Also, while the program 𝑀 will go into an in-finite loop on every input, Algorithm đ” never actually runs 𝑀 : itonly produces its code and feeds it to 𝐮. Hence Algorithm đ” willnot enter into an infinite loop even in this case.) Thus in this case,MONOTONE(𝑁) = MONOTONE(INF) = 1.

If 𝑁 does halt on zero, then step (a) in 𝑀 will eventually concludeand 𝑀 ’s output will be determined by step (b), where it simply out-puts the parity of its input. Hence in this case, 𝑀 computes the non-monotone parity function (i.e., is functionally equivalent to PAR), andso we get that MONOTONE(𝑀) = MONOTONE(PAR) = 0. In bothcases, MONOTONE(𝑀) = 1 − đ»đŽđżđ‘‡ 𝑂𝑁𝑍𝐾𝑅𝑂(𝑁), which is whatwe wanted to prove.

An examination of this proof shows that we did not use anythingabout MONOTONE beyond the fact that it is semantic and non-trivial.For every semantic non-trivial đč , we can use the same proof, replacingPAR and INF with two machines 𝑀0 and 𝑀1 such that đč(𝑀0) = 0 andđč(𝑀1) = 1. Such machines must exist if đč is non trivial.

RRemark 9.16 — Semantic is not the same as uncom-putable. Rice’s Theorem is so powerful and such apopular way of proving uncomputability that peo-ple sometimes get confused and think that it is theonly way to prove uncomputability. In particular, acommon misconception is that if a function đč is notsemantic then it is computable. This is not at all thecase.For example, consider the following functionHALTNOYALE ∶ 0, 1∗ → 0, 1. This is a functionthat on input a string that represents a NAND-TMprogram 𝑃 , outputs 1 if and only if both (i) 𝑃 haltson the input 0, and (ii) the program 𝑃 does not con-tain a variable with the identifier Yale. The function

Page 349: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 349

HALTNOYALE is clearly not semantic, as it will out-put two different values when given as input one ofthe following two functionally equivalent programs:

Yale[0] = NAND(X[0],X[0])Y[0] = NAND(X[0],Yale[0])

and

Harvard[0] = NAND(X[0],X[0])Y[0] = NAND(X[0],Harvard[0])

However, HALTNOYALE is uncomputable since everyprogram 𝑃 can be transformed into an equivalent(and in fact improved :)) program 𝑃 â€Č that does notcontain the variable Yale. Hence if we could computeHALTNOYALE then determine halting on zero forNAND-TM programs (and hence for Turing machinesas well).Moreover, as we will see in Chapter 11, there are un-computable functions whose inputs are not programs,and hence for which the adjective “semantic” is notapplicable.Properties such as “the program contains the variableYale” are sometimes known as syntactic properties.The terms “semantic” and “syntactic” are used be-yond the realm of programming languages: a famousexample of a syntactically correct but semanticallymeaningless sentence in English is Chomsky’s “Color-less green ideas sleep furiously.” However, formallydefining “syntactic properties” is rather subtle and wewill not use this terminology in this book, sticking tothe terms “semantic” and “non semantic” only.

9.5.2 Halting and Rice’s Theorem for other Turing-complete modelsAs we saw before, many natural computational models turn out to beequivalent to one another, in the sense that we can transform a “pro-gram” of one model (such as a 𝜆 expression, or a game-of-life config-urations) into another model (such as a NAND-TM program). Thisequivalence implies that we can translate the uncomputability of theHalting problem for NAND-TM programs into uncomputability forHalting in other models. For example:

Theorem 9.17 — NAND-TM Machine Halting. Let NANDTMHALT ∶0, 1∗ → 0, 1 be the function that on input strings 𝑃 ∈0, 1∗ and đ‘„ ∈ 0, 1∗ outputs 1 if the NAND-TM program de-scribed by 𝑃 halts on the input đ‘„ and outputs 0 otherwise. ThenNANDTMHALT is uncomputable.

Page 350: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

350 introduction to theoretical computer science

POnce again, this is a good point for you to stop and tryto prove the result yourself before reading the proofbelow.

Proof. We have seen in Theorem 7.11 that for every Turing machine𝑀 , there is an equivalent NAND-TM program 𝑃𝑀 such that for ev-ery đ‘„, 𝑃𝑀(đ‘„) = 𝑀(đ‘„). In particular this means that HALT(𝑀) =NANDTMHALT(𝑃𝑀).

The transformation 𝑀 ↩ 𝑃𝑀 that is obtained from the proofof Theorem 7.11 is constructive. That is, the proof yields a way tocompute the map 𝑀 ↩ 𝑃𝑀 . This means that this proof yields areduction from task of computing HALT to the task of computingNANDTMHALT, which means that since HALT is uncomputable,neither is NANDTMHALT.

The same proof carries over to other computational models such asthe 𝜆 calculus, two dimensional (or even one-dimensional) automata etc.Hence for example, there is no algorithm to decide if a 𝜆 expressionevaluates the identity function, and no algorithm to decide whetheran initial configuration of the game of life will result in eventuallycoloring the cell (0, 0) black or not.

Indeed, we can generalize Rice’s Theorem to all these models. Forexample, if đč ∶ 0, 1∗ → 0, 1 is a non-trivial function such thatđč(𝑃) = đč(𝑃 â€Č) for every functionally equivalent NAND-TM programs𝑃 , 𝑃 â€Č then đč is uncomputable, and the same holds for NAND-RAMprograms, 𝜆-expressions, and all other Turing complete models (asdefined in Definition 8.5), see also Exercise 9.12.

9.5.3 Is software verification doomed? (discussion)Programs are increasingly being used for mission critical purposes,whether it’s running our banking system, flying planes, or monitoringnuclear reactors. If we can’t even give a certification algorithm thata program correctly computes the parity function, how can we everbe assured that a program does what it is supposed to do? The keyinsight is that while it is impossible to certify that a general programconforms with a specification, it is possible to write a program inthe first place in a way that will make it easier to certify. As a trivialexample, if you write a program without loops, then you can certifythat it halts. Also, while it might not be possible to certify that anarbitrary program computes the parity function, it is quite possible towrite a particular program 𝑃 for which we can mathematically provethat 𝑃 computes the parity. In fact, writing programs or algorithms

Page 351: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 351

and providing proofs for their correctness is what we do all the time inalgorithms research.

The field of software verification is concerned with verifying thatgiven programs satisfy certain conditions. These conditions can bethat the program computes a certain function, that it never writesinto a dangerous memory location, that is respects certain invari-ants, and others. While the general tasks of verifying this may beuncomputable, researchers have managed to do so for many inter-esting cases, especially if the program is written in the first place ina formalism or programming language that makes verification eas-ier. That said, verification, especially of large and complex programs,remains a highly challenging task in practice as well, and the num-ber of programs that have been formally proven correct is still quitesmall. Moreover, even phrasing the right theorem to prove (i.e., thespecification) if often a highly non-trivial endeavor.

Figure 9.8: The set R of computable Boolean functions(Definition 7.3) is a proper subset of the set of allfunctions mapping 0, 1∗ to 0, 1. In this chapterwe saw a few examples of elements in the latter setthat are not in the former.

Chapter Recap

‱ There is a universal Turing machine (or NAND-TMprogram) 𝑈 such that on input a description of aTuring machine 𝑀 and some input đ‘„, 𝑈(𝑀, đ‘„) haltsand outputs 𝑀(đ‘„) if (and only if) 𝑀 halts on inputđ‘„. Unlike in the case of finite computation (i.e.,NAND-CIRC programs / circuits), the input tothe program 𝑈 can be a machine 𝑀 that has morestates than 𝑈 itself.

‱ Unlike the finite case, there are actually functionsthat are inherently uncomputable in the sense thatthey cannot be computed by any Turing machine.

‱ These include not only some “degenerate” or “eso-teric” functions but also functions that people have

Page 352: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

352 introduction to theoretical computer science

2 A machine with alphabet Σ can have at most |Σ|𝑇choices for the contents of the first 𝑇 locations ofits tape. What happens if the machine repeats apreviously seen configuration, in the sense that thetape contents, the head location, and the current state,are all identical to what they were in some previousstate of the execution?

deeply care about and conjectured that could becomputed.

‱ If the Church-Turing thesis holds then a functionđč that is uncomputable according to our definitioncannot be computed by any means in our physicalworld.

9.6 EXERCISES

Exercise 9.1 — NAND-RAM Halt. Let NANDRAMHALT ∶ 0, 1∗ → 0, 1be the function such that on input (𝑃 , đ‘„) where 𝑃 represents a NAND-RAM program, NANDRAMHALT(𝑃 , đ‘„) = 1 iff 𝑃 halts on the input đ‘„.Prove that NANDRAMHALT is uncomputable.

Exercise 9.2 — Timed halting. Let TIMEDHALT ∶ 0, 1∗ → 0, 1 bethe function that on input (a string representing) a triple (𝑀, đ‘„, 𝑇 ),TIMEDHALT(𝑀, đ‘„, 𝑇 ) = 1 iff the Turing machine 𝑀 , on input đ‘„,halts within at most 𝑇 steps (where a step is defined as one sequenceof reading a symbol from the tape, updating the state, writing a newsymbol and (potentially) moving the head).

Prove that TIMEDHALT is computable.

Exercise 9.3 — Space halting (challenging). Let SPACEHALT ∶ 0, 1∗ →0, 1 be the function that on input (a string representing) a triple(𝑀, đ‘„, 𝑇 ), SPACEHALT(𝑀, đ‘„, 𝑇 ) = 1 iff the Turing machine 𝑀 , oninput đ‘„, halts before its head reached the 𝑇 -th location of its tape. (Wedon’t care how many steps 𝑀 makes, as long as the head stays insidelocations 0, 
 , 𝑇 − 1.)

Prove that SPACEHALT is computable. See footnote for hint2

Exercise 9.4 — Computable compositions. Suppose that đč ∶ 0, 1∗ → 0, 1and đș ∶ 0, 1∗ → 0, 1 are computable functions. For each one of thefollowing functions đ» , either prove that đ» is necessarily computable orgive an example of a pair đč and đș of computable functions such thatđ» will not be computable. Prove your assertions.

1. đ»(đ‘„) = 1 iff đč(đ‘„) = 1 OR đș(đ‘„) = 1.2. đ»(đ‘„) = 1 iff there exist two nonempty strings 𝑱, 𝑣 ∈ 0, 1∗ such

that đ‘„ = 𝑱𝑣 (i.e., đ‘„ is the concatenation of 𝑱 and 𝑣), đč(𝑱) = 1 andđș(𝑣) = 1.3. đ»(đ‘„) = 1 iff there exist a list 𝑱0, 
 , 𝑱𝑡−1 of non empty strings such

that stringsđč(𝑱𝑖) = 1 for every 𝑖 ∈ [𝑡] and đ‘„ = 𝑱0𝑱1 ⋯ 𝑱𝑡−1.

Page 353: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 353

3 Hint: You can use Rice’s Theorem.

4 Hint: While it cannot be applied directly, with alittle “massaging” you can prove this using Rice’sTheorem.

4. đ»(đ‘„) = 1 iff đ‘„ is a valid string representation of a NAND++program 𝑃 such that for every 𝑧 ∈ 0, 1∗, on input 𝑧 the program𝑃 outputs đč(𝑧).

5. đ»(đ‘„) = 1 iff đ‘„ is a valid string representation of a NAND++program 𝑃 such that on input đ‘„ the program 𝑃 outputs đč(đ‘„).

6. đ»(đ‘„) = 1 iff đ‘„ is a valid string representation of a NAND++program 𝑃 such that on input đ‘„, 𝑃 outputs đč(đ‘„) after executing atmost 100 ⋅ |đ‘„|2 lines.

Exercise 9.5 Prove that the following function FINITE ∶ 0, 1∗ → 0, 1is uncomputable. On input 𝑃 ∈ 0, 1∗, we define FINITE(𝑃 ) = 1if and only if 𝑃 is a string that represents a NAND++ program suchthat there only a finite number of inputs đ‘„ ∈ 0, 1∗ s.t. 𝑃(đ‘„) = 1.3

Exercise 9.6 — Computing parity. Prove Theorem 9.13 without using Rice’sTheorem.

Exercise 9.7 — TM Equivalence. Let EQ ∶ 0, 1∗ ∶→ 0, 1 be the func-tion defined as follows: given a string representing a pair (𝑀, 𝑀 â€Č)of Turing machines, EQ(𝑀, 𝑀 â€Č) = 1 iff 𝑀 and 𝑀 â€Č are functionallyequivalent as per Definition 9.14. Prove that EQ is uncomputable.

Note that you cannot use Rice’s Theorem directly, as this theoremonly deals with functions that take a single Turing machine as input,and EQ takes two machines.

Exercise 9.8 For each of the following two functions, say whether it iscomputable or not:

1. Given a NAND-TM program 𝑃 , an input đ‘„, and a number 𝑘, whenwe run 𝑃 on đ‘„, does the index variable i ever reach 𝑘?

2. Given a NAND-TM program 𝑃 , an input đ‘„, and a number 𝑘, whenwe run 𝑃 on đ‘„, does 𝑃 ever write to an array at index 𝑘?

Exercise 9.9 Let đč ∶ 0, 1∗ → 0, 1 be the function that is defined asfollows. On input a string 𝑃 that represents a NAND-RAM programand a String 𝑀 that represents a Turing machine, đč(𝑃 , 𝑀) = 1 if andonly if there exists some input đ‘„ such 𝑃 halts on đ‘„ but 𝑀 does not halton đ‘„. Prove that đč is uncomputable. See footnote for hint.4

Page 354: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

354 introduction to theoretical computer science

5 HALT has this property.

6 You can either use the diagonalization method toprove this directly or show that the set of all recur-sively enumerable functions is countable.

7 HALT has this property: show that if both HALTand đ»đŽđżđ‘‡ were recursively enumerable then HALTwould be in fact computable.

8 Show that any đș satisfying (b) must be semantic.

Exercise 9.10 — Recursively enumerable. Define a function đč ∶ 0, 1∗ ∶→0, 1 to be recursively enumerable if there exists a Turing machine 𝑀such that such that for every đ‘„ ∈ 0, 1∗, if đč(đ‘„) = 1 then 𝑀(đ‘„) = 1,and if đč(đ‘„) = 0 then 𝑀(đ‘„) = ⊄. (i.e., if đč(đ‘„) = 0 then 𝑀 does not halton đ‘„.)1. Prove that every computable đč is also recursively enumerable.

2. Prove that there exists đč that is not computable but is recursivelyenumerable. See footnote for hint.5

3. Prove that there exists a function đč ∶ 0, 1∗ → 0, 1 such that đč isnot recursively enumerable. See footnote for hint.6

4. Prove that there exists a function đč ∶ 0, 1∗ → 0, 1 such thatđč is recursively enumerable but the function đč defined as đč(đ‘„) =1 − đč(đ‘„) is not recursively enumerable. See footnote for hint.7

Exercise 9.11 — Rice’s Theorem: standard form. In this exercise we willprove Rice’s Theorem in the form that it is typically stated in the litera-ture.

For a Turing machine 𝑀 , define 𝐿(𝑀) ⊆ 0, 1∗ to be the set of allđ‘„ ∈ 0, 1∗ such that 𝑀 halts on the input đ‘„ and outputs 1. (The set𝐿(𝑀) is known in the literature as the language recognized by 𝑀 . Notethat 𝑀 might either output a value other than 1 or not halt at all oninputs đ‘„ ∉ 𝐿(𝑀). )1. Prove that for every Turing Machine 𝑀 , if we define đč𝑀 ∶ 0, 1∗ →0, 1 to be the function such that đč𝑀(đ‘„) = 1 iff đ‘„ ∈ 𝐿(𝑀) then đč𝑀

is recursively enumerable as defined in Exercise 9.10.

2. Use Theorem 9.15 to prove that for every đș ∶ 0, 1∗ → 0, 1, if (a)đș is neither the constant zero nor the constant one function, and(b) for every 𝑀, 𝑀 â€Č such that 𝐿(𝑀) = 𝐿(𝑀 â€Č), đș(𝑀) = đș(𝑀 â€Č),then đș is uncomputable. See footnote for hint.8

Exercise 9.12 — Rice’s Theorem for general Turing-equivalent models (optional).

Let ℱ be the set of all partial functions from 0, 1∗ to 0, 1 and ℳ ∶0, 1∗ → ℱ be a Turing-equivalent model as defined in Definition 8.5.We define a function đč ∶ 0, 1∗ → 0, 1 to be ℳ-semantic if thereexists some 𝒱 ∶ ℱ → 0, 1 such that đč(𝑃) = 𝒱(ℳ(𝑃)) for every𝑃 ∈ 0, 1∗.

Prove that for every ℳ-semantic đč ∶ 0, 1∗ → 0, 1 that is neitherthe constant one nor the constant zero function, đč is uncomputable.

Page 355: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

universality and uncomputability 355

9 You will not need to use very specific propertiesof the TOWER function in this exercise. For exam-ple, NBB(𝑛) also grows faster than the Ackermanfunction.

Exercise 9.13 — Busy Beaver. In this question we define the NAND-TM variant of the busy beaver function (see Aaronson’s 1999 essay,2017 blog post and 2020 survey [Aar20]; see also Tao’s highly recom-mended presentation on how civilization’s scientific progress can bemeasured by the quantities we can grasp).

1. Let đ‘‡đ”đ” ∶ 0, 1∗ → ℕ be defined as follows. For every string 𝑃 ∈0, 1∗, if 𝑃 represents a NAND-TM program such that when 𝑃 isexecuted on the input 0 then it halts within 𝑀 steps then đ‘‡đ”đ”(𝑃 ) =𝑀 . Otherwise (if 𝑃 does not represent a NAND-TM program, or itis a program that does not halt on 0), đ‘‡đ”đ”(𝑃 ) = 0. Prove that đ‘‡đ”đ”is uncomputable.

2. Let TOWER(𝑛) denote the number 2⋅⋅⋅2⏟𝑛 times(that is, a “tower of pow-

ers of two” of height 𝑛). To get a sense of how fast this functiongrows, TOWER(1) = 2, TOWER(2) = 22 = 4, TOWER(3) = 222 =16, TOWER(4) = 216 = 65536 and TOWER(5) = 265536 whichis about 1020000. TOWER(6) is already a number that is too big towrite even in scientific notation. Define NBB ∶ ℕ → ℕ (for “NAND-TM Busy Beaver”) to be the function NBB(𝑛) = max𝑃∈0,1𝑛 đ‘‡đ”đ”(𝑃 )where đ‘‡đ”đ” is as defined in Question 6.1. Prove that NBB growsfaster than TOWER, in the sense that TOWER(𝑛) = 𝑜(NBB(𝑛)). Seefootnote for hint9

9.7 BIBLIOGRAPHICAL NOTES

The cartoon of the Halting problem in Fig. 9.1 and taken from CharlesCooper’s website.

Section 7.2 in [MM11] gives a highly recommended overview ofuncomputability. Gödel, Escher, Bach [Hof99] is a classic popularscience book that touches on uncomputability, and unprovability, andspecifically Gödel’s Theorem that we will see in Chapter 11. See alsothe recent book by Holt [Hol18].

The history of the definition of a function is intertwined with thedevelopment of mathematics as a field. For many years, a functionwas identified (as per Euler’s quote above) with the means to calcu-late the output from the input. In the 1800’s, with the invention ofthe Fourier series and with the systematic study of continuity anddifferentiability, people have started looking at more general kinds offunctions, but the modern definition of a function as an arbitrary map-ping was not yet universally accepted. For example, in 1899 Poincarewrote “we have seen a mass of bizarre functions which appear to be forcedto resemble as little as possible honest functions which serve some purpose.

Page 356: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

356 introduction to theoretical computer science


 they are invented on purpose to show that our ancestor’s reasoning was atfault, and we shall never get anything more than that out of them”. Some ofthis fascinating history is discussed in [Gra83; Kle91; LĂŒt02; Gra05].

The existence of a universal Turing machine, and the uncomputabil-ity of HALT was first shown by Turing in his seminal paper [Tur37],though closely related results were shown by Church a year before.These works built on Gödel’s 1931 incompleteness theorem that we willdiscuss in Chapter 11.

Some universal Turing Machines with a small alphabet and numberof states are given in [Rog96], including a single-tape universal Turingmachine with the binary alphabet and with less than 25 states; seealso the survey [WN09]. Adam Yedidia has written software to helpin producing Turing machines with a small number of states. This isrelated to the recreational pastime of “Code Golfing” which is aboutsolving a certain computational task using the as short as possibleprogram. Finding “highly complex” small Turing machine is alsorelated to the “Busy Beaver” problem, see Exercise 9.13 and the survey[Aar20].

The diagonalization argument used to prove uncomputability of đč ∗is derived from Cantor’s argument for the uncountability of the realsdiscussed in Chapter 2.

Christopher Strachey was an English computer scientist and theinventor of the CPL programming language. He was also an earlyartificial intelligence visionary, programming a computer to playCheckers and even write love letters in the early 1950’s, see this NewYorker article and this website.

Rice’s Theorem was proven in [Ric53]. It is typically stated in aform somewhat different than what we used, see Exercise 9.11.

We do not discuss in the chapter the concept of recursively enumer-able languages, but it is covered briefly in Exercise 9.10. As usual, weuse function, as opposed to language, notation.

The cartoon of the Halting problem in Fig. 9.1 is copyright 2019Charles F. Cooper.

Page 357: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

10Restricted computational models

“Happy families are all alike; every unhappy family is unhappy in its ownway”, Leo Tolstoy (opening of the book “Anna Karenina”).

We have seen that many models of computation are Turing equiva-lent, including Turing machines, NAND-TM/NAND-RAM programs,standard programming languages such as C/Python/Javascript, aswell as other models such as the 𝜆 calculus and even the game of life.The flip side of this is that for all these models, Rice’s theorem (The-orem 9.15) holds as well, which means that any semantic property ofprograms in such a model is uncomputable.

The uncomputability of halting and other semantic specificationproblems for Turing equivalent models motivates restricted com-putational models that are (a) powerful enough to capture a set offunctions useful for certain applications but (b) weak enough that wecan still solve semantic specification problems on them. In this chapterwe discuss several such examples.

Big Idea 14 We can use restricted computational models to bypasslimitations such as uncomputability of the Halting problem and Rice’sTheorem. Such models can compute only a restricted subclass offunctions, but allow to answer at least some semantic questions onprograms.

10.1 TURING COMPLETENESS AS A BUG

We have seen that seemingly simple computational models or sys-tems can turn out to be Turing complete. The following webpage listsseveral examples of formalisms that “accidentally” turned out to Tur-ing complete, including supposedly limited languages such as the Cpreprocessor, CSS, (certain variants of) SQL, sendmail configuration,as well as games such as Minecraft, Super Mario, and the card game

Compiled on 8.26.2020 18:10

Learning Objectives:‱ See that Turing completeness is not always a

good thing.‱ Another example of an always-halting

formalism: context-free grammars and simplytyped 𝜆 calculus.

‱ The pumping lemma for non context-freefunctions.

‱ Examples of computable and uncomputablesemantic properties of regular expressions andcontext-free grammars.

Page 358: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

358 introduction to theoretical computer science

Figure 10.1: Some restricted computational models.We have already seen two equivalent restrictedmodels of computation: regular expressions anddeterministic finite automata. We show a morepowerful model: context-free grammars. We alsopresent tools to demonstrate that some functions cannot be computed in these models.

“Magic: The Gathering”. Turing completeness is not always a goodthing, as it means that such formalisms can give rise to arbitrarilycomplex behavior. For example, the postscript format (a precursor ofPDF) is a Turing-complete programming language meant to describedocuments for printing. The expressive power of postscript can allowfor short descriptions of very complex images, but it also gave rise tosome nasty surprises, such as the attacks described in this page rang-ing from using infinite loops as a denial of service attack, to accessingthe printer’s file system.

Example 10.1 — The DAO Hack. An interesting recent example of thepitfalls of Turing-completeness arose in the context of the cryp-tocurrency Ethereum. The distinguishing feature of this currencyis the ability to design “smart contracts” using an expressive (andin particular Turing-complete) programming language. In ourcurrent “human operated” economy, Alice and Bob might sign acontract to agree that if condition X happens then they will jointlyinvest in Charlie’s company. Ethereum allows Alice and Bob tocreate a joint venture where Alice and Bob pool their funds to-gether into an account that will be governed by some program 𝑃that decides under what conditions it disburses funds from it. Forexample, one could imagine a piece of code that interacts betweenAlice, Bob, and some program running on Bob’s car that allowsAlice to rent out Bob’s car without any human intervention oroverhead.

Specifically Ethereum uses the Turing-complete programminglanguage solidity which has a syntax similar to JavaScript. Theflagship of Ethereum was an experiment known as The “Decen-tralized Autonomous Organization” or The DAO. The idea wasto create a smart contract that would create an autonomously rundecentralized venture capital fund, without human managers,where shareholders could decide on investment opportunities. The

Page 359: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

restricted computational models 359

DAO was at the time the biggest crowdfunding success in history.At its height the DAO was worth 150 million dollars, which wasmore than ten percent of the total Ethereum market. Investing inthe DAO (or entering any other “smart contract”) amounts to pro-viding your funds to be run by a computer program. i.e., “codeis law”, or to use the words the DAO described itself: “The DAOis borne from immutable, unstoppable, and irrefutable computer code”.Unfortunately, it turns out that (as we saw in Chapter 9) under-standing the behavior of computer programs is quite a hard thingto do. A hacker (or perhaps, some would say, a savvy investor)was able to fashion an input that caused the DAO code to enterinto an infinite recursive loop in which it continuously transferredfunds into the hacker’s account, thereby cleaning out about 60 mil-lion dollars out of the DAO. While this transaction was “legal” inthe sense that it complied with the code of the smart contract, itwas obviously not what the humans who wrote this code had inmind. The Ethereum community struggled with the response tothis attack. Some tried the “Robin Hood” approach of using thesame loophole to drain the DAO funds into a secure account, butit only had limited success. Eventually, the Ethereum communitydecided that the code can be mutable, stoppable, and refutable.Specifically, the Ethereum maintainers and miners agreed on a“hard fork” (also known as a “bailout”) to revert history to be-fore the hacker’s transaction occurred. Some community membersstrongly opposed this decision, and so an alternative currencycalled Ethereum Classic was created that preserved the originalhistory.

10.2 CONTEXT FREE GRAMMARS

If you have ever written a program, you’ve experienced a syntax error.You probably also had the experience of your program entering intoan infinite loop. What is less likely is that the compiler or interpreterentered an infinite loop while trying to figure out if your program hasa syntax error.

When a person designs a programming language, they need todetermine its syntax. That is, the designer decides which strings corre-sponds to valid programs, and which ones do not (i.e., which stringscontain a syntax error). To ensure that a compiler or interpreter al-ways halts when checking for syntax errors, language designers typi-cally do not use a general Turing-complete mechanism to express theirsyntax. Rather they use a restricted computational model. One of themost popular choices for such models is context free grammars.

Page 360: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

360 introduction to theoretical computer science

To explain context free grammars, let us begin with a canonical ex-ample. Consider the function ARITH ∶ Σ∗ → 0, 1 that takes as inputa string đ‘„ over the alphabet ÎŁ = (, ), +, −, ×, Ă·, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9and returns 1 if and only if the string đ‘„ represents a valid arithmeticexpression. Intuitively, we build expressions by applying an opera-tion such as +,−,× or Ă· to smaller expressions, or enclosing them inparenthesis, where the “base case” corresponds to expressions that aresimply numbers. More precisely, we can make the following defini-tions:

‱ A digit is one of the symbols 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.‱ A number is a sequence of digits. (For simplicity we drop the condi-

tion that the sequence does not have a leading zero, though it is nothard to encode it in a context-free grammar as well.)

‱ An operation is one of +, −, ×, ÷‹ An expression has either the form “number”, the form “sub-

expression1 operation sub-expression2”, or the form “(sub-expression1)”, where “sub-expression1” and “sub-expression2” arethemselves expressions. (Note that this is a recursive definition.)

A context free grammar (CFG) is a formal way of specifying suchconditions. A CFG consists of a set of rules that tell us how to generatestrings from smaller components. In the above example, one of therules is “if đ‘’đ‘„đ‘1 and đ‘’đ‘„đ‘2 are valid expressions, then đ‘’đ‘„đ‘1 × đ‘’đ‘„đ‘2 isalso a valid expression”; we can also write this rule using the short-hand đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘› ⇒ đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘› × đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘›. As in the above ex-ample, the rules of a context-free grammar are often recursive: the ruleđ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘› ⇒ đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘› × đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘› defines valid expressions interms of itself. We now formally define context-free grammars:

Definition 10.2 — Context Free Grammar. Let Σ be some finite set. Acontext free grammar (CFG) over Σ is a triple (𝑉 , 𝑅, 𝑠) such that:

‱ 𝑉 , known as the variables, is a set disjoint from Σ.

‱ 𝑠 ∈ 𝑉 is known as the initial variable.

‱ 𝑅 is a set of rules. Each rule is a pair (𝑣, 𝑧) with 𝑣 ∈ 𝑉 and𝑧 ∈ (ÎŁ âˆȘ 𝑉 )∗. We often write the rule (𝑣, 𝑧) as 𝑣 ⇒ 𝑧 and say thatthe string 𝑧 can be derived from the variable 𝑣.

Page 361: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

restricted computational models 361

Example 10.3 — Context free grammar for arithmetic expressions. Theexample above of well-formed arithmetic expressions can be cap-tured formally by the following context free grammar:

‱ The alphabet ÎŁ is (, ), +, −, ×, Ă·, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9‱ The variables are 𝑉 = đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘› , 𝑛𝑱𝑚𝑏𝑒𝑟 , 𝑑𝑖𝑔𝑖𝑡 , 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛.‱ The rules are the set 𝑅 containing the following 19 rules:

– The 4 rules 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛 ⇒ +, 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛 ⇒ −, 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛 ⇒ ×,and 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛 ⇒ Ă·.

– The 10 rules 𝑑𝑖𝑔𝑖𝑡 ⇒ 0,
, 𝑑𝑖𝑔𝑖𝑡 ⇒ 9.– The rule 𝑛𝑱𝑚𝑏𝑒𝑟 ⇒ 𝑑𝑖𝑔𝑖𝑡.– The rule 𝑛𝑱𝑚𝑏𝑒𝑟 ⇒ 𝑑𝑖𝑔𝑖𝑡 𝑛𝑱𝑚𝑏𝑒𝑟.– The rule đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘› ⇒ 𝑛𝑱𝑚𝑏𝑒𝑟.– The rule đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘› ⇒ đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘› 𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛 đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘›.– The rule đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘› ⇒ (đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘›).

‱ The starting variable is đ‘’đ‘„đ‘đ‘Ÿđ‘’đ‘ đ‘ đ‘–đ‘œđ‘›People use many different notations to write context free grammars.

One of the most common notations is the Backus–Naur form. In thisnotation we write a rule of the form 𝑣 ⇒ 𝑎 (where 𝑣 is a variable and 𝑎is a string) in the form <v> := a. If we have several rules of the form𝑣 ↩ 𝑎, 𝑣 ↩ 𝑏, and 𝑣 ↩ 𝑐 then we can combine them as <v> := a|b|c.(In words we say that 𝑣 can derive either 𝑎, 𝑏, or 𝑐.) For example, theBackus-Naur description for the context free grammar of Example 10.3is the following (using ASCII equivalents for operations):

operation := +|-|*|/digit := 0|1|2|3|4|5|6|7|8|9number := digit|digit numberexpression := number|expression operation

expression|(expression)Another example of a context free grammar is the “matching paren-

thesis” grammar, which can be represented in Backus-Naur as fol-lows:

match := ""|match match|(match)

A string over the alphabet (,) can be generated from this gram-mar (where match is the starting expression and "" corresponds to theempty string) if and only if it consists of a matching set of parenthesis.

Page 362: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

362 introduction to theoretical computer science

1 As in the case of Definition 6.7 we can also uselanguage rather than function notation and say that alanguage 𝐿 ⊆ Σ∗ is context free if the function đč suchthat đč(đ‘„) = 1 iff đ‘„ ∈ 𝐿 is context free.

In contrast, by Lemma 6.19 there is no regular expression that matchesa string đ‘„ if and only if đ‘„ contains a valid sequence of matching paren-thesis.

10.2.1 Context-free grammars as a computational modelWe can think of a context-free grammar over the alphabet ÎŁ as defin-ing a function that maps every string đ‘„ in Σ∗ to 1 or 0 depending onwhether đ‘„ can be generated by the rules of the grammars. We nowmake this definition formally.

Definition 10.4 — Deriving a string from a grammar. If đș = (𝑉 , 𝑅, 𝑠) is acontext-free grammar over ÎŁ, then for two strings đ›Œ, đ›œ ∈ (ÎŁ âˆȘ 𝑉 )∗we say that đ›œ can be derived in one step from đ›Œ, denoted by đ›Œ ⇒đș đ›œ,if we can obtain đ›œ from đ›Œ by applying one of the rules of đș. That is,we obtain đ›œ by replacing in đ›Œ one occurrence of the variable 𝑣 withthe string 𝑧, where 𝑣 ⇒ 𝑧 is a rule of đș.

We say that đ›œ can be derived from đ›Œ, denoted by đ›Œ ⇒∗đș đ›œ, if itcan be derived by some finite number 𝑘 of steps. That is, if thereare đ›Œ1, 
 , đ›Œđ‘˜âˆ’1 ∈ (ÎŁ âˆȘ 𝑉 )∗, so that đ›Œ ⇒đș đ›Œ1 ⇒đș đ›Œ2 ⇒đș ⋯ ⇒đșđ›Œđ‘˜âˆ’1 ⇒đș đ›œ.

We say that đ‘„ ∈ Σ∗ is matched by đș = (𝑉 , 𝑅, 𝑠) if đ‘„ can be de-rived from the starting variable 𝑠 (i.e., if 𝑠 ⇒∗đș đ‘„). We define thefunction computed by (𝑉 , 𝑅, 𝑠) to be the map Ω𝑉 ,𝑅,𝑠 ∶ Σ∗ → 0, 1such that Ω𝑉 ,𝑅,𝑠(đ‘„) = 1 iff đ‘„ is matched by (𝑉 , 𝑅, 𝑠). A functionđč ∶ Σ∗ → 0, 1 is context free if đč = Ω𝑉 ,𝑅,𝑠 for some CFG (𝑉 , 𝑅, 𝑠).1

A priori it might not be clear that the map Ω𝑉 ,𝑅,𝑠 is computable,but it turns out that this is the case.

Theorem 10.5 — Context-free grammars always halt. For every CFG(𝑉 , 𝑅, 𝑠) over 0, 1, the function Ω𝑉 ,𝑅,𝑠 ∶ 0, 1∗ → 0, 1 iscomputable.

As usual we restrict attention to grammars over 0, 1 although theproof extends to any finite alphabet ÎŁ.

Proof. We only sketch the proof. We start with the observation we canconvert every CFG to an equivalent version of Chomsky normal form,where all rules either have the form 𝑱 → đ‘Łđ‘€ for variables 𝑱, 𝑣, đ‘€ or theform 𝑱 → 𝜎 for a variable 𝑱 and symbol 𝜎 ∈ ÎŁ, plus potentially therule 𝑠 → "" where 𝑠 is the starting variable.

The idea behind such a transformation is to simply add new vari-ables as needed, and so for example we can translate a rule such as𝑣 → đ‘ąđœŽđ‘€ into the three rules 𝑣 → 𝑱𝑟, 𝑟 → đ‘Ąđ‘€ and 𝑡 → 𝜎.

Page 363: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

restricted computational models 363

Using the Chomsky Normal form we get a natural recursive algo-rithm for computing whether 𝑠 ⇒∗đș đ‘„ for a given grammar đș andstring đ‘„. We simply try all possible guesses for the first rule 𝑠 → 𝑱𝑣that is used in such a derivation, and then all possible ways to par-tition đ‘„ as a concatenation đ‘„ = đ‘„â€Čđ‘„â€ł. If we guessed the rule and thepartition correctly, then this reduces our task to checking whether𝑱 ⇒∗đș đ‘„â€Č and 𝑣 ⇒∗đș đ‘„â€ł, which (as it involves shorter strings) canbe done recursively. The base cases are when đ‘„ is empty or a singlesymbol, and can be easily handled.

RRemark 10.6 — Parse trees. While we focus on thetask of deciding whether a CFG matches a string, thealgorithm to compute Ω𝑉 ,𝑅,𝑠 actually gives more in-formation than that. That is, on input a string đ‘„, ifΩ𝑉 ,𝑅,𝑠(đ‘„) = 1 then the algorithm yields the sequenceof rules that one can apply from the starting vertex 𝑠to obtain the final string đ‘„. We can think of these rulesas determining a tree with 𝑠 being the root vertex andthe sinks (or leaves) corresponding to the substringsof đ‘„ that are obtained by the rules that do not have avariable in their second element. This tree is knownas the parse tree of đ‘„, and often yields very usefulinformation about the structure of đ‘„.Often the first step in a compiler or interpreter for aprogramming language is a parser that transforms thesource into the parse tree (also known as the abstractsyntax tree). There are also tools that can automati-cally convert a description of a context-free grammarsinto a parser algorithm that computes the parse tree ofa given string. (Indeed, the above recursive algorithmcan be used to achieve this, but there are much moreefficient versions, especially for grammars that haveparticular forms, and programming language design-ers often try to ensure their languages have these moreefficient grammars.)

10.2.2 The power of context free grammarsContext free grammars can capture every regular expression:

Theorem 10.7 — Context free grammars and regular expressions. Let 𝑒 be aregular expression over 0, 1, then there is a CFG (𝑉 , 𝑅, 𝑠) over0, 1 such that Ω𝑉 ,𝑅,𝑠 = Ω𝑒.

Proof. We prove the theorem by induction on the length of 𝑒. If 𝑒 isan expression of one bit length, then 𝑒 = 0 or 𝑒 = 1, in which casewe leave it to the reader to verify that there is a (trivial) CFG that

Page 364: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

364 introduction to theoretical computer science

computes it. Otherwise, we fall into one of the following case: case1: 𝑒 = 𝑒â€Č𝑒″, case 2: 𝑒 = 𝑒â€Č|𝑒″ or case 3: 𝑒 = (𝑒â€Č)∗ where in all cases𝑒â€Č, 𝑒″ are shorter regular expressions. By the induction hypothesishave grammars (𝑉 â€Č, 𝑅â€Č, 𝑠â€Č) and (𝑉 ″, 𝑅″, 𝑠″) that compute Ω𝑒â€Č and Ω𝑒″respectively. By renaming of variables, we can also assume withoutloss of generality that 𝑉 â€Č and 𝑉 ″ are disjoint.

In case 1, we can define the new grammar as follows: we add a newstarting variable 𝑠 ∉ 𝑉 âˆȘ 𝑉 â€Č and the rule 𝑠 ↩ 𝑠â€Č𝑠″. In case 2, we candefine the new grammar as follows: we add a new starting variable𝑠 ∉ 𝑉 âˆȘ 𝑉 â€Č and the rules 𝑠 ↩ 𝑠â€Č and 𝑠 ↩ 𝑠″. Case 3 will be theonly one that uses recursion. As before we add a new starting variable𝑠 ∉ 𝑉 âˆȘ 𝑉 â€Č, but now add the rules 𝑠 ↩ "" (i.e., the empty string) andalso add, for every rule of the form (𝑠â€Č, đ›Œ) ∈ 𝑅â€Č, the rule 𝑠 ↩ đ‘ đ›Œ to 𝑅.

We leave it to the reader as (a very good!) exercise to verify that inall three cases the grammars we produce capture the same function asthe original expression.

It turns out that CFG’s are strictly more powerful than regularexpressions. In particular, as we’ve seen, the “matching parenthesis”function MATCHPAREN can be computed by a context free grammar,whereas, as shown in Lemma 6.19, it cannot be computed by regularexpressions. Here is another example:Solved Exercise 10.1 — Context free grammar for palindromes. Let PAL ∶0, 1, ; ∗ → 0, 1 be the function defined in Solved Exercise 6.4 wherePAL(đ‘€) = 1 iff đ‘€ has the form 𝑱; 𝑱𝑅. Then PAL can be computed by acontext-free grammar

Solution:

A simple grammar computing PAL can be described usingBackus–Naur notation:

start := ; | 0 start 0 | 1 start 1

One can prove by induction that this grammar generates exactlythe strings đ‘€ such that PAL(đ‘€) = 1.

A more interesting example is computing the strings of the form𝑱; 𝑣 that are not palindromes:Solved Exercise 10.2 — Non palindromes. Prove that there is a context freegrammar that computes NPAL ∶ 0, 1, ; ∗ → 0, 1 where NPAL(đ‘€) =1 if đ‘€ = 𝑱; 𝑣 but 𝑣 ≠ 𝑱𝑅.

Page 365: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

restricted computational models 365

Solution:

Using Backus–Naur notation we can describe such a grammar asfollows

palindrome := ; | 0 palindrome 0 | 1 palindrome 1different := 0 palindrome 1 | 1 palindrome 0start := different | 0 start | 1 start | start

0 | start 1In words, this means that we can characterize a string đ‘€ such

that NPAL(đ‘€) = 1 as having the following formđ‘€ = đ›Œđ‘đ‘ą; 𝑱𝑅𝑏â€Čđ›œ (10.1)where đ›Œ, đ›œ, 𝑱 are arbitrary strings and 𝑏 ≠ 𝑏â€Č. Hence we can

generate such a string by first generating a palindrome 𝑱; 𝑱𝑅(palindrome variable), then adding 0 on either the left or right and1 on the opposite side to get something that is not a palindrome(different variable), and then we can add arbitrary number of 0’sand 1’s on either end (the start variable).

10.2.3 Limitations of context-free grammars (optional)Even though context-free grammars are more powerful than regularexpressions, there are some simple languages that are not capturedby context free grammars. One tool to show this is the context-freegrammar analog of the “pumping lemma” (Theorem 6.20):

Theorem 10.8 — Context-free pumping lemma. Let (𝑉 , 𝑅, 𝑠) be a CFGover ÎŁ, then there is some numbers 𝑛0, 𝑛1 ∈ ℕ such that for everyđ‘„ ∈ Σ∗ with |đ‘„| > 𝑛0, if Ω𝑉 ,𝑅,𝑠(đ‘„) = 1 then đ‘„ = 𝑎𝑏𝑐𝑑𝑒 such that|𝑏| + |𝑐| + |𝑑| ≀ 𝑛1, |𝑏| + |𝑑| ≄ 1, and Ω𝑉 ,𝑅,𝑠(𝑎𝑏𝑘𝑐𝑑𝑘𝑒) = 1 for every𝑘 ∈ ℕ.

PThe context-free pumping lemma is even more cum-bersome to state than its regular analog, but you canremember it as saying the following: “If a long enoughstring is matched by a grammar, there must be a variablethat is repeated in the derivation.”

Proof of Theorem 10.8. We only sketch the proof. The idea is that ifthe total number of symbols in the rules of the grammar is 𝑘0, thenthe only way to get |đ‘„| > 𝑛0 with Ω𝑉 ,𝑅,𝑠(đ‘„) = 1 is to use recursion.That is, there must be some variable 𝑣 ∈ 𝑉 such that we are able to

Page 366: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

366 introduction to theoretical computer science

derive from 𝑣 the value 𝑏𝑣𝑑 for some strings 𝑏, 𝑑 ∈ Σ∗, and then furtheron derive from 𝑣 some string 𝑐 ∈ Σ∗ such that 𝑏𝑐𝑑 is a substring ofđ‘„ (in other words, đ‘„ = 𝑎𝑏𝑐𝑑𝑒 for some 𝑎, 𝑒 ∈ 0, 1∗). If we takethe variable 𝑣 satisfying this requirement with a minimum numberof derivation steps, then we can ensure that |𝑏𝑐𝑑| is at most someconstant depending on 𝑛0 and we can set 𝑛1 to be that constant (𝑛1 =10 ⋅ |𝑅| ⋅ 𝑛0 will do, since we will not need more than |𝑅| applicationsof rules, and each such application can grow the string by at most 𝑛0symbols).

Thus by the definition of the grammar, we can repeat the derivationto replace the substring 𝑏𝑐𝑑 in đ‘„ with 𝑏𝑘𝑐𝑑𝑘 for every 𝑘 ∈ ℕ whileretaining the property that the output of Ω𝑉 ,𝑅,𝑠 is still one. Since 𝑏𝑐𝑑is a substring of đ‘„, we can write đ‘„ = 𝑎𝑏𝑐𝑑𝑒 and are guaranteed that𝑎𝑏𝑘𝑐𝑑𝑘𝑒 is matched by the grammar for every 𝑘.

Using Theorem 10.8 one can show that even the simple functionđč ∶ 0, 1∗ → 0, 1 defined as follows:đč(đ‘„) = ⎧⎚⎩1 đ‘„ = đ‘€đ‘€ for some đ‘€ ∈ 0, 1∗0 otherwise(10.2)

is not context free. (In contrast, the function đș ∶ 0, 1∗ → 0, 1defined as đș(đ‘„) = 1 iff đ‘„ = đ‘€0đ‘€1 ⋯ đ‘€đ‘›âˆ’1đ‘€đ‘›âˆ’1đ‘€đ‘›âˆ’2 ⋯ đ‘€0 for someđ‘€ ∈ 0, 1∗ and 𝑛 = |đ‘€| is context free, can you see why?.)Solved Exercise 10.3 — Equality is not context-free. Let EQ ∶ 0, 1, ; ∗ →0, 1 be the function such that EQ(đ‘„) = 1 if and only if đ‘„ = 𝑱; 𝑱 forsome 𝑱 ∈ 0, 1∗. Then EQ is not context free.

Solution:

We use the context-free pumping lemma. Suppose towards thesake of contradiction that there is a grammar đș that computes EQ,and let 𝑛0 be the constant obtained from Theorem 10.8.

Consider the string đ‘„ = 1𝑛00𝑛0 ; 1𝑛00𝑛0 , and write it as đ‘„ = 𝑎𝑏𝑐𝑑𝑒as per Theorem 10.8, with |𝑏𝑐𝑑| ≀ 𝑛0 and with |𝑏| + |𝑑| ≄ 1. By The-orem 10.8, it should hold that EQ(𝑎𝑐𝑒) = 1. However, by case anal-ysis this can be shown to be a contradiction.

Firstly, unless 𝑏 is on the left side of the ; separator and 𝑑 is onthe right side, dropping 𝑏 and 𝑑 will definitely make the two partsdifferent. But if it is the case that 𝑏 is on the left side and 𝑑 is on theright side, then by the condition that |𝑏𝑐𝑑| ≀ 𝑛0 we know that 𝑏 is astring of only zeros and 𝑑 is a string of only ones. If we drop 𝑏 and𝑑 then since one of them is non empty, we get that there are either

Page 367: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

restricted computational models 367

less zeroes on the left side than on the right side, or there are lessones on the right side than on the left side. In either case, we getthat EQ(𝑎𝑐𝑒) = 0, obtaining the desired contradiction.

10.3 SEMANTIC PROPERTIES OF CONTEXT FREE LANGUAGES

As in the case of regular expressions, the limitations of context freegrammars do provide some advantages. For example, emptiness ofcontext free grammars is decidable:

Theorem 10.9 — Emptiness for CFG’s is decidable. There is an algorithmthat on input a context-free grammar đș, outputs 1 if and only if Ίđșis the constant zero function.

Proof Idea:

The proof is easier to see if we transform the grammar to ChomskyNormal Form as in Theorem 10.5. Given a grammar đș, we can recur-sively define a non-terminal variable 𝑣 to be non empty if there is eithera rule of the form 𝑣 ⇒ 𝜎, or there is a rule of the form 𝑣 ⇒ đ‘ąđ‘€ whereboth 𝑱 and đ‘€ are non empty. Then the grammar is non empty if andonly if the starting variable 𝑠 is non-empty.⋆Proof of Theorem 10.9. We assume that the grammar đș in ChomskyNormal Form as in Theorem 10.5. We consider the following proce-dure for marking variables as “non empty”:

1. We start by marking all variables 𝑣 that are involved in a rule of theform 𝑣 ⇒ 𝜎 as non empty.

2. We then continue to mark 𝑣 as non empty if it is involved in a ruleof the form 𝑣 ⇒ đ‘ąđ‘€ where 𝑱, đ‘€ have been marked before.

We continue this way until we cannot mark any more variables. Wethen declare that the grammar is empty if and only if 𝑠 has not beenmarked. To see why this is a valid algorithm, note that if a variable 𝑣has been marked as “non empty” then there is some string đ›Œ ∈ Σ∗ thatcan be derived from 𝑣. On the other hand, if 𝑣 has not been marked,then every sequence of derivations from 𝑣 will always have a variablethat has not been replaced by alphabet symbols. Hence in particularΊđș is the all zero function if and only if the starting variable 𝑠 is notmarked “non empty”.

Page 368: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

368 introduction to theoretical computer science

10.3.1 Uncomputability of context-free grammar equivalence (optional)By analogy to regular expressions, one might have hoped to get analgorithm for deciding whether two given context free grammarsare equivalent. Alas, no such luck. It turns out that the equivalenceproblem for context free grammars is uncomputable. This is a directcorollary of the following theorem:

Theorem 10.10 — Fullness of CFG’s is uncomputable. For every set ÎŁ, letCFGFULLÎŁ be the function that on input a context-free grammar đșover ÎŁ, outputs 1 if and only if đș computes the constant 1 function.Then there is some finite ÎŁ such that CFGFULLÎŁ is uncomputable.

Theorem 10.10 immediately implies that equivalence for context-free grammars is uncomputable, since computing “fullness” of agrammar đș over some alphabet ÎŁ = 𝜎0, 
 , 𝜎𝑘−1 corresponds tochecking whether đș is equivalent to the grammar 𝑠 ⇒ ""|𝑠𝜎0| ⋯ |𝑠𝜎𝑘−1.Note that Theorem 10.10 and Theorem 10.9 together imply thatcontext-free grammars, unlike regular expressions, are not closedunder complement. (Can you see why?) Since we can encode everyelement of ÎŁ using ⌈log |ÎŁ|⌉ bits (and this finite encoding can be easilycarried out within a grammar) Theorem 10.10 implies that fullness isalso uncomputable for grammars over the binary alphabet.

Proof Idea:

We prove the theorem by reducing from the Halting problem. Todo that we use the notion of configurations of NAND-TM programs, asdefined in Definition 8.8. Recall that a configuration of a program 𝑃 is abinary string 𝑠 that encodes all the information about the program inthe current iteration.

We define ÎŁ to be 0, 1 plus some separator characters and defineINVALID𝑃 ∶ Σ∗ → 0, 1 to be the function that maps every string 𝐿 ∈Σ∗ to 1 if and only if 𝐿 does not encode a sequence of configurationsthat correspond to a valid halting history of the computation of 𝑃 onthe empty input.

The heart of the proof is to show that INVALID𝑃 is context-free.Once we do that, we see that 𝑃 halts on the empty input if and only ifINVALID𝑃 (𝐿) = 1 for every 𝐿. To show that, we will encode the listin a special way that makes it amenable to deciding via a context-freegrammar. Specifically we will reverse all the odd-numbered strings.⋆Proof of Theorem 10.10. We only sketch the proof. We will show that ifwe can compute CFGFULL then we can solve HALTONZERO, whichhas been proven uncomputable in Theorem 9.9. Let 𝑀 be an input

Page 369: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

restricted computational models 369

Turing machine for HALTONZERO. We will use the notion of configu-rations of a Turing machine, as defined in Definition 8.8.

Recall that a configuration of Turing machine 𝑀 and input đ‘„ cap-tures the full state of 𝑀 at some point of the computation. The partic-ular details of configurations are not so important, but what you needto remember is that:

‱ A configuration can be encoded by a binary string 𝜎 ∈ 0, 1∗.‱ The initial configuration of 𝑀 on the input 0 is some fixed string.

‱ A halting configuration will have the value a certain state (which canbe easily “read off” from it) set to 1.

‱ If 𝜎 is a configuration at some step 𝑖 of the computation, we denoteby NEXT𝑀(𝜎) as the configuration at the next step. NEXT𝑀(𝜎) isa string that agrees with 𝜎 on all but a constant number of coor-dinates (those encoding the position corresponding to the headposition and the two adjacent ones). On those coordinates, thevalue of NEXT𝑀(𝜎) can be computed by some finite function.

We will let the alphabet ÎŁ = 0, 1 âˆȘ ‖, #. A computation his-tory of 𝑀 on the input 0 is a string 𝐿 ∈ ÎŁ that corresponds to a list‖𝜎0#𝜎1‖𝜎2#𝜎3 ⋯ 𝜎𝑡−2‖𝜎𝑡−1# (i.e., ‖ comes before an even numberedblock, and # comes before an odd numbered one) such that if 𝑖 iseven then 𝜎𝑖 is the string encoding the configuration of 𝑃 on input 0at the beginning of its 𝑖-th iteration, and if 𝑖 is odd then it is the sameexcept the string is reversed. (That is, for odd 𝑖, 𝑟𝑒𝑣(𝜎𝑖) encodes theconfiguration of 𝑃 on input 0 at the beginning of its 𝑖-th iteration.)Reversing the odd-numbered blocks is a technical trick to ensure thatthe function INVALID𝑀 we define below is context free.

We now define INVALID𝑀 ∶ Σ∗ → 0, 1 as follows:

INVALID𝑀(𝐿) = ⎧⎚⎩0 𝐿 is a valid computation history of 𝑀 on 01 otherwise(10.3)

We will show the following claim:CLAIM: INVALID𝑀 is context-free.The claim implies the theorem. Since 𝑀 halts on 0 if and only if

there exists a valid computation history, INVALID𝑀 is the constantone function if and only if 𝑀 does not halt on 0. In particular, thisallows us to reduce determining whether 𝑀 halts on 0 to determiningwhether the grammar đș𝑀 corresponding to INVALID𝑀 is full.

We now turn to the proof of the claim. We will not show all thedetails, but the main point INVALID𝑀(𝐿) = 1 if at least one of thefollowing three conditions hold:

Page 370: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

370 introduction to theoretical computer science

1. 𝐿 is not of the right format, i.e. not of the form ⟹binary-string⟩#⟹binary-string⟩‖⟚binary-string⟩# ⋯.

2. 𝐿 contains a substring of the form ‖𝜎#𝜎â€Č‖ such that𝜎â€Č ≠ 𝑟𝑒𝑣(NEXT𝑃 (𝜎))3. 𝐿 contains a substring of the form #𝜎‖𝜎â€Č# such that𝜎â€Č ≠ NEXT𝑃 (𝑟𝑒𝑣(𝜎))

Since context-free functions are closed under the OR operation, theclaim will follow if we show that we can verify conditions 1, 2 and 3via a context-free grammar.

For condition 1 this is very simple: checking that 𝐿 is of the correctformat can be done using a regular expression. Since regular expres-sions are closed under negation, this means that checking that 𝐿 is notof this format can also be done by a regular expression and hence by acontext-free grammar.

For conditions 2 and 3, this follows via very similar reasoning tothat showing that the function đč such that đč(𝑱#𝑣) = 1 iff 𝑱 ≠ 𝑟𝑒𝑣(𝑣)is context-free, see Solved Exercise 10.2. After all, the NEXT𝑀 functiononly modifies its input in a constant number of places. We leave fillingout the details as an exercise to the reader. Since INVALID𝑀(𝐿) = 1if and only if 𝐿 satisfies one of the conditions 1., 2. or 3., and all threeconditions can be tested for via a context-free grammar, this completesthe proof of the claim and hence the theorem.

10.4 SUMMARY OF SEMANTIC PROPERTIES FOR REGULAR EX-PRESSIONS AND CONTEXT-FREE GRAMMARS

To summarize, we can often trade expressiveness of the model foramenability to analysis. If we consider computational models that arenot Turing complete, then we are sometimes able to bypass Rice’s The-orem and answer certain semantic questions about programs in suchmodels. Here is a summary of some of what is known about semanticquestions for the different models we have seen.

Table 10.1: Computability of semantic properties

Model Halting Emptiness EquivalenceRegular expressions Computable Computable ComputableContext free grammars Computable Computable UncomputableTuring-complete models UncomputableUncomputable Uncomputable

Page 371: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

restricted computational models 371

Chapter Recap

‱ The uncomputability of the Halting problem forgeneral models motivates the definition of re-stricted computational models.

‱ In some restricted models we can answer semanticquestions such as: does a given program terminate,or do two programs compute the same function?

‱ Regular expressions are a restricted model of com-putation that is often useful to capture tasks ofstring matching. We can test efficiently whetheran expression matches a string, as well as answerquestions such as Halting and Equivalence.

‱ Context free grammars is a stronger, yet still not Tur-ing complete, model of computation. The haltingproblem for context free grammars is computable,but equivalence is not computable.

10.5 EXERCISES

Exercise 10.1 — Closure properties of context-free functions. Suppose thatđč, đș ∶ 0, 1∗ → 0, 1 are context free. For each one of the followingdefinitions of the function đ» , either prove that đ» is always contextfree or give a counterexample for regular đč, đș that would make đ» notcontext free.

1. đ»(đ‘„) = đč(đ‘„) √ đș(đ‘„).2. đ»(đ‘„) = đč(đ‘„) ∧ đș(đ‘„)3. đ»(đ‘„) = NAND(đč(đ‘„), đș(đ‘„)).4. đ»(đ‘„) = đč(đ‘„đ‘…) where đ‘„đ‘… is the reverse of đ‘„: đ‘„đ‘… = đ‘„đ‘›âˆ’1đ‘„đ‘›âˆ’2 ⋯ đ‘„đ‘œ for𝑛 = |đ‘„|.5. đ»(đ‘„) = ⎧⎚⎩1 đ‘„ = 𝑱𝑣 s.t. đč(𝑱) = đș(𝑣) = 10 otherwise

6. đ»(đ‘„) = ⎧⎚⎩1 đ‘„ = 𝑱𝑱 s.t. đč(𝑱) = đș(𝑱) = 10 otherwise

7. đ»(đ‘„) = ⎧⎚⎩1 đ‘„ = 𝑱𝑱𝑅 s.t. đč(𝑱) = đș(𝑱) = 10 otherwise

Exercise 10.2 Prove that the function đč ∶ 0, 1∗ → 0, 1 such thatđč(đ‘„) = 1 if and only if |đ‘„| is a power of two is not context free.

Page 372: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

372 introduction to theoretical computer science

2 Try to see if you can “embed” in some way a func-tion that looks similar to MATCHPAREN in SYN, soyou can use a similar proof. Of course for a functionto be non-regular, it does not need to utilize literalparentheses symbols.

Exercise 10.3 — Syntax for programming languages. Consider the followingsyntax of a “programming language” whose source can be writtenusing the ASCII character set:

‱ Variables are obtained by a sequence of letters, numbers and under-scores, but can’t start with a number.

‱ A statement has either the form foo = bar; where foo and bar arevariables, or the form IF (foo) BEGIN ... ENDwhere ... is listof one or more statements, potentially separated by newlines.

A program in our language is simply a sequence of statements (pos-sibly separated by newlines or spaces).

1. Let VAR ∶ 0, 1∗ → 0, 1 be the function that given a stringđ‘„ ∈ 0, 1∗, outputs 1 if and only if đ‘„ corresponds to an ASCIIencoding of a valid variable identifier. Prove that VAR is regular.

2. Let SYN ∶ 0, 1∗ → 0, 1 be the function that given a string𝑠 ∈ 0, 1∗, outputs 1 if and only if 𝑠 is an ASCII encoding of a validprogram in our language. Prove that SYN is context free. (You donot have to specify the full formal grammar for SYN, but you needto show that such a grammar exists.)

3. Prove that SYN is not regular. See footnote for hint2

10.6 BIBLIOGRAPHICAL NOTES

As in the case of regular expressions, there are many resources avail-able that cover context-free grammar in great detail. Chapter 2 of[Sip97] contains many examples of context-free grammars and theirproperties. There are also websites such as Grammophone where youcan input grammars, and see what strings they generate, as well assome of the properties that they satisfy.

The adjective “context free” is used for CFG’s because a rule ofthe form 𝑣 ↩ 𝑎 means that we can always replace 𝑣 with the string𝑎, no matter what is the context in which 𝑣 appears. More generally,we might want to consider cases where the replacement rules dependon the context. This gives rise to the notion of general (aka “Type 0”)grammars that allow rules of the form 𝑎 ⇒ 𝑏 where both 𝑎 and 𝑏 arestrings over (𝑉 âˆȘ ÎŁ)∗. The idea is that if, for example, we wanted toenforce the condition that we only apply some rule such as 𝑣 ↩ 0đ‘€1when 𝑣 is surrounded by three zeroes on both sides, then we could doso by adding a rule of the form 000𝑣000 ↩ 0000đ‘€1000 (and of coursewe can add much more general conditions). Alas, this generality

Page 373: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

restricted computational models 373

comes at a cost - general grammars are Turing complete and hencetheir halting problem is uncomputable. That is, there is no algorithm𝐮 that can determine for every general grammar đș and a string đ‘„,whether or not the grammar đș generates đ‘„.

The Chomsky Hierarchy is a hierarchy of grammars from the leastrestrictive (most powerful) Type 0 grammars, which correspond torecursively enumerable languages (see Exercise 9.10) to the most re-strictive Type 3 grammars, which correspond to regular languages.Context-free languages correspond to Type 2 grammars. Type 1 gram-mars are context sensitive grammars. These are more powerful thancontext-free grammars but still less powerful than Turing machines.In particular functions/languages corresponding to context-sensitivegrammars are always computable, and in fact can be computed by alinear bounded automatons which are non-deterministic algorithmsthat take 𝑂(𝑛) space. For this reason, the class of functions/languagescorresponding to context-sensitive grammars is also known as thecomplexity class NSPACE𝑂(𝑛); we discuss space-bounded com-plexity in Chapter 17). While Rice’s Theorem implies that we cannotcompute any non-trivial semantic property of Type 0 grammars, thesituation is more complex for other types of grammars: some seman-tic properties can be determined and some cannot, depending on thegrammar’s place in the hierarchy.

Page 374: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 375: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

11Is every theorem provable?

“Take any definite unsolved problem, such as 
 the existence of an infinitenumber of prime numbers of the form 2𝑛 + 1. However unapproachable theseproblems may seem to us and however helpless we stand before them, we have,nevertheless, the firm conviction that their solution must follow by a finitenumber of purely logical processes
”“
This conviction of the solvability of every mathematical problem is a pow-erful incentive to the worker. We hear within us the perpetual call: There is theproblem. Seek its solution. You can find it by pure reason, for in mathematicsthere is no ignorabimus.”, David Hilbert, 1900.

“The meaning of a statement is its method of verification.”, Moritz Schlick,1938 (aka “The verification principle” of logical positivism)

The problems shown uncomputable in Chapter 9, while naturaland important, still intimately involved NAND-TM programs or othercomputing mechanisms in their definitions. One could perhaps hopethat as long as we steer clear of functions whose inputs are themselvesprograms, we can avoid the “curse of uncomputability”. Alas, we haveno such luck.

In this chapter we will see an example of a natural and seemingly“computation free” problem that nevertheless turns out to be uncom-putable: solving Diophantine equations. As a corollary, we will seeone of the most striking results of 20th century mathematics: Gödel’sIncompleteness Theorem, which showed that there are some mathemat-ical statements (in fact, in number theory) that are inherently unprov-able. We will actually start with the latter result, and then show theformer.

11.1 HILBERT’S PROGRAM AND GÖDEL’S INCOMPLETENESSTHEOREM

“And what are these 
vanishing increments? They are neither finite quanti-ties, nor quantities infinitely small, nor yet nothing. May we not call them theghosts of departed quantities?”, George Berkeley, Bishop of Cloyne, 1734.

Compiled on 8.26.2020 18:10

Learning Objectives:‱ More examples of uncomputable functions

that are not as tied to computation.‱ Gödel’s incompleteness theorem - a result

that shook the world of mathematics in theearly 20th century.

Page 376: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

376 introduction to theoretical computer science

Figure 11.1: Outline of the results of this chapter. Oneversion of Gödel’s Incompleteness Theorem is animmediate consequence of the uncomputability of theHalting problem. To obtain the theorem as originallystated (for statements about the integers) we firstprove that the QMS problem of determining truthof quantified statements involving both integers andstrings is uncomputable. We do so using the notion ofTuring Machine configurations but there are alternativeapproaches to do so as well, see Remark 11.14.

The 1700’s and 1800’s were a time of great discoveries in mathe-matics but also of several crises. The discovery of calculus by Newtonand Leibnitz in the late 1600’s ushered a golden age of problem solv-ing. Many longstanding challenges succumbed to the new tools thatwere discovered, and mathematicians got ever better at doing sometruly impressive calculations. However, the rigorous foundationsbehind these calculations left much to be desired. Mathematiciansmanipulated infinitesimal quantities and infinite series cavalierly, andwhile most of the time they ended up with the correct results, therewere a few strange examples (such as trying to calculate the valueof the infinite series 1 − 1 + 1 − 1 + 1 + 
) which seemed to giveout different answers depending on the method of calculation. Thisled to a growing sense of unease in the foundations of the subjectwhich was addressed in the works of mathematicians such as Cauchy,Weierstrass, and Riemann, who eventually placed analysis on firmerfoundations, giving rise to the 𝜖’s and 𝛿’s that students taking honorscalculus grapple with to this day.

In the beginning of the 20th century, there was an effort to replicatethis effort, in greater rigor, to all parts of mathematics. The hope wasto show that all the true results of mathematics can be obtained bystarting with a number of axioms, and deriving theorems from themusing logical rules of inference. This effort was known as the Hilbertprogram, named after the influential mathematician David Hilbert.

Alas, it turns out the results we’ve seen dealt a devastating blow tothis program, as was shown by Kurt Gödel in 1931:

Theorem 11.1 — Gödel’s Incompleteness Theorem: informal version. Forevery sound proof system 𝑉 for sufficiently rich mathematicalstatements, there is a mathematical statement that is true but is notprovable in 𝑉 .

Page 377: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

is every theorem provable? 377

1 This happens to be a false statement.

2 It is unknown whether this statement is true or false.

11.1.1 Defining “Proof Systems”Before proving Theorem 11.1, we need to define “proof systems” andeven formally define the notion of a “mathematical statement”. Ingeometry and other areas of mathematics, proof systems are oftendefined by starting with some basic assumptions or axioms and thenderiving more statements by using inference rules such as the famousModus Ponens, but what axioms shall we use? What rules? We willuse an extremely general notion of proof systems, not even restrictingourselves to ones that have the form of axioms and inference.

Mathematical statements. At the highest level, a mathematical statementis simply a piece of text, which we can think of as a string đ‘„ ∈ 0, 1∗.Mathematical statements contain assertions whose truth does notdepend on any empirical fact, but rather only on properties of abstractobjects. For example, the following is a mathematical statement:1

“The number 2,696,635,869,504,783,333,238,805,675,613, 588,278,597,832,162,617,892,474,670,798,113is prime”.

Mathematical statements do not have to involve numbers. Theycan assert properties of any other mathematical object including sets,strings, functions, graphs and yes, even programs. Thus, another exam-ple of a mathematical statement is the following:2

The following Python function halts on every positive integer n

def f(n):if n==1: return 1return f(3*n+1) if n % 2 else f(n//2)

Proof systems. A proof for a statement đ‘„ ∈ 0, 1∗ is another piece oftext đ‘€ ∈ 0, 1∗ that certifies the truth of the statement asserted in đ‘„.The conditions for a valid proof system are:

1. (Effectiveness) Given a statement đ‘„ and a proof đ‘€, there is an algo-rithm to verify whether or not đ‘€ is a valid proof for đ‘„. (For exam-ple, by going line by line and checking that each line follows fromthe preceding ones using one of the allowed inference rules.)

2. (Soundness) If there is a valid proof đ‘€ for đ‘„ then đ‘„ is true.

These are quite minimal requirements for a proof system. Require-ment 2 (soundness) is the very definition of a proof system: youshouldn’t be able to prove things that are not true. Requirement 1is also essential. If there is no set of rules (i.e., an algorithm) to checkthat a proof is valid then in what sense is it a proof system? We could

Page 378: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

378 introduction to theoretical computer science

replace it with a system where the “proof” for a statement đ‘„ is “trustme: it’s true”.

We formally define proof systems as an algorithm 𝑉 where𝑉 (đ‘„, đ‘€) = 1 holds if the string đ‘€ is a valid proof for the statement đ‘„.Even if đ‘„ is true, the string đ‘€ does not have to be a valid proof for it(there are plenty of wrong proofs for true statements such as 4=2+2)but if đ‘€ is a valid proof for đ‘„ then đ‘„ must be true.

Definition 11.2 — Proof systems. Let 𝒯 ⊆ 0, 1∗ be some set (whichwe consider the “true” statements). A proof system for 𝒯 is an algo-rithm 𝑉 that satisfies:

1. (Effectiveness) For every đ‘„, đ‘€ ∈ 0, 1∗, 𝑉 (đ‘„, đ‘€) halts with an out-put of either 0 or 1.

2. (Soundness) For every đ‘„ ∉ 𝒯 and đ‘€ ∈ 0, 1∗, 𝑉 (đ‘„, đ‘€) = 0.A true statement đ‘„ ∈ 𝒯 is unprovable (with respect to 𝑉 ) if for

every đ‘€ ∈ 0, 1∗, 𝑉 (đ‘„, đ‘€) = 0. We say that 𝑉 is complete if theredoes not exist a true statement đ‘„ that is unprovable with respect to𝑉 .

Big Idea 15 A proof is just a string of text whose meaning is givenby a verification algorithm.

11.2 GÖDEL’S INCOMPLETENESS THEOREM: COMPUTATIONALVARIANT

Our first formalization of Theorem 11.1 involves statements aboutTuring machines. We let ℋ be the set of strings đ‘„ ∈ 0, 1∗ that havethe form “Turing machine 𝑀 halts on the zero input”.

Theorem 11.3 — Gödel’s Incompleteness Theorem: computational variant.

There does not exist a complete proof system for ℋ.

Proof Idea:

If we had such a complete and sound proof system then we couldsolve the HALTONZERO problem. On input a Turing machine 𝑀 ,we would search all purported proofs đ‘€ and halt as soon as we finda proof of either “𝑀 halts on zero” or “𝑀 does not halt on zero”. Ifthe system is sound and complete then we will eventually find such aproof, and it will provide us with the correct output.⋆

Page 379: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

is every theorem provable? 379

Proof of Theorem 11.3. Assume for the sake of contradiction that therewas such a proof system 𝑉 . We will use 𝑉 to build an algorithm 𝐮that computes HALTONZERO, hence contradicting Theorem 9.9. Ouralgorithm 𝐮 will will work as follows:

Algorithm 11.4 — Halting from proofs.

Input: Turing Machine 𝑀Output: 1 𝑀 if halts on theInput: 0; 0 otherwise.1: for 𝑛 = 1, 2, 3, 
 do2: for đ‘€ ∈ 0, 1𝑛 do3: if 𝑉 (”𝑀 halts on 0”, đ‘€) = 1 then4: return 15: end if6: if 𝑉 (”𝑀 does not halt on 0”, đ‘€) = 1 then7: return 08: end if9: end for

10: end for

If 𝑀 halts on 0 then under our assumption there exists đ‘€ thatproves this fact, and so when Algorithm 𝐮 reaches 𝑛 = |đ‘€| we willeventually find this đ‘€ and output 1, unless we already halted be-fore. But we cannot halt before and output a wrong answer becauseit would contradict the soundness of the proof system. Similarly, thisshows that if 𝑀 does not halt on 0 then (since we assume there is aproof of this fact too) our algorithm 𝐮 will eventually halt and output0.

RRemark 11.5 — The Gödel statement (optional). One canextract from the proof of Theorem 11.3 a procedurethat for every proof system 𝑉 , yields a true statementđ‘„âˆ— that cannot be proven in 𝑉 . But Gödel’s proofgave a very explicit description of such a statement đ‘„âˆ—which is closely related to the “Liar’s paradox”. Thatis, Gödel’s statement đ‘„âˆ— was designed to be true if andonly if âˆ€đ‘€âˆˆ0,1∗ 𝑉 (đ‘„, đ‘€) = 0. In other words, it satisfiedthe following property

đ‘„âˆ— is true ⇔ đ‘„âˆ— does not have a proof in 𝑉 (11.1)

One can see that if đ‘„âˆ— is true, then it does not have aproof, but it is false then (assuming the proof systemis sound) then it cannot have a proof, and hence đ‘„âˆ—

Page 380: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

380 introduction to theoretical computer science

must be both true and unprovable. One might wonderhow is it possible to come up with an đ‘„âˆ— that satisfiesa condition such as (11.1) where the same string đ‘„âˆ—appears on both the righthand side and the lefthandside of the equation. The idea is that the proof of The-orem 11.3 yields a way to transform every statement đ‘„into a statement đč(đ‘„) that is true if and only if đ‘„ doesnot have a proof in 𝑉 . Thus đ‘„âˆ— needs to be a fixed pointof đč : a sentence such that đ‘„âˆ— = đč(đ‘„âˆ—). It turns out thatwe can always find such a fixed point of đč . We’ve al-ready seen this phenomenon in the 𝜆 calculus, wherethe 𝑌 combinator maps every đč into a fixed point 𝑌 đčof đč . This is very related to the idea of programs thatcan print their own code. Indeed, Scott Aaronson likesto describe Gödel’s statement as follows:

The following sentence repeated twice, the sec-ond time in quotes, is not provable in the formalsystem 𝑉 . “The following sentence repeatedtwice, the second time in quotes, is not provablein the formal system 𝑉 .”

In the argument above we actually showed that đ‘„âˆ— istrue, under the assumption that 𝑉 is sound. Since đ‘„âˆ—is true and does not have a proof in 𝑉 , this means thatwe cannot carry the above argument in the system 𝑉 ,which means that 𝑉 cannot prove its own soundness(or even consistency: that there is no proof of both astatement and its negation). Using this idea, it’s nothard to get Gödel’s second incompleteness theorem,which says that every sufficiently rich 𝑉 cannot proveits own consistency. That is, if we formalize the state-ment 𝑐∗ that is true if and only if 𝑉 is consistent (i.e.,𝑉 cannot prove both a statement and the statement’snegation), then 𝑐∗ cannot be proven in 𝑉 .

11.3 QUANTIFIED INTEGER STATEMENTS

There is something “unsatisfying” about Theorem 11.3. Sure, it showsthere are statements that are unprovable, but they don’t feel like “real”statements about math. After all, they talk about programs rather thannumbers, matrices, or derivatives, or whatever it is they teach in mathcourses. It turns out that we can get an analogous result for statementssuch as “there are no positive integers đ‘„ and 𝑩 such that đ‘„2 − 2 =𝑩7”, or “there are positive integers đ‘„, 𝑩, 𝑧 such that đ‘„2 + 𝑩6 = 𝑧11”that only talk about natural numbers. It doesn’t get much more “realmath” than this. Indeed, the 19th century mathematician LeopoldKronecker famously said that “God made the integers, all else is thework of man.” (By the way, the status of the above two statements isunknown.)

Page 381: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

is every theorem provable? 381

To make this more precise, let us define the notion of quantifiedinteger statements:

Definition 11.6 — Quantified integer statements. A quantified integer state-ment is a well-formed statement with no unbound variables involv-ing integers, variables, the operators >, <, ×, +, −, =, the logicaloperations ÂŹ (NOT), ∧ (AND), and √ (OR), as well as quantifiersof the form âˆƒđ‘„âˆˆâ„• and ∀𝑩∈ℕ where đ‘„, 𝑩 are variable names.

We often care deeply about determining the truth of quantifiedinteger statements. For example, the statement that Fermat’s LastTheorem is true for 𝑛 = 3 can be phrased as the quantified integerstatement

¬∃𝑎∈ℕ∃𝑏∈ℕ∃𝑐∈ℕ(𝑎 > 0)∧(𝑏 > 0)∧(𝑐 > 0)∧(𝑎 × 𝑎 × 𝑎 + 𝑏 × 𝑏 × 𝑏 = 𝑐 × 𝑐 × 𝑐) .(11.2)

The twin prime conjecture, that states that there is an infinite num-ber of numbers 𝑝 such that both 𝑝 and 𝑝 + 2 are primes can be phrasedas the quantified integer statement∀𝑛∈ℕ∃𝑝∈ℕ(𝑝 > 𝑛) ∧ PRIME(𝑝) ∧ PRIME(𝑝 + 2) (11.3)

where we replace an instance of PRIME(𝑞) with the statement (𝑞 >1) ∧ ∀𝑎∈ℕ∀𝑏∈ℕ(𝑎 = 1) ∹ (𝑎 = 𝑞) ∹ ¬(𝑎 × 𝑏 = 𝑞).The claim (mentioned in Hilbert’s quote above) that are infinitely

many primes of the form 𝑝 = 2𝑛 + 1 can be phrased as follows:

∀𝑛∈ℕ∃𝑝∈ℕ(𝑝 > 𝑛) ∧ PRIME(𝑝)∧(∀𝑘∈ℕ(𝑘 ≠ 2 ∧ PRIME(𝑘)) ⇒ ¬DIVIDES(𝑘, 𝑝 − 1)) (11.4)

where DIVIDES(𝑎, 𝑏) is the statement ∃𝑐∈ℕ𝑏 × 𝑐 = 𝑎. In English, thiscorresponds to the claim that for every 𝑛 there is some 𝑝 > 𝑛 such thatall of 𝑝 − 1’s prime factors are equal to 2.

RRemark 11.7 — Syntactic sugar for quantified integerstatements. To make our statements more readable,we often use syntactic sugar and so write đ‘„ ≠ 𝑩 asshorthand for ÂŹ(đ‘„ = 𝑩), and so on. Similarly, the“implication operator” 𝑎 ⇒ 𝑏 is “syntactic sugar” orshorthand for ¬𝑎 √ 𝑏, and the “if and only if operator”𝑎 ⇔ is shorthand for (𝑎 ⇒ 𝑏) ∧ (𝑏 ⇒ 𝑎). We willalso allow ourselves the use of “macros”: plugging inone quantified integer statement in another, as we didwith DIVIDES and PRIME above.

Page 382: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

382 introduction to theoretical computer science

Much of number theory is concerned with determining the truthof quantified integer statements. Since our experience has been that,given enough time (which could sometimes be several centuries) hu-manity has managed to do so for the statements that it cared enoughabout, one could (as Hilbert did) hope that eventually we would beable to prove or disprove all such statements. Alas, this turns out to beimpossible:

Theorem 11.8 — Gödel’s Incompleteness Theorem for quantified integer state-

ments. Let 𝑉 ∶ 0, 1∗ → 0, 1 a computable purported verificationprocedure for quantified integer statements. Then either:

‱ 𝑉 is not sound: There exists a false statement đ‘„ and a stringđ‘€ ∈ 0, 1∗ such that 𝑉 (đ‘„, đ‘€) = 1.or

‱ 𝑉 is not complete: There exists a true statement đ‘„ such that forevery đ‘€ ∈ 0, 1∗, 𝑉 (đ‘„, đ‘€) = 0.

Theorem 11.8 is a direct corollary of the following result, justas Theorem 11.3 was a direct corollary of the uncomputability ofHALTONZERO:

Theorem 11.9 — Uncomputability of quantified integer statements. LetQIS ∶ 0, 1∗ → 0, 1 be the function that given a (string rep-resentation of) a quantified integer statement outputs 1 if it is trueand 0 if it is false. Then QIS is uncomputable.

Since a quantified integer statement is simply a sequence of sym-bols, we can easily represent it as a string. For simplicity we will as-sume that every string represents some quantified integer statement,by mapping strings that do not correspond to such a statement to anarbitrary statement such as âˆƒđ‘„âˆˆâ„•đ‘„ = 1.

PPlease stop here and make sure you understandwhy the uncomputability of QIS (i.e., Theorem 11.9)means that there is no sound and complete proofsystem for proving quantified integer statements (i.e.,Theorem 11.8). This follows in the same way thatTheorem 11.3 followed from the uncomputability ofHALTONZERO, but working out the details is a greatexercise (see Exercise 11.1)

In the rest of this chapter, we will show the proof of Theorem 11.8,following the outline illustrated in Fig. 11.1.

Page 383: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

is every theorem provable? 383

Figure 11.2: Diophantine equations such as findinga positive integer solution to the equation 𝑎(𝑎 +𝑏)(𝑎 + 𝑐) + 𝑏(𝑏 + 𝑎)(𝑏 + 𝑐) + 𝑐(𝑐 + 𝑎)(𝑐 + 𝑏) =4(𝑎 + 𝑏)(𝑎 + 𝑐)(𝑏 + 𝑐) (depicted more compactlyand whimsically above) can be surprisingly difficult.There are many equations for which we do not knowif they have a solution, and there is no algorithm tosolve them in general. The smallest solution for thisequation has 80 digits! See this Quora post for moreinformation, including the credits for this image.3 This is a special case of what’s known as “Fermat’sLast Theorem” which states that 𝑎𝑛 + 𝑏𝑛 = 𝑐𝑛 has nosolution in integers for 𝑛 > 2. This was conjectured in1637 by Pierre de Fermat but only proven by AndrewWiles in 1991. The case 𝑛 = 11 (along with all otherso called “regular prime exponents”) was establishedby Kummer in 1850.

11.4 DIOPHANTINE EQUATIONS AND THE MRDP THEOREM

Many of the functions people wanted to compute over the years in-volved solving equations. These have a much longer history thanmechanical computers. The Babylonians already knew how to solvesome quadratic equations in 2000BC, and the formula for all quadrat-ics appears in the Bakhshali Manuscript that was composed in Indiaaround the 3rd century. During the Renaissance, Italian mathemati-cians discovered generalization of these formulas for cubic and quar-tic (degrees 3 and 4) equations. Many of the greatest minds of the17th and 18th century, including Euler, Lagrange, Leibniz and Gaussworked on the problem of finding such a formula for quintic equationsto no avail, until in the 19th century Ruffini, Abel and Galois showedthat no such formula exists, along the way giving birth to group theory.

However, the fact that there is no closed-form formula doesnot mean we can not solve such equations. People have beensolving higher degree equations numerically for ages. The Chinesemanuscript Jiuzhang Suanshu from the first century mentions suchapproaches. Solving polynomial equations is by no means restrictedonly to ancient history or to students’ homework. The gradientdescent method is the workhorse powering many of the machinelearning tools that have revolutionized Computer Science over the lastseveral years.

But there are some equations that we simply do not know how tosolve by any means. For example, it took more than 200 years until peo-ple succeeded in proving that the equation 𝑎11 + 𝑏11 = 𝑐11 has nosolution in integers.3 The notorious difficulty of so called Diophantineequations (i.e., finding integer roots of a polynomial) motivated themathematician David Hilbert in 1900 to include the question of find-ing a general procedure for solving such equations in his famous listof twenty-three open problems for mathematics of the 20th century. Idon’t think Hilbert doubted that such a procedure exists. After all, thewhole history of mathematics up to this point involved the discoveryof ever more powerful methods, and even impossibility results suchas the inability to trisect an angle with a straightedge and compass, orthe non-existence of an algebraic formula for quintic equations, merelypointed out to the need to use more general methods.

Alas, this turned out not to be the case for Diophantine equations.In 1970, Yuri Matiyasevich, building on a decades long line of work byMartin Davis, Hilary Putnam and Julia Robinson, showed that there issimply no method to solve such equations in general:

Theorem 11.10 — MRDP Theorem. Let DIO ∶ 0, 1∗ → 0, 1 be thefunction that takes as input a string describing a 100-variable poly-

Page 384: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

384 introduction to theoretical computer science

nomial with integer coefficients 𝑃(đ‘„0, 
 , đ‘„99) and outputs 1 if andonly if there exists 𝑧0, 
 , 𝑧99 ∈ ℕ s.t. 𝑃(𝑧0, 
 , 𝑧99) = 0.

Then DIO is uncomputable.

As usual, we assume some standard way to express numbers andtext as binary strings. The constant 100 is of course arbitrary; the prob-lem is known to be uncomputable even for polynomials of degreefour and at most 58 variables. In fact the number of variables can bereduced to nine, at the expense of the polynomial having a larger (butstill constant) degree. See Jones’s paper for more about this issue.

RRemark 11.11 — Active code vs static data. The diffi-culty in finding a way to distinguish between “code”such as NAND-TM programs, and “static content”such as polynomials is just another manifestation ofthe phenomenon that code is the same as data. Whilea fool-proof solution for distinguishing between thetwo is inherently impossible, finding heuristics that doa reasonable job keeps many firewall and anti-virusmanufacturers very busy (and finding ways to bypassthese tools keeps many hackers busy as well).

11.5 HARDNESS OF QUANTIFIED INTEGER STATEMENTS

We will not prove the MRDP Theorem (Theorem 11.10). However, aswe mentioned, we will prove the uncomputability of QIS (i.e., Theo-rem 11.9), which is a special case of the MRDP Theorem. The reasonis that a Diophantine equation is a special case of a quantified integerstatement where the only quantifier is ∃. This means that deciding thetruth of quantified integer statements is a potentially harder problemthan solving Diophantine equations, and so it is potentially easier toprove that QIS is uncomputable.

PIf you find the last sentence confusing, it is worth-while to reread it until you are sure you follow itslogic. We are so accustomed to trying to find solu-tions for problems that it can sometimes be hard tofollow the arguments for showing that problems areuncomputable.

Our proof of the uncomputability of QIS (i.e. Theorem 11.9) will, asusual, go by reduction from the Halting problem, but we will do so intwo steps:

Page 385: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

is every theorem provable? 385

1. We will first use a reduction from the Halting problem to show thatdeciding the truth of quantified mixed statements is uncomputable.Quantified mixed statements involve both strings and integers.Since quantified mixed statements are a more general concept thanquantified integer statements, it is easier to prove the uncomputabil-ity of deciding their truth.

2. We will then reduce the problem of quantified mixed statements toquantifier integer statements.

11.5.1 Step 1: Quantified mixed statements and computation historiesWe define quantified mixed statements as statements involving not justintegers and the usual arithmetic operators, but also string variables aswell.

Definition 11.12 — Quantified mixed statements. A quantified mixed state-ment is a well-formed statement with no unbound variables involv-ing integers, variables, the operators >, <, ×, +, −, =, the logicaloperations ÂŹ (NOT), ∧ (AND), and √ (OR), as well as quanti-fiers of the form âˆƒđ‘„âˆˆâ„•, ∃𝑎∈0,1∗ , ∀𝑩∈ℕ, ∀𝑏∈0,1∗ where đ‘„, 𝑩, 𝑎, 𝑏 arevariable names. These also include the operator |𝑎| which returnsthe length of a string valued variable 𝑎, as well as the operator 𝑎𝑖where 𝑎 is a string-valued variable and 𝑖 is an integer valued ex-pression which is true if 𝑖 is smaller than the length of 𝑎 and the 𝑖𝑡ℎcoordinate of 𝑎 is 1, and is false otherwise.

For example, the true statement that for every string 𝑎 there is astring 𝑏 that corresponds to 𝑎 in reverse order can be phrased as thefollowing quantified mixed statement∀𝑎∈0,1∗∃𝑏∈0,1∗(|𝑎| = |𝑏|) ∧ (∀𝑖∈ℕ𝑖 < |𝑎| ⇒ (𝑎𝑖 ⇔ 𝑏|𝑎|−𝑖)) . (11.5)

Quantified mixed statements are more general than quantifiedinteger statements, and so the following theorem is potentially easierto prove than Theorem 11.9:

Theorem 11.13 — Uncomputability of quantified mixed statements. LetQMS ∶ 0, 1∗ → 0, 1 be the function that given a (string rep-resentation of) a quantified mixed statement outputs 1 if it is trueand 0 if it is false. Then QMS is uncomputable.

Proof Idea:

The idea behind the proof is similar to that used in showing thatone-dimensional cellular automata are Turing complete (Theorem 8.7)as well as showing that equivalence (or even “fullness”) of contextfree grammars is uncomputable (Theorem 10.10). We use the notion

Page 386: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

386 introduction to theoretical computer science

of a configuration of a NAND-TM program as in Definition 8.8. Sucha configuration can be thought of as a string đ›Œ over some large-but-finite alphabet ÎŁ describing its current state, including the valuesof all arrays, scalars, and the index variable i. It can be shown thatif đ›Œ is the configuration at a certain step of the execution and đ›œ isthe configuration at the next step, then đ›œđ‘— = đ›Œđ‘— for all 𝑗 outside of𝑖 − 1, 𝑖, 𝑖 + 1 where 𝑖 is the value of i. In particular, every value đ›œđ‘— issimply a function of đ›Œđ‘—âˆ’1,𝑗,𝑗+1. Using these observations we can writea quantified mixed statement NEXT(đ›Œ, đ›œ) that will be true if and only ifđ›œ is the configuration encoding the next step after đ›Œ. Since a program𝑃 halts on input đ‘„ if and only if there is a sequence of configurationsđ›Œ0, 
 , đ›Œđ‘Ąâˆ’1 (known as a computation history) starting with the initialconfiguration with input đ‘„ and ending in a halting configuration, wecan define a quantified mixed statement to determine if there is sucha statement by taking a universal quantifier over all strings đ» (forhistory) that encode a tuple (đ›Œ0, đ›Œ1, 
 , đ›Œđ‘Ąâˆ’1) and then checking thatđ›Œ0 and đ›Œđ‘Ąâˆ’1 are valid starting and halting configurations, and thatNEXT(đ›Œđ‘—, đ›Œđ‘—+1) is true for every 𝑗 ∈ 0, 
 , 𝑡 − 2.⋆Proof of Theorem 11.13. The proof is obtained by a reduction from theHalting problem. Specifically, we will use the notion of a configura-tion of a Turing Machines (Definition 8.8) that we have seen in thecontext of proving that one dimensional cellular automata are Turingcomplete. We need the following facts about configurations:

‱ For every Turing Machine 𝑀 , there is a finite alphabet ÎŁ, and aconfiguration of 𝑀 is a string đ›Œ ∈ Σ∗.

‱ A configuration đ›Œ encodes all the state of the program at a particu-lar iteration, including the array, scalar, and index variables.

‱ If đ›Œ is a configuration, then đ›œ = NEXT𝑃 (đ›Œ) denotes the configura-tion of the computation after one more iteration. đ›œ is a string over ÎŁof length either |đ›Œ| or |đ›Œ| + 1, and every coordinate of đ›œ is a functionof just three coordinates in đ›Œ. That is, for every 𝑗 ∈ 0, 
 , |đ›œ| − 1,đ›œđ‘— = MAP𝑃 (đ›Œđ‘—âˆ’1, đ›Œđ‘—, đ›Œđ‘—+1) where MAP𝑃 ∶ ÎŁ3 → ÎŁ is some functiondepending on 𝑃 .

‱ There are simple conditions to check whether a string đ›Œ is a validstarting configuration corresponding to an input đ‘„, as well as tocheck whether a string đ›Œ is a halting configuration. In particularthese conditions can be phrased as quantified mixed statements.

‱ A program 𝑀 halts on input đ‘„ if and only if there exists a sequenceof configurations đ» = (đ›Œ0, đ›Œ1, 
 , đ›Œđ‘‡ −1) such that (i) đ›Œ0 is a valid

Page 387: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

is every theorem provable? 387

starting configuration of 𝑀 with input đ‘„, (ii) đ›Œđ‘‡ −1 is a valid haltingconfiguration of 𝑃 , and (iii) đ›Œđ‘–+1 = NEXT𝑃 (đ›Œđ‘–) for every 𝑖 ∈0, 
 , 𝑇 − 2.We can encode such a sequence đ» of configuration as a binary

string. For concreteness, we let ℓ = ⌈log(|ÎŁ| + 1)⌉ and encode eachsymbol 𝜎 in ÎŁ âˆȘ "; " by a string in 0, 1ℓ. We use “;” as a “separator”symbol, and so encode đ» = (đ›Œ0, đ›Œ1, 
 , đ›Œđ‘‡ −1) as the concatenationof the encodings of each configuration, using “;” to separate the en-coding of đ›Œđ‘– and đ›Œđ‘–+1 for every 𝑖 ∈ [𝑇 ]. In particular for every TuringMachine 𝑀 , 𝑀 halts on the input 0 if and only if the following state-ment 𝜑𝑀 is true

âˆƒđ»âˆˆ0,1âˆ—đ» encodes halting configuration sequence starting with input 0 .(11.6)

If we can encode the statement 𝜑𝑀 as a mixed-integer statementthen, since 𝜑𝑀 is true if and only if HALTONZERO(𝑀) = 1, thiswould reduce the task of computing HALTONZERO to computingMIS, and hence imply (using Theorem 9.9 ) that MIS is uncomputable,completing the proof. Indeed, 𝜑𝑀 can be encoded as a mixed-integerstatement for the following reasons:

1. Let đ›Œ, đ›œ ∈ 0, 1∗ be two strings that encode configurations of 𝑀 .We can define a quantified mixed predicate NEXT(đ›Œ, đ›œ) that is trueif and only if đ›œ = NEXT𝑀(đ›œ) (i.e., đ›œ encodes the configurationobtained by proceeding from đ›Œ in one computational step). IndeedNEXT(đ›Œ, đ›œ) is true if for every 𝑖 ∈ 0, 
 , |đ›œ| which is a multipleof ℓ, đ›œđ‘–,
,𝑖+ℓ−1 = MAP𝑀(đ›Œđ‘–âˆ’â„“,⋯,𝑖+2ℓ−1) where MAP𝑀 ∶ 0, 13ℓ →0, 1ℓ is the finite function above (identifying elements of ÎŁ withtheir encoding in 0, 1ℓ). Since MAP𝑀 is a finite function, we canexpress it using the logical operations AND,OR, NOT (for exampleby computing MAP𝑀 with NAND’s).

2. Using the above we can now write the condition that for everysubstring of đ» that has the form đ›ŒENC(; )đ›œ with đ›Œ, đ›œ ∈ 0, 1ℓand ENC(; ) being the encoding of the separator “;”, it holds thatNEXT(đ›Œ, đ›œ) is true.

3. Finally, if đ›Œ0 is a binary string encoding the initial configuration of𝑀 on input 0, checking that the first |đ›Œ0| bits of đ» equal đ›Œ0 can beexpressed using AND,OR, and NOT’s. Similarly checking that thelast configuration encoded by đ» corresponds to a state in which 𝑀will halt can also be expressed as a quantified statement.

Together the above yields a computable procedure that maps everyTuring Machine 𝑀 into a quantified mixed statement 𝜑𝑀 such that

Page 388: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

388 introduction to theoretical computer science

HALTONZERO(𝑀) = 1 if and only if QMS(𝜑𝑀) = 1. This reducescomputing HALTONZERO to computing QMS, and hence the uncom-putability of HALTONZERO implies the uncomputability of QMS.

RRemark 11.14 — Alternative proofs. There are sev-eral other ways to show that QMS is uncomputable.For example, we can express the condition that a 1-dimensional cellular automaton eventually writes a“1” to a given cell from a given initial configurationas a quantified mixed statement over a string encod-ing the history of all configurations. We can then usethe fact that cellular automatons can simulate Tur-ing machines (Theorem 8.7) to reduce the haltingproblem to QMS. We can also use other well knownuncomputable problems such as tiling or the post cor-respondence problem. Exercise 11.5 and Exercise 11.6explore two alternative proofs of Theorem 11.13.

11.5.2 Step 2: Reducing mixed statements to integer statementsWe now show how to prove Theorem 11.9 using Theorem 11.13. Theidea is again a proof by reduction. We will show a transformation ofevery quantifier mixed statement 𝜑 into a quantified integer statement𝜉 that does not use string-valued variables such that 𝜑 is true if andonly if 𝜉 is true.

To remove string-valued variables from a statement, we encodeevery string by a pair integer. We will show that we can encode astring đ‘„ ∈ 0, 1∗ by a pair of numbers (𝑋, 𝑛) ∈ ℕ s.t.

‱ 𝑛 = |đ‘„|‱ There is a quantified integer statement COORD(𝑋, 𝑖) that for every𝑖 < 𝑛, will be true if đ‘„đ‘– = 1 and will be false otherwise.

This will mean that we can replace a “for all” quantifier over stringssuch as âˆ€đ‘„âˆˆ0,1∗ with a pair of quantifiers over integers of the form∀𝑋∈ℕ∀𝑛∈ℕ (and similarly replace an existential quantifier of the formâˆƒđ‘„âˆˆ0,1∗ with a pair of quantifiers ∃𝑋∈ℕ∃𝑛∈ℕ) . We can then replace allcalls to |đ‘„| by 𝑛 and all calls to đ‘„đ‘– by COORD(𝑋, 𝑖). This means thatif we are able to define COORD via a quantified integer statement,then we obtain a proof of Theorem 11.9, since we can use it to mapevery mixed quantified statement 𝜑 to an equivalent quantified inte-ger statement 𝜉 such that 𝜉 is true if and only if 𝜑 is true, and henceQMS(𝜑) = QIS(𝜉). Such a procedure implies that the task of comput-ing QMS reduces to the task of computing QIS, which means that theuncomputability of QMS implies the uncomputability of QIS.

Page 389: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

is every theorem provable? 389

The above shows that proof of Theorem 11.9 all boils down to find-ing the right encoding of strings as integers, and the right way toimplement COORD as a quantified integer statement. To achieve thiswe use the following technical result :Lemma 11.15 — Constructible prime sequence. There is a sequence of primenumbers 𝑝0 < 𝑝1 < 𝑝2 < ⋯ such that there is a quantified integerstatement PSEQ(𝑝, 𝑖) that is true if and only if 𝑝 = 𝑝𝑖.

Using Lemma 11.15 we can encode a đ‘„ ∈ 0, 1∗ by the numbers(𝑋, 𝑛) where 𝑋 = âˆđ‘„đ‘–=1 𝑝𝑖 and 𝑛 = |đ‘„|. We can then define thestatement COORD(𝑋, 𝑖) as

COORD(𝑋, 𝑖) = ∃𝑝∈ℕPSEQ(𝑝, 𝑖) ∧ DIVIDES(𝑝, 𝑋) (11.7)

where DIVIDES(𝑎, 𝑏), as before, is defined as ∃𝑐∈ℕ𝑎 × 𝑐 = 𝑏. Note thatindeed if 𝑋, 𝑛 encodes the string đ‘„ ∈ 0, 1∗, then for every 𝑖 < 𝑛,COORD(𝑋, 𝑖) = đ‘„đ‘–, since 𝑝𝑖 divides 𝑋 if and only if đ‘„đ‘– = 1.

Thus all that is left to conclude the proof of Theorem 11.9 is toprove Lemma 11.15, which we now proceed to do.

Proof. The sequence of prime numbers we consider is the following:We fix đ¶ to be a sufficiently large constant (đ¶ = 2234 will do) anddefine 𝑝𝑖 to be the smallest prime number that is in the interval [(𝑖 +đ¶)3 + 1, (𝑖 + đ¶ + 1)3 − 1]. It is known that there exists such a primenumber for every 𝑖 ∈ ℕ. Given this, the definition of PSEQ(𝑝, 𝑖) issimple:(𝑝 > (𝑖+đ¶)×(𝑖+đ¶)×(𝑖+đ¶))∧(𝑝 < (𝑖+đ¶+1)×(𝑖+đ¶+1)×(𝑖+đ¶+1))∧(∀𝑝â€ČÂŹPRIME(𝑝â€Č) √ (𝑝â€Č ≀ 𝑖) √ (𝑝â€Č ≄ 𝑝)) ,

(11.8)We leave it to the reader to verify that PSEQ(𝑝, 𝑖) is true iff 𝑝 = 𝑝𝑖.

To sum up we have shown that for every quantified mixed state-ment 𝜑, we can compute a quantified integer statement 𝜉 such thatQMS(𝜑) = 1 if and only if QIS(𝜉) = 1. Hence the uncomputabilityof QMS (Theorem 11.13) implies the uncomputability of QIS, com-pleting the proof of Theorem 11.9, and so also the proof of Gödel’sIncompleteness Theorem for quantified integer statements (Theo-rem 11.8).

Chapter Recap

‱ Uncomputable functions include also functionsthat seem to have nothing to do with NAND-TMprograms or other computational models suchas determining the satisfiability of Diophantineequations.

Page 390: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

390 introduction to theoretical computer science

4 Hint: think of đ‘„ as saying “Turing Machine 𝑀 haltson input 𝑱” and đ‘€ being a proof that is the number ofsteps that it will take for this to happen. Can you findan always-halting 𝑉 that will verify such statements?

Figure 11.3: In the puzzle problem, the input can bethought of as a finite collection ÎŁ of types of puz-zle pieces and the goal is to find out whether or notfind a way to arrange pieces from these types in arectangle. Formally, we model the input as a pair offunctions 𝑚𝑎𝑡𝑐ℎ↔, 𝑚𝑎𝑡𝑐ℎ ∶ ÎŁ2 → 0, 1 thatsuch that 𝑚𝑎𝑡𝑐ℎ↔(𝑙𝑒𝑓𝑡, 𝑟𝑖𝑔ℎ𝑡) = 1 (respectively𝑚𝑎𝑡𝑐ℎ(𝑱𝑝, đ‘‘đ‘œđ‘€đ‘›) = 1 ) if the pair of pieces arecompatible when placed in their respective posi-tions. We assume ÎŁ contains a special symbol ∅corresponding to having no piece, and an arrange-ment of puzzle pieces by an (𝑚 − 2) × (𝑛 − 2)rectangle is modeled by a string đ‘„ ∈ Σ𝑚⋅𝑛 whose“outer coordinates’ ’ are ∅ and such that for every𝑖 ∈ [𝑛 − 1], 𝑗 ∈ [𝑚 − 1], 𝑚𝑎𝑡𝑐ℎ(đ‘„đ‘–,𝑗, đ‘„đ‘–+1,𝑗) = 1 and𝑚𝑎𝑡𝑐ℎ↔(đ‘„đ‘–,𝑗, đ‘„đ‘–,𝑗+1) = 1.

‱ This also implies that for any sound proof system(and in particular every finite axiomatic system) 𝑆,there are interesting statements 𝑋 (namely of theform “đč(đ‘„) = 0” for an uncomputable functionđč) such that 𝑆 is not able to prove either 𝑋 or itsnegation.

11.6 EXERCISES

Exercise 11.1 — Gödel’s Theorem from uncomputability of đ‘„đŒđ‘†. Prove Theo-rem 11.8 using Theorem 11.9.

Exercise 11.2 — Proof systems and uncomputability. Let FINDPROOF ∶0, 1∗ → 0, 1 be the following function. On input a Turing machine𝑉 (which we think of as the verifying algorithm for a proof system)and a string đ‘„ ∈ 0, 1∗, FINDPROOF(𝑉 , đ‘„) = 1 if and only if thereexists đ‘€ ∈ 0, 1∗ such that 𝑉 (đ‘„, đ‘€) = 1.1. Prove that FINDPROOF is uncomputable.

2. Prove that there exists a Turing machine 𝑉 such that 𝑉 haltson every input đ‘„, 𝑣 but the function FINDPROOF𝑉 defined asFINDPROOF𝑉 (đ‘„) = FINDPROOF(𝑉 , đ‘„) is uncomputable. Seefootnote for hint.4

Exercise 11.3 — Expression for floor. Let FSQRT(𝑛, 𝑚) = ∀𝑗∈ℕ((𝑗 × 𝑗) >𝑚) √ (𝑗 ≀ 𝑛). Prove that FSQRT(𝑛, 𝑚) is true if and only if 𝑛 = ⌊√𝑚⌋.

Exercise 11.4 — axiomatic proof systems. For every representation of logicalstatements as strings, we can define an axiomatic proof system toconsist of a finite set of strings 𝐮 and a finite set of rules đŒ0, 
 , đŒđ‘šâˆ’1with đŒđ‘— ∶ (0, 1∗)𝑘𝑗 → 0, 1∗ such that a proof (𝑠1, 
 , 𝑠𝑛) that 𝑠𝑛is true is valid if for every 𝑖, either 𝑠𝑖 ∈ 𝐮 or is some 𝑗 ∈ [𝑚] andare 𝑖1, 
 , 𝑖𝑘𝑗 < 𝑖 such that 𝑠𝑖 = đŒđ‘—(𝑠𝑖1 , 
 , 𝑖𝑘𝑗). A system is sound ifwhenever there is no false 𝑠 such that there is a proof that 𝑠 is true.Prove that for every uncomputable function đč ∶ 0, 1∗ → 0, 1and every sound axiomatic proof system 𝑆 (that is characterized by afinite number of axioms and inference rules), there is some input đ‘„ forwhich the proof system 𝑆 is not able to prove neither that đč(đ‘„) = 0nor that đč(đ‘„) ≠ 0.

Exercise 11.5 — Post Corrrespondence Problem. In the Post CorrespondenceProblem the input is a set 𝑆 = (đ›Œ0, đ›œ0), 
 , (đ›œđ‘âˆ’1, đ›œđ‘âˆ’1) where each

Page 391: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

is every theorem provable? 391

đ›Œđ‘– and đ›œđ‘— is a string in 0, 1∗. We say that PCP(𝑆) = 1 if and only ifthere exists a list (đ›Œ0, đ›œ0), 
 , (đ›Œđ‘šâˆ’1, đ›œđ‘šâˆ’1) of pairs in 𝑆 such thatđ›Œ0đ›Œ1 ⋯ đ›Œđ‘šâˆ’1 = đ›œ0đ›œ1 ⋯ đ›œđ‘šâˆ’1 . (11.9)

(We can think of each pair (đ›Œ, đ›œ) ∈ 𝑆 as a “domino tile” and the ques-tion is whether we can stack a list of such tiles so that the top and thebottom yield the same string.) It can be shown that the PCP is uncom-putable by a fairly straightforward though somewhat tedious proof(see for example the Wikipedia page for the Post CorrespondenceProblem or Section 5.2 in [Sip97]).

Use this fact to provide a direct proof that QMS is uncomputable byshowing that there exists a computable map 𝑅 ∶ 0, 1∗ → 0, 1∗ suchthat PCP(𝑆) = QMS(𝑅(𝑆)) for every string 𝑆 encoding an instance ofthe post correspondence problem.

Exercise 11.6 — Uncomputability of puzzle. Let PUZZLE ∶ 0, 1∗ → 0, 1 bethe problem of determining, given a finite collection of types of “puz-zle pieces”, whether it is possible to put them together in a rectangle,see Fig. 11.3. Formally, we think of such a collection as a finite set ÎŁ(see Fig. 11.3). We model the criteria as to which pieces “fit together”by a pair of finite function 𝑚𝑎𝑡𝑐ℎ, 𝑚𝑎𝑡𝑐ℎ↔ ∶ ÎŁ2 → 0, 1 such that apiece 𝑎 fits above a piece 𝑏 if and only if 𝑚𝑎𝑡𝑐ℎ(𝑎, 𝑏) = 1 and a piece𝑐 fits to the left of a piece 𝑑 if and only if 𝑚𝑎𝑡𝑐ℎ↔(𝑐, 𝑑) = 1. To modelthe “straight edge” pieces that can be placed next to a “blank spot”we assume that ÎŁ contains the symbol ∅ and the matching functionsare defined accordingly. A square tiling of ÎŁ is an 𝑚 × 𝑛 long stringđ‘„ ∈ Σ𝑚𝑛, such that for every 𝑖 ∈ 1, 
 , 𝑚 − 2 and 𝑗 ∈ 1, 
 , 𝑛 − 2,𝑚𝑎𝑡𝑐ℎ(đ‘„đ‘–,𝑗, đ‘„đ‘–âˆ’1,𝑗, đ‘„đ‘–+1,𝑗, đ‘„đ‘–,𝑗−1, đ‘„đ‘–,𝑗+1) = 1 (i.e., every “internal pieve”fits in with the pieces adjacent to it). We also require all of the “outerpieces” (i.e., đ‘„đ‘–,𝑗 where 𝑖 ∈ 0, 𝑚 − 1 of 𝑗 ∈ 0, 𝑛 − 1) are “blank”or equal to ∅. The function PUZZLE takes as input a string describingthe set ÎŁ and the function 𝑚𝑎𝑡𝑐ℎ and outputs 1 if and only if there issome square tiling of ÎŁ: some not all blank string đ‘„ ∈ Σ𝑚𝑛 satisfyingthe above condition.

1. Prove that PUZZLE is uncomputable.

2. Give a reduction from PUZZLE to QMS.

Exercise 11.7 — MRDP exercise. The MRDP theorem states that theproblem of determining, given a 𝑘-variable polynomial 𝑝 with integercoefficients, whether there exists integers đ‘„0, 
 , đ‘„đ‘˜âˆ’1 such that𝑝(đ‘„0, 
 , đ‘„đ‘˜âˆ’1) = 0 is uncomputable. Consider the following quadratic

Page 392: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

392 introduction to theoretical computer science

5 You can replace the equation 𝑩 = đ‘„4 with the pairof equations 𝑩 = 𝑧2 and 𝑧 = đ‘„2. Also, you canreplace the equation đ‘€ = đ‘„6 with the three equationsđ‘€ = 𝑩𝑱, 𝑩 = đ‘„4 and 𝑱 = đ‘„2.

6 You will not need to use very specific properties ofthe TOWER function in this exercise. For example,NBB(𝑛) also grows faster than the Ackerman func-tion. You might find Aaronson’s blog post on thesame topic to be quite interesting, and relevant to thisbook at large. If you like it then you might also enjoythis piece by Terence Tao.

integer equation problem: the input is a list of polynomials 𝑝0, 
 , 𝑝𝑚−1over 𝑘 variables with integer coefficients, where each of the polynomi-als is of degree at most two (i.e., it is a quadratic function). The goalis to determine whether there exist integers đ‘„0, 
 , đ‘„đ‘˜âˆ’1 that solve theequations 𝑝0(đ‘„) = ⋯ = 𝑝𝑚−1(đ‘„) = 0.

Use the MRDP Theorem to prove that this problem is uncom-putable. That is, show that the function QUADINTEQ ∶ 0, 1∗ →0, 1 is uncomputable, where this function gets as input a string de-scribing the polynomials 𝑝0, 
 , 𝑝𝑚−1 (each with integer coefficientsand degree at most two), and outputs 1 if and only if there existsđ‘„0, 
 , đ‘„đ‘˜âˆ’1 ∈ â„€ such that for every 𝑖 ∈ [𝑚], 𝑝𝑖(đ‘„0, 
 , đ‘„đ‘˜âˆ’1) = 0. Seefootnote for hint5

Exercise 11.8 — The Busy Beaver problem. In this question we define theNAND-TM variant of the busy beaver function.

1. We define the function 𝑇 ∶ 0, 1∗ → ℕ as follows: for everystring 𝑃 ∈ 0, 1∗, if 𝑃 represents a NAND-TM program such thatwhen 𝑃 is executed on the input 0 (i.e., the string of length 1 that issimply 0), a total of 𝑀 lines are executed before the program halts,then 𝑇 (𝑃) = 𝑀 . Otherwise (if 𝑃 does not represent a NAND-TMprogram, or it is a program that does not halt on 0), 𝑇 (𝑃) = 0.Prove that 𝑇 is uncomputable.

2. Let TOWER(𝑛) denote the number 222.

.

.

2⏟𝑛 times(that is, a “tower of pow-

ers of two” of height 𝑛). To get a sense of how fast this functiongrows, TOWER(1) = 2, TOWER(2) = 22 = 4, TOWER(3) = 222 =16, TOWER(4) = 216 = 65536 and TOWER(5) = 265536 whichis about 1020000. TOWER(6) is already a number that is too big towrite even in scientific notation. Define NBB ∶ ℕ → ℕ (for “NAND-TM Busy Beaver”) to be the function NBB(𝑛) = max𝑃∈0,1𝑛 𝑇 (𝑃)where 𝑇 ∶ ℕ → ℕ is the function defined in Item 1. Prove thatNBB grows faster than TOWER, in the sense that TOWER(𝑛) =𝑜(NBB(𝑛)) (i.e., for every 𝜖 > 0, there exists 𝑛0 such that for every𝑛 > 𝑛0, TOWER(𝑛) < 𝜖 ⋅ NBB(𝑛).).6

11.7 BIBLIOGRAPHICAL NOTES

As mentioned before, Gödel, Escher, Bach [Hof99] is a highly recom-mended book covering Gödel’s Theorem. A classic popular sciencebook about Fermat’s Last Theorem is [Sin97].

Cantor’s are used for both Turing and Gödel’s theorems. In a twistof fate, using techniques originating from the works of Gödel and Tur-

Page 393: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

is every theorem provable? 393

ing, Paul Cohen showed in 1963 that Cantor’s Continuum Hypothesisis independent of the axioms of set theory, which means that neitherit nor its negation is provable from these axioms and hence in somesense can be considered as “neither true nor false” (see [Coh08]). TheContinuum Hypothesis is the conjecture that for every subset 𝑆 of ℝ,either there is a one-to-one and onto map between 𝑆 and ℕ or thereis a one-to-one and onto map between 𝑆 and ℝ. It was conjecturedby Cantor and listed by Hilbert in 1900 as one of the most importantproblems in mathematics. See also the non-conventional survey ofShelah [She03]. See here for recent progress on a related question.

Thanks to Alex Lombardi for pointing out an embarrassing mistakein the description of Fermat’s Last Theorem. (I said that it was openfor exponent 11 before Wiles’ work.)

Page 394: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 395: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

IIIEFFICIENT ALGORITHMS

Page 396: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 397: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

12Efficient computation: An informal introduction

“The problem of distinguishing prime numbers from composite and of resolvingthe latter into their prime factors is 
 one of the most important and usefulin arithmetic 
 Nevertheless we must confess that all methods 
 are eitherrestricted to very special cases or are so laborious 
 they try the patience ofeven the practiced calculator 
 and do not apply at all to larger numbers.”,Carl Friedrich Gauss, 1798

“For practical purposes, the difference between algebraic and exponential orderis often more crucial than the difference between finite and non-finite.”, JackEdmunds, “Paths, Trees, and Flowers”, 1963

“What is the most efficient way to sort a million 32-bit integers?”, EricSchmidt to Barack Obama, 2008“I think the bubble sort would be the wrong way to go.”, Barack Obama.

So far we have been concerned with which functions are computableand which ones are not. In this chapter we look at the finer questionof the time that it takes to compute functions, as a function of their inputlength. Time complexity is extremely important to both the theory andpractice of computing, but in introductory courses, coding interviews,and software development, terms such as “𝑂(𝑛) running time” are of-ten used in an informal way. People don’t have a precise definition ofwhat a linear-time algorithm is, but rather assume that “they’ll knowit when they see it”. In this book we will define running time pre-cisely, using the mathematical models of computation we developedin the previous chapters. This will allow us to ask (and sometimesanswer) questions such as:

‱ “Is there a function that can be computed in 𝑂(𝑛2) time but not in𝑂(𝑛) time?”

‱ “Are there natural problems for which the best algorithm (and notjust the best known) requires 2Ω(𝑛) time?”

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Describe at a high level some interesting

computational problems.‱ The difference between polynomial and

exponential time.‱ Examples of techniques for obtaining efficient

algorithms‱ Examples of how seemingly small differences

in problems can potentially make hugedifferences in their computational complexity.

Page 398: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

398 introduction to theoretical computer science

Big Idea 16 The running time of an algorithm is not a number, it isa function of the length of the input.

This chapter: A non-mathy overviewIn this chapter, we informally survey examples of compu-tational problems. For some of these problems we knowefficient (i.e., 𝑂(𝑛𝑐)-time for a small constant 𝑐) algorithms,and for others the best known algorithms are exponential.We present these examples to get a feel as to the kinds ofproblems that lie on each side of this divide and also see howsometimes seemingly minor changes in problem formula-tion can make the (known) complexity of a problem “jump”from polynomial to exponential. We do not formally definethe notion of running time in this chapter, but use the same“I know it when I see it” notion of an 𝑂(𝑛) or 𝑂(𝑛2) timealgorithms as the one you’ve seen in introduction to com-puter science courses. We will see the precise definition ofrunning time (using Turing machines and RAM machines /NAND-RAM) in Chapter 13.

While the difference between 𝑂(𝑛) and 𝑂(𝑛2) time can be crucial inpractice, in this book we focus on the even bigger difference betweenpolynomial and exponential running time. As we will see, the differencebetween polynomial versus exponential time is typically insensitive tothe choice of the particular computational model, a polynomial-timealgorithm is still polynomial whether you use Turing machines, RAMmachines, or parallel cluster as your model of computation, and sim-ilarly an exponential-time algorithm will remain exponential in all ofthese platforms. One of the interesting phenomena of computing isthat there is often a kind of a “threshold phenomenon” or “zero-onelaw” for running time. Many natural problems can either be solvedin polynomial running time with a not-too-large exponent (e.g., some-thing like 𝑂(𝑛2) or 𝑂(𝑛3)), or require exponential (e.g., at least 2Ω(𝑛)or 2Ω(√𝑛)) time to solve. The reasons for this phenomenon are still notfully understood, but some light on it is shed by the concept of NPcompleteness, which we will see in Chapter 15.

This chapter is merely a tiny sample of the landscape of computa-tional problems and efficient algorithms. If you want to explore thefield of algorithms and data structures more deeply (which I verymuch hope you do!), the bibliographical notes contain references tosome excellent texts, some of which are available freely on the web.

Page 399: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

efficient computation: an informal introduction 399

RRemark 12.1 — Relations between parts of this book.Part I of this book contained a quantitative study ofcomputation of finite functions. We asked what arethe resources (in terms of gates of Boolean circuits orlines in straight-line programs) required to computevarious finite functions.Part II of the book contained a qualitative study ofcomputation of infinite functions (i.e., functions ofunbounded input length). In that part we asked thequalitative question of whether or not a function is com-putable at all, regardless of the number of operations.Part III of the book, beginning with this chapter,merges the two approaches and contains a quantitativestudy of computation of infinite functions. In this partwe ask how do resources for computing a functionscale with the length of the input. In Chapter 13 wedefine the notion of running time, and the class P offunctions that can be computed using a number ofsteps that scales polynomially with the input length.In Section 13.6 we will relate this class to the modelsof Boolean circuits and straightline programs that westudied in Part I.

12.1 PROBLEMS ON GRAPHS

In this chapter we discuss several examples of important computa-tional problems. Many of the problems will involve graphs. We havealready encountered graphs before (see Section 1.4.4) but now quicklyrecall the basic notation. A graph đș consists of a set of vertices 𝑉 andedges 𝐾 where each edge is a pair of vertices. We typically denote by𝑛 the number of vertices (and in fact often consider graphs where theset of vertices 𝑉 equals the set [𝑛] of the integers between 0 and 𝑛 − 1).In a directed graph, an edge is an ordered pair (𝑱, 𝑣), which we some-times denote as 𝑱 𝑣. In an undirected graph, an edge is an unorderedpair (or simply a set) 𝑱, 𝑣 which we sometimes denote as 𝑱 𝑣 or𝑱 ∌ 𝑣. An equivalent viewpoint is that an undirected graph corre-sponds to a directed graph satisfying the property that whenever theedge 𝑱 𝑣 is present then so is the edge 𝑣 𝑱. In this chapter we restrictour attention to graphs that are undirected and simple (i.e., containingno parallel edges or self-loops). Graphs can be represented either inthe adjacency list or adjacency matrix representation. We can transformbetween these two representations using 𝑂(𝑛2) operations, and hencefor our purposes we will mostly consider them as equivalent.

Graphs are so ubiquitous in computer science and other sciencesbecause they can be used to model a great many of the data that weencounter. These are not just the “obvious” data such as the road

Page 400: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

400 introduction to theoretical computer science

Figure 12.1: Some examples of graphs found on theInternet.

1 A queue is a data structure for storing a list of el-ements in “First In First Out (FIFO)” order. Each“pop” operation removes an element from the queuein the order that they were “pushed” into it; see theWikipedia page.

network (which can be thought of as a graph of whose vertices arelocations with edges corresponding to road segments), or the web(which can be thought of as a graph whose vertices are web pageswith edges corresponding to links), or social networks (which canbe thought of as a graph whose vertices are people and the edgescorrespond to friend relation). Graphs can also denote correlations indata (e.g., graph of observations of features with edges correspondingto features that tend to appear together), causal relations (e.g., generegulatory networks, where a gene is connected to gene products itderives), or the state space of a system (e.g., graph of configurationsof a physical system, with edges corresponding to states that can bereached from one another in one step).

12.1.1 Finding the shortest path in a graphThe shortest path problem is the task of finding, given a graph đș =(𝑉 , 𝐾) and two vertices 𝑠, 𝑡 ∈ 𝑉 , the length of the shortest pathbetween 𝑠 and 𝑡 (if such a path exists). That is, we want to find thesmallest number 𝑘 such that there are vertices 𝑣0, 𝑣1, 
 , 𝑣𝑘 with 𝑣0 = 𝑠,𝑣𝑘 = 𝑡 and for every 𝑖 ∈ 0, 
 , 𝑘 − 1 an edge between 𝑣𝑖 and 𝑣𝑖+1. For-mally, we define MINPATH ∶ 0, 1∗ → 0, 1∗ to be the function thaton input a triple (đș, 𝑠, 𝑡) (represented as a string) outputs the number𝑘 which is the length of the shortest path in đș between 𝑠 and 𝑡 or astring representing no path if no such path exists. (In practice peopleoften want to also find the actual path and not just its length; it turnsout that the algorithms to compute the length of the path often yieldthe actual path itself as a byproduct, and so everything we say aboutthe task of computing the length also applies to the task of finding thepath.)

If each vertex has at least two neighbors then there can be an expo-nential number of paths from 𝑠 to 𝑡, but fortunately we do not have toenumerate them all to find the shortest path. We can find the short-est path using a breadth first search (BFS), enumerating 𝑠’s neigh-bors, and then neighbors’ neighbors, etc.. in order. If we maintainthe neighbors in a list we can perform a BFS in 𝑂(𝑛2) time, while us-ing a queue we can do this in 𝑂(𝑚) time.1 Dijkstra’s algorithm is awell-known generalization of BFS to weighted graphs. More formally,the algorithm for computing the function MINPATH is described inAlgorithm 12.2.

Page 401: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

efficient computation: an informal introduction 401

Algorithm 12.2 — Shortest path via BFS.

Input: Graph đș = (𝑉 , 𝐾) and vertices 𝑠, 𝑡 ∈ 𝑉 . Assume𝑉 = [𝑛].Output: Length 𝑘 of shortest path from 𝑠 to 𝑡 or ∞ if no

such path exists.1: Let đ· be length-𝑛 array.2: Set đ·[𝑠] = 0 and đ·[𝑖] = ∞ for all 𝑖 ∈ [𝑛] ⧔ 𝑠.3: Initialize queue 𝑄 to contain 𝑠.4: while 𝑄 non empty do5: Pop 𝑣 from 𝑄6: if 𝑣 = 𝑡 then7: return đ·[𝑣]8: end if9: for 𝑱 neighbor of 𝑣 with đ·[𝑱] = ∞ do

10: Set đ·[𝑱] ← đ·[𝑣] + 111: Add 𝑱 to 𝑄.12: end for13: end while14: return ∞

Since we only add to the queue vertices đ‘€ with đ·[đ‘€] = ∞ (andthen immediately set đ·[đ‘€] to an actual number), we never push tothe queue a vertex more than once, and hence the algorithm makes atmost 𝑛 “push” and “pop” operations. For each vertex 𝑣, the numberof times we run the inner loop is equal to the degree of 𝑣 and hencethe total running time is proportional to the sum of all degrees whichequals twice the number 𝑚 of edges. Algorithm 12.2 returns the cor-rect answer since the vertices are added to the queue in the order oftheir distance from 𝑠, and hence we will reach 𝑡 after we have exploredall the vertices that are closer to 𝑠 than 𝑡.

RRemark 12.3 — On data structures. If you’ve ever takenan algorithms course, you have probably encounteredmany data structures such as lists, arrays, queues,stacks, heaps, search trees, hash tables and manymore. Data structures are extremely important in com-puter science, and each one of those offers differenttradeoffs between overhead in storage, operationssupported, cost in time for each operation, and more.For example, if we store 𝑛 items in a list, we will needa linear (i.e., 𝑂(𝑛) time) scan to retrieve an element,while we achieve the same operation in 𝑂(1) time ifwe used a hash table. However, when we only careabout polynomial-time algorithms, such factors of𝑂(𝑛) in the running time will not make much differ-

Page 402: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

402 introduction to theoretical computer science

Figure 12.2: A knight’s tour can be thought of as amaximally long path on the graph corresponding toa chessboard where we put an edge between any twosquares that can be reached by one step via a legalknight move.

ence. Similarly, if we don’t care about the differencebetween 𝑂(𝑛) and 𝑂(𝑛2), then it doesn’t matter if werepresent graphs as adjacency lists or adjacency matri-ces. Hence we will often describe our algorithms at avery high level, without specifying the particular datastructures that are used to implement them. How-ever, it will always be clear that there exists some datastructure that is sufficient for our purposes.

12.1.2 Finding the longest path in a graphThe longest path problem is the task of finding the length of the longestsimple (i.e., non intersecting) path between a given pair of vertices𝑠 and 𝑡 in a given graph đș. If the graph is a road network, then thelongest path might seem less motivated than the shortest path (unlessyou are the kind of person that always prefers the “scenic route”).But graphs can and are used to model a variety of phenomena, and inmany such cases finding the longest path (and some of its variants)can be very useful. In particular, finding the longest path is a gener-alization of the famous Hamiltonian path problem which asks for amaximally long simple path (i.e., path that visits all 𝑛 vertices once)between 𝑠 and 𝑡, as well as the notorious traveling salesman problem(TSP) of finding (in a weighted graph) a path visiting all vertices ofcost at most đ‘€. TSP is a classical optimization problem, with appli-cations ranging from planning and logistics to DNA sequencing andastronomy.

Surprisingly, while we can find the shortest path in 𝑂(𝑚) time,there is no known algorithm for the longest path problem that signif-icantly improves on the trivial “exhaustive search” or “brute force”algorithm that enumerates all the exponentially many possibilitiesfor such paths. Specifically, the best known algorithms for the longestpath problem take 𝑂(𝑐𝑛) time for some constant 𝑐 > 1. (At the mo-ment the best record is 𝑐 ∌ 1.65 or so; even obtaining an 𝑂(2𝑛) timebound is not that simple, see Exercise 12.1.)

12.1.3 Finding the minimum cut in a graphGiven a graph đș = (𝑉 , 𝐾), a cut of đș is a subset 𝑆 ⊆ 𝑉 such that 𝑆is neither empty nor is it all of 𝑉 . The edges cut by 𝑆 are those edgeswhere one of their endpoints is in 𝑆 and the other is in 𝑆 = 𝑉 ⧔ 𝑆. Wedenote this set of edges by 𝐾(𝑆, 𝑆). If 𝑠, 𝑡 ∈ 𝑉 are a pair of verticesthen an 𝑠, 𝑡 cut is a cut such that 𝑠 ∈ 𝑆 and 𝑡 ∈ 𝑆 (see Fig. 12.3).The minimum 𝑠, 𝑡 cut problem is the task of finding, given 𝑠 and 𝑡, theminimum number 𝑘 such that there is an 𝑠, 𝑡 cut cutting 𝑘 edges (theproblem is also sometimes phrased as finding the set that achievesthis minimum; it turns out that algorithms to compute the numberoften yield the set as well). Formally, we define MINCUT ∶ 0, 1∗ →

Page 403: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

efficient computation: an informal introduction 403

Figure 12.3: A cut in a graph đș = (𝑉 , 𝐾) is simply asubset 𝑆 of its vertices. The edges that are cut by 𝑆are all those whose one endpoint is in 𝑆 and the otherone is in 𝑆 = 𝑉 ⧔ 𝑆. The cut edges are colored red inthis figure.

0, 1∗ to be the function that on input a string representing a triple(đș = (𝑉 , 𝐾), 𝑠, 𝑡) of a graph and two vertices, outputs the minimumnumber 𝑘 such that there exists a set 𝑆 ⊆ 𝑉 with 𝑠 ∈ 𝑆, 𝑡 ∉ 𝑆 and|𝐾(𝑆, 𝑆)| = 𝑘.

Computing minimum 𝑠, 𝑡 cuts is useful in many applications sinceminimum cuts often correspond to bottlenecks. For example, in a com-munication or railroad network the minimum cut between 𝑠 and 𝑡corresponds to the smallest number of edges that, if dropped, willdisconnect 𝑠 from 𝑡. (This was actually the original motivation for thisproblem; see Section 12.6.) Similar applications arise in schedulingand planning. In the setting of image segmentation, one can define agraph whose vertices are pixels and whose edges correspond to neigh-boring pixels of distinct colors. If we want to separate the foregroundfrom the background then we can pick (or guess) a foreground pixel 𝑠and background pixel 𝑡 and ask for a minimum cut between them.

The naive algorithm for computing MINCUT will check all 2𝑛 pos-sible subsets of an 𝑛-vertex graph, but it turns out we can do muchbetter than that. As we’ve seen in this book time and again, there ismore than one algorithm to compute the same function, and someof those algorithms might be more efficient than others. Luckily theminimum cut problem is one of those cases. In particular, as we willsee in the next section, there are algorithms that compute MINCUT intime which is polynomial in the number of vertices.

12.1.4 Min-Cut Max-Flow and Linear programmingWe can obtain a polynomial-time algorithm for computing MINCUTusing the Max-Flow Min-Cut Theorem. This theorem says that theminimum cut between 𝑠 and 𝑡 equals the maximum amount of flowwe can send from 𝑠 to 𝑡, if every edge has unit capacity. Specifically,imagine that every edge of the graph corresponded to a pipe thatcould carry one unit of fluid per one unit of time (say 1 liter of waterper second). The maximum 𝑠, 𝑡 flow is the maximum units of waterthat we could transfer from 𝑠 to 𝑡 over these pipes. If there is an 𝑠, 𝑡cut of 𝑘 edges, then the maximum flow is at most 𝑘. The reason isthat such a cut 𝑆 acts as a “bottleneck” since at most 𝑘 units can flowfrom 𝑆 to its complement at any given unit of time. This means thatthe maximum 𝑠, 𝑡 flow is always at most the value of the minimum𝑠, 𝑡 cut. The surprising and non-trivial content of the Max-Flow Min-Cut Theorem is that the maximum flow is also at least the value of theminimum cut, and hence computing the cut is the same as computingthe flow.

The Max-Flow Min-Cut Theorem reduces the task of computing aminimum cut to the task of computing a maximum flow. However, thisstill does not show how to compute such a flow. The Ford-Fulkerson

Page 404: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

404 introduction to theoretical computer science

Algorithm is a direct way to compute a flow using incremental im-provements. But computing flows in polynomial time is also a specialcase of a much more general tool known as linear programming.

A flow on a graph đș of 𝑚 edges can be modeled as a vector đ‘„ ∈ ℝ𝑚where for every edge 𝑒, đ‘„đ‘’ corresponds to the amount of water pertime-unit that flows on 𝑒. We think of an edge 𝑒 as an ordered pair(𝑱, 𝑣) (we can choose the order arbitrarily) and let đ‘„đ‘’ be the amountof flow that goes from 𝑱 to 𝑣. (If the flow is in the other direction thenwe make đ‘„đ‘’ negative.) Since every edge has capacity one, we knowthat −1 ≀ đ‘„đ‘’ ≀ 1 for every edge 𝑒. A valid flow has the property thatthe amount of water leaving the source 𝑠 is the same as the amountentering the sink 𝑡, and that for every other vertex 𝑣, the amount ofwater entering and leaving 𝑣 is the same.

Mathematically, we can write these conditions as follows:∑𝑒∋𝑠 đ‘„đ‘’ + ∑𝑒∋𝑡 đ‘„đ‘’ = 0∑𝑒∋𝑣 đ‘„đ‘’ = 0 ∀𝑣∈𝑉 â§”đ‘ ,𝑡−1 ≀ đ‘„đ‘’ ≀ 1 ∀𝑒∈𝐾(12.1)

where for every vertex 𝑣, summing over 𝑒 ∋ 𝑣 means summing over allthe edges that touch 𝑣.

The maximum flow problem can be thought of as the task of max-imizing ∑𝑒∋𝑠 đ‘„đ‘’ over all the vectors đ‘„ ∈ ℝ𝑚 that satisfy the aboveconditions (12.1). Maximizing a linear function ℓ(đ‘„) over the set ofđ‘„ ∈ ℝ𝑚 that satisfy certain linear equalities and inequalities is knownas linear programming. Luckily, there are polynomial-time algorithmsfor solving linear programming, and hence we can solve the maxi-mum flow (and so, equivalently, minimum cut) problem in polyno-mial time. In fact, there are much better algorithms for maximum-flow/minimum-cut, even for weighted directed graphs, with currentlythe record standing at 𝑂(min𝑚10/7, 𝑚√𝑛) time.Solved Exercise 12.1 — Global minimum cut. Given a graph đș = (𝑉 , 𝐾),define the global minimum cut of đș to be the minimum over all 𝑆 ⊆ 𝑉with 𝑆 ≠ ∅ and 𝑆 ≠ 𝑉 of the number of edges cut by 𝑆. Prove thatthere is a polynomial-time algorithm to compute the global minimumcut of a graph.

Solution:

By the above we know that there is a polynomial-time algorithm𝐮 that on input (đș, 𝑠, 𝑡) finds the minimum 𝑠, 𝑡 cut in the graph

Page 405: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

efficient computation: an informal introduction 405

Figure 12.4: In a convex function 𝑓 (left figure), forevery đ‘„ and 𝑩 and 𝑝 ∈ [0, 1] it holds that 𝑓(đ‘đ‘„ + (1 −𝑝)𝑩) ≀ 𝑝⋅𝑓(đ‘„)+(1−𝑝)⋅𝑓(𝑩). In particular this meansthat every local minimum of 𝑓 is also a global minimum.In contrast in a non convex function there can be manylocal minima.

Figure 12.5: In the high dimensional case, if 𝑓 is aconvex function (left figure) the global minimumis the only local minimum, and we can find it bya local-search algorithm which can be thought ofas dropping a marble and letting it “slide down”until it reaches the global minimum. In contrast, anon-convex function (right figure) might have anexponential number of local minima in which anylocal-search algorithm could get stuck.

đș. Using 𝐮, we can obtain an algorithm đ” that on input a graph đșcomputes the global minimum cut as follows:

1. For every distinct pair 𝑠, 𝑡 ∈ 𝑉 , Algorithms đ” sets 𝑘𝑠,𝑡 ←𝐮(đș, 𝑠, 𝑡).2. đ” returns the minimum of 𝑘𝑠,𝑡 over all distinct pairs 𝑠, 𝑡

The running time of đ” will be 𝑂(𝑛2) times the running time of 𝐮and hence polynomial time. Moreover, if the the global minimumcut is 𝑆, then when đ” reaches an iteration with 𝑠 ∈ 𝑆 and 𝑡 ∉ 𝑆 itwill obtain the value of this cut, and hence the value output by đ”will be the value of the global minimum cut.

The above is our first example of a reduction in the context ofpolynomial-time algorithms. Namely, we reduced the task of com-puting the global minimum cut to the task of computing minimum𝑠, 𝑡 cuts.

12.1.5 Finding the maximum cut in a graphThe maximum cut problem is the task of finding, given an input graphđș = (𝑉 , 𝐾), the subset 𝑆 ⊆ 𝑉 that maximizes the number of edgescut by 𝑆. (We can also define an 𝑠, 𝑡-cut variant of the maximum cutlike we did for minimum cut; the two variants have similar complexitybut the global maximum cut is more common in the literature.) Likeits cousin the minimum cut problem, the maximum cut problem isalso very well motivated. For example, maximum cut arises in VLSIdesign, and also has some surprising relation to analyzing the Isingmodel in statistical physics.

Surprisingly, while (as we’ve seen) there is a polynomial-time al-gorithm for the minimum cut problem, there is no known algorithmsolving maximum cut much faster than the trivial “brute force” algo-rithm that tries all 2𝑛 possibilities for the set 𝑆.

12.1.6 A note on convexityThere is an underlying reason for the sometimes radical differencebetween the difficulty of maximizing and minimizing a function overa domain. If đ· ⊆ ℝ𝑛, then a function 𝑓 ∶ đ· → 𝑅 is convex if for everyđ‘„, 𝑩 ∈ đ· and 𝑝 ∈ [0, 1] 𝑓(đ‘đ‘„ + (1 − 𝑝)𝑩) ≀ 𝑝𝑓(đ‘„) + (1 − 𝑝)𝑓(𝑩). Thatis, 𝑓 applied to the 𝑝-weighted midpoint between đ‘„ and 𝑩 is smallerthan the 𝑝-weighted average value of 𝑓 . If đ· itself is convex (whichmeans that if đ‘„, 𝑩 are in đ· then so is the line segment between them),then this means that if đ‘„ is a local minimum of 𝑓 then it is also a globalminimum. The reason is that if 𝑓(𝑩) < 𝑓(đ‘„) then every point 𝑧 =đ‘đ‘„ + (1 − 𝑝)𝑩 on the line segment between đ‘„ and 𝑩 will satisfy 𝑓(𝑧) â‰€đ‘đ‘“(đ‘„) + (1 − 𝑝)𝑓(𝑩) < 𝑓(đ‘„) and hence in particular đ‘„ cannot be a local

Page 406: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

406 introduction to theoretical computer science

minimum. Intuitively, local minima of functions are much easier tofind than global ones: after all, any “local search” algorithm that keepsfinding a nearby point on which the value is lower, will eventuallyarrive at a local minima. One example of such a local search algorithmis gradient descent which takes a sequence of small steps, each one inthe direction that would reduce the value by the most amount basedon the current derivative.

Indeed, under certain technical conditions, we can often efficientlyfind the minimum of convex functions over a convex domain, andthis is the reason why problems such as minimum cut and shortestpath are easy to solve. On the other hand, maximizing a convex func-tion over a convex domain (or equivalently, minimizing a concavefunction) can often be a hard computational task. A linear functionis both convex and concave, which is the reason that both the maxi-mization and minimization problems for linear functions can be doneefficiently.

The minimum cut problem is not a priori a convex minimizationtask, because the set of potential cuts is discrete and not continuous.However, it turns out that we can embed it in a continuous and con-vex set via the (linear) maximum flow problem. The “max flow mincut” theorem ensures that this embedding is “tight” in the sense thatthe minimum “fractional cut” that we obtain through the maximum-flow linear program will be the same as the true minimum cut. Un-fortunately, we don’t know of such a tight embedding in the setting ofthe maximum cut problem.

Convexity arises time and again in the context of efficient computa-tion. For example, one of the basic tasks in machine learning is empir-ical risk minimization. This is the task of finding a classifier for a givenset of training examples. That is, the input is a list of labeled examples(đ‘„0, 𝑩0), 
 , (đ‘„đ‘šâˆ’1, 𝑩𝑚−1), where each đ‘„đ‘– ∈ 0, 1𝑛 and 𝑩𝑖 ∈ 0, 1,and the goal is to find a classifier ℎ ∶ 0, 1𝑛 → 0, 1 (or sometimesℎ ∶ 0, 1𝑛 → ℝ) that minimizes the number of errors. More generally,we want to find ℎ that minimizes𝑚−1∑𝑖=0 𝐿(𝑩𝑖, ℎ(đ‘„đ‘–)) (12.2)

where 𝐿 is some loss function measuring how far is the predicted la-bel ℎ(đ‘„đ‘–) from the true label 𝑩𝑖. When 𝐿 is the square loss function𝐿(𝑩, 𝑩â€Č) = (𝑩 − 𝑩â€Č)2 and ℎ is a linear function, empirical risk mini-mization corresponds to the well-known convex minimization task oflinear regression. In other cases, when the task is non convex, there canbe many global or local minima. That said, even if we don’t find theglobal (or even a local) minima, this continuous embedding can stillhelp us. In particular, when running a local improvement algorithm

Page 407: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

efficient computation: an informal introduction 407

such as Gradient Descent, we might still find a function ℎ that is “use-ful” in the sense of having a small error on future examples from thesame distribution.

12.2 BEYOND GRAPHS

Not all computational problems arise from graphs. We now list someother examples of computational problems that are of great interest.

12.2.1 SATA propositional formula 𝜑 involves 𝑛 variables đ‘„1, 
 , đ‘„đ‘› and the logicaloperators AND (∧), OR (√), and NOT (ÂŹ, also denoted as ⋅). We saythat such a formula is in conjunctive normal form (CNF for short) if it isan AND of ORs of variables or their negations (we call a term of theform đ‘„đ‘– or đ‘„đ‘– a literal). For example, this is a CNF formula(đ‘„7 √ đ‘„22 √ đ‘„15) ∧ (đ‘„37 √ đ‘„22) ∧ (đ‘„55 √ đ‘„7) (12.3)

The satisfiability problem is the task of determining, given a CNFformula 𝜑, whether or not there exists a satisfying assignment for 𝜑. Asatisfying assignment for 𝜑 is a string đ‘„ ∈ 0, 1𝑛 such that 𝜑 evalu-ates to True if we assign its variables the values of đ‘„. The SAT problemmight seem as an abstract question of interest only in logic but in factSAT is of huge interest in industrial optimization, with applicationsincluding manufacturing planning, circuit synthesis, software verifica-tion, air-traffic control, scheduling sports tournaments, and more.

2SAT. We say that a formula is a 𝑘-CNF it is an AND of ORs whereeach OR involves exactly 𝑘 literals. The 𝑘-SAT problem is the restric-tion of the satisfiability problem for the case that the input formula isa 𝑘-CNF. In particular, the 2SAT problem is to find out, given a 2-CNFformula 𝜑, whether there is an assignment đ‘„ ∈ 0, 1𝑛 that satisfies𝜑, in the sense that it makes it evaluate to 1 or “True”. The trivial,brute-force, algorithm for 2SAT will enumerate all the 2𝑛 assignmentsđ‘„ ∈ 0, 1𝑛 but fortunately we can do much better. The key is thatwe can think of every constraint of the form ℓ𝑖 √ ℓ𝑗 (where ℓ𝑖, ℓ𝑗 areliterals, corresponding to variables or their negations) as an implicationℓ𝑖 ⇒ ℓ𝑗, since it corresponds to the constraints that if the literal ℓâ€Č𝑖 = ℓ𝑖is true then it must be the case that ℓ𝑗 is true as well. Hence we canthink of 𝜑 as a directed graph between the 2𝑛 literals, with an edgefrom ℓ𝑖 to ℓ𝑗 corresponding to an implication from the former to thelatter. It can be shown that 𝜑 is unsatisfiable if and only if there is avariable đ‘„đ‘– such that there is a directed path from đ‘„đ‘– to đ‘„đ‘– as well asa directed path from đ‘„đ‘– to đ‘„đ‘– (see Exercise 12.2). This reduces 2SATto the (efficiently solvable) problem of determining connectivity indirected graphs.

Page 408: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

408 introduction to theoretical computer science

3SAT. The 3SAT problem is the task of determining satisfiabilityfor 3CNFs. One might think that changing from two to three wouldnot make that much of a difference for complexity. One would bewrong. Despite much effort, we do not know of a significantly betterthan brute force algorithm for 3SAT (the best known algorithms takeroughly 1.3𝑛 steps).

Interestingly, a similar issue arises time and again in computation,where the difference between two and three often corresponds tothe difference between tractable and intractable. We do not fully un-derstand the reasons for this phenomenon, though the notion of NPcompleteness we will see later does offer a partial explanation. It maybe related to the fact that optimizing a polynomial often amounts toequations on its derivative. The derivative of a quadratic polynomial islinear, while the derivative of a cubic is quadratic, and, as we will see,the difference between solving linear and quadratic equations can bequite profound.

12.2.2 Solving linear equationsOne of the most useful problems that people have been solving timeand again is solving 𝑛 linear equations in 𝑛 variables. That is, solveequations of the form𝑎0,0đ‘„0 + 𝑎0,1đ‘„1 + ⋯ + 𝑎0,𝑛−1đ‘„đ‘›âˆ’1 = 𝑏0𝑎1,0đ‘„0 + 𝑎1,1đ‘„1 + ⋯ + 𝑎1,𝑛−1đ‘„đ‘›âˆ’1 = 𝑏1⋼+ ⋼ + ⋼ + ⋼ =⋼𝑎𝑛−1,0đ‘„0 + 𝑎𝑛−1,1đ‘„1 + ⋯ + 𝑎𝑛−1,𝑛−1đ‘„đ‘›âˆ’1 = 𝑏𝑛−1

(12.4)

where 𝑎𝑖,𝑗𝑖,𝑗∈[𝑛] and 𝑏𝑖𝑖∈[𝑛] are real (or rational) numbers. Morecompactly, we can write this as the equations đŽđ‘„ = 𝑏 where 𝐮 is an𝑛 × 𝑛 matrix, and we think of đ‘„, 𝑏 are column vectors in ℝ𝑛.

The standard Gaussian elimination algorithm can be used to solvesuch equations in polynomial time (i.e., determine if they have a so-lution, and if so, to find it). As we discussed above, if we are willingto allow some loss in precision, we even have algorithms that handlelinear inequalities, also known as linear programming. In contrast, ifwe insist on integer solutions, the task of solving for linear equalitiesor inequalities is known as integer programming, and the best knownalgorithms are exponential time in the worst case.

RRemark 12.4 — Bit complexity of numbers. Whenever wediscuss problems whose inputs correspond to num-bers, the input length corresponds to how many bitsare needed to describe the number (or, as is equiv-alent up to a constant factor, the number of digits

Page 409: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

efficient computation: an informal introduction 409

in base 10, 16 or any other constant). The differencebetween the length of the input and the magnitudeof the number itself can be of course quite profound.For example, most people would agree that there isa huge difference between having a billion (i.e. 109)dollars and having nine dollars. Similarly there is ahuge difference between an algorithm that takes 𝑛steps on an 𝑛-bit number and an algorithm that takes2𝑛 steps.One example is the problem (discussed below) offinding the prime factors of a given integer 𝑁 . Thenatural algorithm is to search for such a factor by try-ing all numbers from 1 to 𝑁 , but that would take 𝑁steps which is exponential in the input length, whichis the number of bits needed to describe 𝑁 . (The run-ning time of this algorithm can be easily improved toroughly

√𝑁 , but this is still exponential (i.e., 2𝑛/2) inthe number 𝑛 of bits to describe 𝑁 .) It is an importantand long open question whether there is such an algo-rithm that runs in time polynomial in the input length(i.e., polynomial in log𝑁).

12.2.3 Solving quadratic equationsSuppose that we want to solve not just linear but also equations in-volving quadratic terms of the form 𝑎𝑖,𝑗,đ‘˜đ‘„đ‘—đ‘„đ‘˜. That is, suppose thatwe are given a set of quadratic polynomials 𝑝1, 
 , 𝑝𝑚 and considerthe equations 𝑝𝑖(đ‘„) = 0. To avoid issues with bit representations,we will always assume that the equations contain the constraintsđ‘„2𝑖 − đ‘„đ‘– = 0𝑖∈[𝑛]. Since only 0 and 1 satisfy the equation 𝑎2 − 𝑎 = 0,this assumption means that we can restrict attention to solutions in0, 1𝑛. Solving quadratic equations in several variables is a classicaland extremely well motivated problem. This is the generalization ofthe classical case of single-variable quadratic equations that gener-ations of high school students grapple with. It also generalizes thequadratic assignment problem, introduced in the 1950’s as a way tooptimize assignment of economic activities. Once again, we do notknow a much better algorithm for this problem than the one that enu-merates over all the 2𝑛 possibilities.

12.3 MORE ADVANCED EXAMPLES

We now list a few more examples of interesting problems that are alittle more advanced but are of significant interest in areas such asphysics, economics, number theory, and cryptography.

12.3.1 Determinant of a matrixThe determinant of a 𝑛 × 𝑛 matrix 𝐮, denoted by det(𝐮), is an ex-tremely important quantity in linear algebra. For example, it is known

Page 410: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

410 introduction to theoretical computer science

that det(𝐮) ≠ 0 if and only if 𝐮 is nonsingular, which means that ithas an inverse 𝐮−1, and hence we can always uniquely solve equationsof the form đŽđ‘„ = 𝑏 where đ‘„ and 𝑏 are 𝑛-dimensional vectors. Moregenerally, the determinant can be thought of as a quantitative measureas to what extent 𝐮 is far from being singular. If the rows of 𝐮 are “al-most” linearly dependent (for example, if the third row is very closeto being a linear combination of the first two rows) then the determi-nant will be small, while if they are far from it (for example, if they areare orthogonal to one another, then the determinant will be large). Inparticular, for every matrix 𝐮, the absolute value of the determinantof 𝐮 is at most the product of the norms (i.e., square root of sum ofsquares of entries) of the rows, with equality if and only if the rowsare orthogonal to one another.

The determinant can be defined in several ways. One way to definethe determinant of an 𝑛 × 𝑛 matrix 𝐮 is:

det(𝐮) = ∑𝜋∈𝑆𝑛 sign(𝜋) ∏𝑖∈[𝑛] 𝐮𝑖,𝜋(𝑖) (12.5)

where 𝑆𝑛 is the set of all permutations from [𝑛] to [𝑛] and the sign ofa permutation 𝜋 is equal to −1 raised to the power of the number ofinversions in 𝜋 (pairs 𝑖, 𝑗 such that 𝑖 > 𝑗 but 𝜋(𝑖) < 𝜋(𝑗)).

This definition suggests that computing det(𝐮) might requiresumming over |𝑆𝑛| terms which would take exponential time since|𝑆𝑛| = 𝑛! > 2𝑛. However, there are other ways to compute the de-terminant. For example, it is known that det is the only function thatsatisfies the following conditions:

1. det(AB) = det(𝐮)det(đ”) for every square matrices 𝐮, đ”.

2. For every 𝑛 × 𝑛 triangular matrix 𝑇 with diagonal entries𝑑0, 
 , 𝑑𝑛−1, det(𝑇 ) = ∏𝑛𝑖=0 𝑑𝑖. In particular det(đŒ) = 1 where đŒ isthe identity matrix. (A triangular matrix is one in which either allentries below the diagonal, or all entries above the diagonal, arezero.)

3. det(𝑆) = −1 where 𝑆 is a “swap matrix” that corresponds toswapping two rows or two columns of đŒ . That is, there are two

coordinates 𝑎, 𝑏 such that for every 𝑖, 𝑗, 𝑆𝑖,𝑗 = ⎧⎚⎩1 𝑖 = 𝑗 , 𝑖 ∉ 𝑎, 𝑏1 𝑖, 𝑗 = 𝑎, 𝑏0 otherwise

.

Using these rules and the Gaussian elimination algorithm, it ispossible to tell whether 𝐮 is singular or not, and in the latter case, de-compose 𝐮 as a product of a polynomial number of swap matricesand triangular matrices. (Indeed one can verify that the row opera-tions in Gaussian elimination corresponds to either multiplying by a

Page 411: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

efficient computation: an informal introduction 411

swap matrix or by a triangular matrix.) Hence we can compute thedeterminant for an 𝑛 × 𝑛 matrix using a polynomial time of arithmeticoperations.

12.3.2 Permanent of a matrixGiven an 𝑛 × 𝑛 matrix 𝐮, the permanent of 𝐮 is defined as

perm(𝐮) = ∑𝜋∈𝑆𝑛 ∏𝑖∈[𝑛] 𝐮𝑖,𝜋(𝑖) . (12.6)

That is, perm(𝐮) is defined analogously to the determinant in (12.5)except that we drop the term sign(𝜋). The permanent of a matrix is anatural quantity, and has been studied in several contexts includingcombinatorics and graph theory. It also arises in physics where it canbe used to describe the quantum state of multiple Boson particles (seehere and here).

Permanent modulo 2. If the entries of 𝐮 are integers, then we can de-fine the Boolean function 𝑝𝑒𝑟𝑚2 which outputs on input a matrix 𝐮the result of the permanent of 𝐮 modulo 2. It turns out that we cancompute 𝑝𝑒𝑟𝑚2(𝐮) in polynomial time. The key is that modulo 2, âˆ’đ‘„and +đ‘„ are the same quantity and hence, since the only differencebetween (12.5) and (12.6) is that some terms are multiplied by −1,det(𝐮) mod 2 = perm(𝐮) mod 2 for every 𝐮.

Permanent modulo 3. Emboldened by our good fortune above, wemight hope to be able to compute the permanent modulo any prime 𝑝and perhaps in full generality. Alas, we have no such luck. In a similar“two to three” type of a phenomenon, we do not know of a muchbetter than brute force algorithm to even compute the permanentmodulo 3.12.3.3 Finding a zero-sum equilibriumA zero sum game is a game between two players where the payoff forone is the same as the penalty for the other. That is, whatever the firstplayer gains, the second player loses. As much as we want to avoidthem, zero sum games do arise in life, and the one good thing aboutthem is that at least we can compute the optimal strategy.

A zero sum game can be specified by an 𝑛 × 𝑛 matrix 𝐮, where ifplayer 1 chooses action 𝑖 and player 2 chooses action 𝑗 then player onegets 𝐮𝑖,𝑗 and player 2 loses the same amount. The famous Min MaxTheorem by John von Neumann states that if we allow probabilistic or“mixed” strategies (where a player does not choose a single action butrather a distribution over actions) then it does not matter who playsfirst and the end result will be the same. Mathematically the min maxtheorem is that if we let Δ𝑛 be the set of probability distributions over

Page 412: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

412 introduction to theoretical computer science

[𝑛] (i.e., non-negative columns vectors in ℝ𝑛 whose entries sum to 1)then

max𝑝∈∆𝑛 min𝑞∈∆𝑛 đ‘âŠ€đŽđ‘ž = min𝑞∈∆𝑛 max𝑝∈∆𝑛 đ‘âŠ€đŽđ‘ž (12.7)

The min-max theorem turns out to be a corollary of linear pro-gramming duality, and indeed the value of (12.7) can be computedefficiently by a linear program.

12.3.4 Finding a Nash equilibriumFortunately, not all real-world games are zero sum, and we do havemore general games, where the payoff of one player does not neces-sarily equal the loss of the other. John Nash won the Nobel prize forshowing that there is a notion of equilibrium for such games as well.In many economic texts it is taken as an article of faith that whenactual agents are involved in such a game then they reach a Nashequilibrium. However, unlike zero sum games, we do not know ofan efficient algorithm for finding a Nash equilibrium given the de-scription of a general (non zero sum) game. In particular this meansthat, despite economists’ intuitions, there are games for which naturalstrategies will take an exponential number of steps to converge to anequilibrium.

12.3.5 Primality testingAnother classical computational problem, that has been of interestsince the ancient Greeks, is to determine whether a given number𝑁 is prime or composite. Clearly we can do so by trying to divide itwith all the numbers in 2, 
 , 𝑁 − 1, but this would take at least 𝑁steps which is exponential in its bit complexity 𝑛 = log𝑁 . We canreduce these 𝑁 steps to

√𝑁 by observing that if 𝑁 is a composite ofthe form 𝑁 = PQ then either 𝑃 or 𝑄 is smaller than

√𝑁 . But this isstill quite terrible. If 𝑁 is a 1024 bit integer,

√𝑁 is about 2512, and sorunning this algorithm on such an input would take much more thanthe lifetime of the universe.

Luckily, it turns out we can do radically better. In the 1970’s, Ra-bin and Miller gave probabilistic algorithms to determine whether agiven number 𝑁 is prime or composite in time 𝑝𝑜𝑙𝑩(𝑛) for 𝑛 = log𝑁 .We will discuss the probabilistic model of computation later in thiscourse. In 2002, Agrawal, Kayal, and Saxena found a deterministic𝑝𝑜𝑙𝑩(𝑛) time algorithm for this problem. This is surely a developmentthat mathematicians from Archimedes till Gauss would have foundexciting.

Page 413: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

efficient computation: an informal introduction 413

Figure 12.6: The current computational status ofseveral interesting problems. For all of them we eitherknow a polynomial-time algorithm or the knownalgorithms require at least 2𝑛𝑐 for some 𝑐 > 0. Infact for all except the factoring problem, we eitherknow an 𝑂(𝑛3) time algorithm or the best knownalgorithm require at least 2Ω(𝑛) time where 𝑛 is anatural parameter such that there is a brute forcealgorithm taking roughly 2𝑛 or 𝑛! time. Whether this“cliff” between the easy and hard problem is a realphenomenon or a reflection of our ignorance is still anopen question.

12.3.6 Integer factoringGiven that we can efficiently determine whether a number 𝑁 is primeor composite, we could expect that in the latter case we could also ef-ficiently find the factorization of 𝑁 . Alas, no such algorithm is known.In a surprising and exciting turn of events, the non existence of such analgorithm has been used as a basis for encryptions, and indeed it un-derlies much of the security of the world wide web. We will return tothe factoring problem later in this course. We remark that we do knowmuch better than brute force algorithms for this problem. While thebrute force algorithms would require 2Ω(𝑛) time to factor an 𝑛-bit inte-ger, there are known algorithms running in time roughly 2𝑂(√𝑛) andalso algorithms that are widely believed (though not fully rigorouslyanalyzed) to run in time roughly 2𝑂(𝑛1/3). (By “roughly” we mean thatwe neglect factors that are polylogarithmic in 𝑛.)12.4 OUR CURRENT KNOWLEDGE

The difference between an exponential and polynomial time algo-rithm might seem merely “quantitative” but it is in fact extremelysignificant. As we’ve already seen, the brute force exponential timealgorithm runs out of steam very very fast, and as Edmonds says, inpractice there might not be much difference between a problem wherethe best algorithm is exponential and a problem that is not solvableat all. Thus the efficient algorithms we mentioned above are widelyused and power many computer science applications. Moreover, apolynomial-time algorithm often arises out of significant insight tothe problem at hand, whether it is the “max-flow min-cut” result, thesolvability of the determinant, or the group theoretic structure thatenables primality testing. Such insight can be useful regardless of itscomputational implications.

At the moment we do not know whether the “hard” problems aretruly hard, or whether it is merely because we haven’t yet found theright algorithms for them. However, we will now see that there areproblems that do inherently require exponential time. We just don’tknow if any of the examples above fall into that category.

Chapter Recap

‱ There are many natural problems that havepolynomial-time algorithms, and other naturalproblems that we’d love to solve, but for which thebest known algorithms are exponential.

‱ Often a polynomial time algorithm relies on dis-covering some hidden structure in the problem, orfinding a surprising equivalent formulation for it.

Page 414: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

414 introduction to theoretical computer science

2 Hint: Use dynamic programming to compute forevery 𝑠, 𝑡 ∈ [𝑛] and 𝑆 ⊆ [𝑛] the value 𝑃(𝑠, 𝑡, 𝑆)which equals 1 if there is a simple path from 𝑠 to 𝑡that uses exactly the vertices in 𝑆. Do this iterativelyfor 𝑆’s of growing sizes.

‱ There are many interesting problems where thereis an exponential gap between the best known algo-rithm and the best algorithm that we can rule out.Closing this gap is one of the main open questionsof theoretical computer science.

12.5 EXERCISES

Exercise 12.1 — exponential time algorithm for longest path. The naive algo-rithm for computing the longest path in a given graph could takemore than 𝑛! steps. Give a 𝑝𝑜𝑙𝑩(𝑛)2𝑛 time algorithm for the longestpath problem in 𝑛 vertex graphs.2

Exercise 12.2 — 2SAT algorithm. For every 2CNF 𝜑, define the graph đș𝜑on 2𝑛 vertices corresponding to the literals đ‘„1, 
 , đ‘„đ‘›, đ‘„1, 
 , đ‘„đ‘›, suchthat there is an edge ℓ𝑖 ℓ𝑗 iff the constraint ℓ𝑖 √ ℓ𝑗 is in 𝜑. Prove that 𝜑is unsatisfiable if and only if there is some 𝑖 such that there is a pathfrom đ‘„đ‘– to đ‘„đ‘– and from đ‘„đ‘– to đ‘„đ‘– in đș𝜑. Show how to use this to solve2SAT in polynomial time.

Exercise 12.3 — Reductions for showing algorithms. The following fact istrue: there is a polynomial-time algorithm BIP that on input a graphđș = (𝑉 , 𝐾) outputs 1 if and only if the graph is bipartite: there is apartition of 𝑉 to disjoint parts 𝑆 and 𝑇 such that every edge (𝑱, 𝑣) ∈ 𝐾satisfies either 𝑱 ∈ 𝑆 and 𝑣 ∈ 𝑇 or 𝑱 ∈ 𝑇 and 𝑣 ∈ 𝑆. Use thisfact to prove that there is a polynomial-time algorithm to computethat following function CLIQUEPARTITION that on input a graphđș = (𝑉 , 𝐾) outputs 1 if and only if there is a partition of 𝑉 the graphinto two parts 𝑆 and 𝑇 such that both 𝑆 and 𝑇 are cliques: for everypair of distinct vertices 𝑱, 𝑣 ∈ 𝑆, the edge (𝑱, 𝑣) is in 𝐾 and similarly forevery pair of distinct vertices 𝑱, 𝑣 ∈ 𝑇 , the edge (𝑱, 𝑣) is in 𝐾.

12.6 BIBLIOGRAPHICAL NOTES

The classic undergraduate introduction to algorithms text is[Cor+09]. Two texts that are less “encyclopedic” are Kleinberg andTardos [KT06], and Dasgupta, Papadimitriou and Vazirani [DPV08].Jeff Erickson’s book is an excellent algorithms text that is freelyavailable online.

The origins of the minimum cut problem date to the Cold War.Specifically, Ford and Fulkerson discovered their max-flow/min-cutalgorithm in 1955 as a way to find out the minimum amount of train

Page 415: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

efficient computation: an informal introduction 415

tracks that would need to be blown up to disconnect Russia from therest of Europe. See the survey [Sch05] for more.

Some algorithms for the longest path problem are given in [Wil09;Bjo14].

12.7 FURTHER EXPLORATIONS

Some topics related to this chapter that might be accessible to ad-vanced students include: (to be completed)

Page 416: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 417: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

13Modeling running time

“When the measure of the problem-size is reasonable and when thesizes assume values arbitrarily large, an asymptotic estimate of 
 the or-der of difficulty of [an] algorithm .. is theoretically important. It cannotbe rigged by making the algorithm artificially difficult for smaller sizes”,Jack Edmonds, “Paths, Trees, and Flowers”, 1963

Max Newman: It is all very well to say that a machine could 
 do this orthat, but 
 what about the time it would take to do it?Alan Turing: To my mind this time factor is the one question which willinvolve all the real technical difficulty.BBC radio panel on “Can automatic Calculating Machines Be Said toThink?”, 1952

In Chapter 12 we saw examples of efficient algorithms, and madesome claims about their running time, but did not give a mathemati-cally precise definition for this concept. We do so in this chapter, usingthe models of Turing machines and RAM machines (or equivalentlyNAND-TM and NAND-RAM) we have seen before. The runningtime of an algorithm is not a fixed number since any non-trivial algo-rithm will take longer to run on longer inputs. Thus, what we wantto measure is the dependence between the number of steps the algo-rithms takes and the length of the input. In particular we care aboutthe distinction between algorithms that take at most polynomial time(i.e., 𝑂(𝑛𝑐) time for some constant 𝑐) and problems for which everyalgorithm requires at least exponential time (i.e., Ω(2𝑛𝑐) for some 𝑐). Asmentioned in Edmond’s quote in Chapter 12, the difference betweenthese two can sometimes be as important as the difference betweenbeing computable and uncomputable.

This chapter: A non-mathy overviewIn this chapter we formally define what it means for a func-tion to be computable in a certain number of steps. As dis-cussed in Chapter 12, running time is not a number, rather

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Formally modeling running time, and in

particular notions such as 𝑂(𝑛) or 𝑂(𝑛3) timealgorithms.

‱ The classes P and EXP modelling polynomialand exponential time respectively.

‱ The time hierarchy theorem, that in particularsays that for every 𝑘 ≄ 1 there are functionswe can compute in 𝑂(𝑛𝑘+1) time but can notcompute in 𝑂(𝑛𝑘) time.

‱ The class P/poly of non uniform computationand the result that P ⊆ P/poly

Page 418: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

418 introduction to theoretical computer science

Figure 13.1: Overview of the results of this chapter.

what we care about is the scaling behevaiour of the numberof steps as the input size grows. We can use either Turingmachines or RAM machines to give such a formal definition- it turns out that this doesn’t make a difference at the reso-lution we care about. We make several important definitionsand prove some important theorems in this chapter. We willdefine the main time complexity classes we use in this book,and also show the Time Hierarchy Theorem which states thatgiven more resources (more time steps per input size) we cancompute more functions.

To put this in more “mathy” language, in this chapter we definewhat it means for a function đč ∶ 0, 1∗ → 0, 1∗ to be computablein time 𝑇 (𝑛) steps, where 𝑇 is some function mapping the length 𝑛of the input to the number of computation steps allowed. Using thisdefinition we will do the following (see also Fig. 13.1):

‱ We define the class P of Boolean functions that can be computedin polynomial time and the class EXP of functions that can be com-puted in exponential time. Note that P ⊆ EXP if we can compute afunction in polynomial time, we can certainly compute it in expo-nential time.

‱ We show that the times to compute a function using a Turing Ma-chine and using a RAM machine (or NAND-RAM program) arepolynomially related. In particular this means that the classes P andEXP are identical regardless of whether they are defined usingTuring Machines or RAM machines / NAND-RAM programs.

Page 419: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 419

‱ We give an efficient universal NAND-RAM program and use this toestablish the time hierarchy theorem that in particular implies that P isa strict subset of EXP.

‱ We relate the notions defined here to the non uniform models ofBoolean circuits and NAND-CIRC programs defined in Chapter 3.We define P/poly to be the class of functions that can be computedby a sequence of polynomial-sized circuits. We prove that P ⊆ P/polyand that P/poly contains uncomputable functions.

13.1 FORMALLY DEFINING RUNNING TIME

Our models of computation such Turing Machines, NAND-TM andNAND-RAM programs and others all operate by executing a se-quence of instructions on an input one step at a time. We can definethe running time of an algorithm 𝑀 in one of these models by measur-ing the number of steps 𝑀 takes on input đ‘„ as a function of the length|đ‘„| of the input. We start by defining running time with respect to Tur-ing Machines:

Definition 13.1 — Running time (Turing Machines). Let 𝑇 ∶ ℕ → ℕ be somefunction mapping natural numbers to natural numbers. We saythat a function đč ∶ 0, 1∗ → 0, 1∗ is computable in 𝑇 (𝑛) Turing-Machine time (TM-time for short) if there exists a Turing Machine 𝑀such that for every sufficiently large 𝑛 and every đ‘„ ∈ 0, 1𝑛, whengiven input đ‘„, the machine 𝑀 halts after executing at most 𝑇 (𝑛)steps and outputs đč(đ‘„).

We define TIMETM(𝑇 (𝑛)) to be the set of Boolean functions(functions mapping 0, 1∗ to 0, 1) that are computable in 𝑇 (𝑛)TM time.

Big Idea 17 For a function đč ∶ 0, 1∗ → 0, 1 and 𝑇 ∶ℕ → ℕ, we can formally define what it means for đč to be computablein time at most 𝑇 (𝑛) where 𝑛 is the size of the input.

PDefinition 13.1 is not very complicated but is one ofthe most important definitions of this book. As usual,TIMETM(𝑇 (𝑛)) is a class of functions, not of machines. If𝑀 is a Turing Machine then a statement such as “𝑀is a member of TIMETM(𝑛2)” does not make sense.The concept of TM-time as defined here is sometimesknown as “single-tape Turing machine time” in theliterature, since some texts consider Turing machineswith more than one working tape.

Page 420: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

420 introduction to theoretical computer science

Figure 13.2: Comparing 𝑇 (𝑛) = 10𝑛3 with 𝑇 â€Č(𝑛) =2𝑛 (on the right figure the Y axis is in log scale).Since for every large enough 𝑛, 𝑇 â€Č(𝑛) ≄ 𝑇 (𝑛),TIMETM(𝑇 (𝑛)) ⊆ TIMETM(𝑇 â€Č(𝑛)).

The relaxation of considering only “sufficiently large” 𝑛’s is notvery important but it is convenient since it allows us to avoid dealingexplicitly with un-interesting “edge cases”. We will mostly anyway beinterested in determining running time only up to constant and evenpolynomial factors.

While the notion of being computable within a certain running timecan be defined for every function, the class TIMETM(𝑇 (𝑛)) is a classof Boolean functions that have a single bit of output. This choice is notvery important, but is made for simplicity and convenience later on.In fact, every non-Boolean function has a computationally equivalentBoolean variant, see Exercise 13.3.Solved Exercise 13.1 — Example of time bounds. Prove that TIMETM(10⋅𝑛3) ⊆TIMETM(2𝑛).

Solution:

The proof is illustrated in Fig. 13.2. Suppose that đč ∈ TIMETM(10⋅𝑛3) and hence there some number 𝑁0 and a machine 𝑀 such thatfor every 𝑛 > 𝑁0, and đ‘„ ∈ 0, 1∗, 𝑀(đ‘„) outputs đč(đ‘„) within atmost 10 ⋅ 𝑛3 steps. Since 10 ⋅ 𝑛3 = 𝑜(2𝑛), there is some number𝑁1 such that for every 𝑛 > 𝑁1, 10 ⋅ 𝑛3 < 2𝑛. Hence for every𝑛 > max𝑁0, 𝑁1, 𝑀(đ‘„) will output đč(đ‘„) within at most 2𝑛 steps,just demonstrating that đč ∈ TIMETM(2𝑛).

13.1.1 Polynomial and Exponential TimeUnlike the notion of computability, the exact running time can be afunction of the model we use. However, it turns out that if we onlycare about “coarse enough” resolution (as will most often be the case)then the choice of the model, whether Turing Machines, RAM ma-chines, NAND-TM/NAND-RAM programs, or C/Python programs,does not matter. This is known as the extended Church-Turing Thesis.Specifically we will mostly care about the difference between polyno-mial and exponential time.

The two main time complexity classes we will be interested in arethe following:

‱ Polynomial time: A function đč ∶ 0, 1∗ → 0, 1 is computable inpolynomial time if it is in the class P = âˆȘ𝑐∈1,2,3,
TIMETM(𝑛𝑐). Thatis, đč ∈ P if there is an algorithm to compute đč that runs in time atmost polynomial (i.e., at most 𝑛𝑐 for some constant 𝑐) in the lengthof the input.

‱ Exponential time: A function đč ∶ 0, 1∗ → 0, 1 is computable inexponential time if it is in the class EXP = âˆȘ𝑐∈1,2,3,
TIMETM(2𝑛𝑐).

Page 421: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 421

That is, đč ∈ EXP if there is an algorithm to compute đč that runs intime at most exponential (i.e., at most 2𝑛𝑐 for some constant 𝑐) in thelength of the input.

In other words, these are defined as follows:

Definition 13.2 — P and EXP. Let đč ∶ 0, 1∗ → 0, 1. We say thatđč ∈ P if there is a polynomial 𝑝 ∶ ℕ → ℝ and a Turing Machine𝑀 such that for every đ‘„ ∈ 0, 1∗, when given input đ‘„, the Turingmachine halts within at most 𝑝(|đ‘„|) steps and outputs đč(đ‘„).

We say that đč ∈ EXP if there is a polynomial 𝑝 ∶ ℕ → ℝ anda Turing Machine 𝑀 such that for every đ‘„ ∈ 0, 1∗, when giveninput đ‘„, 𝑀 halts within at most 2𝑝(|đ‘„|) steps and outputs đč(đ‘„).

PPlease take the time to make sure you understandthese definitions. In particular, sometimes studentsthink of the class EXP as corresponding to functionsthat are not in P. However, this is not the case. If đč isin EXP then it can be computed in exponential time.This does not mean that it cannot be computed inpolynomial time as well.

Solved Exercise 13.2 — Differerent definitions of P. Prove that P as defined inDefinition 13.2 is equal to âˆȘ𝑐∈1,2,3,
TIMETM(𝑛𝑐)

Solution:

To show these two sets are equal we need to show that P ⊆âˆȘ𝑐∈1,2,3,
TIMETM(𝑛𝑐) and âˆȘ𝑐∈1,2,3,
TIMETM(𝑛𝑐) ⊆ P. We startwith the former inclusion. Suppose that đč ∈ P. Then there is somepolynomial 𝑝 ∶ ℕ → ℝ and a Turing machine 𝑀 such that 𝑀computes đč and 𝑀 halts on every input đ‘„ within at most 𝑝(|đ‘„|)steps. We can write the polynomial 𝑝 ∶ ℕ → ℝ in the form𝑝(𝑛) = ∑𝑑𝑖=0 𝑎𝑖𝑛𝑖 where 𝑎0, 
 , 𝑎𝑑 ∈ ℝ, and we assume that 𝑎𝑑is nonzero (or otherwise we just let 𝑑 correspond to the largestnumber such that 𝑎𝑑 is nonzero). The degree if 𝑝 the number 𝑑.Since 𝑛𝑑 = 𝑜(𝑛𝑑+1), no matter what is the coefficient 𝑎𝑑, for largeenough 𝑛, 𝑝(𝑛) < 𝑛𝑑+1 which means that the Turing machine 𝑀will halt on inputs of length 𝑛 within fewer than 𝑛𝑑+1 steps, andhence đč ∈ TIMETM(𝑛𝑑+1) ⊆ âˆȘ𝑐∈1,2,3,
TIMETM(𝑛𝑐).

For the second inclusion, suppose that đč ∈ âˆȘ𝑐∈1,2,3,
TIMETM(𝑛𝑐).Then there is some positive 𝑐 ∈ ℕ such that đč ∈ TIMETM(𝑛𝑐) whichmeans that there is a Turing Machine 𝑀 and some number 𝑁0 such

Page 422: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

422 introduction to theoretical computer science

Figure 13.3: Some examples of problems that areknown to be in P and problems that are known tobe in EXP but not known whether or not they arein P. Since both P and EXP are classes of Booleanfunctions, in this figure we always refer to the Boolean(i.e., Yes/No) variant of the problems.

that 𝑀 computes đč and for every 𝑛 > 𝑁0, 𝑀 halts on length 𝑛inputs within at most 𝑛𝑐 steps. Let 𝑇0 be the maximum numberof steps that 𝑀 takes on inputs of length at most 𝑁0. Then if wedefine the polynomial 𝑝(𝑛) = 𝑛𝑐 + 𝑇0 then we see that 𝑀 halts onevery input đ‘„ within at most 𝑝(|đ‘„|) steps and hence the existence of𝑀 demonstrates that đč ∈ P.

Since exponential time is much larger than polynomial time, P ⊆EXP. All of the problems we listed in Chapter 12 are in EXP, but aswe’ve seen, for some of them there are much better algorithms thatdemonstrate that they are in fact in the smaller class P.

P EXP (but not known to be in P)Shortest path Longest PathMin cut Max cut2SAT 3SATLinear eqs Quad. eqsZerosum NashDeterminant PermanentPrimality Factoring

Table : A table of the examples from Chapter 12. All these problemsare in EXP but only the ones on the left column are currently known tobe in P as well (i.e., they have a polynomial-time algorithm). See alsoFig. 13.3.

RRemark 13.3 — Boolean versions of problems. Manyof the problems defined in Chapter 12 correspond tonon Boolean functions (functions with more than onebit of output) while P and EXP are sets of Booleanfunctions. However, for every non-Boolean functionđč we can always define a computationally-equivalentBoolean function đș by letting đș(đ‘„, 𝑖) be the 𝑖-th bitof đč(đ‘„) (see Exercise 13.3). Hence the table above,as well as Fig. 13.3, refer to the computationally-equivalent Boolean variants of these problems.

13.2 MODELING RUNNING TIME USING RAM MACHINES / NAND-RAM

Turing Machines are a clean theoretical model of computation, butdo not closely correspond to real-world computing architectures. Thediscrepancy between Turing Machines and actual computers doesnot matter much when we consider the question of which functions

Page 423: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 423

are computable, but can make a difference in the context of efficiency.Even a basic staple of undergraduate algorithms such as “merge sort”cannot be implemented on a Turing Machine in 𝑂(𝑛 log𝑛) time (seeSection 13.8). RAM machines (or equivalently, NAND-RAM programs)match more closely actual computing architecture and what we meanwhen we say 𝑂(𝑛) or 𝑂(𝑛 log𝑛) algorithms in algorithms coursesor whiteboard coding interviews. We can define running time withrespect to NAND-RAM programs just as we did for Turing Machines.

Definition 13.4 — Running time (RAM). Let 𝑇 ∶ ℕ → ℕ be some func-tion mapping natural numbers to natural numbers. We say thata function đč ∶ 0, 1∗ → 0, 1∗ is computable in 𝑇 (𝑛) RAM time(RAM-time for short) if there exists a NAND-RAM program 𝑃 suchthat for every sufficiently large 𝑛 and every đ‘„ ∈ 0, 1𝑛, when giveninput đ‘„, the program 𝑃 halts after executing at most 𝑇 (𝑛) lines andoutputs đč(đ‘„).

We define TIMERAM(𝑇 (𝑛)) to be the set of Boolean functions(functions mapping 0, 1∗ to 0, 1) that are computable in 𝑇 (𝑛)RAM time.

Because NAND-RAM programs correspond more closely to ournatural notions of running time, we will use NAND-RAM as our“default” model of running time, and hence use TIME(𝑇 (𝑛)) (withoutany subscript) to denote TIMERAM(𝑇 (𝑛)). However, it turns out thatas long as we only care about the difference between exponential andpolynomial time, this does not make much difference. The reason isthat Turing Machines can simulate NAND-RAM programs with atmost a polynomial overhead (see also Fig. 13.4):

Theorem 13.5 — Relating RAM and Turing machines. Let 𝑇 ∶ ℕ → ℕ be afunction such that 𝑇 (𝑛) ≄ 𝑛 for every 𝑛 and the map 𝑛 ↩ 𝑇 (𝑛) canbe computed by a Turing machine in time 𝑂(𝑇 (𝑛)). Then

TIMETM(𝑇 (𝑛)) ⊆ TIMERAM(10 ⋅ 𝑇 (𝑛)) ⊆ TIMETM(𝑇 (𝑛)4) . (13.1)

PThe technical details of Theorem 13.5, such as the con-dition that 𝑛 ↩ 𝑇 (𝑛) is computable in 𝑂(𝑇 (𝑛)) timeor the constants 10 and 4 in (13.1) (which are not tightand can be improved), are not very important. In par-ticular, all non pathological time bound functions weencounter in practice such as 𝑇 (𝑛) = 𝑛, 𝑇 (𝑛) = 𝑛 log𝑛,𝑇 (𝑛) = 2𝑛 etc. will satisfy the conditions of Theo-rem 13.5, see also Remark 13.6.

Page 424: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

424 introduction to theoretical computer science

Figure 13.4: The proof of Theorem 13.5 shows thatwe can simulate 𝑇 steps of a Turing Machine with 𝑇steps of a NAND-RAM program, and can simulate𝑇 steps of a NAND-RAM program with 𝑜(𝑇 4)steps of a Turing Machine. Hence TIMETM(𝑇 (𝑛)) ⊆TIMERAM(10 ⋅ 𝑇 (𝑛)) ⊆ TIMETM(𝑇 (𝑛)4).

The main message of the theorem is Turing Machinesand RAM machines are “roughly equivalent” in thesense that one can simulate the other with polyno-mial overhead. Similarly, while the proof involvessome technical details, it’s not very deep or hard, andmerely follows the simulation of RAM machines withTuring Machines we saw in Theorem 8.1 with morecareful “book keeping”.

For example, by instantiating Theorem 13.5 with 𝑇 (𝑛) = 𝑛𝑎 andusing the fact that 10𝑛𝑎 = 𝑜(𝑛𝑎+1), we see that TIMETM(𝑛𝑎) ⊆TIMERAM(𝑛𝑎+1) ⊆ TIMETM(𝑛4𝑎+4) which means that (by Solved Ex-ercise 13.2)

P = âˆȘ𝑎=1,2,
TIMETM(𝑛𝑎) = âˆȘ𝑎=1,2,
TIMERAM(𝑛𝑎) . (13.2)That is, we could have equally well defined P as the class of functionscomputable by NAND-RAM programs (instead of Turing Machines)that run in time polynomial in the length of the input. Similarly, byinstantiating Theorem 13.5 with 𝑇 (𝑛) = 2𝑛𝑎 we see that the class EXPcan also be defined as the set of functions computable by NAND-RAMprograms in time at most 2𝑝(𝑛) where 𝑝 is some polynomial. Similarequivalence results are known for many models including cellularautomata, C/Python/Javascript programs, parallel computers, and agreat many other models, which justifies the choice of P as capturinga technology-independent notion of tractability. (See Section 13.3for more discussion of this issue.) This equivalence between Turingmachines and NAND-RAM (as well as other models) allows us topick our favorite model depending on the task at hand (i.e., “have ourcake and eat it too”) even when we study questions of efficiency, aslong as we only care about the gap between polynomial and exponentialtime. When we want to design an algorithm, we can use the extrapower and convenience afforded by NAND-RAM. When we wantto analyze a program or prove a negative result, we can restrict ourattention to Turing machines.

Big Idea 18 All “reasonable” computational models are equiv-alent if we only care about the distinction between polynomial andexponential.

The adjective “reasonable” above refers to all scalable computa-tional models that have been implemented, with the possible excep-tion of quantum computers, see Section 13.3 and Chapter 23.Proof Idea:

The direction TIMETM(𝑇 (𝑛)) ⊆ TIMERAM(10 ⋅ 𝑇 (𝑛)) is not hard toshow, since a NAND-RAM program 𝑃 can simulate a Turing Machine

Page 425: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 425

𝑀 with constant overhead by storing the transition table of 𝑀 inan array (as is done in the proof of Theorem 9.1). Simulating everystep of the Turing machine can be done in a constant number 𝑐 ofsteps of RAM, and it can be shown this constant 𝑐 is smaller than10. Thus the heart of the theorem is to prove that TIMERAM(𝑇 (𝑛)) ⊆TIMETM(𝑇 (𝑛)4). This proof closely follows the proof of Theorem 8.1,where we have shown that every function đč that is computable bya NAND-RAM program 𝑃 is computable by a Turing Machine (orequivalently a NAND-TM program) 𝑀 . To prove Theorem 13.5, wefollow the exact same proof but just check that the overhead of thesimulation of 𝑃 by 𝑀 is polynomial. The proof has many details, butis not deep. It is therefore much more important that you understandthe statement of this theorem than its proof.⋆Proof of Theorem 13.5. We only focus on the non-trivial directionTIMERAM(𝑇 (𝑛)) ⊆ TIMETM(𝑇 (𝑛)4). Let đč ∈ TIMERAM(𝑇 (𝑛)). đč canbe computed in time 𝑇 (𝑛) by some NAND-RAM program 𝑃 and weneed to show that it can also be computed in time 𝑇 (𝑛)4 by a TuringMachine 𝑀 . This will follow from showing that đč can be computedin time 𝑇 (𝑛)4 by a NAND-TM program, since for every NAND-TMprogram 𝑄 there is a Turing Machine 𝑀 simulating it such that eachiteration of 𝑄 corresponds to a single step of 𝑀 .

As mentioned above, we follow the proof of Theorem 8.1 (simula-tion of NAND-RAM programs using NAND-TM programs) and usethe exact same simulation, but with a more careful accounting of thenumber of steps that the simulation costs. Recall, that the simulationof NAND-RAM works by “peeling off” features of NAND-RAM oneby one, until we are left with NAND-TM.

We will not provide the full details but will present the main ideasused in showing that every feature of NAND-RAM can be simulatedby NAND-TM with at most a polynomial overhead:

1. Recall that every NAND-RAM variable or array element can con-tain an integer between 0 and 𝑇 where 𝑇 is the number of lines thathave been executed so far. Therefore if 𝑃 is a NAND-RAM pro-gram that computes đč in 𝑇 (𝑛) time, then on inputs of length 𝑛, allintegers used by 𝑃 are of magnitude at most 𝑇 (𝑛). This means thatthe largest value i can ever reach is at most 𝑇 (𝑛) and so each one of𝑃 ’s variables can be thought of as an array of at most 𝑇 (𝑛) indices,each of which holds a natural number of magnitude at most 𝑇 (𝑛).We let ℓ = ⌈log𝑇 (𝑛)⌉ be the number of bits needed to encode suchnumbers. (We can start off the simulation by computing 𝑇 (𝑛) andℓ.)

Page 426: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

426 introduction to theoretical computer science

2. We can encode a NAND-RAM array of length ≀ 𝑇 (𝑛) containingnumbers in 0, 
 , 𝑇 (𝑛) − 1 as an Boolean (i.e., NAND-TM) arrayof 𝑇 (𝑛)ℓ = 𝑂(𝑇 (𝑛) log𝑇 (𝑛)) bits, which we can also think of asa two dimensional array as we did in the proof of Theorem 8.1. Weencode a NAND-RAM scalar containing a number in 0, 
 , 𝑇 (𝑛) −1 simply by a shorter NAND-TM array of ℓ bits.

3. We can simulate the two dimensional arrays using one-dimensional arrays of length 𝑇 (𝑛)ℓ = 𝑂(𝑇 (𝑛) log𝑇 (𝑛). All thearithmetic operations on integers use the grade-school algorithms,that take time that is polynomial in the number ℓ of bits of theintegers, which is 𝑝𝑜𝑙𝑩(log𝑇 (𝑛)) in our case. Hence we can simulate𝑇 (𝑛) steps of NAND-RAM with 𝑂(𝑇 (𝑛)𝑝𝑜𝑙𝑩(log𝑇 (𝑛)) steps of amodel that uses random access memory but only Boolean-valuedone-dimensional arrays.

4. The most expensive step is to translate from random access mem-ory to the sequential memory model of NAND-TM/Turing Ma-chines. As we did in the proof of Theorem 8.1 (see Section 8.2), wecan simulate accessing an array Foo at some location encoded in anarray Bar by:

a. Copying Bar to some temporary array Tempb. Having an array Index which is initially all zeros except 1 at the

first location.c. Repeating the following until Temp encodes the number 0:

(Number of repetitions is at most 𝑇 (𝑛).)‱ Decrease the number encoded temp by 1. (Take number of steps

polynomial in ℓ = ⌈log𝑇 (𝑛)⌉.)‱ Decrease i until it is equal to 0. (Take 𝑂(𝑇 (𝑛) steps.)‱ Scan Index until we reach the point in which it equals 1 and

then change this 1 to 0 and go one step further and write 1 inthis location. (Takes 𝑂(𝑇 (𝑛)) steps.)

d. When we are done we know that if we scan Index until we reachthe point in which Index[i]= 1 then i contains the value thatwas encoded by Bar (Takes 𝑂(𝑇 (𝑛) steps.)

The total cost for each such operation is 𝑂(𝑇 (𝑛)2+𝑇 (𝑛)𝑝𝑜𝑙𝑩(log𝑇 (𝑛))) =𝑂(𝑇 (𝑛)2) steps.In sum, we simulate a single step of NAND-RAM using𝑂(𝑇 (𝑛)2𝑝𝑜𝑙𝑩(log𝑇 (𝑛))) steps of NAND-TM, and hence the total

simulation time is 𝑂(𝑇 (𝑛)3𝑝𝑜𝑙𝑩(log𝑇 (𝑛))) which is smaller than 𝑇 (𝑛)4for sufficiently large 𝑛.

Page 427: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 427

RRemark 13.6 — Nice time bounds. When consideringgeneral time bounds such we need to make sure torule out some “pathological” cases such as functions 𝑇that don’t give enough time for the algorithm to readthe input, or functions where the time bound itself isuncomputable. We say that a function 𝑇 ∶ ℕ → ℕ isa nice time bound function (or nice function for short)if for every 𝑛 ∈ ℕ, 𝑇 (𝑛) ≄ 𝑛 (i.e., 𝑇 allows enoughtime to read the input), for every 𝑛â€Č ≄ 𝑛, 𝑇 (𝑛â€Č) ≄ 𝑇 (𝑛)(i.e., 𝑇 allows more time on longer inputs), and themap đč(đ‘„) = 1𝑇 (|đ‘„|) (i.e., mapping a string of length𝑛 to a sequence of 𝑇 (𝑛) ones) can be computed by aNAND-RAM program in 𝑂(𝑇 (𝑛)) time.All the “normal” time complexity bounds we en-counter in applications such as 𝑇 (𝑛) = 100𝑛,𝑇 (𝑛) = 𝑛2 log𝑛,𝑇 (𝑛) = 2√𝑛, etc. are “nice”.Hence from now on we will only care about theclass TIME(𝑇 (𝑛)) when 𝑇 is a “nice” function. Thecomputability condition is in particular typically easilysatisfied. For example, for arithmetic functions suchas 𝑇 (𝑛) = 𝑛3, we can typically compute the binaryrepresentation of 𝑇 (𝑛) in time polynomial in the num-ber of bits of 𝑇 (𝑛) and hence poly-logarithmic in 𝑇 (𝑛).Hence the time to write the string 1𝑇 (𝑛) in such caseswill be 𝑇 (𝑛) + 𝑝𝑜𝑙𝑩(log𝑇 (𝑛)) = 𝑂(𝑇 (𝑛)).

13.3 EXTENDED CHURCH-TURING THESIS (DISCUSSION)

Theorem 13.5 shows that the computational models of Turing Machinesand RAMMachines / NAND-RAM programs are equivalent up to poly-nomial factors in the running time. Other examples of polynomiallyequivalent models include:

‱ All standard programming languages, including C/Python/-JavaScript/Lisp/etc.

‱ The 𝜆 calculus (see also Section 13.8).

‱ Cellular automata

‱ Parallel computers

‱ Biological computing devices such as DNA-based computers.

The Extended Church Turing Thesis is the statement that this is truefor all physically realizable computing models. In other words, theextended Church Turing thesis says that for every scalable computingdevice đ¶ (which has a finite description but can be in principle usedto run computation on arbitrarily large inputs), there is some con-stant 𝑎 such that for every function đč ∶ 0, 1∗ → 0, 1 that đ¶ can

Page 428: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

428 introduction to theoretical computer science

compute on 𝑛 length inputs using an 𝑆(𝑛) amount of physical re-sources, đč is in TIME(𝑆(𝑛)𝑎). This is a strengthening of the (“plain”)Church-Turing Thesis, discussed in Section 8.8, which states that theset of computable functions is the same for all physically realizablemodels, but without requiring the overhead in the simulation betweendifferent models to be at most polynomial.

All the current constructions of scalable computational models andprogramming languages conform to the Extended Church-TuringThesis, in the sense that they can be simulated with polynomial over-head by Turing Machines (and hence also by NAND-TM or NAND-RAM programs). Consequently, the classes P and EXP are robust tothe choice of model, and we can use the programming language ofour choice, or high level descriptions of an algorithm, to determinewhether or not a problem is in P.

Like the Church-Turing thesis itself, the extended Church-Turingthesis is in the asymptotic setting and does not directly yield an ex-perimentally testable prediction. However, it can be instantiated withmore concrete bounds on the overhead, yielding experimentally-testable predictions such as the Physical Extended Church-Turing Thesiswe mentioned in Section 5.6.

In the last hundred+ years of studying and mechanizing com-putation, no one has yet constructed a scalable computing devicethat violates the extended Church Turing Thesis. However, quan-tum computing, if realized, will pose a serious challenge to the ex-tended Church-Turing Thesis (see Chapter 23). However, even ifthe promises of quantum computing are fully realized, the extendedChurch-Turing thesis is “morally” correct, in the sense that, while wedo need to adapt the thesis to account for the possibility of quantumcomputing, its broad outline remains unchanged. We are still ableto model computation mathematically, we can still treat programsas strings and have a universal program, we still have time hierarchyand uncomputability results, and there is still no reason to doubt the(“plain”) Church-Turing thesis. Moreover, the prospect of quantumcomputing does not seem to make a difference for the time complexityof many (though not all!) of the concrete problems that we care about.In particular, as far as we know, out of all the example problems men-tioned in Chapter 12 the complexity of only one— integer factoring—is affected by modifying our model to include quantum computers aswell.

Page 429: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 429

Figure 13.5: The universal NAND-RAM program𝑈 simulates an input NAND-RAM program 𝑃by storing all of 𝑃 ’s variables inside a single arrayVars of 𝑈 . If 𝑃 has 𝑡 variables, then the array Varsis divided into blocks of length 𝑡, where the 𝑗-thcoordinate of the 𝑖-th block contains the 𝑖-th elementof the 𝑗-th array of 𝑃 . If the 𝑗-th variable of 𝑃 isscalar, then we just store its value in the zeroth blockof Vars.

13.4 EFFICIENT UNIVERSAL MACHINE: A NAND-RAM INTER-PRETER IN NAND-RAM

We have seen in Theorem 9.1 the “universal Turing Machine”. Exam-ining that proof, and combining it with Theorem 13.5 , we can see thatthe program 𝑈 has a polynomial overhead, in the sense that it can sim-ulate 𝑇 steps of a given NAND-TM (or NAND-RAM) program 𝑃 onan input đ‘„ in 𝑂(𝑇 4) steps. But in fact, by directly simulating NAND-RAM programs we can do better with only a constant multiplicativeoverhead. That is, there is a universal NAND-RAM program 𝑈 such thatfor every NAND-RAM program 𝑃 , 𝑈 simulates 𝑇 steps of 𝑃 usingonly 𝑂(𝑇 ) steps. (The implicit constant in the 𝑂 notation can dependon the program 𝑃 but does not depend on the length of the input.)

Theorem 13.7 — Efficient universality of NAND-RAM. There exists a NAND-RAM program 𝑈 satisfying the following:

1. (𝑈 is a universal NAND-RAM program.) For every NAND-RAMprogram 𝑃 and input đ‘„, 𝑈(𝑃 , đ‘„) = 𝑃(đ‘„) where by 𝑈(𝑃 , đ‘„) wedenote the output of 𝑈 on a string encoding the pair (𝑃 , đ‘„).

2. (𝑈 is efficient.) There are some constants 𝑎, 𝑏 such that for ev-ery NAND-RAM program 𝑃 , if 𝑃 halts on input đ‘„ after most𝑇 steps, then 𝑈(𝑃 , đ‘„) halts after at most đ¶ ⋅ 𝑇 steps wheređ¶ ≀ 𝑎|𝑃 |𝑏.

PAs in the case of Theorem 13.5, the proof of Theo-rem 13.7 is not very deep and so it is more importantto understand its statement. Specifically, if you under-stand how you would go about writing an interpreterfor NAND-RAM using a modern programming lan-guage such as Python, then you know everything youneed to know about the proof of this theorem.

Proof of Theorem 13.7. To present a universal NAND-RAM programin full we would need to describe a precise representation scheme,as well as the full NAND-RAM instructions for the program. Whilethis can be done, it is more important to focus on the main ideas, andso we just sketch the proof here. A specification of NAND-RAM isgiven in the appendix, and for the purposes of this simulation, we cansimply use the representation of the code NAND-RAM as an ASCIIstring.

Page 430: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

430 introduction to theoretical computer science

The program 𝑈 gets as input a NAND-RAM program 𝑃 and aninput đ‘„ and simulates 𝑃 one step at a time. To do so, 𝑈 does the fol-lowing:

1. 𝑈 maintains variables program_counter, and number_steps for thecurrent line to be executed and the number of steps executed so far.

2. 𝑈 initially scans the code of 𝑃 to find the number 𝑡 of unique vari-able names that 𝑃 uses. It will translate each variable name into anumber between 0 and 𝑡 − 1 and use an array Program to store 𝑃 ’scode where for every line ℓ, Program[ℓ] will store the ℓ-th line of 𝑃where the variable names have been translated to numbers. (Moreconcretely, we will use a constant number of arrays to separatelyencode the operation used in this line, and the variable names andindices of the operands.)

3. 𝑈 maintains a single array Vars that contains all the values of 𝑃 ’svariables. We divide Vars into blocks of length 𝑡. If 𝑠 is a num-ber corresponding to an array variable Foo of 𝑃 , then we storeFoo[0] in Vars[𝑠], we store Foo[1] in Var_values[𝑡 + 𝑠], Foo[2]in Vars[2𝑡 + 𝑠] and so on and so forth (see Fig. 13.5). Generally,ifthe 𝑠-th variable of 𝑃 is a scalar variable, then its value will bestored in location Vars[𝑠]. If it is an array variable then the value ofits 𝑖-th element will be stored in location Vars[𝑡 ⋅ 𝑖 + 𝑠].

4. To simulate a single step of 𝑃 , the program 𝑈 recovers from Pro-gram the line corresponding to program_counter and executes it.Since NAND-RAM has a constant number of arithmetic operations,we can implement the logic of which operation to execute using asequence of a constant number of if-then-else’s. Retrieving fromVars the values of the operands of each instruction can be doneusing a constant number of arithmetic operations.

The setup stages take only a constant (depending on |𝑃 | but noton the input đ‘„) number of steps. Once we are done with the setup, tosimulate a single step of 𝑃 , we just need to retrieve the correspondingline and do a constant number of “if elses” and accesses to Vars tosimulate it. Hence the total running time to simulate 𝑇 steps of theprogram 𝑃 is at most 𝑂(𝑇 ) when suppressing constants that dependon the program 𝑃 .

13.4.1 Timed Universal Turing MachineOne corollary of the efficient universal machine is the following.Given any Turing Machine 𝑀 , input đ‘„, and “step budget” 𝑇 , we cansimulate the execution of 𝑀 for 𝑇 steps in time that is polynomial in

Page 431: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 431

Figure 13.6: The timed universal Turing Machine takesas input a Turing machine 𝑀 , an input đ‘„, and a timebound 𝑇 , and outputs 𝑀(đ‘„) if 𝑀 halts within atmost 𝑇 steps. Theorem 13.8 states that there is such amachine that runs in time polynomial in 𝑇 .

𝑇 . Formally, we define a function TIMEDEVAL that takes the threeparameters 𝑀 , đ‘„, and the time budget, and outputs 𝑀(đ‘„) if 𝑀 haltswithin at most 𝑇 steps, and outputs 0 otherwise. The timed univer-sal Turing Machine computes TIMEDEVAL in polynomial time (seeFig. 13.6). (Since we measure time as a function of the input length,we define TIMEDEVAL as taking the input 𝑇 represented in unary: astring of 𝑇 ones.)

Theorem 13.8 — Timed Universal Turing Machine. Let TIMEDEVAL ∶0, 1∗ → 0, 1∗ be the function defined as

TIMEDEVAL(𝑀, đ‘„, 1𝑇 ) = âŽ§âŽšâŽ©đ‘€(đ‘„) 𝑀 halts within ≀ 𝑇 steps on đ‘„0 otherwise.

(13.3)Then TIMEDEVAL ∈ P.

Proof. We only sketch the proof since the result follows fairly directlyfrom Theorem 13.5 and Theorem 13.7. By Theorem 13.5 to show thatTIMEDEVAL ∈ P, it suffices to give a polynomial-time NAND-RAMprogram to compute TIMEDEVAL.

Such a program can be obtained as follows. Given a Turing Ma-chine 𝑀 , by Theorem 13.5 we can transform it in time polynomial inits description into a functionally-equivalent NAND-RAM program𝑃 such that the execution of 𝑀 on 𝑇 steps can be simulated by theexecution of 𝑃 on 𝑐 ⋅ 𝑇 steps. We can then run the universal NAND-RAM machine of Theorem 13.7 to simulate 𝑃 for 𝑐 ⋅ 𝑇 steps, using𝑂(𝑇 ) time, and output 0 if the execution did not halt within this bud-get. This shows that TIMEDEVAL can be computed by a NAND-RAMprogram in time polynomial in |𝑀| and linear in 𝑇 , which meansTIMEDEVAL ∈ P.

13.5 THE TIME HIERARCHY THEOREM

Some functions are uncomputable, but are there functions that canbe computed, but only at an exorbitant cost? For example, is there afunction that can be computed in time 2𝑛, but can not be computed intime 20.9𝑛? It turns out that the answer is Yes:

Theorem 13.9 — Time Hierarchy Theorem. For every nice function 𝑇 ∶ℕ → ℕ, there is a function đč ∶ 0, 1∗ → 0, 1 in TIME(𝑇 (𝑛) log𝑛)⧔TIME(𝑇 (𝑛)).There is nothing special about log𝑛, and we could have used any

other efficiently computable function that tends to infinity with 𝑛.

Page 432: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

432 introduction to theoretical computer science

Big Idea 19 If we have more time, we can compute more functions.

RRemark 13.10 — Simpler corollary of the time hierarchytheorem. The generality of the time hierarchy theoremcan make its proof a little hard to read. It might beeasier to follow the proof if you first try to prove byyourself the easier statement P ⊊ EXP.You can do so by showing that the following functionđč ∶ 0, 1∗ ∶→ 0, 1 is in EXP ⧔ P: for every TuringMachine 𝑀 and input đ‘„, đč(𝑀, đ‘„) = 1 if and only if𝑀 halts on đ‘„ within at most |đ‘„|log |đ‘„| steps. One canshow that đč ∈ TIME(𝑛𝑂(log𝑛)) ⊆ EXP using theuniversal Turing machine (or the efficient universalNAND-RAM program of Theorem 13.7). On the otherharnd, we can use similar ideas to those used to showthe uncomputability of HALT in Section 9.3.2 to provethat đč ∉ P.

Figure 13.7: The Time Hierarchy Theorem (Theo-rem 13.9) states that all of these classes are distinct.

Proof Idea:

In the proof of Theorem 9.6 (the uncomputability of the Haltingproblem), we have shown that the function HALT cannot be com-puted in any finite time. An examination of the proof shows that itgives something stronger. Namely, the proof shows that if we fix ourcomputational budget to be 𝑇 steps, then not only we can’t distinguishbetween programs that halt and those that do not, but cannot evendistinguish between programs that halt within at most 𝑇 â€Č steps andthose that take more than that (where 𝑇 â€Č is some number dependingon 𝑇 ). Therefore, the proof of Theorem 13.9 follows the ideas of the

Page 433: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 433

uncomputability of the halting problem, but again with a more carefulaccounting of the running time.⋆Proof of Theorem 13.9. Our proof is inspired by the proof of the un-computability of the halting problem. Specifically, for every function𝑇 as in the theorem’s statement, we define the Bounded Halting func-tion HALT𝑇 as follows. The input to HALT𝑇 is a pair (𝑃 , đ‘„) such that|𝑃 | ≀ log log |đ‘„| encodes some NAND-RAM program. We define

HALT𝑇 (𝑃 , đ‘„) = ⎧⎚⎩1, 𝑃 halts on đ‘„ within ≀ 100 ⋅ 𝑇 (|𝑃 | + |đ‘„|) steps0, otherwise.

(13.4)(The constant 100 and the function log log𝑛 are rather arbitrary, andare chosen for convenience in this proof.)

Theorem 13.9 is an immediate consequence of the following twoclaims:

Claim 1: HALT𝑇 ∈ TIME(𝑇 (𝑛) ⋅ log𝑛)andClaim 2: HALT𝑇 ∉ TIME(𝑇 (𝑛)).Please make sure you understand why indeed the theorem follows

directly from the combination of these two claims. We now turn toproving them.

Proof of claim 1: We can easily check in linear time whether aninput has the form 𝑃 , đ‘„ where |𝑃 | ≀ log log |đ‘„|. Since 𝑇 (⋅) is a nicefunction, we can evaluate it in 𝑂(𝑇 (𝑛)) time. Thus, we can computeHALT𝑇 (𝑃 , đ‘„) as follows:

1. Compute 𝑇0 = 𝑇 (|𝑃 | + |đ‘„|) in 𝑂(𝑇0) steps.

2. Use the universal NAND-RAM program of Theorem 13.7 to simu-late 100⋅𝑇0 steps of 𝑃 on the input đ‘„ using at most 𝑝𝑜𝑙𝑩(|𝑃 |)𝑇0 steps.(Recall that we use 𝑝𝑜𝑙𝑩(ℓ) to denote a quantity that is bounded by𝑎ℓ𝑏 for some constants 𝑎, 𝑏.)

3. If 𝑃 halts within these 100 ⋅ 𝑇0 steps then output 1, else output 0.The length of the input is 𝑛 = |𝑃 | + |đ‘„|. Since |đ‘„| ≀ 𝑛 and(log log |đ‘„|)𝑏 = 𝑜(log |đ‘„|) for every 𝑏, the running time will be𝑜(𝑇 (|𝑃 | + |đ‘„|) log𝑛) and hence the above algorithm demonstrates that

HALT𝑇 ∈ TIME(𝑇 (𝑛) ⋅ log𝑛), completing the proof of Claim 1.Proof of claim 2: This proof is the heart of Theorem 13.9, and is

very reminiscent of the proof that HALT is not computable. Assume,for the sake of contradiction, that there is some NAND-RAM program𝑃 ∗ that computes HALT𝑇 (𝑃 , đ‘„) within 𝑇 (|𝑃 | + |đ‘„|) steps. We are going

Page 434: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

434 introduction to theoretical computer science

to show a contradiction by creating a program 𝑄 and showing thatunder our assumptions, if 𝑄 runs for less than 𝑇 (𝑛) steps when given(a padded version of) its own code as input then it actually runs formore than 𝑇 (𝑛) steps and vice versa. (It is worth re-reading the lastsentence twice or thrice to make sure you understand this logic. It isvery similar to the direct proof of the uncomputability of the haltingproblem where we obtained a contradiction by using an assumed“halting solver” to construct a program that, given its own code asinput, halts if and only if it does not halt.)

We will define 𝑄∗ to be the program that on input a string 𝑧 doesthe following:

1. If 𝑧 does not have the form 𝑧 = 𝑃1𝑚 where 𝑃 represents a NAND-RAM program and |𝑃 | < 0.1 log log𝑚 then return 0. (Recall that1𝑚 denotes the string of 𝑚 ones.)

2. Compute 𝑏 = 𝑃 ∗(𝑃 , 𝑧) (at a cost of at most 𝑇 (|𝑃 | + |𝑧|) steps, underour assumptions).

3. If 𝑏 = 1 then 𝑄∗ goes into an infinite loop, otherwise it halts.

Let ℓ be the length description of 𝑄∗ as a string, and let 𝑚 be largerthan 221000ℓ . We will reach a contradiction by splitting into cases ac-cording to whether or not HALT𝑇 (𝑄∗, 𝑄∗1𝑚) equals 0 or 1.

On the one hand, if HALT𝑇 (𝑄∗, 𝑄∗1𝑚) = 1, then under our as-sumption that 𝑃 ∗ computes HALT𝑇 , 𝑄∗ will go into an infinite loopon input 𝑧 = 𝑄∗1𝑚, and hence in particular 𝑄∗ does not halt within100𝑇 (|𝑄∗| + 𝑚) steps on the input 𝑧. But this contradicts our assump-tion that HALT𝑇 (𝑄∗, 𝑄∗1𝑚) = 1.

This means that it must hold that HALT𝑇 (𝑄∗, 𝑄∗1𝑚) = 0. Butin this case, since we assume 𝑃 ∗ computes HALT𝑇 , 𝑄∗ does not doanything in phase 3 of its computation, and so the only computa-tion costs come in phases 1 and 2 of the computation. It is not hardto verify that Phase 1 can be done in linear and in fact less than 5|𝑧|steps. Phase 2 involves executing 𝑃 ∗, which under our assumptionrequires 𝑇 (|𝑄∗| + 𝑚) steps. In total we can perform both phases inless than 10𝑇 (|𝑄∗| + 𝑚) in steps, which by definition means thatHALT𝑇 (𝑄∗, 𝑄∗1𝑚) = 1, but this is of course a contradiction. Thiscompletes the proof of Claim 2 and hence of Theorem 13.9.

Solved Exercise 13.3 — P vs EXP. Prove that P ⊊ EXP.

Solution:

Page 435: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 435

Figure 13.8: Some complexity classes and some of thefunctions we know (or conjecture) to be contained inthem.

We show why this statement follows from the time hierarchytheorem, but it can be an instructive exercise to prove it directly,see Remark 13.10. We need to show that there exists đč ∈ EXP ⧔ P.Let 𝑇 (𝑛) = 𝑛log𝑛 and 𝑇 â€Č(𝑛) = 𝑛log𝑛/2. Both are nice functions.Since 𝑇 (𝑛)/𝑇 â€Č(𝑛) = 𝜔(log𝑛), by Theorem 13.9 there exists someđč in TIME(𝑇 â€Č(𝑛)) ⊊ TIME(𝑇 (𝑛)). Since for sufficiently large 𝑛,2𝑛 > 𝑛log𝑛, đč ∈ TIME(2𝑛) ⊆ EXP. On the other hand, đč ∉ P.Indeed, suppose otherwise that there was a constant 𝑐 > 0 anda Turing Machine computing đč on 𝑛-length input in at most 𝑛𝑐steps for all sufficiently large 𝑛. Then since for 𝑛 large enough𝑛𝑐 < 𝑛log𝑛/2, it would have followed that đč ∈ TIME(𝑛log𝑛/2)contradicting our choice of đč .

The time hierarchy theorem tells us that there are functions we cancompute in 𝑂(𝑛2) time but not 𝑂(𝑛), in 2𝑛 time, but not 2√𝑛, etc.. Inparticular there are most definitely functions that we can compute intime 2𝑛 but not 𝑂(𝑛). We have seen that we have no shortage of natu-ral functions for which the best known algorithm requires roughly 2𝑛time, and that many people have invested significant effort in tryingto improve that. However, unlike in the finite vs. infinite case, for allof the examples above at the moment we do not know how to ruleout even an 𝑂(𝑛) time algorithm. We will however see that there is asingle unproven conjecture that would imply such a result for most ofthese problems.

The time hierarchy theorem relies on the existence of an efficientuniversal NAND-RAM program, as proven in Theorem 13.7. Forother models such as Turing Machines we have similar time hierarchyresults showing that there are functions computable in time 𝑇 (𝑛) andnot in time 𝑇 (𝑛)/𝑓(𝑛) where 𝑓(𝑛) corresponds to the overhead in thecorresponding universal machine.

13.6 NON UNIFORM COMPUTATION

We have now seen two measures of “computation cost” for functions.In Section 4.6 we defined the complexity of computing finite functionsusing circuits / straightline programs. Specifically, for a finite function𝑔 ∶ 0, 1𝑛 → 0, 1 and number 𝑇 ∈ ℕ, 𝑔 ∈ SIZE(𝑇 ) if there is a circuitof at most 𝑇 NAND gates (or equivalently a 𝑇 -line NAND-CIRCprogram) that computes 𝑔. To relate this to the classes TIME(𝑇 (𝑛))defined in this chapter we first need to extend the class SIZE(𝑇 (𝑛))from finite functions to functions with unbounded input length.

Definition 13.11 — Non uniform computation. Let đč ∶ 0, 1∗ → 0, 1and 𝑇 ∶ ℕ → ℕ be a nice time bound. For every 𝑛 ∈ ℕ, define

Page 436: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

436 introduction to theoretical computer science

Figure 13.9: We can think of an infinite functionđč ∶ 0, 1∗ → 0, 1 as a collection of finite functionsđč0, đč1, đč2, 
 where đč𝑛 ∶ 0, 1𝑛 → 0, 1 is therestriction of đč to inputs of length 𝑛. We say đč is inP/poly if for every 𝑛, the function đč𝑛 is computableby a polynomial size NAND-CIRC program, orequivalently, a polynomial sized Boolean circuit.

đč𝑛 ∶ 0, 1𝑛 → 0, 1 to be the restriction of đč to inputs of size 𝑛.That is, đč𝑛 is the function mapping 0, 1𝑛 to 0, 1 such that forevery đ‘„ ∈ 0, 1𝑛, đč𝑛(đ‘„) = đč(đ‘„).

We say that đč is non-uniformly computable in at most 𝑇 (𝑛) size, de-noted by đč ∈ SIZE(𝑇 (𝑛)) if there exists a sequence (đ¶0, đ¶1, đ¶2, 
)of NAND circuits such that:

‱ For every 𝑛 ∈ ℕ, đ¶đ‘› computes the function đč𝑛‱ For every sufficiently large 𝑛, đ¶đ‘› has at most 𝑇 (𝑛) gates.

The non uniform analog to the class P is the class P/poly defined as

P/poly = âˆȘ𝑐∈ℕSIZE(𝑛𝑐) . (13.5)There is a big difference between non uniform computation and uni-form complexity classes such as TIME(𝑇 (𝑛)) or P. The conditionđč ∈ P means that there is a single Turing machine 𝑀 that computesđč on all inputs in polynomial time. The condition đč ∈ P/poly onlymeans that for every input length 𝑛 there can be a different circuit đ¶đ‘›that computes đč using polynomially many gates on inputs of theselengths. As we will see, đč ∈ P/poly does not necessarily imply thatđč ∈ P. However, the other direction is true:

Theorem 13.12 — Nonuniform computation contains uniform computa-

tion. There is some 𝑎 ∈ ℕ s.t. for every nice 𝑇 ∶ ℕ → ℕ andđč ∶ 0, 1∗ → 0, 1,TIME(𝑇 (𝑛)) ⊆ SIZE(𝑇 (𝑛)𝑎) . (13.6)

In particular, Theorem 13.12 shows that for every 𝑐, TIME(𝑛𝑐) ⊆SIZE(𝑛𝑐𝑎) and hence P ⊆ P/poly.Proof Idea:

The idea behind the proof is to “unroll the loop”. Specifically, wewill use the programming language variants of non-uniform and uni-form computation: namely NAND-CIRC and NAND-TM. The maindifference between the two is that NAND-TM has loops. However, forevery fixed 𝑛, if we know that a NAND-TM program runs in at most𝑇 (𝑛) steps, then we can replace its loop by simply “copying and past-ing” its code 𝑇 (𝑛) times, similar to how in Python we can replace codesuch as

for i in range(4):print(i)

with the “loop free” code

Page 437: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 437

print(0)print(1)print(2)print(3)

To make this idea into an actual proof we need to tackle one tech-nical difficulty, and this is to ensure that the NAND-TM program isoblivious in the sense that the value of the index variable i in the 𝑗-thiteration of the loop will depend only on 𝑗 and not on the contents ofthe input. We make a digression to do just that in Section 13.6.1 andthen complete the proof of Theorem 13.12.⋆13.6.1 Oblivious NAND-TM programsOur approach for proving Theorem 13.12 involves “unrolling theloop”. For example, consider the following NAND-TM to compute theXOR function on inputs of arbitrary length:

temp_0 = NAND(X[0],X[0])Y_nonblank[0] = NAND(X[0],temp_0)temp_2 = NAND(X[i],Y[0])temp_3 = NAND(X[i],temp_2)temp_4 = NAND(Y[0],temp_2)Y[0] = NAND(temp_3,temp_4)MODANDJUMP(X_nonblank[i],X_nonblank[i])

Setting (as an example) 𝑛 = 3, we can attempt to translate thisNAND-TM program into a NAND-CIRC program for computingXOR3 ∶ 0, 13 → 0, 1 by simply “copying and pasting” the loopthree times (dropping the MODANDJMP line):

temp_0 = NAND(X[0],X[0])Y_nonblank[0] = NAND(X[0],temp_0)temp_2 = NAND(X[i],Y[0])temp_3 = NAND(X[i],temp_2)temp_4 = NAND(Y[0],temp_2)Y[0] = NAND(temp_3,temp_4)temp_0 = NAND(X[0],X[0])Y_nonblank[0] = NAND(X[0],temp_0)temp_2 = NAND(X[i],Y[0])temp_3 = NAND(X[i],temp_2)temp_4 = NAND(Y[0],temp_2)Y[0] = NAND(temp_3,temp_4)temp_0 = NAND(X[0],X[0])Y_nonblank[0] = NAND(X[0],temp_0)

Page 438: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

438 introduction to theoretical computer science

Figure 13.10: A NAND circuit for XOR3 obtained by“unrolling the loop” of the NAND-TM program forcomputing XOR three times.

temp_2 = NAND(X[i],Y[0])temp_3 = NAND(X[i],temp_2)temp_4 = NAND(Y[0],temp_2)Y[0] = NAND(temp_3,temp_4)

However, the above is still not a valid NAND-CIRC program sinceit contains references to the special variable i. To make it into a validNAND-CIRC program, we replace references to i in the first iterationwith 0, references in the second iteration with 1, and references in thethird iteration with 2. (We also create a variable zero and use it for thefirst time any variable is instantiated, as well as remove assignments tonon-output variables that are never used later on.) The resulting pro-gram is a standard “loop free and index free” NAND-CIRC programthat computes XOR3 (see also Fig. 13.10):

temp_0 = NAND(X[0],X[0])one = NAND(X[0],temp_0)zero = NAND(one,one)temp_2 = NAND(X[0],zero)temp_3 = NAND(X[0],temp_2)temp_4 = NAND(zero,temp_2)Y[0] = NAND(temp_3,temp_4)temp_2 = NAND(X[1],Y[0])temp_3 = NAND(X[1],temp_2)temp_4 = NAND(Y[0],temp_2)Y[0] = NAND(temp_3,temp_4)temp_2 = NAND(X[2],Y[0])temp_3 = NAND(X[2],temp_2)temp_4 = NAND(Y[0],temp_2)Y[0] = NAND(temp_3,temp_4)

Key to this transformation was the fact that in our original NAND-TM program for XOR, regardless of whether the input is 011, 100, orany other string, the index variable i is guaranteed to equal 0 in thefirst iteration, 1 in the second iteration, 2 in the third iteration, and soon and so forth. The particular sequence 0, 1, 2, 
 is immaterial: thecrucial property is that the NAND-TM program for XOR is obliviousin the sense that the value of the index i in the 𝑗-th iteration dependsonly on 𝑗 and does not depend on the particular choice of the input.Luckily, it is possible to transform every NAND-TM program intoa functionally equivalent oblivious program with at most quadraticoverhead. (Similarly we can transform any Turing machine into afunctionally equivalent oblivious Turing machine, see Exercise 13.6.)

Page 439: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 439

Figure 13.11: We simulate a 𝑇 (𝑛)-time NAND-TMprogram 𝑃 â€Č with an oblivious NAND-TM program 𝑃by adding special arrays Atstart and Atend to markpositions 0 and 𝑇 − 1 respectively. The program 𝑃will simply “sweep” its arrays from right to left andback again. If the original program 𝑃 â€Č would havemoved i in a different direction then we wait 𝑂(𝑇 )steps until we reach the same point back again, and so𝑃 runs in 𝑂(𝑇 (𝑛)2) time.

Theorem 13.13 — Making NAND-TM oblivious. Let 𝑇 ∶ ℕ → ℕ be a nicefunction and let đč ∈ TIMETM(𝑇 (𝑛)). Then there is a NAND-TMprogram 𝑃 that computes đč in 𝑂(𝑇 (𝑛)2) steps and satisfying thefollowing. For every 𝑛 ∈ ℕ there is a sequence 𝑖0, 𝑖1, 
 , 𝑖𝑚−1 suchthat for every đ‘„ ∈ 0, 1𝑛, if 𝑃 is executed on input đ‘„ then in the𝑗-th iteration the variable i is equal to 𝑖𝑗.In other words, Theorem 13.13 implies that if we can compute đč in𝑇 (𝑛) steps, then we can compute it in 𝑂(𝑇 (𝑛)2) steps with a program𝑃 in which the position of i in the 𝑗-th iteration depends only on 𝑗

and the length of the input, and not on the contents of the input. Sucha program can be easily translated into a NAND-CIRC program of𝑂(𝑇 (𝑛)2) lines by “unrolling the loop”.Proof Idea:

We can translate any NAND-TM program 𝑃 â€Č into an obliviousprogram 𝑃 by making 𝑃 “sweep” its arrays. That is, the index i in𝑃 will always move all the way from position 0 to position 𝑇 (𝑛) − 1and back again. We can then simulate the program 𝑃 â€Č with at most𝑇 (𝑛) overhead: if 𝑃 â€Č wants to move i left when we are in a rightwardsweep then we simply wait the at most 2𝑇 (𝑛) steps until the next timewe are back in the same position while sweeping to the left.⋆Proof of Theorem 13.13. Let 𝑃 â€Č be a NAND-TM program computing đčin 𝑇 (𝑛) steps. We construct an oblivious NAND-TM program 𝑃 forcomputing đč as follows (see also Fig. 13.11).

1. On input đ‘„, 𝑃 will compute 𝑇 = 𝑇 (|đ‘„|) and set up arrays Atstartand Atend satisfying Atstart[0]= 1 and Atstart[𝑖]= 0 for 𝑖 > 0and Atend[𝑇 − 1]= 1 and Atend[i]= 0 for all 𝑖 ≠ 𝑇 − 1. We can dothis because 𝑇 is a nice function. Note that since this computationdoes not depend on đ‘„ but only on its length, it is oblivious.

2. 𝑃 will also have a special array Marker initialized to all zeroes.

3. The index variable of 𝑃 will change direction of movement tothe right whenever Atstart[i]= 1 and to the left wheneverAtend[i]= 1.

4. The program 𝑃 simulates the execution of 𝑃 â€Č. However, if theMODANDJMP instruction in 𝑃 â€Č attempts to move to the right when 𝑃is moving left (or vice versa) then 𝑃 will set Marker[i] to 1 andenter into a special “waiting mode”. In this mode 𝑃 will wait untilthe next time in which Marker[i]= 1 (at the next sweep) at whichpoints 𝑃 zeroes Marker[i] and continues with the simulation. In

Page 440: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

440 introduction to theoretical computer science

Figure 13.12: The function UNROLL takes as input aTuring Machine 𝑀 , an input length parameter 𝑛, astep budget parameter 𝑇 , and outputs a circuit đ¶ ofsize 𝑝𝑜𝑙𝑩(𝑇 ) that takes 𝑛 bits of inputs and outputs𝑀(đ‘„) if 𝑀 halts on đ‘„ within at most 𝑇 steps.

the worst case this will take 2𝑇 (𝑛) steps (if 𝑃 has to go all the wayfrom one end to the other and back again.)

5. We also modify 𝑃 to ensure it ends the computation after simu-lating exactly 𝑇 (𝑛) steps of 𝑃 â€Č, adding “dummy steps” if 𝑃 â€Č endsearly.

We see that 𝑃 simulates the execution of 𝑃 â€Č with an overhead of𝑂(𝑇 (𝑛)) steps of 𝑃 per one step of 𝑃 â€Č, hence completing the proof.

Theorem 13.13 implies Theorem 13.12. Indeed, if 𝑃 is a 𝑘-line obliv-ious NAND-TM program computing đč in time 𝑇 (𝑛) then for every 𝑛we can obtain a NAND-CIRC program of (𝑘 − 1) ⋅ 𝑇 (𝑛) lines by simplymaking 𝑇 (𝑛) copies of 𝑃 (dropping the final MODANDJMP line). In the𝑗-th copy we replace all references of the form Foo[i] to foo_𝑖𝑗 where𝑖𝑗 is the value of i in the 𝑗-th iteration.

13.6.2 “Unrolling the loop”: algorithmic transformation of Turing Machinesto circuits

The proof of Theorem 13.12 is algorithmic, in the sense that the proofyields a polynomial-time algorithm that given a Turing Machine 𝑀and parameters 𝑇 and 𝑛, produces a circuit of 𝑂(𝑇 2) gates that agreeswith 𝑀 on all inputs đ‘„ ∈ 0, 1𝑛 (as long as 𝑀 runs for less than 𝑇steps these inputs.) We record this fact in the following theorem, sinceit will be useful for us later on:

Theorem 13.14 — Turing-machine to circuit compiler. There is algorithmUNROLL such that for every Turing Machine 𝑀 and numbers 𝑛, 𝑇 ,UNROLL(𝑀, 1𝑇 , 1𝑛) runs for 𝑝𝑜𝑙𝑩(|𝑀|, 𝑇 , 𝑛) steps and outputs aNAND circuit đ¶ with 𝑛 inputs, 𝑂(𝑇 2) gates, and one output, suchthat đ¶(đ‘„) = âŽ§âŽšâŽ©đ‘Š 𝑀 halts in ≀ 𝑇 steps and outputs 𝑩0 otherwise

. (13.7)

Proof. We only sketch the proof since it follows by directly translat-ing the proof of Theorem 13.12 into an algorithm together with thesimulation of Turing machines by NAND-TM programs (see alsoFig. 13.13). Specifically, UNROLL does the following:

1. Transform the Turing Machine 𝑀 into an equivalent NAND-TMprogram 𝑃 .

2. Transform the NAND-TM program 𝑃 into an equivalent obliviousprogram 𝑃 â€Č following the proof of Theorem 13.13. The program 𝑃 â€Čtakes 𝑇 â€Č = 𝑂(𝑇 2) steps to simulate 𝑇 steps of 𝑃 .

Page 441: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 441

3. “Unroll the loop” of 𝑃 â€Č by obtaining a NAND-CIRC program of𝑂(𝑇 â€Č) lines (or equivalently a NAND circuit with 𝑂(𝑇 2) gates)corresponding to the execution of 𝑇 â€Č iterations of 𝑃 â€Č.

Figure 13.13: We can transform a Turing Machine 𝑀 ,input length parameter 𝑛, and time bound 𝑇 into an𝑂(𝑇 2) sized NAND circuit that agrees with 𝑀 on allinputs đ‘„ ∈ 0, 1𝑛 on which 𝑀 halts in at most 𝑇steps. The transformation is obtained by first usingthe equivalence of Turing Machines and NAND-TM programs 𝑃 , then turning 𝑃 into an equivalentoblivious NAND-TM program 𝑃 â€Č via Theorem 13.13,then “unrolling” 𝑂(𝑇 2) iterations of the loop of𝑃 â€Č to obtain an 𝑂(𝑇 2) line NAND-CIRC programthat agrees with 𝑃 â€Č on length 𝑛 inputs, and finallytranslating this program into an equivalent circuit.

Big Idea 20 By “unrolling the loop” we can transform an al-gorithm that takes 𝑇 (𝑛) steps to compute đč into a circuit that uses𝑝𝑜𝑙𝑩(𝑇 (𝑛)) gates to compute the restriction of đč to 0, 1𝑛.

PReviewing the transformations described in Fig. 13.13,as well as solving the following two exercises is a greatway to get more comfort with non-uniform complexityand in particular with P/poly and its relation to P.

Solved Exercise 13.4 — Alternative characterization of P. Prove that for everyđč ∶ 0, 1∗ → 0, 1, đč ∈ P if and only if there is a polynomial-time Turing Machine 𝑀 such that for every 𝑛 ∈ ℕ, 𝑀(1𝑛) outputs adescription of an 𝑛 input circuit đ¶đ‘› that computes the restriction đč𝑛of đč to inputs in 0, 1𝑛.

Solution:

We start with the “if” direction. Suppose that there is a polynomial-time Turing Machine 𝑀 that on input 1𝑛 outputs a circuit đ¶đ‘› that

Page 442: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

442 introduction to theoretical computer science

computes đč𝑛. Then the following is a polynomial-time TuringMachine 𝑀 â€Č to compute đč . On input đ‘„ ∈ 0, 1∗, 𝑀 â€Č will:

1. Let 𝑛 = |đ‘„| and compute đ¶đ‘› = 𝑀(1𝑛).2. Return the evaluation of đ¶đ‘› on đ‘„.

Since we can evaluate a Boolean circuit on an input in poly-nomial time, 𝑀 â€Č runs in polynomial time and computes đč(đ‘„) onevery input đ‘„.

For the “only if” direction, if 𝑀 â€Č is a Turing Machine that com-putes đč in polynomial-time, then (applying the equivalence of Tur-ing Machines and NAND-TM as well as Theorem 13.13) there isalso an oblivious NAND-TM program 𝑃 that computes đč in time𝑝(𝑛) for some polynomial 𝑝. We can now define 𝑀 to be the TuringMachine that on input 1𝑛 outputs the NAND circuit obtained by“unrolling the loop” of 𝑃 for 𝑝(𝑛) iterations. The resulting NANDcircuit computes đč𝑛 and has 𝑂(𝑝(𝑛)) gates. It can also be trans-formed to a Boolean circuit with 𝑂(𝑝(𝑛)) AND/OR/NOT gates.

Solved Exercise 13.5 — P/poly characterization by advice. Let đč ∶ 0, 1∗ →0, 1. Then đč ∈ P/poly if and only if there exists a polynomial 𝑝 ∶ ℕ →ℕ, a polynomial-time Turing Machine 𝑀 and a sequence 𝑎𝑛𝑛∈ℕ ofstrings, such that for every 𝑛 ∈ ℕ:

‱ |𝑎𝑛| ≀ 𝑝(𝑛)‱ For every đ‘„ ∈ 0, 1𝑛, 𝑀(𝑎𝑛, đ‘„) = đč(đ‘„).

Solution:

We only sketch the proof. For the “only if” direction, if đč ∈P/poly then we can use for 𝑎𝑛 simply the description of the cor-responding circuit đ¶đ‘› and for 𝑀 the program that computes inpolynomial time the evaluation of a circuit on its input.

For the “if” direction, we can use the same “unrolling the loop”technique of Theorem 13.12 to show that if 𝑃 is a polynomial-timeNAND-TM program, then for every 𝑛 ∈ ℕ, the map đ‘„ ↩ 𝑃(𝑎𝑛, đ‘„)can be computed by a polynomial size NAND-CIRC program 𝑄𝑛.

13.6.3 Can uniform algorithms simulate non uniform ones?Theorem 13.12 shows that every function in TIME(𝑇 (𝑛)) is inSIZE(𝑝𝑜𝑙𝑩(𝑇 (𝑛))). One can ask if there is an inverse relation. Supposethat đč is such that đč𝑛 has a “short” NAND-CIRC program for every𝑛. Can we say that it must be in TIME(𝑇 (𝑛)) for some “small” 𝑇 ? The

Page 443: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 443

answer is an emphatic no. Not only is P/poly not contained in P, in factP/poly contains functions that are uncomputable!

Theorem 13.15 — P/poly contains uncomputable functions. There exists anuncomputable function đč ∶ 0, 1∗ → 0, 1 such that đč ∈ P/poly.

Proof Idea:

Since P/poly corresponds to non uniform computation, a functionđč is in P/poly if for every 𝑛 ∈ ℕ, the restriction đč𝑛 to inputs of length𝑛 has a small circuit/program, even if the circuits for different valuesof 𝑛 are completely different from one another. In particular, if đč hasthe property that for every equal-length inputs đ‘„ and đ‘„â€Č, đč(đ‘„) =đč(đ‘„â€Č) then this means that đč𝑛 is either the constant function zeroor the constant function one for every 𝑛 ∈ ℕ. Since the constantfunction has a (very!) small circuit, such a function đč will alwaysbe in P/poly (indeed even in smaller classes). Yet by a reduction fromthe Halting problem, we can obtain a function with this property thatis uncomputable.⋆Proof of Theorem 13.15. Consider the following “unary halting func-tion” UH ∶ 0, 1∗ → 0, 1 defined as follows. We let 𝑆 ∶ ℕ → 0, 1∗be the function that on input 𝑛 ∈ ℕ, outputs the string that corre-sponds to the binary representation of the number 𝑛 without the mostsignificant 1 digit. Note that 𝑆 is onto. For every đ‘„ ∈ 0, 1, we de-fine UH(đ‘„) = HALTONZERO(𝑆(|đ‘„|)). That is, if 𝑛 is the length of đ‘„,then UH(đ‘„) = 1 if and only if the string 𝑆(𝑛) encodes a NAND-TMprogram that halts on the input 0.

UH is uncomputable, since otherwise we could computeHALTONZERO by transforming the input program 𝑃 into the integer𝑛 such that 𝑃 = 𝑆(𝑛) and then running UH(1𝑛) (i.e., UH on the stringof 𝑛 ones). On the other hand, for every 𝑛, UH𝑛(đ‘„) is either equalto 0 for all inputs đ‘„ or equal to 1 on all inputs đ‘„, and hence can becomputed by a NAND-CIRC program of a constant number of lines.

The issue here is of course uniformity. For a function đč ∶ 0, 1∗ →0, 1, if đč is in TIME(𝑇 (𝑛)) then we have a single algorithm thatcan compute đč𝑛 for every 𝑛. On the other hand, đč𝑛 might be inSIZE(𝑇 (𝑛)) for every 𝑛 using a completely different algorithm for ev-ery input length. For this reason we typically use P/poly not as a modelof efficient computation but rather as a way to model inefficient compu-tation. For example, in cryptography people often define an encryp-tion scheme to be secure if breaking it for a key of length 𝑛 requires

Page 444: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

444 introduction to theoretical computer science

more than a polynomial number of NAND lines. Since P ⊆ P/poly,this in particular precludes a polynomial time algorithm for doing so,but there are technical reasons why working in a non uniform modelmakes more sense in cryptography. It also allows to talk about se-curity in non asymptotic terms such as a scheme having “128 bits ofsecurity”.

While it can sometimes be a real issue, in many natural settings thedifference between uniform and non-uniform computation does notseem so important. In particular, in all the examples of problems notknown to be in P we discussed before: longest path, 3SAT, factoring,etc., these problems are also not known to be in P/poly either. Thus,for “natural” functions, if you pretend that TIME(𝑇 (𝑛)) is roughly thesame as SIZE(𝑇 (𝑛)), you will be right more often than wrong.

Figure 13.14: Relations between P, EXP, and P/poly. Itis known that P ⊆ EXP, P ⊆ P/poly and that P/polycontains uncomputable functions (which in particularare outside of EXP). It is not known whether or notEXP ⊆ P/poly though it is believed that EXP ⊈ P/poly.

13.6.4 Uniform vs. Nonuniform computation: A recapTo summarize, the two models of computation we have described sofar are:‱ Uniform models: Turing machines, NAND-TM programs, RAM ma-

chines, NAND-RAM programs, C/JavaScript/Python, etc. These mod-els include loops and unbounded memory hence a single programcan compute a function with unbounded input length.

‱ Non-uniform models: Boolean Circuits or straightline programs haveno loops and can only compute finite functions. The time to executethem is exactly the number of lines or gates they contain.For a function đč ∶ 0, 1∗ → 0, 1 and some nice time bound𝑇 ∶ ℕ → ℕ, we know that:

‱ If đč is uniformly computable in time 𝑇 (𝑛) then there is a sequenceof circuits đ¶1, đ¶2, 
 where đ¶đ‘› has 𝑝𝑜𝑙𝑩(𝑇 (𝑛)) gates and computesđč𝑛 (i.e., restriction of đč to 0, 1𝑛) for every 𝑛.

‱ The reverse direction is not necessarily true - there are examples offunctions đč ∶ 0, 1𝑛 → 0, 1 such that đč𝑛 can be computed byeven a constant size circuit but đč is uncomputable.

Page 445: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 445

This means that non uniform complexity is more useful to establishhardness of a function than its easiness.

Chapter Recap

‱ We can define the time complexity of a functionusing NAND-TM programs, and similarly to thenotion of computability, this appears to capture theinherent complexity of the function.

‱ There are many natural problems that havepolynomial-time algorithms, and other naturalproblems that we’d love to solve, but for which thebest known algorithms are exponential.

‱ The definition of polynomial time, and hence theclass P, is robust to the choice of model, whetherit is Turing machines, NAND-TM, NAND-RAM,modern programming languages, and many othermodels.

‱ The time hierarchy theorem shows that there aresome problems that can be solved in exponential,but not in polynomial time. However, we do notknow if that is the case for the natural examplesthat we described in this lecture.

‱ By “unrolling the loop” we can show that everyfunction computable in time 𝑇 (𝑛) can be computedby a sequence of NAND-CIRC programs (one forevery input length) each of size at most 𝑝𝑜𝑙𝑩(𝑇 (𝑛))

13.7 EXERCISES

Exercise 13.1 — Equivalence of different definitions of P and EXP.. Provethat the classes P and EXP defined in Definition 13.2 are equal toâˆȘ𝑐∈1,2,3,
TIME(𝑛𝑐) and âˆȘ𝑐∈1,2,3,
TIME(2𝑛𝑐) respectively. (If𝑆1, 𝑆2, 𝑆3, 
 is a collection of sets then the set 𝑆 = âˆȘ𝑐∈1,2,3,
𝑆𝑐 isthe set of all elements 𝑒 such that there exists some 𝑐 ∈ 1, 2, 3, 
where 𝑒 ∈ 𝑆𝑐.)

Exercise 13.2 — Robustness to representation. Theorem 13.5 shows that theclasses P and EXP are robust with respect to variations in the choiceof the computational model. This exercise shows that these classesare also robust with respect to our choice of the representation of theinput.

Specifically, let đč be a function mapping graphs to 0, 1, and letđč â€Č, đč ″ ∶ 0, 1∗ → 0, 1 be the functions defined as follows. For everyđ‘„ ∈ 0, 1∗:

Page 446: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

446 introduction to theoretical computer science

1 Hint: This is the Turing Machine analog of Theo-rem 13.13. We replace one step of the original TM 𝑀â€Čcomputing đč with a “sweep” of the obliviouss TM 𝑀in which it goes 𝑇 steps to the right and then 𝑇 stepsto the left.

‱ đč â€Č(đ‘„) = 1 iff đ‘„ represents a graph đș via the adjacency matrixrepresentation such that đč(đș) = 1.

‱ đč ″(đ‘„) = 1 iff đ‘„ represents a graph đș via the adjacency list represen-tation such that đč(đș) = 1.Prove that đč â€Č ∈ P iff đč ″ ∈ P.More generally, for every function đč ∶ 0, 1∗ → 0, 1, the answer

to the question of whether đč ∈ P (or whether đč ∈ EXP) is unchangedby switching representations, as long as transforming one represen-tation to the other can be done in polynomial time (which essentiallyholds for all reasonable representations).

Exercise 13.3 — Boolean functions. For every function đč ∶ 0, 1∗ → 0, 1∗,define đ”đ‘œđ‘œđ‘™(đč) to be the function mapping 0, 1∗ to 0, 1 such thaton input a (string representation of a) triple (đ‘„, 𝑖, 𝜎) with đ‘„ ∈ 0, 1∗,𝑖 ∈ ℕ and 𝜎 ∈ 0, 1,

đ”đ‘œđ‘œđ‘™(đč)(đ‘„, 𝑖, 𝜎) = ⎧⎚⎩đč(đ‘„)𝑖 𝜎 = 0, 𝑖 < |đč(đ‘„)|1 𝜎 = 1, 𝑖 < |đč(đ‘„)|0 otherwise

(13.8)

where đč(đ‘„)𝑖 is the 𝑖-th bit of the string đč(đ‘„).Prove that đč ∈ P if and only if đ”đ‘œđ‘œđ‘™(đč) ∈ P.

Exercise 13.4 — Composition of polynomial time. Prove that ifđč, đș ∶ 0, 1∗ → 0, 1∗ are in P then their composition đč ∘ đș,which is the function đ» s.t. đ»(đ‘„) = đč(đș(đ‘„)), is also in P.

Exercise 13.5 — Non composition of exponential time. Prove that there is someđč, đș ∶ 0, 1∗ → 0, 1∗ s.t. đč, đș ∈ EXP but đč ∘ đș is not in EXP.

Exercise 13.6 — Oblivious Turing Machines. We say that a Turing machine 𝑀is oblivious if there is some function 𝑇 ∶ ℕ × ℕ → â„€ such that for everyinput đ‘„ of length 𝑛, and 𝑡 ∈ ℕ it holds that:

‱ If 𝑀 takes more than 𝑡 steps to halt on the input đ‘„, then in the 𝑡-th step 𝑀 ’s head will be in the position 𝑇 (𝑛, 𝑡). (Note that thisposition depends only on the length of đ‘„ and not its contents.)

‱ If 𝑀 halts before the 𝑡-th step then 𝑇 (𝑛, 𝑡) = −1.Prove that if đč ∈ P then there exists an oblivious Turing machine 𝑀

that computes đč in polynomial time. See footnote for hint.1

Page 447: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 447

Exercise 13.7 Let EDGE ∶ 0, 1∗ → 0, 1 be the function such that oninput a string representing a triple (𝐿, 𝑖, 𝑗), where 𝐿 is the adjacencylist representation of an 𝑛 vertex graph đș, and 𝑖 and 𝑗 are numbers in[𝑛], EDGE(𝐿, 𝑖, 𝑗) = 1 if the edge 𝑖, 𝑗 is present in the graph. EDGEoutputs 0 on all other inputs.

1. Prove that EDGE ∈ P.

2. Let PLANARMATRIX ∶ 0, 1∗ → 0, 1 be the function thaton input an adjacency matrix 𝐮 outputs 1 if and only if the graphrepresented by 𝐮 is planar (that is, can be drawn on the plane with-out edges crossing one another). For this question, you can usewithout proof the fact that PLANARMATRIX ∈ P. Prove thatPLANARLIST ∈ P where PLANARLIST ∶ 0, 1∗ → 0, 1 is thefunction that on input an adjacency list 𝐿 outputs 1 if and only if 𝐿represents a planar graph.

Exercise 13.8 — Evaluate NAND circuits. Let NANDEVAL ∶ 0, 1∗ →0, 1 be the function such that for every string representing a pair(𝑄, đ‘„) where 𝑄 is an 𝑛-input 1-output NAND-CIRC (not NAND-TM!)program and đ‘„ ∈ 0, 1𝑛, NANDEVAL(𝑄, đ‘„) = 𝑄(đ‘„). On all otherinputs NANDEVAL outputs 0.

Prove that NANDEVAL ∈ P.

Exercise 13.9 — Find hard function. Let NANDHARD ∶ 0, 1∗ → 0, 1be the function such that on input a string representing a pair (𝑓, 𝑠)where

‱ 𝑓 ∈ 0, 12𝑛 for some 𝑛 ∈ ℕ‱ 𝑠 ∈ ℕ

NANDHARD(𝑓, 𝑠) = 1 if there is no NAND-CIRC program 𝑄of at most 𝑠 lines that computes the function đč ∶ 0, 1𝑛 → 0, 1whose truth table is the string 𝑓 . That is, NANDHARD(𝑓, 𝑠) = 1if for every NAND-CIRC program 𝑄 of at most 𝑠 lines, there existssome đ‘„ ∈ 0, 1𝑛 such that 𝑄(đ‘„) ≠ đ‘“đ‘„ where đ‘“đ‘„ denote the đ‘„-thecoordinate of 𝑓 , using the binary representation to identify 0, 1𝑛with the numbers 0, 
 , 2𝑛 − 1.1. Prove that NANDHARD ∈ EXP.

2. (Challenge) Prove that there is an algorithm FINDHARD suchthat if 𝑛 is sufficiently large, then FINDHARD(1𝑛) runs in time22𝑂(𝑛) and outputs a string 𝑓 ∈ 0, 12𝑛 that is the truth table ofa function that is not contained in SIZE(2𝑛/(1000𝑛)). (In other

Page 448: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

448 introduction to theoretical computer science

2 Hint: Use Item 1, the existence of functions requir-ing exponentially hard NAND programs, and the factthat there are only finitely many functions mapping0, 1𝑛 to 0, 1.

words, if 𝑓 is the string output by FINDHARD(1𝑛) then if we letđč ∶ 0, 1𝑛 → 0, 1 be the function such that đč(đ‘„) outputs the đ‘„-thcoordinate of 𝑓 , then đč ∉ SIZE(2𝑛/(1000𝑛)).2

Exercise 13.10 Suppose that you are in charge of scheduling courses incomputer science in University X. In University X, computer sciencestudents wake up late, and have to work on their startups in the af-ternoon, and take long weekends with their investors. So you onlyhave two possible slots: you can schedule a course either Monday-Wednesday 11am-1pm or Tuesday-Thursday 11am-1pm.

Let SCHEDULE ∶ 0, 1∗ → 0, 1 be the function that takes as inputa list of courses 𝐿 and a list of conflicts đ¶ (i.e., list of pairs of coursesthat cannot share the same time slot) and outputs 1 if and only if thereis a “conflict free” scheduling of the courses in 𝐿, where no pair in đ¶ isscheduled in the same time slot.

More precisely, the list 𝐿 is a list of strings (𝑐0, 
 , 𝑐𝑛−1) and the listđ¶ is a list of pairs of the form (𝑐𝑖, 𝑐𝑗). SCHEDULE(𝐿, đ¶) = 1 if andonly if there exists a partition of 𝑐0, 
 , 𝑐𝑛−1 into two parts so that thereis no pair (𝑐𝑖, 𝑐𝑗) ∈ đ¶ such that both 𝑐𝑖 and 𝑐𝑗 are in the same part.

Prove that SCHEDULE ∈ P. As usual, you do not have to providethe full code to show that this is the case, and can describe operationsas a high level, as well as appeal to any data structures or other resultsmentioned in the book or in lecture. Note that to show that a functionđč is in P you need to both (1) present an algorithm 𝐮 that computesđč in polynomial time, (2) prove that 𝐮 does indeed run in polynomialtime, and does indeed compute the correct answer.

Try to think whether or not your algorithm extends to the casewhere there are three possible time slots.

13.8 BIBLIOGRAPHICAL NOTES

Because we are interested in the maximum number of steps for inputsof a given length, running-time as we defined it is often known asworst case complexity. The minimum number of steps (or “best case”complexity) to compute a function on length 𝑛 inputs is typically nota meaningful quantity since essentially every natural problem willhave some trivially easy instances. However, the average case complexity(i.e., complexity on a “typical” or “random” input) is an interestingconcept which we’ll return to when we discuss cryptography. Thatsaid, worst-case complexity is the most standard and basic of thecomplexity measures, and will be our focus in most of this book.

Some lower bounds for single-tape Turing machines are given in[Maa85].

Page 449: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling running time 449

For defining efficiency in the 𝜆 calculus, one needs to be carefulabout the order of application of the reduction steps, which can matterfor computational efficiency, see for example this paper.

The notation P/poly is used for historical reasons. It was introducedby Karp and Lipton, who considered this class as corresponding tofunctions that can be computed by polynomial-time Turing Machinesthat are given for any input length 𝑛 an advice string of length polyno-mial in 𝑛.

Page 450: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 451: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

14Polynomial-time reductions

Consider some of the problems we have encountered in Chapter 12:

1. The 3SAT problem: deciding whether a given 3CNF formula has asatisfying assignment.

2. Finding the longest path in a graph.

3. Finding the maximum cut in a graph.

4. Solving quadratic equations over 𝑛 variables đ‘„0, 
 , đ‘„đ‘›âˆ’1 ∈ ℝ.

All of these problems have the following properties:

‱ These are important problems, and people have spent significanteffort on trying to find better algorithms for them.

‱ Each one of these is a search problem, whereby we search for asolution that is “good” in some easy to define sense (e.g., a longpath, a satisfying assignment, etc.).

‱ Each of these problems has a trivial exponential time algorithm thatinvolve enumerating all possible solutions.

‱ At the moment, for all these problems the best known algorithm isnot much faster than the trivial one in the worst case.

In this chapter and in Chapter 15 we will see that, despite theirapparent differences, we can relate the computational complexity ofthese and many other problems. In fact, it turns out that the prob-lems above are computationally equivalent, in the sense that solving oneof them immediately implies solving the others. This phenomenon,known as NP completeness, is one of the surprising discoveries of the-oretical computer science, and we will see that it has far-reachingramifications.

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Introduce the notion of polynomial-time

reductions as a way to relate the complexity ofproblems to one another.

‱ See several examples of such reductions.‱ 3SAT as a basic starting point for reductions.

Page 452: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

452 introduction to theoretical computer science

This chapter: A non-mathy overviewThis chapter introduces the concept of a polynomial time re-duction which is a central object in computational complexityand this book in particular. A polynomial-time reduction is away to reduce the task of solving one problem to another. Theway we use reductions in complexity is to argue that if thefirst problem is hard to solve efficiently, then the second mustalso be hard. We see several examples for reductions in thischapter, and reductions will be the basis for the theory of NPcompleteness that we will develop in Chapter 15.

Figure 14.1: In this chapter we show that if the 3SATproblem cannot be solved in polynomial time, thenneither can the QUADEQ, LONGESTPATH, ISETand MAXCUT problems. We do this by using thereduction paradigm showing for example “if pigs couldwhistle” (i.e., if we had an efficient algorithm forQUADEQ) then “horses could fly” (i.e., we wouldhave an efficient algorithm for 3SAT.)

In this chapter we will see that for each one of the problems of find-ing a longest path in a graph, solving quadratic equations, and findingthe maximum cut, if there exists a polynomial-time algorithm for thisproblem then there exists a polynomial-time algorithm for the 3SATproblem as well. In other words, we will reduce the task of solving3SAT to each one of the above tasks. Another way to interpret theseresults is that if there does not exist a polynomial-time algorithm for3SAT then there does not exist a polynomial-time algorithm for theseother problems as well. In Chapter 15 we will see evidence (thoughno proof!) that all of the above problems do not have polynomial-timealgorithms and hence are inherently intractable.

14.1 FORMAL DEFINITIONS OF PROBLEMS

For reasons of technical convenience rather than anything substantial,we concern ourselves with decision problems (i.e., Yes/No questions) orin other words Boolean (i.e., one-bit output) functions. We model the

Page 453: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 453

problems above as functions mapping 0, 1∗ to 0, 1 in the followingway:

3SAT. The 3SAT problem can be phrased as the function 3SAT ∶0, 1∗ → 0, 1 that takes as input a 3CNF formula 𝜑 (i.e., a formulaof the form đ¶0 ∧ ⋯ ∧ đ¶đ‘šâˆ’1 where each đ¶đ‘– is the OR of three variablesor their negation) and maps 𝜑 to 1 if there exists some assignment tothe variables of 𝜑 that causes it to evalute to true, and to 0 otherwise.For example

3SAT ("(đ‘„0 √ đ‘„1 √ đ‘„2) ∧ (đ‘„1 √ đ‘„2 √ đ‘„3) ∧ (đ‘„0 √ đ‘„2 √ đ‘„3)") = 1 (14.1)

since the assignment đ‘„ = 1101 satisfies the input formula. In theabove we assume some representation of formulas as strings, anddefine the function to output 0 if its input is not a valid representation;we use the same convention for all the other functions below.

Quadratic equations. The quadratic equations problem corresponds to thefunction QUADEQ ∶ 0, 1∗ → 0, 1 that maps a set of quadraticequations 𝐾 to 1 if there is an assignment đ‘„ that satisfies all equations,and to 0 otherwise.

Longest path. The longest path problem corresponds to the functionLONGPATH ∶ 0, 1∗ → 0, 1 that maps a graph đș and a number 𝑘to 1 if there is a simple path in đș of length at least 𝑘, and maps (đș, 𝑘)to 0 otherwise. The longest path problem is a generalization of thewell-known Hamiltonian Path Problem of determining whether a pathof length 𝑛 exists in a given 𝑛 vertex graph.

Maximum cut. The maximum cut problem corresponds to the functionMAXCUT ∶ 0, 1∗ → 0, 1 that maps a graph đș and a number 𝑘 to1 if there is a cut in đș that cuts at least 𝑘 edges, and maps (đș, 𝑘) to 0otherwise.

All of the problems above are in EXP but it is not known whetheror not they are in P. However, we will see in this chapter that if eitherQUADEQ , LONGPATH or MAXCUT are in P, then so is 3SAT.14.2 POLYNOMIAL-TIME REDUCTIONS

Suppose that đč, đș ∶ 0, 1∗ → 0, 1 are two Boolean functions. Apolynomial-time reduction (or sometimes just “reduction” for short) fromđč to đș is a way to show that đč is “no harder” than đș, in the sensethat a polynomial-time algorithm for đș implies a polynomial-timealgorithm for đč .

Page 454: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

454 introduction to theoretical computer science

Figure 14.2: If đč â‰€đ‘ đș then we can transform apolynomial-time algorithm đ” that computes đșinto a polynomial-time algorithm 𝐮 that computesđč . To compute đč(đ‘„) we can run the reduction 𝑅guaranteed by the fact that đč â‰€đ‘ đș to obtain 𝑩 =đč(đ‘„) and then run our algorithm đ” for đș to computeđș(𝑩).

Definition 14.1 — Polynomial-time reductions. Let đč, đș ∶ 0, 1∗ → 0, 1.We say that đč reduces to đș, denoted by đč â‰€đ‘ đș if there is apolynomial-time computable 𝑅 ∶ 0, 1∗ → 0, 1∗ such thatfor every đ‘„ ∈ 0, 1∗, đč(đ‘„) = đș(𝑅(đ‘„)) . (14.2)

We say that đč and đș have equivalent complexity if đč â‰€đ‘ đș and đș â‰€đ‘đč .

The following exercise justifies our intuition that đč â‰€đ‘ đș signifiesthat ”đč is no harder than đș.Solved Exercise 14.1 — Reductions and P. Prove that if đč â‰€đ‘ đș and đș ∈ Pthen đč ∈ P.

PAs usual, solving this exercise on your own is an excel-lent way to make sure you understand Definition 14.1.

Solution:

Suppose there was an algorithm đ” that compute đș in time 𝑝(𝑛)where 𝑝 is its input size. Then, (14.2) directly gives an algorithm𝐮 to compute đč (see Fig. 14.2). Indeed, on input đ‘„ ∈ 0, 1∗, Al-gorithm 𝐮 will run the polynomial-time reduction 𝑅 to obtain𝑩 = 𝑅(đ‘„) and then return đ”(𝑩). By (14.2), đș(𝑅(đ‘„)) = đč(đ‘„) andhence Algorithm 𝐮 will indeed compute đč .

We now show that 𝐮 runs in polynomial time. By assumption, 𝑅can be computed in time 𝑞(𝑛) for some polynomial 𝑞. In particular,this means that |𝑩| ≀ 𝑞(|đ‘„|) (as just writing down 𝑩 takes |𝑩| steps).Computing đ”(𝑩) will take at most 𝑝(|𝑩|) ≀ 𝑝(𝑞(|đ‘„|)) steps. Thusthe total running time of 𝐮 on inputs of length 𝑛 is at most the timeto compute 𝑩, which is bounded by 𝑞(𝑛), and the time to computeđ”(𝑩), which is bounded by 𝑝(𝑞(𝑛)), and since the composition oftwo polynomials is a polynomial, 𝐮 runs in polynomial time.

Big Idea 21 A reduction đč â‰€đ‘ đș shows that đč is “no harder thanđș” or equivalently that đș is “no easier than đč”.

14.2.1 Whistling pigs and flying horsesA reduction from đč to đș can be used for two purposes:

Page 455: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 455

‱ If we already know an algorithm for đș and đč â‰€đ‘ đș then we canuse the reduction to obtain an algorithm for đč . This is a widelyused tool in algorithm design. For example in Section 12.1.4 we sawhow the Min-Cut Max-Flow theorem allows to reduce the task ofcomputing a minimum cut in a graph to the task of computing amaximum flow in it.

‱ If we have proven (or have evidence) that there exists no polynomial-time algorithm for đč and đč â‰€đ‘ đș then the existence of this reductionallows us to conclude that there exists no polynomial-time algo-rithm for đș. This is the “if pigs could whistle then horses couldfly” interpretation we’ve seen in Section 9.4. We show that if therewas an hypothetical efficient algorithm for đș (a “whistling pig”)then since đč â‰€đ‘ đș then there would be an efficient algorithm forđč (a “flying horse”). In this book we often use reductions for thissecond purpose, although the lines between the two is sometimesblurry (see the bibliographical notes in Section 14.9).

The most crucial difference between the notion in Definition 14.1and the reductions we saw in the context of uncomputability (e.g.,in Section 9.4) is that for relating time complexity of problems, weneed the reduction to be computable in polynomial time, as opposed tomerely computable. Definition 14.1 also restricts reductions to have avery specific format. That is, to show that đč â‰€đ‘ đș, rather than allow-ing a general algorithm for đč that uses a “magic box” that computesđș, we only allow an algorithm that computes đč(đ‘„) by outputtingđș(𝑅(đ‘„)). This restricted form is convenient for us, but people havedefined and used more general reductions as well (see Section 14.9).

In this chapter we use reductions to relate the computational com-plexity of the problems mentioned above: 3SAT, Quadratic Equations,Maximum Cut, and Longest Path, as well as a few others. We willreduce 3SAT to the latter problems, demonstrating that solving anyone of them efficiently will result in an efficient algorithm for 3SAT.In Chapter 15 we show the other direction: reducing each one of theseproblems to 3SAT in one fell swoop.

Transitivity of reductions. Since we think of đč â‰€đ‘ đș as saying that(as far as polynomial-time computation is concerned) đč is “easier orequal in difficulty to” đș, we would expect that if đč â‰€đ‘ đș and đș â‰€đ‘ đ» ,then it would hold that đč â‰€đ‘ đ» . Indeed this is the case:Solved Exercise 14.2 — Transitivity of polynomial-time reductions. For everyđč, đș, đ» ∶ 0, 1∗ → 0, 1, if đč â‰€đ‘ đș and đș â‰€đ‘ đ» then đč â‰€đ‘ đ» .

Page 456: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

456 introduction to theoretical computer science

1 If you are familiar with matrix notation you maynote that such equations can be written as đŽđ‘„ = bwhere 𝐮 is an 𝑚 × 𝑛 matrix with entries in 0/1 andb ∈ ℕ𝑚.

Solution:

If đč â‰€đ‘ đș and đș â‰€đ‘ đ» then there exist polynomial-time com-putable functions 𝑅1 and 𝑅2 mapping 0, 1∗ to 0, 1∗ such thatfor every đ‘„ ∈ 0, 1∗, đč(đ‘„) = đș(𝑅1(đ‘„)) and for every 𝑩 ∈ 0, 1∗,đș(𝑩) = đ»(𝑅2(𝑩)). Combining these two equalities, we see thatfor every đ‘„ ∈ 0, 1∗, đč(đ‘„) = đ»(𝑅2(𝑅1(đ‘„))) and so to show thatđč â‰€đ‘ đ» , it is sufficient to show that the map đ‘„ ↩ 𝑅2(𝑅1(đ‘„)) iscomputable in polynomial time. But if there are some constants 𝑐, 𝑑such that 𝑅1(đ‘„) is computable in time |đ‘„|𝑐 and 𝑅2(𝑩) is computablein time |𝑩|𝑑 then 𝑅2(𝑅1(đ‘„)) is computable in time (|đ‘„|𝑐)𝑑 = |đ‘„|𝑐𝑑which is polynomial.

14.3 REDUCING 3SAT TO ZERO ONE AND QUADRATIC EQUATIONS

We now show our first example of a reduction. The Zero-One Lin-ear Equations problem corresponds to the function 01EQ ∶ 0, 1∗ →0, 1 whose input is a collection 𝐾 of linear equations in variablesđ‘„0, 
 , đ‘„đ‘›âˆ’1, and the output is 1 iff there is an assignment đ‘„ ∈ 0, 1𝑛of 0/1 values to the variables that satisfies all the equations. For exam-ple, if the input 𝐾 is a string encoding the set of equationsđ‘„0 + đ‘„1 + đ‘„2 = 2đ‘„0 + đ‘„2 = 1đ‘„1 + đ‘„2 = 2 (14.3)

then 01EQ(𝐾) = 1 since the assignment đ‘„ = 011 satisfies all threeequations. We specifically restrict attention to linear equations invariables đ‘„0, 
 , đ‘„đ‘›âˆ’1 in which every equation has the form ∑𝑖∈𝑆 đ‘„đ‘– =𝑏 where 𝑆 ⊆ [𝑛] and 𝑏 ∈ ℕ.1

If we asked the question of whether there is a solution đ‘„ ∈ ℝ𝑛 ofreal numbers to 𝐾, then this can be solved using the famous Gaussianelimination algorithm in polynomial time. However, there is no knownefficient algorithm to solve 01EQ. Indeed, such an algorithm wouldimply an algorithm for 3SAT as shown by the following theorem:

Theorem 14.2 — Hardness of 01𝐾𝑄. 3SAT â‰€đ‘ 01EQProof Idea:

A constraint đ‘„2 √ đ‘„5 √ đ‘„7 can be written as đ‘„2 + (1 − đ‘„5) + đ‘„7 ≄ 1.This is a linear inequality but since the sum on the left-hand side isat most three, we can also turn it into an equality by adding two newvariables 𝑩, 𝑧 and writing it as đ‘„2 + (1 − đ‘„5) + đ‘„7 + 𝑩 + 𝑧 = 3. (We willuse fresh such variables 𝑩, 𝑧 for every constraint.) Finally, for everyvariable đ‘„đ‘– we can add a variable đ‘„â€Č𝑖 corresponding to its negation by

Page 457: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 457

adding the equation đ‘„đ‘– + đ‘„â€Č𝑖 = 1, hence mapping the original constraintđ‘„2 √ đ‘„5 √ đ‘„7 to đ‘„2 + đ‘„â€Č5 + đ‘„7 + 𝑩 + 𝑧 = 3. The main takeawaytechnique from this reduction is the idea of adding auxiliary variablesto replace an equation such as đ‘„1 + đ‘„2 + đ‘„3 ≄ 1 that is not quite in theform we want with the equivalent (for 0/1 valued variables) equationđ‘„1 + đ‘„2 + đ‘„3 + 𝑱 + 𝑣 = 3 which is in the form we want.⋆

Figure 14.3: Left: Python code implementing thereduction of 3SAT to 01EQ. Right: Example output ofthe reduction. Code is in our repository.

Proof of Theorem 14.2. To prove the theorem we need to:

1. Describe an algorithm 𝑅 for mapping an input 𝜑 for 3SAT into aninput 𝐾 for 01EQ.

2. Prove that the algorithm runs in polynomial time.

3. Prove that 01EQ(𝑅(𝜑)) = 3SAT(𝜑) for every 3CNF formula 𝜑.

We now proceed to do just that. Since this is our first reduction, wewill spell out this proof in detail. However it straightforwardly followsthe proof idea.

Page 458: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

458 introduction to theoretical computer science

Algorithm 14.3 — 3𝑆𝐮𝑇 to 01𝐾𝑄 reduction.

Input: 3CNF formula 𝜑 with 𝑛 variables đ‘„0, 
 , đ‘„đ‘›âˆ’1 and 𝑚clauses.

Output: Set 𝐾 of linear equations over 0/1 such that3𝑆𝐮𝑇 (𝜑) = 1 -iff 01𝐾𝑄(𝐾) = 1.1: Let 𝐾’s variables be đ‘„0, 
 , đ‘„đ‘›âˆ’1, đ‘„â€Č0, 
 , đ‘„â€Č𝑛−1, 𝑩0, 
 , 𝑩𝑚−1,𝑧0, 
 , 𝑧𝑚−1.2: for 𝑖 ∈ [𝑛] do3: add to 𝐾 the equation đ‘„đ‘– + đ‘„â€Č𝑖 = 14: end for5: for j∈[m] do6: Let 𝑗-th clause be đ‘€0 √ đ‘€1 √ đ‘€2 where đ‘€0, đ‘€1, đ‘€2 are

literals.7: for 𝑎 ∈ [3] do8: if đ‘€đ‘Ž is variable đ‘„đ‘– then9: set 𝑡𝑎 ← đ‘„đ‘–

10: end if11: if đ‘€đ‘Ž is negation ÂŹđ‘„đ‘– then12: set 𝑡𝑎 ← đ‘„â€Č𝑖13: end if14: end for15: Add to 𝐾 the equation 𝑡0 + 𝑡1 + 𝑡2 + 𝑩𝑗 + 𝑧𝑗 = 3.16: end for17: return 𝐾

The reduction is described in Algorithm 14.3, see also Fig. 14.3. Ifthe input formula has 𝑛 variable and 𝑚 steps, Algorithm 14.3 creates aset 𝐾 of 𝑛+𝑚 equations over 2𝑛+2𝑚 variables. Algorithm 14.3 makesan initial loop of 𝑛 steps (each taking constant time) and then anotherloop of 𝑚 steps (each taking constant time) to create the equations,and hence it runs in polynomial time.

Let 𝑅 be the function computed by Algorithm 14.3. The heart ofthe proof is to show that for every 3CNF 𝜑, 01EQ(𝑅(𝜑)) = 3SAT(𝜑).We split the proof into two parts. The first part, traditionally knownas the completeness property, is to show that if 3SAT(𝜑) = 1 then𝑂1EQ(𝑅(𝜑)) = 1. The second part, traditionally known as the sound-ness property, is to show that if 01EQ(𝑅(𝜑)) = 1 then 3SAT(𝜑) = 1.(The names “completeness” and “soundness” derive viewing a so-lution to 𝑅(𝜑) as a “proof” that 𝜑 is satisfiable, in which case theseconditions corresponds to completeness and soundness as definedin Section 11.1.1. However, if you find the names confusing you cansimply think of completeness as the “1-instance maps to 1-instance”

Page 459: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 459

property and soundness as the “0-instance maps to 0-instance” prop-erty.)

We complete the proof by showing both parts:

‱ Completeness: Suppose that 3SAT(𝜑) = 1, which means thatthere is an assignment đ‘„ ∈ 0, 1𝑛 that satisfies 𝜑. If we use theassignment đ‘„0, 
 , đ‘„đ‘›âˆ’1 and 1 − đ‘„0, 
 , 1 − đ‘„đ‘›âˆ’1 for the first 2𝑛variables of 𝐾 = 𝑅(𝜑) then we will satisfy all equations of the formđ‘„đ‘– + đ‘„â€Č𝑖 = 1. Moreover, for every 𝑗 ∈ [𝑛], if 𝑡0 + 𝑡1 + 𝑡2 + 𝑩𝑗 + 𝑧𝑗 =3(∗) is the equation arising from the 𝑗th clause of 𝜑 (with 𝑡0, 𝑡1, 𝑡2being variables of the form đ‘„đ‘– or đ‘„â€Č𝑖 depending on the literals of theclause) then our assignment to the first 2𝑛 variables ensures that𝑡0 + 𝑡1 + 𝑡2 ≄ 1 (since đ‘„ satisfied 𝜑) and hence we can assign valuesto 𝑩𝑗 and 𝑧𝑗 that will ensure that the equation (∗) is satisfied. Hencein this case 𝐾 = 𝑅(𝜑) is satisfied, meaning that 01EQ(𝑅(𝜑)) = 1.

‱ Soundness: Suppose that 01EQ(𝑅(𝜑)) = 1, which means that theset of equations 𝐾 = 𝑅(𝜑) has a satisfying assignment đ‘„0, 
 , đ‘„đ‘›âˆ’1,đ‘„â€Č0, 
 , đ‘„â€Č𝑛−1, 𝑩0, 
 , 𝑩𝑚−1, 𝑧0, 
 , 𝑧𝑚−1. Then, since the equationscontain the condition đ‘„đ‘– + đ‘„â€Č𝑖 = 1, for every 𝑖 ∈ [𝑛], đ‘„â€Č𝑖 is the negationof đ‘„đ‘–, and morover, for every 𝑗 ∈ [𝑚], if đ¶ has the form đ‘€0 √ đ‘€1 √ đ‘€2is the 𝑗-th clause of đ¶, then the corresponding assignment đ‘„ willensure that đ‘€0 + đ‘€1 + đ‘€2 ≄ 1, implying that đ¶ is satisfied. Hence inthis case 3SAT(𝜑) = 1.

14.3.1 Quadratic equationsNow that we reduced 3SAT to 01EQ, we can use this to reduce 3SATto the quadratic equations problem. This is the function QUADEQ inwhich the input is a list of 𝑛-variate polynomials 𝑝0, 
 , 𝑝𝑚−1 ∶ ℝ𝑛 → ℝthat are all of degree at most two (i.e., they are quadratic) and withinteger coefficients. (The latter condition is for convenience and canbe achieved by scaling.) We define QUADEQ(𝑝0, 
 , 𝑝𝑚−1) to equal 1if and only if there is a solution đ‘„ ∈ ℝ𝑛 to the equations 𝑝0(đ‘„) = 0,𝑝1(đ‘„) = 0, 
, 𝑝𝑚−1(đ‘„) = 0.

For example, the following is a set of quadratic equations over thevariables đ‘„0, đ‘„1, đ‘„2: đ‘„20 − đ‘„0 = 0đ‘„21 − đ‘„1 = 0đ‘„22 − đ‘„2 = 01 − đ‘„0 − đ‘„1 + đ‘„0đ‘„1 = 0 (14.4)

You can verify that đ‘„ ∈ ℝ3 satisfies this set of equations if and only ifđ‘„ ∈ 0, 13 and đ‘„0 √ đ‘„1 = 1.

Page 460: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

460 introduction to theoretical computer science

Theorem 14.4 — Hardness of quadratic equations.3SAT â‰€đ‘ QUADEQ (14.5)

Proof Idea:

Using the transitivity of reductions (Solved Exercise 14.2), it isenough to show that 01EQ â‰€đ‘ QUADEQ, but this follows since wecan phrase the equation đ‘„đ‘– ∈ 0, 1 as the quadratic constraint đ‘„2𝑖 âˆ’đ‘„đ‘– = 0. The takeaway technique of this reduction is that we can usenonlinearity to force continuous variables (e.g., variables taking valuesin ℝ) to be discrete (e.g., take values in 0, 1).⋆Proof of Theorem 14.4. By Theorem 14.2 and Solved Exercise 14.2,it is sufficient to prove that 01EQ â‰€đ‘ QUADEQ. Let 𝐾 be an in-stance of 01EQ with variables đ‘„0, 
 , đ‘„đ‘šâˆ’1. We map 𝐾 to the set ofquadratic equations 𝐾â€Č that is obtained by taking the linear equationsin 𝐾 and adding to them the 𝑛 quadratic equations đ‘„2𝑖 − đ‘„đ‘– = 0 forall 𝑖 ∈ [𝑛]. (See Algorithm 14.5.) The map 𝐾 ↩ 𝐾â€Č can be com-puted in polynomial time. We claim that 01EQ(𝐾) = 1 if and onlyif QUADEQ(𝐾â€Č) = 1. Indeed, the only difference between the twoinstances is that:

‱ In the 01EQ instance 𝐾, the equations are over variables đ‘„0, 
 , đ‘„đ‘›âˆ’1in 0, 1.

‱ In the QUADEQ instance 𝐾â€Č, the equations are over variablesđ‘„0, 
 , đ‘„đ‘›âˆ’1 ∈ ℝ but we have the extra constraints đ‘„2𝑖 − đ‘„đ‘– = 0for all 𝑖 ∈ [𝑛].Since for every 𝑎 ∈ ℝ, 𝑎2 − 𝑎 = 0 if and only if 𝑎 ∈ 0, 1, the two

sets of equations are equivalent and 01EQ(𝐾) = QUADEQ(𝐾â€Č) whichis what we wanted to prove.

Page 461: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 461

Algorithm 14.5 — 3𝑆𝐮𝑇 to 01𝐾𝑄 reduction.

Input: Set 𝐾 of linear equations over 𝑛 variables đ‘„0, 
 , đ‘„đ‘›âˆ’1.Output: Set 𝐾â€Č of quadratic eqations ovar 𝑚 variablesđ‘€0, 
 , đ‘€đ‘šâˆ’1 such that there is an 0/1 assignmentđ‘„ ∈ 0, 1𝑛1: satisfying the equations of 𝐾 -iff there is an assignmentđ‘€ ∈ ℝ𝑚 satisfying the equations of 𝐾â€Č.2: That is, 𝑂1𝐾𝑄(𝐾) = đ‘„đ‘ˆđŽđ·đžđ‘„(𝐾â€Č).3: Let 𝑚 ← 𝑛.4: Variables of 𝐾â€Č are set to be same variable đ‘„0, 
 , đ‘„đ‘›âˆ’1

as 𝐾.5: for every equation 𝑒 ∈ 𝐾 do6: Add 𝑒 to 𝐾â€Č7: end for8: for 𝑖 ∈ [𝑛] do9: Add to 𝐾â€Č the equation đ‘„2𝑖 − đ‘„đ‘– = 0.

10: end for11: return 𝐾â€Č

14.4 THE INDEPENDENT SET PROBLEM

For a graph đș = (𝑉 , 𝐾), an independent set (also known as a stableset) is a subset 𝑆 ⊆ 𝑉 such that there are no edges with both end-points in 𝑆 (in other words, 𝐾(𝑆, 𝑆) = ∅). Every “singleton” (setconsisting of a single vertex) is trivially an independent set, but find-ing larger independent sets can be challenging. The maximum indepen-dent set problem (henceforth simply “independent set”) is the task offinding the largest independent set in the graph. The independent setproblem is naturally related to scheduling problems: if we put an edgebetween two conflicting tasks, then an independent set correspondsto a set of tasks that can all be scheduled together without conflicts.The independent set problem has been studied in a variety of settings,including for example in the case of algorithms for finding structure inprotein-protein interaction graphs.

As mentioned in Section 14.1, we think of the independent set prob-lem as the function ISET ∶ 0, 1∗ → 0, 1 that on input a graph đșand a number 𝑘 outputs 1 if and only if the graph đș contains an in-dependent set of size at least 𝑘. We now reduce 3SAT to Independentset.

Theorem 14.6 — Hardness of Independent Set. 3SAT â‰€đ‘ ISET.

Proof Idea:

Page 462: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

462 introduction to theoretical computer science

Figure 14.4: An example of the reduction of 3SATto ISET for the case the original input formula is𝜑 = (đ‘„0 âˆšđ‘„1 âˆšđ‘„2)∧(đ‘„0 âˆšđ‘„1 âˆšđ‘„2)∧(đ‘„1 âˆšđ‘„2 âˆšđ‘„3). Wemap each clause of 𝜑 to a triangle of three vertices,each tagged above with â€œđ‘„đ‘– = 0” or â€œđ‘„đ‘– = 1”depending on the value of đ‘„đ‘– that would satisfy theparticular literal. We put an edge between every twoliterals that are conflicting (i.e., tagged with â€œđ‘„đ‘– = 0”and â€œđ‘„đ‘– = 1” respectively).

The idea is that finding a satisfying assignment to a 3SAT formulacorresponds to satisfying many local constraints without creatingany conflicts. One can think of â€œđ‘„17 = 0” and â€œđ‘„17 = 1” as twoconflicting events, and of the constraints đ‘„17 √ đ‘„5 √ đ‘„9 as creatinga conflict between the events â€œđ‘„17 = 0”, â€œđ‘„5 = 1” and â€œđ‘„9 = 0”,saying that these three cannot simultaneously co-occur. Using theseideas, we can we can think of solving a 3SAT problem as trying toschedule non conflicting events, though the devil is, as usual, in thedetails. The takeaway technique here is to map each clause of theoriginal formula into a gadget which is a small subgraph (or moregenerally “subinstance”) satisfying some convenient properties. Wewill see these “gadgets” used time and again in the construction ofpolynomial-time reductions.⋆

Algorithm 14.7 — 3𝑆𝐮𝑇 to đŒđ‘† reduction.

Input: 3𝑆𝐮𝑇 formula 𝜑 with 𝑛 variables and 𝑚 clauses.Output: Graph đș = (𝑉 , 𝐾) and number 𝑘, such that đș

has an independent set of size 𝑘 -iff 𝜑 has a satisfyingassignment.

1: That is, 3𝑆𝐮𝑇 (𝜑) = đŒđ‘†đžđ‘‡ (đș, 𝑘),2: Initialize 𝑉 ← ∅, 𝐾 ← ∅3: for every clause đ¶ = 𝑩 √ 𝑩â€Č √ 𝑩″ of 𝜑 do4: Add three vertices (đ¶, 𝑩), (đ¶, 𝑩â€Č), (đ¶, 𝑩″) to 𝑉5: Add edges (đ¶, 𝑩), (đ¶, 𝑩â€Č), (đ¶, 𝑩â€Č), (đ¶, 𝑩″),(đ¶, 𝑩″), (đ¶, 𝑩) to 𝐾.6: end for7: for every distinct clauses đ¶, đ¶â€Č in 𝜑 do8: for every 𝑖 ∈ [𝑛] do9: if đ¶ contains literal đ‘„đ‘– and đ¶â€Č contains literal đ‘„đ‘–

then10: Add edge (đ¶, đ‘„đ‘–), (đ¶, đ‘„đ‘–) to 𝐾11: end if12: end for13: end for14: return đș = (𝑉 , 𝐾)

Proof of Theorem 14.6. Given a 3SAT formula 𝜑 on 𝑛 variables andwith 𝑚 clauses, we will create a graph đș with 3𝑚 vertices as follows.(See Algorithm 14.7, see also Fig. 14.4 for an example and Fig. 14.5 forPython code.)

‱ A clause đ¶ in 𝜑 has the form đ¶ = 𝑩 √ 𝑩â€Č √ 𝑩″ where 𝑩, 𝑩â€Č, 𝑩″ areliterals (variables or their negation). For each such clause đ¶, we will

Page 463: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 463

add three vertices to đș, and label them (đ¶, 𝑩), (đ¶, 𝑩â€Č), and (đ¶, 𝑩″)respectively. We will also add the three edges between all pairs ofthese vertices, so they form a triangle. Since there are 𝑚 clauses in 𝜑,the graph đș will have 3𝑚 vertices.

‱ In addition to the above edges, we also add an edge between everypair vertices of the form (đ¶, 𝑩) and (đ¶â€Č, 𝑩â€Č) where 𝑩 and 𝑩â€Č are con-flicting literals. That is, we add an edge between (đ¶, 𝑩) and (đ¶â€Č, 𝑩â€Č)if there is an 𝑖 such that 𝑩 = đ‘„đ‘– and 𝑩â€Č = đ‘„đ‘– or vice versa.

The algorithm constructing of đș based on 𝜑 takes polynomial timesince it involves two loops, the first taking 𝑂(𝑚) steps and the secondtaking 𝑂(𝑚2𝑛) steps (see Algorithm 14.7). Hence to prove the theo-rem we need to show that 𝜑 is satisfiable if and only if đș contains anindependent set of 𝑚 vertices. We now show both directions of thisequivalence:

Part 1: Completeness. The “completeness” direction is to show thatif 𝜑 has a satisfying assignment đ‘„âˆ—, then đș has an independent set 𝑆∗of 𝑚 vertices. Let us now show this.

Indeed, suppose that 𝜑 has a satisfying assignment đ‘„âˆ— ∈ 0, 1𝑛.Then for every clause đ¶ = 𝑩 √ 𝑩â€Č √ 𝑩″ of 𝜑, one of the literals 𝑩, 𝑩â€Č, 𝑩″must evaluate to true under the assignment đ‘„âˆ— (as otherwise it wouldnot satisfy 𝜑). We let 𝑆 be a set of 𝑚 vertices that is obtained by choos-ing for every clause đ¶ one vertex of the form (đ¶, 𝑩) such that 𝑩 eval-uates to true under đ‘„âˆ—. (If there is more than one such vertex for thesame đ¶, we arbitrarily choose one of them.)

We claim that 𝑆 is an independent set. Indeed, suppose otherwisethat there was a pair of vertices (đ¶, 𝑩) and (đ¶â€Č, 𝑩â€Č) in 𝑆 that have anedge between them. Since we picked one vertex out of each trianglecorresponding to a clause, it must be that đ¶ ≠ đ¶â€Č. Hence the onlyway that there is an edge between (đ¶, 𝑩) and (đ¶, 𝑩â€Č) is if 𝑩 and 𝑩â€Č areconflicting literals (i.e. 𝑩 = đ‘„đ‘– and 𝑩â€Č = đ‘„đ‘– for some 𝑖). But then theycan’t both evaluate to true under the assignment đ‘„âˆ—, which contradictsthe way we constructed the set 𝑆. This completes the proof of thecompleteness condition.

Part 2: Soundness. The “soundness” direction is to show that ifđș has an independent set 𝑆∗ of 𝑚 vertices, then 𝜑 has a satisfyingassignment đ‘„âˆ— ∈ 0, 1𝑛. Let us now show this.

Indeed, suppose that đș has an independent set 𝑆∗ with 𝑚 vertices.We will define an assignment đ‘„âˆ— ∈ 0, 1𝑛 for the variables of 𝜑 asfollows. For every 𝑖 ∈ [𝑛], we set đ‘„âˆ—đ‘– according to the following rules:

‱ If 𝑆∗ contains a vertex of the form (đ¶, đ‘„đ‘–) then we set đ‘„âˆ—đ‘– = 1.‱ If 𝑆∗ contains a vertex of the form (đ¶, đ‘„đ‘–) then we set đ‘„âˆ—đ‘– = 0.

Page 464: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

464 introduction to theoretical computer science

‱ If 𝑆∗ does not contain a vertex of either of these forms, then it doesnot matter which value we give to đ‘„âˆ—đ‘– , but for concreteness we’ll setđ‘„âˆ—đ‘– = 0.The first observation is that đ‘„âˆ— is indeed well defined, in the sense

that the rules above do not conflict with one another, and ask to set đ‘„âˆ—đ‘–to be both 0 and 1. This follows from the fact that 𝑆∗ is an independentset and hence if it contains a vertex of the form (đ¶, đ‘„đ‘–) then it cannotcontain a vertex of the form (đ¶â€Č, đ‘„đ‘–).

We now claim that đ‘„âˆ— is a satisfying assignment for 𝜑. Indeed, since𝑆∗ is an independent set, it cannot have more than one vertex insideeach one of the 𝑚 triangles (đ¶, 𝑩), (đ¶, 𝑩â€Č), (đ¶, 𝑩″) corresponding to aclause of 𝜑. Hence since |𝑆∗| = 𝑚, it must have exactly one vertex ineach such triangle. For every clause đ¶ of 𝜑, if (đ¶, 𝑩) is the vertex in𝑆∗ in the triangle corresponding to đ¶, then by the way we defined đ‘„âˆ—,the literal 𝑩 must evaluate to true, which means that đ‘„âˆ— satisfies thisclause. Therefore đ‘„âˆ— satisfies all clauses of 𝜑, which is the definition ofa satisfying assignment.

This completes the proof of Theorem 14.6

Figure 14.5: The reduction of 3SAT to Independent Set.On the righthand side is Python code that implementsthis reduction. On the lefthand side is a sampleoutput of the reduction. We use black for the “triangleedges” and red for the “conflict edges”. Note that thesatisfying assignment đ‘„âˆ— = 0110 corresponds to theindependent set (0, ÂŹđ‘„3), (1, ÂŹđ‘„0), (2, đ‘„2).

14.5 SOME EXERCISES AND ANATOMY OF A REDUCTION.

Reductions can be confusing and working out exercises is a great wayto gain more comfort with them. Here is one such example. As usual,I recommend you try it out yourself before looking at the solution.Solved Exercise 14.3 — Vertex cover. A vertex cover in a graph đș = (𝑉 , 𝐾)is a subset 𝑆 ⊆ 𝑉 of vertices such that every edge touches at least onevertex of 𝑆 (see ??). The vertex cover problem is the task to determine,given a graph đș and a number 𝑘, whether there exists a vertex coverin the graph with at most 𝑘 vertices. Formally, this is the functionVC ∶ 0, 1∗ → 0, 1 such that for every đș = (𝑉 , 𝐾) and 𝑘 ∈ ℕ,

Page 465: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 465

Figure 14.6: A vertex cover in a graph is a subset ofvertices that touches all edges. In this 7-vertex graph,the 3 filled vertices are a vertex cover.

VC(đș, 𝑘) = 1 if and only if there exists a vertex cover 𝑆 ⊆ 𝑉 such that|𝑆| ≀ 𝑘.Prove that 3SAT â‰€đ‘ VC.

Solution:

The key observation is that if 𝑆 ⊆ 𝑉 is a vertex cover thattouches all vertices, then there is no edge 𝑒 such that both 𝑠’s end-points are in the set 𝑆 = 𝑉 ⧔ 𝑆, and vice versa. In other words,𝑆 is a vertex cover if and only if 𝑆 is an independent set. Sincethe size of 𝑆 is |𝑉 | − |𝑆|, we see that the polynomial-time map𝑅(đș, 𝑘) = (đș, 𝑛 − 𝑘) (where 𝑛 is the number of vertices of đș)satisfies that VC(𝑅(đș, 𝑘)) = ISET(đș, 𝑘) which means that it is areduction from independent set to vertex cover.

Solved Exercise 14.4 — Clique is equivalent to independent set. The maximumclique problem corresponds to the function CLIQUE ∶ 0, 1∗ → 0, 1such that for a graph đș and a number 𝑘, CLIQUE(đș, 𝑘) = 1 iff thereis a 𝑆 subset of 𝑘 vertices such that for every distinct 𝑱, 𝑣 ∈ 𝑆, the edge𝑱, 𝑣 is in đș. Such a set is known as a clique.

Prove that CLIQUE â‰€đ‘ ISET and ISET â‰€đ‘ CLIQUE.

Solution:

If đș = (𝑉 , 𝐾) is a graph, we denote by đș its complement whichis the graph on the same vertices 𝑉 and such that for every distinct𝑱, 𝑣 ∈ 𝑉 , the edge 𝑱, 𝑣 is present in đș if and only if this edge isnot present in đș.

This means that for every set 𝑆, 𝑆 is an independent set in đș ifand only if 𝑆 is a clique in đș. Therefore for every 𝑘, ISET(đș, 𝑘) =CLIQUE(đș, 𝑘). Since the map đș ↩ đș can be computed efficiently,this yields a reduction ISET â‰€đ‘ CLIQUE. Moreover, since đș = đșthis yields a reduction in the other direction as well.

14.5.1 Dominating setIn the two examples above, the reduction was almost “trivial”: thereduction from independent set to vertex cover merely changes thenumber 𝑘 to 𝑛 − 𝑘, and the reduction from independent set to cliqueflips edges to non-edges and vice versa. The following exercise re-quires a somewhat more interesting reduction.Solved Exercise 14.5 — Dominating set. A dominating set in a graph đș =(𝑉 , 𝐾) is a subset 𝑆 ⊆ 𝑉 of vertices such that for every 𝑱 ∈ 𝑉 ⧔ 𝑆 is aneighbor in đș of some 𝑠 ∈ 𝑆 (see Fig. 14.7). The dominating set problem

Page 466: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

466 introduction to theoretical computer science

Figure 14.7: A dominating set is a subset 𝑆 of verticessuch that every vertex in the graph is either in 𝑆 or aneighbor of 𝑆. The figure above are two copies of thesame graph. The red vertices on the left are a vertexcover that is not a dominating set. The blue verticeson the right are a dominating set that is not a vertexcover.

is the task, given a graph đș = (𝑉 , 𝐾) and number 𝑘, of determiningwhether there exists a dominating set 𝑆 ⊆ 𝑉 with |𝑆| ≀ 𝑘. Formally,this is the function DS ∶ 0, 1∗ → 0, 1 such that DS(đș, 𝑘) = 1 iffthere is a dominating set in đș of at most 𝑘 vertices.

Prove that ISET â‰€đ‘ DS.

Solution:

Since we know that ISET â‰€đ‘ VC, using transitivity, it is enoughto show that VC â‰€đ‘ DS. As Fig. 14.7 shows, a dominating set isnot the same thing as a vertex cover. However, we can still relatethe two problems. The idea is to map a graph đș into a graph đ»such that a vertex cover in đș would translate into a dominating setin đ» and vice versa. We do so by including in đ» all the verticesand edges of đș, but for every edge 𝑱, 𝑣 of đș we also add to đ» anew vertex đ‘€đ‘ą,𝑣 and connect it to both 𝑱 and 𝑣. Let ℓ be the numberof isolated vertices in đș. The idea behind the proof is that we cantransform a vertex cover 𝑆 of 𝑘 vertices in đș into a dominating setof 𝑘 + ℓ vertices in đ» by adding to 𝑆 all the isolated vertices, andmoreover we can transform every 𝑘 + ℓ sized dominating set in đ»into a vertex cover in đș. We now give the details.

Description of the algorithm. Given an instance (đș, 𝑘) for thevertex cover problem, we will map đș into an instance (đ», 𝑘â€Č) forthe dominating set problem as follows (see Fig. 14.8 for Pythonimplementation):

Algorithm 14.8 — 𝑉 đ¶ to đ·đ‘† reduction.

Input: Graph đș = (𝑉 , 𝐾) and number 𝑘.Output: Graph đ» = (𝑉 â€Č, 𝐾â€Č) and number 𝑘â€Č, such thatđș has a vertex cover of size 𝑘 -iff đ» has a dominating

set of size 𝑘â€Č1: That is, đ·đ‘†(đ», 𝑘â€Č) = đŒđ‘†đžđ‘‡ (đș, 𝑘),2: Initialize 𝑉 â€Č ← 𝑉 , 𝐾â€Č ← 𝐾3: for every edge 𝑱, 𝑣 ∈ 𝐾 do4: Add vertex đ‘€đ‘ą,𝑣 to 𝑉 â€Č5: Add edges 𝑱, đ‘€đ‘ą,𝑣, 𝑣, đ‘€đ‘ą,𝑣 to 𝐾â€Č.6: end for7: Let ℓ ← number of isolated vertices in đș8: return (đ» = (𝑉 â€Č, 𝐾â€Č) , 𝑘 + ℓ)

Algorithm 14.8 runs in polynomial time, since the loop takes𝑂(𝑚) steps where 𝑚 is the number of edges, with each step can beimplemented in constant or at most linear time (depending on the

Page 467: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 467

representation of the graph đ»). Counting the number of isolatedvertices in an 𝑛 vertex graph đș can be done in time 𝑂(𝑛2) if đș isrepresented in the adjacency matrix representation and 𝑂(𝑛) timeif it is represented in the adjacency list representation. Regardlessthe algorithm runs in polynomial time.

To complete the proof we need to prove that for every đș, 𝑘, ifđ», 𝑘â€Č is the output of Algorithm 14.8 on input (đș, 𝑘), thenDS(đ», 𝑘â€Č) = VC(đș, 𝑘). We split the proof into two parts. The

completeness part is that if VC(đș, 𝑘) = 1 then DS(đ», 𝑘â€Č) = 1. Thesoundness part is that if DS(đ», 𝑘â€Č) = 1 then VC(đș, 𝑘) = 1.

Completeness. Suppose that VC(đș, 𝑘) = 1. Then there is a ver-tex cover 𝑆 ⊆ 𝑉 of at most 𝑘 vertices. Let đŒ be the set of isolatedvertices in đș and ℓ be their number. Then |𝑆 âˆȘ đŒ| ≀ 𝑘 + ℓ. We claimthat 𝑆 âˆȘ đŒ is a dominating set in đ»â€Č. Indeed for every vertex 𝑣 of đ»â€Čthere are three cases:

‱ Case 1: 𝑣 is an isolated vertex of đș. In this case 𝑣 is in 𝑆 âˆȘ đŒ .‱ Case 2: 𝑣 is a non-isolated vertex of đș and hence there is an edge𝑱, 𝑣 of đș for some 𝑱. In this case since 𝑆 is a vertex cover, one

of 𝑱, 𝑣 has to be in 𝑆, and hence either 𝑣 or a neighbor of 𝑣 has tobe in 𝑆 ⊆ 𝑆 âˆȘ đŒ .

‱ Case 3: 𝑣 is of the form đ‘€đ‘ą,𝑱â€Č for some two neighbors 𝑱, 𝑱â€Č in đș.But then since 𝑆 is a vertex cover, one of 𝑱, 𝑱â€Č has to be in 𝑆 andhence 𝑆 contains a neighbor of 𝑣.We conclude that 𝑆 âˆȘ đŒ is a dominating set of size at most𝑘â€Č = 𝑘 + ℓ in đ»â€Č and hence under the assumption that VC(đș.𝑘) = 1,

DS(đ»â€Č, 𝑘â€Č) = 1.Soundness. Suppose that DS(đ», 𝑘â€Č) = 1. Then there is a domi-

nating set đ· of size at most 𝑘â€Č = 𝑘 + ℓ in đ» . For every edge 𝑱, 𝑣 inthe graph đș, if đ· contains the vertex đ‘€đ‘ą,𝑣 then we remove this ver-tex and add 𝑱 in its place. The only two neighbors of đ‘€đ‘ą,𝑣 are 𝑱 and𝑣, and since 𝑱 is a neighbor of both đ‘€đ‘ą,𝑣 and of 𝑣, replacing đ‘€đ‘ą,𝑣with 𝑣 maintains the property that it is a dominating set. Moreover,this change cannot increase the size of đ·. Thus following this mod-ification, we can assume that đ· is a dominating set of at most 𝑘 + ℓvertices that does not contain any vertices of the form đ‘€đ‘ą,𝑣.

Let đŒ be the set of isolated vertices in đș. These vertices are alsoisolated in đ» and hence must be included in đ· (an isolated ver-tex must be in any dominating set, since it has no neighbors). Welet 𝑆 = đ· ⧔ đŒ . Then |𝑆| ≀ đŒ . We claim that 𝑆 is a vertex coverin đș. Indeed, for every edge 𝑱, 𝑣 of đș, either the vertex đ‘€đ‘ą,𝑣 or

Page 468: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

468 introduction to theoretical computer science

one of its neighbors must be in 𝑆 by the dominating set property.But since we ensured 𝑆 doesn’t contain any of the vertices of theform đ‘€đ‘ą,𝑣, it must be the case that either 𝑱 or 𝑣 is in 𝑆. This showsthat 𝑆 is a vertex cover of đș of size at most 𝑘, hence proving thatVC(đș, 𝑘) = 1.

A corollary of Algorithm 14.8 and the other reduction we have seenso far is that if DS ∈ P (i.e., dominating set has a polynomial-time al-gorithm) then 3SAT ∈ P (i.e., 3SAT has a polynomial-time algorithm).By the contra-positive, if 3SAT does not have a polynomial-time algo-rithm then neither does dominating set.

Figure 14.8: Python implementation of the reductionfrom vertex cover to dominating set, together with anexample of an input graph and the resulting outputgraph. This reduction allows to transform a hypothet-ical polynomial-time algorithm for dominating set (a“whistling pig”) into a hypothetical polynomial-timealgorithm for vertex-cover (a “flying horse”).

14.5.2 Anatomy of a reduction

Figure 14.9: The four components of a reduction,illustrated for the particular reduction of vertex coverto dominating set. A reduction from problem đč toproblem đș is an algorithm that maps an input đ‘„ for đčinto an input 𝑅(đ‘„) for đș. To show that the reductionis correct we need to show the properties of efficiency:algorithm 𝑅 runs in polynomial time, completeness:if đč(đ‘„) = 1 then đș(𝑅(đ‘„)) = 1, and soundness: ifđč(𝑅(đ‘„)) = 1 then đș(đ‘„) = 1.

The reduction of Solved Exercise 14.5 gives a good illustration ofthe anatomy of a reduction. A reduction consists of four parts:‱ Algorithm description: This is the description of how the algorithm

maps an input into the output. For example, in Solved Exercise 14.5this is the description of how we map an instance (đș, 𝑘) of thevertex cover problem into an instance (đ», 𝑘â€Č) of the dominating setproblem.

Page 469: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 469

‱ Algorithm analysis: It is not enough to describe how the algorithmworks but we need to also explain why it works. In particular weneed to provide an analysis explaining why the reduction is bothefficient (i.e., runs in polynomial time) and correct (satisfies thatđș(𝑅(đ‘„)) = đč(đ‘„) for every đ‘„). Specifically, the components ofanalysis of a reduction 𝑅 include:

– Efficiency: We need to show that 𝑅 runs in polynomial time. Inmost reductions we encounter this part is straightforward, as thereductions we typically use involve a constant number of nestedloops, each involving a constant number of operations. For ex-ample, the reduction of Solved Exercise 14.5 just enumerates overthe edges and vertices of the input graph.

– Completeness: In a reduction 𝑅 demonstrating đč â‰€đ‘ đș, thecompleteness condition is the condition that for every đ‘„ ∈ 0, 1∗,if đč(đ‘„) = 1 then đș(𝑅(đ‘„)) = 1. Typically we construct thereduction to ensure that this holds, by giving a way to map a“certificate/solution” certifying that đč(đ‘„) = 1 into a solutioncertifying that đș(𝑅(đ‘„)) = 1. For example, in Solved Exercise 14.5we constructed the graph đ» such that for every vertex cover 𝑆in đș, the set 𝑆 âˆȘ đŒ (where đŒ is the isolated vertices) would be adominating set in đ» .

– Soundness: This is the condition that if đč(đ‘„) = 0 thenđș(𝑅(đ‘„)) = 0 or (taking the contrapositive) if đș(𝑅(đ‘„)) = 1 thenđč(đ‘„) = 1. This is sometimes straightforward but can often beharder to show than the completeness condition, and in moreadvanced reductions (such as the reduction SAT â‰€đ‘ ISETof Theorem 14.6) demonstrating soundness is the main partof the analysis. For example, in Solved Exercise 14.5 to showsoundness we needed to show that for every dominating set đ· inthe graph đ» , there exists a vertex cover 𝑆 of size at most |đ·| − ℓin the graph đș (where ℓ is the number of isolated vertices).This was challenging since the dominating set đ· might not benecessarily the one we “had in mind”. In particular, in the proofabove we needed to modify đ· to ensure that it does not containvertices of the form đ‘€đ‘ą,𝑣, and it was important to show that thismodification still maintains the property that đ· is a dominatingset, and also does not make it bigger.

Whenever you need to provide a reduction, you should make surethat your description has all these components. While it is sometimestempting to weave together the description of the reduction and itsanalysis, it is usually clearer if you separate the two, and also breakdown the analysis to its three components of efficiency, completeness,and soundness.

Page 470: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

470 introduction to theoretical computer science

14.6 REDUCING INDEPENDENT SET TO MAXIMUM CUT

We now show that the independent set problem reduces to the maxi-mum cut (or “max cut”) problem, modeled as the function MAXCUTthat on input a pair (đș, 𝑘) outputs 1 iff đș contains a cut of at least 𝑘edges. Since both are graph problems, a reduction from independentset to max cut maps one graph into the other, but as we will see theoutput graph does not have to have the same vertices or edges as theinput graph.

Theorem 14.9 — Hardness of Max Cut. ISET â‰€đ‘ MAXCUT

Proof Idea:

We will map a graph đș into a graph đ» such that a large indepen-dent set in đș becomes a partition cutting many edges in đ» . We canthink of a cut in đ» as coloring each vertex either “blue” or “red”. Wewill add a special “source” vertex 𝑠∗, connect it to all other vertices,and assume without loss of generality that it is colored blue. Hencethe more vertices we color red, the more edges from 𝑠∗ we cut. Now,for every edge 𝑱, 𝑣 in the original graph đș we will add a special “gad-get” which will be a small subgraph that involves 𝑱,𝑣, the source 𝑠∗,and two other additional vertices. We design the gadget in a way sothat if the red vertices are not an independent set in đș then the cor-responding cut in đ» will be “penalized” in the sense that it wouldnot cut as many edges. Once we set for ourselves this objective, it isnot hard to find a gadget that achieves it− see the proof below. Onceagain the takeaway technique is to use (this time a slightly moreclever) gadget.⋆

Figure 14.10: In the reduction of ISET to MAXCUTwe map an 𝑛-vertex 𝑚-edge graph đș into the𝑛 + 2𝑚 + 1 vertex and 𝑛 + 5𝑚 edge graph đ» asfollows. The graph đ» contains a special “source”vertex 𝑠∗,𝑛 vertices 𝑣0, 
 , 𝑣𝑛−1, and 2𝑚 ver-tices 𝑒00, 𝑒10, 
 , 𝑒0𝑚−1, 𝑒1𝑚−1 with each pair cor-responding to an edge of đș. We put an edge be-tween 𝑠∗ and 𝑣𝑖 for every 𝑖 ∈ [𝑛], and if the 𝑡-thedge of đș was (𝑣𝑖, 𝑣𝑗) then we add the five edges(𝑠∗, 𝑒0𝑡 ), (𝑠∗, 𝑒1𝑡 ), (𝑣𝑖, 𝑒0𝑡 ), (𝑣𝑗, 𝑒1𝑡 ), (𝑒0𝑡 , 𝑒1𝑡 ). The intentis that if cut at most one of 𝑣𝑖, 𝑣𝑗 from 𝑠∗ then we’llbe able to cut 4 out of these five edges, while if wecut both 𝑣𝑖 and 𝑣𝑗 from 𝑠∗ then we’ll be able to cut atmost three of them.

Proof of Theorem 14.9. We will transform a graph đș of 𝑛 vertices and 𝑚edges into a graph đ» of 𝑛 + 1 + 2𝑚 vertices and 𝑛 + 5𝑚 edges in thefollowing way (see also Fig. 14.10). The graph đ» contains all vertices

Page 471: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 471

Figure 14.11: In the reduction of independent setto max cut, for every 𝑡 ∈ [𝑚], we have a “gadget”corresponding to the 𝑡-th edge 𝑒 = 𝑣𝑖, 𝑣𝑗 in theoriginal graph. If we think of the side of the cutcontaining the special source vertex 𝑠∗ as “white” andthe other side as “blue”, then the leftmost and centerfigures show that if 𝑣𝑖 and 𝑣𝑗 are not both blue thenwe can cut four edges from the gadget. In contrast,by enumerating all possibilities one can verify thatif both 𝑱 and 𝑣 are blue, then no matter how wecolor the intermediate vertices 𝑒0𝑡 , 𝑒1𝑡 , we will cut atmost three edges from the gadget. The figure abovecontains only the gadget edges and ignores the edgesconnecting 𝑠∗ to the vertices 𝑣0, 
 , 𝑣𝑛−1.

of đș (though not the edges between them!) and in addition đ» alsohas:

* A special vertex 𝑠∗ that is connected to all the vertices of đș* For every edge 𝑒 = 𝑱, 𝑣 ∈ 𝐾(đș), two vertices 𝑒0, 𝑒1 such that 𝑒0

is connected to 𝑱 and 𝑒1 is connected to 𝑣, and moreover we add theedges 𝑒0, 𝑒1, 𝑒0, 𝑠∗, 𝑒1, 𝑠∗ to đ» .

Theorem 14.9 will follow by showing that đș contains an indepen-dent set of size at least 𝑘 if and only if đ» has a cut cutting at least𝑘 + 4𝑚 edges. We now prove both directions of this equivalence:

Part 1: Completeness. If đŒ is an independent 𝑘-sized set in đș, thenwe can define 𝑆 to be a cut in đ» of the following form: we let 𝑆 con-tain all the vertices of đŒ and for every edge 𝑒 = 𝑱, 𝑣 ∈ 𝐾(đș), if 𝑱 ∈ đŒand 𝑣 ∉ đŒ then we add 𝑒1 to 𝑆; if 𝑱 ∉ đŒ and 𝑣 ∈ đŒ then we add 𝑒0 to𝑆; and if 𝑱 ∉ đŒ and 𝑣 ∉ đŒ then we add both 𝑒0 and 𝑒1 to 𝑆. (We don’tneed to worry about the case that both 𝑱 and 𝑣 are in đŒ since it is anindependent set.) We can verify that in all cases the number of edgesfrom 𝑆 to its complement in the gadget corresponding to 𝑒 will be four(see Fig. 14.11). Since 𝑠∗ is not in 𝑆, we also have 𝑘 edges from 𝑠∗ to đŒ ,for a total of 𝑘 + 4𝑚 edges.

Part 2: Soundness. Suppose that 𝑆 is a cut in đ» that cuts at leastđ¶ = 𝑘 + 4𝑚 edges. We can assume that 𝑠∗ is not in 𝑆 (otherwise wecan “flip” 𝑆 to its complement 𝑆, since this does not change the sizeof the cut). Now let đŒ be the set of vertices in 𝑆 that correspond to theoriginal vertices of đș. If đŒ was an independent set of size 𝑘 then wewould be done. This might not always be the case but we will see thatif đŒ is not an independent set then it’s also larger than 𝑘. Specifically,we define 𝑚𝑖𝑛 = |𝐾(đŒ, đŒ)| be the set of edges in đș that are containedin đŒ and let 𝑚𝑜𝑱𝑡 = 𝑚 − 𝑚𝑖𝑛 (i.e., if đŒ is an independent set then𝑚𝑖𝑛 = 0 and 𝑚𝑜𝑱𝑡 = 𝑚). By the properties of our gadget we knowthat for every edge 𝑱, 𝑣 of đș, we can cut at most three edges whenboth 𝑱 and 𝑣 are in 𝑆, and at most four edges otherwise. Hence thenumber đ¶ of edges cut by 𝑆 satisfies đ¶ ≀ |đŒ| + 3𝑚𝑖𝑛 + 4𝑚𝑜𝑱𝑡 =|đŒ| + 3𝑚𝑖𝑛 + 4(𝑚 − 𝑚𝑖𝑛) = |đŒ| + 4𝑚 − 𝑚𝑖𝑛. Since đ¶ = 𝑘 + 4𝑚 weget that |đŒ| − 𝑚𝑖𝑛 ≄ 𝑘. Now we can transform đŒ into an independentset đŒâ€Č by going over every one of the 𝑚𝑖𝑛 edges that are inside đŒ andremoving one of the endpoints of the edge from it. The resulting set đŒâ€Čis an independent set in the graph đș of size |đŒ| − 𝑚𝑖𝑛 ≄ 𝑘 and so thisconcludes the proof of the soundness condition.

Page 472: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

472 introduction to theoretical computer science

Figure 14.12: The reduction of independent set tomax cut. On the righthand side is Python codeimplementing the reduction. On the lefthand side isan example output of the reduction where we applyit to the independent set instance that is obtained byrunning the reduction of Theorem 14.6 on the 3CNFformula (đ‘„0 âˆšđ‘„3 âˆšđ‘„2)∧(đ‘„0 âˆšđ‘„1 âˆšđ‘„2)∧(đ‘„1 âˆšđ‘„2 âˆšđ‘„3).

Figure 14.13: We can transform a 3SAT formula 𝜑 intoa graph đș such that the longest path in the graph đșwould correspond to a satisfying assignment in 𝜑. Inthis graph, the black colored part corresponds to thevariables of 𝜑 and the blue colored part correspondsto the vertices. A sufficiently long path would have tofirst “snake” through the black part, for each variablechoosing either the “upper path” (correspondingto assigning it the value True) or the “lower path”(corresponding to assigning it the value False). Thento achieve maximum length the path would traversethrough the blue part, where to go between twovertices corresponding to a clause such as đ‘„17 √ đ‘„32 âˆšđ‘„57, the corresponding vertices would have to havebeen not traversed before.

Figure 14.14: The graph above with the longest pathmarked on it, the part of the path corresponding tovariables is in green and part corresponding to theclauses is in pink.

14.7 REDUCING 3SAT TO LONGEST PATH

Note: This section is still a little messy; feel free to skip it or just readit without going into the proof details. The proof appears in Section7.5 in Sipser’s book.

One of the most basic algorithms in Computer Science is Dijkstra’salgorithm to find the shortest path between two vertices. We now showthat in contrast, an efficient algorithm for the longest path problemwould imply a polynomial-time algorithm for 3SAT.

Theorem 14.10 — Hardness of longest path.3SAT â‰€đ‘ LONGPATH (14.6)

Proof Idea:

To prove Theorem 14.10 need to show how to transform a 3CNFformula 𝜑 into a graph đș and two vertices 𝑠, 𝑡 such that đș has a pathof length at least 𝑘 if and only if 𝜑 is satisfiable. The idea of the reduc-tion is sketched in Fig. 14.13 and Fig. 14.14. We will construct a graphthat contains a potentially long “snaking path” that corresponds toall variables in the formula. We will add a “gadget” correspondingto each clause of 𝜑 in a way that we would only be able to use thegadgets if we have a satisfying assignment.⋆def TSAT2LONGPATH(φ):

"""Reduce 3SAT to LONGPATH"""def var(v): # return variable and True/False depending

if positive or negatedreturn int(v[2:]),False if v[0]=="ÂŹ" else

int(v[1:]),Truen = numvars(φ)clauses = getclauses(φ)m = len(clauses)G =Graph()

Page 473: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 473

G.edge("start","start_0")for i in range(n): # add 2 length-m paths per variable

G.edge(f"start_i",f"v_i_0_T")G.edge(f"start_i",f"v_i_0_F")for j in range(m-1):

G.edge(f"v_i_j_T",f"v_i_j+1_T")G.edge(f"v_i_j_F",f"v_i_j+1_F")

G.edge(f"v_i_m-1_T",f"end_i")G.edge(f"v_i_m-1_F",f"end_i")if i<n-1:

G.edge(f"end_i",f"start_i+1")G.edge(f"end_n-1","start_clauses")for j,C in enumerate(clauses): # add gadget for each

clausefor v in enumerate(C):

i,sign = var(v[1])s = "F" if sign else "T"G.edge(f"C_j_in",f"v_i_j_s")G.edge(f"v_i_j_s",f"C_j_out")

if j<m-1:G.edge(f"C_j_out",f"C_j+1_in")

G.edge("start_clauses","C_0_in")G.edge(f"C_m-1_out","end")return G, 1+n*(m+1)+1+2*m+1

Proof of Theorem 14.10. We build a graph đș that “snakes” from 𝑠 to 𝑡 asfollows. After 𝑠 we add a sequence of 𝑛 long loops. Each loop has an“upper path” and a “lower path”. A simple path cannot take both theupper path and the lower path, and so it will need to take exactly oneof them to reach 𝑠 from 𝑡.

Our intention is that a path in the graph will correspond to an as-signment đ‘„ ∈ 0, 1𝑛 in the sense that taking the upper path in the 𝑖𝑡ℎloop corresponds to assigning đ‘„đ‘– = 1 and taking the lower path cor-responds to assigning đ‘„đ‘– = 0. When we are done snaking through allthe 𝑛 loops corresponding to the variables to reach 𝑡 we need to passthrough 𝑚 “obstacles”: for each clause 𝑗 we will have a small gad-get consisting of a pair of vertices 𝑠𝑗, 𝑡𝑗 that have three paths betweenthem. For example, if the 𝑗𝑡ℎ clause had the form đ‘„17 √ đ‘„55 √ đ‘„72 thenone path would go through a vertex in the lower loop correspondingto đ‘„17, one path would go through a vertex in the upper loop corre-sponding to đ‘„55 and the third would go through the lower loop cor-responding to đ‘„72. We see that if we went in the first stage accordingto a satisfying assignment then we will be able to find a free vertex totravel from 𝑠𝑗 to 𝑡𝑗. We link 𝑡1 to 𝑠2, 𝑡2 to 𝑠3, etc and link 𝑡𝑚 to 𝑡. Thus

Page 474: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

474 introduction to theoretical computer science

Figure 14.15: The result of applying the reduction of3SAT to LONGPATH to the formula (đ‘„0 √ ÂŹđ‘„3 √ đ‘„2) ∧(ÂŹđ‘„0 √ đ‘„1 √ ÂŹđ‘„2) ∧ (đ‘„1 √ đ‘„2 √ ÂŹđ‘„3).

a satisfying assignment would correspond to a path from 𝑠 to 𝑡 thatgoes through one path in each loop corresponding to the variables,and one path in each loop corresponding to the clauses. We can makethe loop corresponding to the variables long enough so that we musttake the entire path in each loop in order to have a fighting chance ofgetting a path as long as the one corresponds to a satisfying assign-ment. But if we do that, then the only way if we are able to reach 𝑡 isif the paths we took corresponded to a satisfying assignment, sinceotherwise we will have one clause 𝑗 where we cannot reach 𝑡𝑗 from 𝑠𝑗without using a vertex we already used before.

14.7.1 Summary of relationsWe have shown that there are a number of functions đč for which wecan prove a statement of the form “If đč ∈ P then 3SAT ∈ P”. Hencecoming up with a polynomial-time algorithm for even one of theseproblems will entail a polynomial-time algorithm for 3SAT (see forexample Fig. 14.16). In Chapter 15 we will show the inverse direction(“If 3SAT ∈ P then đč ∈ P”) for these functions, hence allowing us toconclude that they have equivalent complexity to 3SAT.

Figure 14.16: So far we have shown that P ⊆ EXPand that several problems we care about such as3SAT and MAXCUT are in EXP but it is not knownwhether or not they are in EXP. However, since3SAT â‰€đ‘ MAXCUT we can rule out the possiblitythat MAXCUT ∈ P but 3SAT ∉ P. The relation ofP/poly to the class EXP is not known. We know thatEXP does not contain P/poly since the latter evencontains uncomputable functions, but we do notknow whether ot not EXP ⊆ P/poly (though it isbelieved that this is not the case and in particular thatboth 3SAT and MAXCUT are not in P/poly). Chapter Recap

‱ The computational complexity of many seeminglyunrelated computational problems can be relatedto one another through the use of reductions.

‱ If đč â‰€đ‘ đș then a polynomial-time algorithmfor đș can be transformed into a polynomial-timealgorithm for đč .

‱ Equivalently, if đč â‰€đ‘ đș and đč does not have apolynomial-time algorithm then neither does đș.

‱ We’ve developed many techniques to show that3SAT â‰€đ‘ đč for interesting functions đč . Sometimeswe can do so by using transitivity of reductions: if3SAT â‰€đ‘ đș and đș â‰€đ‘ đč then 3SAT â‰€đ‘ đč .

Page 475: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

polynomial-time reductions 475

14.8 EXERCISES

14.9 BIBLIOGRAPHICAL NOTES

Several notions of reductions are defined in the literature. The notiondefined in Definition 14.1 is often known as a mapping reduction, manyto one reduction or a Karp reduction.

The maximal (as opposed to maximum) independent set is the taskof finding a “local maximum” of an independent set: an independentset 𝑆 such that one cannot add a vertex to it without losing the in-dependence property (such a set is known as a vertex cover). Unlikefinding a maximum independent set, finding a maximal independentset can be done efficiently by a greedy algorithm, but this local maxi-mum can be much smaller than the global maximum.

Reduction of independent set to max cut taken from these notes.Image of Hamiltonian Path through Dodecahedron by ChristophSommer.

We have mentioned that the line between reductions used for algo-rithm design and showing hardness is sometimes blurry. An excellentexample for this is the area of SAT Solvers (see [Gom+08]). In thisfield people use algorithms for SAT (that take exponential time in theworst case but often are much faster on many instances in practice)together with reductions of the form đč â‰€đ‘ SAT to derive algorithmsfor other functions đč of interest.

Page 476: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 477: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

15NP, NP completeness, and the Cook-Levin Theorem

“In this paper we give theorems that suggest, but do not imply, that theseproblems, as well as many others, will remain intractable perpetually”, RichardKarp, 1972

“Sad to say, but it will be many more years, if ever before we really understandthe Mystical Power of Twoness
 2-SAT is easy, 3-SAT is hard, 2-dimensionalmatching is easy, 3-dimensional matching is hard. Why? oh, Why?” EugeneLawler

So far we have shown that 3SAT is no harder than Quadratic Equa-tions, Independent Set, Maximum Cut, and Longest Path. But to showthat these problems are computationally equivalent we need to give re-ductions in the other direction, reducing each one of these problems to3SAT as well. It turns out we can reduce all three problems to 3SAT inone fell swoop.

In fact, this result extends far beyond these particular problems. Allof the problems we discussed in Chapter 14, and a great many otherproblems, share the same commonality: they are all search problems,where the goal is to decide, given an instance đ‘„, whether there existsa solution 𝑩 that satisfies some condition that can be verified in poly-nomial time. For example, in 3SAT, the instance is a formula and thesolution is an assignment to the variable; in Max-Cut the instance is agraph and the solution is a cut in the graph; and so on and so forth. Itturns out that every such search problem can be reduced to 3SAT.

15.1 THE CLASS NPTo make the above precise, we will make the following mathematicaldefinition. We define the class NP to contain all Boolean functions thatcorrespond to a search problem of the form above. That is, a Booleanfunction đč is in NP if đč has the form that on input a string đ‘„, đč(đ‘„) = 1if and only if there exists a “solution” string đ‘€ such that the pair (đ‘„, đ‘€)satisfies some polynomial-time checkable condition. Formally, NP isdefined as follows:

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Introduce the class NP capturing a great many

important computational problems‱ NP-completeness: evidence that a problem

might be intractable.‱ The P vs NP problem.

Page 478: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

478 introduction to theoretical computer science

Figure 15.1: Overview of the results of this chapter.We define NP to contain all decision problems forwhich a solution can be efficiently verified. The mainresult of this chapter is the Cook Levin Theorem (The-orem 15.6) which states that 3SAT has a polynomial-time algorithm if and only if every problem in NPhas a polynomial-time algorithm. Another way tostate this theorem is that 3SAT is NP complete. Wewill prove the Cook-Levin theorem by defining thetwo intermediate problems NANDSAT and 3NAND,proving that NANDSAT is NP complete, and thenproving that NANDSAT â‰€đ‘ 3NAND â‰€đ‘ 3SAT.

Figure 15.2: The class NP corresponds to problemswhere solutions can be efficiently verified. That is, thisis the class of functions đč such that đč(đ‘„) = 1 if thereis a “solution” đ‘€ of length polynomial in |đ‘„| that canbe verified by a polynomial-time algorithm 𝑉 .

Definition 15.1 — NP. We say that đč ∶ 0, 1∗ → 0, 1 is in NP if thereexists some integer 𝑎 > 0 and 𝑉 ∶ 0, 1∗ → 0, 1 such that 𝑉 ∈ Pand for every đ‘„ ∈ 0, 1𝑛,đč(đ‘„) = 1 ⇔ âˆƒđ‘€âˆˆ0,1𝑛𝑎 s.t. 𝑉 (đ‘„đ‘€) = 1 . (15.1)

In other words, for đč to be in NP, there needs to exist somepolynomial-time computable verification function 𝑉 , such that ifđč(đ‘„) = 1 then there must exist đ‘€ (of length polynomial in |đ‘„|) suchthat 𝑉 (đ‘„đ‘€) = 1, and if đč(đ‘„) = 0 then for every such đ‘€, 𝑉 (đ‘„đ‘€) = 0.Since the existence of this string đ‘€ certifies that đč(đ‘„) = 1, đ‘€ is oftenreferred to as a certificate, witness, or proof that đč(đ‘„) = 1.

See also Fig. 15.2 for an illustration of Definition 15.1. The nameNP stands for “nondeterministic polynomial time” and is used forhistorical reasons; see the bibiographical notes. The string đ‘€ in (15.1)is sometimes known as a solution, certificate, or witness for the instanceđ‘„.Solved Exercise 15.1 — Alternative definition of NP. Show that the conditionthat |đ‘€| = |đ‘„|𝑎 in Definition 15.1 can be replaced by the conditionthat |đ‘€| ≀ 𝑝(|đ‘„|) for some polynomial 𝑝. That is, prove that for everyđč ∶ 0, 1∗ → 0, 1, đč ∈ NP if and only if there is a polynomial-time Turing machine 𝑉 and a polynomial 𝑝 ∶ ℕ → ℕ such that forevery đ‘„ ∈ 0, 1∗ đč(đ‘„) = 1 if and only if there exists đ‘€ ∈ 0, 1∗ with|đ‘€| ≀ 𝑝(|đ‘„|) such that 𝑉 (đ‘„, đ‘€) = 1.

Page 479: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

np, np completeness, and the cook-levin theorem 479

Solution:

The “only if” direction (namely that if đč ∈ NP then there is analgorithm 𝑉 and a polynomial 𝑝 as above) follows immediatelyfrom Definition 15.1 by letting 𝑝(𝑛) = 𝑛𝑎. For the “if” direc-tion, the idea is that if a string đ‘€ is of size at most 𝑝(𝑛) for degree𝑑 polynomial 𝑝, then there is some 𝑛0 such that for all 𝑛 > 𝑛0,|đ‘€| < 𝑛𝑑+1. Hence we can encode đ‘€ by a string of exactly length𝑛𝑑+1 by padding it with 1 and an appropriate number of zeroes.Hence if there is an algorithm 𝑉 and polynomial 𝑝 as above, thenwe can define an algorithm 𝑉 â€Č that does the following on inputđ‘„, đ‘€â€Č with |đ‘„| = 𝑛 and |đ‘€â€Č| = 𝑛𝑎:‱ If 𝑛 ≀ 𝑛0 then 𝑉 â€Č(đ‘„, đ‘€â€Č) ignores đ‘€â€Č and enumerates over all đ‘€

of length at most 𝑝(𝑛) and outputs 1 if there exists đ‘€ such that𝑉 (đ‘„, đ‘€) = 1. (Since 𝑛 < 𝑛0, this only takes a constant number ofsteps.)

‱ If 𝑛 > 𝑛0 then 𝑉 â€Č(đ‘„, đ‘€â€Č) “strips out” the padding by droppingall the rightmost zeroes from đ‘€ until it reaches out the first 1(which it drops as well) and obtains a string đ‘€. If |đ‘€| ≀ 𝑝(𝑛)then 𝑉 â€Č outputs 𝑉 (đ‘„, đ‘€).Since 𝑉 runs in polynomial time, 𝑉 â€Č runs in polynomial time

as well, and by definition for every đ‘„, there exists đ‘€â€Č ∈ 0, 1|đ‘„|𝑎such that 𝑉 â€Č(đ‘„đ‘€â€Č) = 1 if and only if there exists đ‘€ ∈ 0, 1∗ with|đ‘€| ≀ 𝑝(|đ‘„|) such that 𝑉 (đ‘„đ‘€) = 1.

The definition of NP means that for every đč ∈ NP and stringđ‘„ ∈ 0, 1∗, đč(đ‘„) = 1 if and only if there is a short and efficientlyverifiable proof of this fact. That is, we can think of the function 𝑉 inDefinition 15.1 as a verifier algorithm, similar to what we’ve seen inSection 11.1. The verifier checks whether a given string đ‘€ ∈ 0, 1∗ is avalid proof for the statement “đč(đ‘„) = 1”. Essentially all proof systemsconsidered in mathematics involve line-by-line checks that can be car-ried out in polynomial time. Thus the heart of NP is asking for state-ments that have short (i.e., polynomial in the size of the statements)proof. Indeed, as we will see in Chapter 16, Kurt Gödel phrased thequestion of whether NP = P as asking whether “the mental work ofa mathematician [in proving theorems] could be completely replacedby a machine”.

RRemark 15.2 — NP not (necessarily) closed under com-plement. Definition 15.1 is asymmetric in the sense that

Page 480: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

480 introduction to theoretical computer science

there is a difference between an output of 1 and anoutput of 0. You should make sure you understandwhy this definition does not guarantee that if đč ∈ NPthen the function 1 − đč (i.e., the map đ‘„ ↩ 1 − đč(đ‘„)) isin NP as well.In fact, it is believed that there do exist functions đčsuch that đč ∈ NP but 1 − đč ∉ NP. For example, asshown below, 3SAT ∈ NP, but the function 3SAT thaton input a 3CNF formula 𝜑 outputs 1 if and only if 𝜑is not satisfiable is not known (nor believed) to be inNP. This is in contrast to the class P which does satisfythat if đč ∈ P then 1 − đč is in P as well.

15.1.1 Examples of functions in NPWe now present some examples of functions that are in the class NP.We start with the canonical example of the 3SAT function.

Example 15.3 — 3𝑆𝐮𝑇 ∈ NP. 3SAT is in NP since for every ℓ-variable formula 𝜑, 3SAT(𝜑) = 1 if and only if there exists asatisfying assignment đ‘„ ∈ 0, 1ℓ such that 𝜑(đ‘„) = 1, and wecan check this condition in polynomial time.

The above reasoning explains why 3SAT is in NP, but since thisis our first example, we will now belabor the point and expand outin full formality the precise representation of the witness đ‘€ and thealgorithm 𝑉 that demonstrate that 3SAT is in NP. Since demon-strating that functions are in NP is fairly straightforward, in futurecases we will not use as much detail, and the reader can also feelfree to skip the rest of this example.

Using Solved Exercise 15.1, it is OK if witness is of size at mostpolynomial in the input length 𝑛, rather than of precisely size 𝑛𝑎for some integer 𝑎 > 0. Specifically, we can represent a 3CNFformula 𝜑 with 𝑘 variables and 𝑚 clauses as a string of length𝑛 = 𝑂(𝑚 log 𝑘), since every one of the 𝑚 clauses involves threevariables and their negation, and the identity of each variable canbe represented using ⌈log2 𝑘⌉. We assume that every variable par-ticipates in some clause (as otherwise it can be ignored) and hencethat 𝑚 ≄ 𝑘, which in particular means that the input length 𝑛 is atleast as large as 𝑚 and 𝑘.

We can represent an assignment to the 𝑘 variables using a 𝑘-length string đ‘€. The following algorithm checks whether a given đ‘€satisfies the formula 𝜑:

Page 481: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

np, np completeness, and the cook-levin theorem 481

Algorithm 15.4 — Verifier for 3𝑆𝐮𝑇 .

Input: 3CNF formula 𝜑 on 𝑘 variables and with 𝑚clauses, string đ‘€ ∈ 0, 1𝑘

Output: 1 iff đ‘€ satisfies 𝜑1: for 𝑗 ∈ [𝑚] do2: Let ℓ1 √ ℓ2 √ ℓ𝑗 be the 𝑗-th clause of 𝜑3: if đ‘€ violates all three literals then4: return 05: end if6: end for7: return 1

Algorithm 15.4 takes 𝑂(𝑚) time to enumerate over all clauses,and will return 1 if and only if 𝑩 satisfies all the clauses.

Here are some more examples for problems in NP. For each oneof these problems we merely sketch how the witness is representedand why it is efficiently checkable, but working out the details can be agood way to get more comfortable with Definition 15.1:

‱ QUADEQ is in NP since for every ℓ-variable instance of quadraticequations 𝐾, QUADEQ(𝐾) = 1 if and only if there exists an assign-ment đ‘„ ∈ 0, 1ℓ that satisfies 𝐾. We can check the condition thatđ‘„ satisfies 𝐾 in polynomial time by enumerating over all the equa-tions in 𝐾, and for each such equation 𝑒, plug in the values of đ‘„ andverify that 𝑒 is satisfied.

‱ ISET is in NP since for every graph đș and integer 𝑘, ISET(đș, 𝑘) =1 if and only if there exists a set 𝑆 of 𝑘 vertices that contains nopair of neighbors in đș. We can check the condition that 𝑆 is anindependent set of size ≄ 𝑘 in polynomial time by first checkingthat |𝑆| ≄ 𝑘 and then enumerating over all edges 𝑱, 𝑣 in đș, andfor each such edge verify that either 𝑱 ∉ 𝑆 or 𝑣 ∉ 𝑆.

‱ LONGPATH is in NP since for every graph đș and integer 𝑘,LONGPATH(đș, 𝑘) = 1 if and only if there exists a simple path 𝑃in đș that is of length at least 𝑘. We can check the condition that 𝑃is a simple path of length 𝑘 in polynomial time by checking that ithas the form (𝑣0, 𝑣1, 
 , 𝑣𝑘) where each 𝑣𝑖 is a vertex in đș, no 𝑣𝑖 isrepeated, and for every 𝑖 ∈ [𝑘], the edge 𝑣𝑖, 𝑣𝑖+1 is present in thegraph.

‱ MAXCUT is in NP since for every graph đș and integer 𝑘,MAXCUT(đș, 𝑘) = 1 if and only if there exists a cut (𝑆, 𝑆) in đș thatcuts at least 𝑘 edges. We can check that condition that (𝑆, 𝑆) is acut of value at least 𝑘 in polynomial time by checking that 𝑆 is a

Page 482: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

482 introduction to theoretical computer science

subset of đș’s vertices and enumerating over all the edges 𝑱, 𝑣 ofđș, counting those edges such that 𝑱 ∈ 𝑆 and 𝑣 ∉ 𝑆 or vice versa.

15.1.2 Basic facts about NPThe definition of NP is one of the most important definitions of thisbook, and is worth while taking the time to digest and internalize. Thefollowing solved exercises establish some basic properties of this class.As usual, I highly recommend that you try to work out the solutionsyourself.Solved Exercise 15.2 — Verifying is no harder than solving. Prove that P ⊆ NP.

Solution:

Suppose that đč ∈ P. Define the following function 𝑉 : 𝑉 (đ‘„0𝑛) =1 iff 𝑛 = |đ‘„| and đč(đ‘„) = 1. (𝑉 outputs 0 on all other inputs.) Sinceđč ∈ P we can clearly compute 𝑉 in polynomial time as well.Let đ‘„ ∈ 0, 1𝑛 be some string. If đč(đ‘„) = 1 then 𝑉 (đ‘„0𝑛) = 1. On

the other hand, if đč(đ‘„) = 0 then for every đ‘€ ∈ 0, 1𝑛, 𝑉 (đ‘„đ‘€) = 0.Therefore, setting 𝑎 = 𝑏 = 1, we see that 𝑉 satisfies (15.1), and es-tablishes that đč ∈ NP.

RRemark 15.5 — NP does not mean non-polynomial!.People sometimes think that NP stands for “non poly-nomial time”. As Solved Exercise 15.2 shows, this isfar from the truth, and in fact every polynomial-timecomputable function is in NP as well.If đč is in NP it certainly does not mean that đč is hardto compute (though it does not, as far as we know,necessarily mean that it’s easy to compute either).Rather, it means that đč is easy to verify, in the technicalsense of Definition 15.1.

Solved Exercise 15.3 — NP is in exponential time. Prove that NP ⊆ EXP.

Solution:

Suppose that đč ∈ NP and let 𝑉 be the polynomial-time com-putable function that satisfies (15.1) and 𝑎 the correspondingconstant. Then given every đ‘„ ∈ 0, 1𝑛, we can check whetherđč(đ‘„) = 1 in time 𝑝𝑜𝑙𝑩(𝑛) ⋅ 2𝑛𝑎 = 𝑜(2𝑛𝑎+1) by enumerating overall the 2𝑛𝑎 strings đ‘€ ∈ 0, 1𝑛𝑎 and checking whether 𝑉 (đ‘„đ‘€) = 1,in which case we return 1. If 𝑉 (đ‘„đ‘€) = 0 for every such đ‘€ then wereturn 0. By construction, the algorithm above will run in time at

Page 483: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

np, np completeness, and the cook-levin theorem 483

most exponential in its input length and by the definition of NP itwill return đč(đ‘„) for every đ‘„.

Solved Exercise 15.2 and Solved Exercise 15.3 together imply that

P ⊆ NP ⊆ EXP . (15.2)

The time hierarchy theorem (Theorem 13.9) implies that P ⊊ EXPand hence at least one of the two inclusions P ⊆ NP or NP ⊆ EXPis strict. It is believed that both of them are in fact strict inclusions.That is, it is believed that there are functions in NP that cannot becomputed in polynomial time (this is the P ≠ NP conjecture) andthat there are functions đč in EXP for which we cannot even effi-ciently certify that đč(đ‘„) = 1 for a given input đ‘„. One function đčthat is believed to lie in EXP ⧔ NP is the function 3SAT defined as3SAT(𝜑) = 1 − 3SAT(𝜑) for every 3CNF formula 𝜑. The conjecturethat 3SAT ∉ NP is known as the “NP ≠ co − NP” conjecture. Itimplies the P ≠ NP conjecture (see Exercise 15.2).

We have previously informally equated the notion of đč â‰€đ‘ đș withđč being “no harder than đș” and in particular have seen in SolvedExercise 14.1 that if đș ∈ P and đč â‰€đ‘ đș, then đč ∈ P as well. Thefollowing exercise shows that if đč â‰€đ‘ đș then it is also “no harder toverify” than đș. That is, regardless of whether or not it is in P, if đș hasthe property that solutions to it can be efficiently verified, then so doesđč .Solved Exercise 15.4 — Reductions and NP. Let đč, đș ∶ 0, 1∗ → 0, 1.Show that if đč â‰€đ‘ đș and đș ∈ NP then đč ∈ NP.

Solution:

Suppose that đș is in NP and in particular there exists 𝑎 and 𝑉 ∈P such that for every 𝑩 ∈ 0, 1∗, đș(𝑩) = 1 ⇔ âˆƒđ‘€âˆˆ0,1|𝑩|𝑎 𝑉 (đ‘Šđ‘€) = 1.Suppose also that đč â‰€đ‘ đș and so in particular there is a 𝑛𝑏-time computable function 𝑅 such that đč(đ‘„) = đș(𝑅(đ‘„)) for allđ‘„ ∈ 0, 1∗. Define 𝑉 â€Č to be a Turing Machine that on input a pair(đ‘„, đ‘€) computes 𝑩 = 𝑅(đ‘„) and returns 1 if and only if |đ‘€| = |𝑩|𝑎and 𝑉 (đ‘Šđ‘€) = 1. Then 𝑉 â€Č runs in polynomial time, and for everyđ‘„ ∈ 0, 1∗, đč(đ‘„) = 1 iff there exists đ‘€ of size |𝑅(đ‘„)|𝑎 which is atmost polynomial in |đ‘„| such that 𝑉 â€Č(đ‘„, đ‘€) = 1, hence demonstratingthat đč ∈ NP.

Page 484: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

484 introduction to theoretical computer science

15.2 FROM NP TO 3SAT: THE COOK-LEVIN THEOREM

We have seen several examples of problems for which we do not knowif their best algorithm is polynomial or exponential, but we can showthat they are in NP. That is, we don’t know if they are easy to solve, butwe do know that it is easy to verify a given solution. There are many,many, many, more examples of interesting functions we would like tocompute that are easily shown to be in NP. What is quite amazing isthat if we can solve 3SAT then we can solve all of them!

The following is one of the most fundamental theorems in Com-puter Science:

Theorem 15.6 — Cook-Levin Theorem. For every đč ∈ NP, đč â‰€đ‘ 3SAT.We will soon show the proof of Theorem 15.6, but note that it im-

mediately implies that QUADEQ, LONGPATH, and MAXCUT allreduce to 3SAT. Combining it with the reductions we’ve seen in Chap-ter 14, it implies that all these problems are equivalent! For example,to reduce QUADEQ to LONGPATH, we can first reduce QUADEQ to3SAT using Theorem 15.6 and use the reduction we’ve seen in Theo-rem 14.10 from 3SAT to LONGPATH. That is, since QUADEQ ∈ NP,Theorem 15.6 implies that QUADEQ â‰€đ‘ 3SAT, and Theorem 14.10implies that 3SAT â‰€đ‘ LONGPATH, which by the transitivity of reduc-tions (Solved Exercise 14.2) means that QUADEQ â‰€đ‘ LONGPATH.Similarly, since LONGPATH ∈ NP, we can use Theorem 15.6 andTheorem 14.4 to show that LONGPATH â‰€đ‘ 3SAT â‰€đ‘ QUADEQ,concluding that LONGPATH and QUADEQ are computationallyequivalent.

There is of course nothing special about QUADEQ and LONGPATHhere: by combining (15.6) with the reductions we saw, we see that justlike 3SAT, every đč ∈ NP reduces to LONGPATH, and the same is truefor QUADEQ and MAXCUT. All these problems are in some sense“the hardest in NP” since an efficient algorithm for any one of themwould imply an efficient algorithm for all the problems in NP. Thismotivates the following definition:

Definition 15.7 — NP-hardness and NP-completeness. Let đș ∶ 0, 1∗ →0, 1. We say that đș is NP hard if for every đč ∈ NP, đč â‰€đ‘ đș.We say that đș is NP complete if đș is NP hard and đș ∈ NP.

The Cook-Levin Theorem (Theorem 15.6) can be rephrased assaying that 3SAT is NP hard, and since it is also in NP, this means that3SAT is NP complete. Together with the reductions of Chapter 14,Theorem 15.6 shows that despite their superficial differences, 3SAT,quadratic equations, longest path, independent set, and maximum

Page 485: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

np, np completeness, and the cook-levin theorem 485

Figure 15.3: The world if P ≠ NP (left) and P = NP(right). In the former case the set of NP-completeproblems is disjoint from P and Ladner’s theoremshows that there exist problems that are neither inP nor are NP-complete. (There are remarkably fewnatural candidates for such problems, with someprominent examples being decision variants ofproblems such as integer factoring, lattice shortestvector, and finding Nash equilibria.) In the latter casethat P = NP the notion of NP-completeness loses itsmeaning, as essentially all functions in P (save for thetrivial constant zero and constant one functions) areNP-complete.

Figure 15.4: A rough illustration of the (conjectured)status of problems in exponential time. Darker colorscorrespond to higher running time, and the circle inthe middle is the problems in P. NP is a (conjecturedto be proper) superclass of P and the NP-completeproblems (or NPC for short) are the “hardest” prob-lems in NP, in the sense that a solution for one ofthem implies a solution for all other problems in NP.It is conjectured that all the NP-complete problemsrequire at least exp(𝑛𝜖) time to solve for a constant𝜖 > 0, and many require exp(Ω(𝑛)) time. The per-manent is not believed to be contained in NP thoughit is NP-hard, which means that a polynomial-timealgorithm for it implies that P = NP.

cut, are all NP-complete. Many thousands of additional problemshave been shown to be NP-complete, arising from all the sciences,mathematics, economics, engineering and many other fields. (For afew examples, see this Wikipedia page and this website.)

Big Idea 22 If a single NP-complete has a polynomial-time algo-rithm, then there is such an algorithm for every decision problem thatcorresponds to the existence of an efficiently-verifiable solution.

15.2.1 What does this mean?As we’ve seen in Solved Exercise 15.2, P ⊆ NP. The most famous con-jecture in Computer Science is that this containment is strict. That is,it is widely conjectured that P ≠ NP. One way to refute the conjec-ture that P ≠ NP is to give a polynomial-time algorithm for even asingle one of the NP-complete problems such as 3SAT, Max Cut, orthe thousands of others that have been studied in all fields of humanendeavors. The fact that these problems have been studied by so manypeople, and yet not a single polynomial-time algorithm for any ofthem has been found, supports that conjecture that indeed P ≠ NP. Infact, for many of these problems (including all the ones we mentionedabove), we don’t even know of a 2𝑜(𝑛)-time algorithm! However, to thefrustration of computer scientists, we have not yet been able to provethat P ≠ NP or even rule out the existence of an 𝑂(𝑛)-time algorithmfor 3SAT. Resolving whether or not P = NP is known as the P vs NPproblem. A million-dollar prize has been offered for the solution ofthis problem, a popular book has been written, and every year a newpaper comes out claiming a proof of P = NP or P ≠ NP, only to witherunder scrutiny.

One of the mysteries of computation is that people have observed acertain empirical “zero-one law” or “dichotomy” in the computationalcomplexity of natural problems, in the sense that many natural prob-lems are either in P (often in TIME(𝑂(𝑛)) or TIME(𝑂(𝑛2))), or theyare are NP hard. This is related to the fact that for most natural prob-lems, the best known algorithm is either exponential or polynomial,with not too many examples where the best running time is somestrange intermediate complexity such as 22√log𝑛 . However, it is be-lieved that there exist problems in NP that are neither in P nor are NP-complete, and in fact a result known as “Ladner’s Theorem” showsthat if P ≠ NP then this is indeed the case (see also Exercise 15.1 andFig. 15.3).

Page 486: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

486 introduction to theoretical computer science

15.2.2 The Cook-Levin Theorem: Proof outlineWe will now prove the Cook-Levin Theorem, which is the underpin-ning to a great web of reductions from 3SAT to thousands of problemsacross many great fields. Some problems that have been shown to beNP-complete include: minimum-energy protein folding, minimumsurface-area foam configuration, map coloring, optimal Nash equi-librium, quantum state entanglement, minimum supersequence ofa genome, minimum codeword problem, shortest vector in a lattice,minimum genus knots, positive Diophantine equations, integer pro-gramming, and many many more. The worst-case complexity of allthese problems is (up to polynomial factors) equivalent to that of3SAT, and through the Cook-Levin Theorem, to all problems in NP.

To prove Theorem 15.6 we need to show that đč â‰€đ‘ 3SAT for everyđč ∈ NP. We will do so in three stages. We define two intermediateproblems: NANDSAT and 3NAND. We will shortly show the def-initions of these two problems, but Theorem 15.6 will follow fromcombining the following three results:

1. NANDSAT is NP hard (Lemma 15.8).

2. NANDSAT â‰€đ‘ 3NAND (Lemma 15.9).

3. 3NAND â‰€đ‘ 3SAT (Lemma 15.10).

By the transitivity of reductions, it will follow that for every đč ∈NP, đč â‰€đ‘ NANDSAT â‰€đ‘ 3NAND â‰€đ‘ 3SAT (15.3)

hence establishing Theorem 15.6.We will prove these three results Lemma 15.8, Lemma 15.9 and

Lemma 15.10 one by one, providing the requisite definitions as we goalong.

15.3 THE NANDSAT PROBLEM, AND WHY IT IS NP HARD

The function NANDSAT ∶ 0, 1∗ → 0, 1 is defined as follows:

‱ The input to NANDSAT is a string 𝑄 representing a NAND-CIRCprogram (or equivalently, a circuit with NAND gates).

‱ The output of NANDSAT on input 𝑄 is 1 if and only if there exists astring đ‘€ ∈ 0, 1𝑛 (where 𝑛 is the number of inputs to 𝑄) such that𝑄(đ‘€) = 1.

Solved Exercise 15.5 — đ‘đŽđ‘đ·đ‘†đŽđ‘‡ ∈ NP. Prove that NANDSAT ∈ NP.

Page 487: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

np, np completeness, and the cook-levin theorem 487

Solution:

We have seen that the circuit (or straightline program) evalua-tion problem can be computed in polynomial time. Specifically,given a NAND-CIRC program 𝑄 of 𝑠 lines and 𝑛 inputs, andđ‘€ ∈ 0, 1𝑛, we can evaluate 𝑄 on the input đ‘€ in time which ispolynomial in 𝑠 and hence verify whether or not 𝑄(đ‘€) = 1.

We now prove that NANDSAT is NP hard.Lemma 15.8 NANDSAT is NP hard.

Proof Idea:

The proof closely follows the proof that P ⊆ P/poly (Theorem 13.12, see also Section 13.6.2). Specifically, if đč ∈ NP then there is a poly-nomial time Turing machine 𝑀 and positive integer 𝑎 such that forevery đ‘„ ∈ 0, 1𝑛, đč(đ‘„) = 1 iff there is some đ‘€ ∈ 0, 1𝑛𝑎 such that𝑀(đ‘„đ‘€) = 1. The proof that P ⊆ P/poly gave us way (via “unrolling theloop”) to come up in polynomial time with a Boolean circuit đ¶ on 𝑛𝑎inputs that computes the function đ‘€ ↩ 𝑀(đ‘„đ‘€). We can then translateđ¶ into an equivalent NAND circuit (or NAND-CIRC program) 𝑄. Wesee that there is a string đ‘€ ∈ 0, 1𝑛𝑎 such that 𝑄(đ‘€) = 1 if and only ifthere is such đ‘€ satisfying 𝑀(đ‘„đ‘€) = 1 which (by definition) happens ifand only if đč(đ‘„) = 1. Hence the translation of đ‘„ into the circuit 𝑄 is areduction showing đč â‰€đ‘ NANDSAT.⋆

PThe proof is a little bit technical but ultimately followsquite directly from the definition of NP, as well as theability to “unroll the loop” of NAND-TM programs asdiscussed in Section 13.6.2. If you find it confusing, tryto pause here and think how you would implementin your favorite programming language the functionunroll which on input a NAND-TM program 𝑃and numbers 𝑇 , 𝑛 outputs an 𝑛-input NAND-CIRCprogram 𝑄 of 𝑂(|𝑇 |) lines such that for every input𝑧 ∈ 0, 1𝑛, if 𝑃 halts on 𝑧 within at most 𝑇 steps andoutputs 𝑩, then 𝑄(𝑧) = 𝑩.

Proof of Lemma 15.8. Let đč ∈ NP. To prove Lemma 15.8 we need togive a polynomial-time computable function that will map every đ‘„âˆ— ∈0, 1∗ to a NAND-CIRC program 𝑄 such that đč(đ‘„) = NANDSAT(𝑄).

Let đ‘„âˆ— ∈ 0, 1∗ be such a string and let 𝑛 = |đ‘„âˆ—| be its length. ByDefinition 15.1 there exists 𝑉 ∈ P and positive 𝑎ℕ such that đč(đ‘„âˆ—) = 1if and only if there exists đ‘€ ∈ 0, 1𝑛𝑎 satisfying 𝑉 (đ‘„âˆ—đ‘€) = 1.

Page 488: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

488 introduction to theoretical computer science

Let 𝑚 = 𝑛𝑎. Since 𝑉 ∈ P there is some NAND-TM program 𝑃 ∗ thatcomputes 𝑉 on inputs of the form đ‘„đ‘€ with đ‘„ ∈ 0, 1𝑛 and đ‘€ ∈ 0, 1𝑚in at most (𝑛 + 𝑚)𝑐 time for some constant 𝑐. Using our “unrollingthe loop NAND-TM to NAND compiler” of Theorem 13.14, we canobtain a NAND-CIRC program 𝑄â€Č that has 𝑛 + 𝑚 inputs and at most𝑂((𝑛 + 𝑚)2𝑐) lines such that 𝑄â€Č(đ‘„đ‘€) = 𝑃 ∗(đ‘„đ‘€) for every đ‘„ ∈ 0, 1𝑛and đ‘€ ∈ 0, 1𝑚.

We can then use a simple “hardwiring” technique, reminiscent ofRemark 9.11 to map 𝑄â€Č into a circuit/NAND-CIRC program 𝑄 on 𝑚inputs such that 𝑄(đ‘€) = 𝑄â€Č(đ‘„âˆ—đ‘€) for every đ‘€ ∈ 0, 1𝑚.

CLAIM: There is a polynomial-time algorithm that on input aNAND-CIRC program 𝑄â€Č on 𝑛 + 𝑚 inputs and đ‘„âˆ— ∈ 0, 1𝑛, outputsa NAND-CIRC program 𝑄 such that for every đ‘€ ∈ 0, 1𝑛, 𝑄(đ‘€) =𝑄â€Č(đ‘„âˆ—đ‘€).

PROOF OF CLAIM: We can do so by adding a few lines to ensurethat the variables zero and one are 0 and 1 respectively, and thensimply replacing any reference in 𝑄â€Č to an input đ‘„đ‘– with 𝑖 ∈ [𝑛] thecorresponding value based on đ‘„âˆ—đ‘– . See Fig. 15.5 for an implementationof this reduction in Python.

Our final reduction maps an input đ‘„âˆ—, into the NAND-CIRC pro-gram 𝑄 obtained above. By the above discussion, this reduction runsin polynomial time. Since we know that đč(đ‘„âˆ—) = 1 if and only if thereexists đ‘€ ∈ 0, 1𝑚 such that 𝑃 ∗(đ‘„âˆ—đ‘€) = 1, this means that đč(đ‘„âˆ—) = 1 ifand only if NANDSAT(𝑄) = 1, which is what we wanted to prove.

Figure 15.5: Given an 𝑇 -line NAND-CIRC program𝑄 that has 𝑛 + 𝑚 inputs and some đ‘„âˆ— ∈ 0, 1𝑛,we can transform 𝑄 into a 𝑇 + 3 line NAND-CIRCprogram 𝑄â€Č that computes the map đ‘€ ↩ 𝑄(đ‘„âˆ—đ‘€)for đ‘€ ∈ 0, 1𝑚 by simply adding code to computethe zero and one constants, replacing all references toX[𝑖] with either zero or one depending on the valueof đ‘„âˆ—đ‘– , and then replacing the remaining referencesto X[𝑗] with X[𝑗 − 𝑛]. Above is Python code thatimplements this transformation, as well as an exampleof its execution on a simple program.

15.4 THE 3NAND PROBLEM

The 3NAND problem is defined as follows:

‱ The input is a logical formula ι on a set of variables 𝑧0, 
 , 𝑧𝑟−1which is an AND of constraints of the form 𝑧𝑖 = NAND(𝑧𝑗, 𝑧𝑘).

Page 489: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

np, np completeness, and the cook-levin theorem 489

‱ The output is 1 if and only if there is an input 𝑧 ∈ 0, 1𝑟 thatsatisfies all of the constraints.

For example, the following is a 3NAND formula with 5 variablesand 3 constraints:

ι = (𝑧3 = NAND(𝑧0, 𝑧2))∧(𝑧1 = NAND(𝑧0, 𝑧2))∧(𝑧4 = NAND(𝑧3, 𝑧1)) .(15.4)

In this case 3NAND(Κ) = 1 since the assignment 𝑧 = 01010 satisfiesit. Given a 3NAND formula Κ on 𝑟 variables and an assignment 𝑧 ∈0, 1𝑟, we can check in polynomial time whether Κ(𝑧) = 1, and hence3NAND ∈ NP. We now prove that 3NAND is NP hard:Lemma 15.9 NANDSAT â‰€đ‘ 3NAND.

Proof Idea:

To prove Lemma 15.9 we need to give a polynomial-time map fromevery NAND-CIRC program 𝑄 to a 3NAND formula Κ such that thereexists đ‘€ such that 𝑄(đ‘€) = 1 if and only if there exists 𝑧 satisfying Κ.For every line 𝑖 of 𝑄, we define a corresponding variable 𝑧𝑖 of Κ. Ifthe line 𝑖 has the form foo = NAND(bar,blah) then we will add theclause 𝑧𝑖 = NAND(𝑧𝑗, 𝑧𝑘) where 𝑗 and 𝑘 are the last lines in which barand blah were written to. We will also set variables correspondingto the input variables, as well as add a clause to ensure that the finaloutput is 1. The resulting reduction can be implemented in about adozen lines of Python, see Fig. 15.6.⋆

Figure 15.6: Python code to reduce an instance 𝑄 ofNANDSAT to an instance ι of 3NAND. In the exam-ple above we transform the NAND-CIRC programxor5 which has 5 input variables and 16 lines, intoa 3NAND formula ι that has 24 variables and 20clauses. Since xor5 outputs 1 on the input 1, 0, 0, 1, 1,there exists an assignment 𝑧 ∈ 0, 124 to ι such that(𝑧0, 𝑧1, 𝑧2, 𝑧3, 𝑧4) = (1, 0, 0, 1, 1) and ι evaluates totrue on 𝑧.

Page 490: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

490 introduction to theoretical computer science

Proof of Lemma 15.9. To prove Lemma 15.9 we need to give a reductionfrom NANDSAT to 3NAND. Let 𝑄 be a NAND-CIRC program with𝑛 inputs, one output, and 𝑚 lines. We can assume without loss ofgenerality that 𝑄 contains the variables one and zero as usual.

We map 𝑄 to a 3NAND formula ι as follows:

‱ ι has 𝑚 + 𝑛 variables 𝑧0, 
 , 𝑧𝑚+𝑛−1.‱ The first 𝑛 variables 𝑧0, 
 , 𝑧𝑛−1 will corresponds to the inputs of 𝑄.

The next 𝑚 variables 𝑧𝑛, 
 , 𝑧𝑛+𝑚−1 will correspond to the 𝑚 linesof 𝑄.

‱ For every ℓ ∈ 𝑛, 𝑛 + 1, 
 , 𝑛 + 𝑚, if the ℓ − 𝑛-th line of the program𝑄 is foo = NAND(bar,blah) then we add to ι the constraint 𝑧ℓ =NAND(𝑧𝑗, 𝑧𝑘) where 𝑗 − 𝑛 and 𝑘 − 𝑛 correspond to the last linesin which the variables bar and blah (respectively) were written to.If one or both of bar and blah was not written to before then weuse 𝑧ℓ0 instead of the corresponding value 𝑧𝑗 or 𝑧𝑘 in the constraint,where ℓ0 − 𝑛 is the line in which zero is assigned a value. If one orboth of bar and blah is an input variable X[i] then we use 𝑧𝑖 in theconstraint.

‱ Let ℓ∗ be the last line in which the output y_0 is assigned a value.Then we add the constraint 𝑧ℓ∗ = NAND(𝑧ℓ0 , 𝑧ℓ0) where ℓ0 − 𝑛 is asabove the last line in which zero is assigned a value. Note that thisis effectively the constraint 𝑧ℓ∗ = NAND(0, 0) = 1.To complete the proof we need to show that there exists đ‘€ ∈ 0, 1𝑛

s.t. 𝑄(đ‘€) = 1 if and only if there exists 𝑧 ∈ 0, 1𝑛+𝑚 that satisfies allconstraints in Κ. We now show both sides of this equivalence.

Part I: Completeness. Suppose that there is đ‘€ ∈ 0, 1𝑛 s.t. 𝑄(đ‘€) =1. Let 𝑧 ∈ 0, 1𝑛+𝑚 be defined as follows: for 𝑖 ∈ [𝑛], 𝑧𝑖 = đ‘€đ‘– andfor 𝑖 ∈ 𝑛, 𝑛 + 1, 
 , 𝑛 + 𝑚 𝑧𝑖 equals the value that is assigned inthe (𝑖 − 𝑛)-th line of 𝑄 when executed on đ‘€. Then by construction𝑧 satisfies all of the constraints of Κ (including the constraint that𝑧ℓ∗ = NAND(0, 0) = 1 since 𝑄(đ‘€) = 1.)

Part II: Soundness. Suppose that there exists 𝑧 ∈ 0, 1𝑛+𝑚 satisfy-ing Κ. Soundness will follow by showing that 𝑄(𝑧0, 
 , 𝑧𝑛−1) = 1 (andhence in particular there exists đ‘€ ∈ 0, 1𝑛, namely đ‘€ = 𝑧0 ⋯ 𝑧𝑛−1,such that 𝑄(đ‘€) = 1). To do this we will prove the following claim(∗): for every ℓ ∈ [𝑚], 𝑧ℓ+𝑛 equals the value assigned in the ℓ-th stepof the execution of the program 𝑄 on 𝑧0, 
 , 𝑧𝑛−1. Note that because 𝑧satisfies the constraints of Κ, (∗) is sufficient to prove the soundnesscondition since these constraints imply that the last value assigned tothe variable y_0 in the execution of 𝑄 on 𝑧0 ⋯ đ‘€đ‘›âˆ’1 is equal to 1. Toprove (∗) suppose, towards a contradiction, that it is false, and let ℓ be

Page 491: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

np, np completeness, and the cook-levin theorem 491

Figure 15.7: A 3NAND instance that is obtained bytaking a NAND-TM program for computing theAND function, unrolling it to obtain a NANDSATinstance, and then composing it with the reduction ofLemma 15.9.

the smallest number such that 𝑧ℓ+𝑛 is not equal to the value assignedin the ℓ-th step of the execution of 𝑄 on 𝑧0, 
 , 𝑧𝑛−1. But since 𝑧 sat-isfies the constraints of ι, we get that 𝑧ℓ+𝑛 = NAND(𝑧𝑖, 𝑧𝑗) where(by the assumption above that ℓ is smallest with this property) thesevalues do correspond to the values last assigned to the variables on therighthand side of the assignment operator in the ℓ-th line of the pro-gram. But this means that the value assigned in the ℓ-th step is indeedsimply the NAND of 𝑧𝑖 and 𝑧𝑗, contradicting our assumption on thechoice of ℓ.

15.5 FROM 3NAND TO 3SATThe final step in the proof of Theorem 15.6 is the following:Lemma 15.10 3NAND â‰€đ‘ 3SAT.Proof Idea:

To prove Lemma 15.10 we need to map a 3NAND formula 𝜑 intoa 3SAT formula 𝜓 such that 𝜑 is satisfiable if and only if 𝜓 is. Theidea is that we can transform every NAND constraint of the form𝑎 = NAND(𝑏, 𝑐) into the AND of ORs involving the variables 𝑎, 𝑏, 𝑐and their negations, where each of the ORs contains at most threeterms. The construction is fairly straightforward, and the details aregiven below.⋆

PIt is a good exercise for you to try to find a 3CNF for-mula 𝜉 on three variables 𝑎, 𝑏, 𝑐 such that 𝜉(𝑎, 𝑏, 𝑐) istrue if and only if 𝑎 = NAND(𝑏, 𝑐). Once you do so, tryto see why this implies a reduction from 3NAND to3SAT, and hence completes the proof of Lemma 15.10

Figure 15.8: Code and example output for the reduc-tion given in Lemma 15.10 of 3NAND to 3SAT.

Page 492: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

492 introduction to theoretical computer science

1 The resulting formula will have some of the OR’sinvolving only two variables. If we wanted to insist oneach formula involving three distinct variables we canalways add a “dummy variable” 𝑧𝑛+𝑚 and include itin all the OR’s involving only two variables, and add aconstraint requiring this dummy variable to be zero.

Proof of Lemma 15.10. The constraint𝑧𝑖 = NAND(𝑧𝑗, 𝑧𝑘) (15.5)is satisfied if 𝑧𝑖 = 1 whenever (𝑧𝑗, 𝑧𝑘) ≠ (1, 1). By going through allcases, we can verify that (15.5) is equivalent to the constraint(𝑧𝑖 ∹ 𝑧𝑗 ∹ 𝑧𝑘) ∧ (𝑧𝑖 ∹ 𝑧𝑗) ∧ (𝑧𝑖 ∹ 𝑧𝑘) . (15.6)

Indeed if 𝑧𝑗 = 𝑧𝑘 = 1 then the first constraint of Eq. (15.6) is onlytrue if 𝑧𝑖 = 0. On the other hand, if either of 𝑧𝑗 or 𝑧𝑘 equals 0 then un-less 𝑧𝑖 = 1 either the second or third constraints will fail. This meansthat, given any 3NAND formula 𝜑 over 𝑛 variables 𝑧0, 
 , 𝑧𝑛−1, we canobtain a 3SAT formula 𝜓 over the same variables by replacing every3NAND constraint of 𝜑 with three 3OR constraints as in Eq. (15.6).1Because of the equivalence of (15.5) and (15.6), the formula 𝜓 sat-isfies that 𝜓(𝑧0, 
 , 𝑧𝑛−1) = 𝜑(𝑧0, 
 , 𝑧𝑛−1) for every assignment𝑧0, 
 , 𝑧𝑛−1 ∈ 0, 1𝑛 to the variables. In particular 𝜓 is satisfiable ifand only if 𝜑 is, thus completing the proof.

Figure 15.9: An instance of the independent set problemobtained by applying the reductions NANDSAT â‰€đ‘3NAND â‰€đ‘ 3SAT â‰€đ‘ ISAT starting with the xor5NAND-CIRC program.

15.6 WRAPPING UP

We have shown that for every function đč in NP, đč â‰€đ‘ NANDSAT â‰€đ‘3NAND â‰€đ‘ 3SAT, and so 3SAT is NP-hard. Since in Chapter 14 wesaw that 3SAT â‰€đ‘ QUADEQ, 3SAT â‰€đ‘ ISET, 3SAT â‰€đ‘ MAXCUTand 3SAT â‰€đ‘ LONGPATH, all these problems are NP-hard as well.Finally, since all the aforementioned problems are in NP, they areall in fact NP-complete and have equivalent complexity. There arethousands of other natural problems that are NP-complete as well.Finding a polynomial-time algorithm for any one of them will imply apolynomial-time algorithm for all of them.

Page 493: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

np, np completeness, and the cook-levin theorem 493

Figure 15.10: We believe that P ≠ NP and all NPcomplete problems lie outside of P, but we cannotrule out the possiblity that P = NP. However, wecan rule out the possiblity that some NP-completeproblems are in P and other do not, since we knowthat if even one NP-complete problem is in P thenP = NP. The relation between P/poly and NP isnot known though it can be shown that if one NP-complete problem is in P/poly then NP ⊆ P/poly.

2 Hint: Use the function đč that on input a formula 𝜑and a string of the form 1𝑡, outputs 1 if and only if 𝜑is satisfiable and 𝑡 = |𝜑|log |𝜑|.3 Hint: Prove and then use the fact that P is closedunder complement.

Chapter Recap

‱ Many of the problems for which we don’t knowpolynomial-time algorithms are NP-complete,which means that finding a polynomial-time algo-rithm for one of them would imply a polynomial-time algorithm for all of them.

‱ It is conjectured that NP ≠ P which means thatwe believe that polynomial-time algorithms forthese problems are not merely unknown but arenonexistent.

‱ While an NP-hardness result means for examplethat a full-fledged “textbook” solution to a problemsuch as MAX-CUT that is as clean and general asthe algorithm for MIN-CUT probably does notexist, it does not mean that we need to give upwhenever we see a MAX-CUT instance. Later inthis course we will discuss several strategies to dealwith NP-hardness, including average-case complexityand approximation algorithms.

15.7 EXERCISES

Exercise 15.1 — Poor man’s Ladner’s Theorem. Prove that if there is no𝑛𝑂(log2 𝑛) time algorithm for 3SAT then there is some đč ∈ NP suchthat đč ∉ P and đč is not NP complete.2

Exercise 15.2 — NP ≠ co − NP ⇒ NP ≠ P. Let 3SAT be the functionthat on input a 3CNF formula 𝜑 return 1 − 3SAT(𝜑). Prove that if3SAT ∉ NP then P ≠ NP. See footnote for hint.3

Exercise 15.3 Define WSAT to be the following function: the input is aCNF formula 𝜑 where each clause is the OR of one to three variables(without negations), and a number 𝑘 ∈ ℕ. For example, the followingformula can be used for a valid input to WSAT: 𝜑 = (đ‘„5 √ đ‘„2 √ đ‘„1) ∧(đ‘„1 √ đ‘„3 √ đ‘„0) ∧ (đ‘„2 √ đ‘„4 √ đ‘„0). The output WSAT(𝜑, 𝑘) = 1 if andonly if there exists a satisfying assignment to 𝜑 in which exactly 𝑘of the variables get the value 1. For example for the formula above

Page 494: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

494 introduction to theoretical computer science

WSAT(𝜑, 2) = 1 since the assignment (1, 1, 0, 0, 0, 0) satisfies all theclauses. However WSAT(𝜑, 1) = 0 since there is no single variableappearing in all clauses.

Prove that WSAT is NP-complete.

Exercise 15.4 In the employee recruiting problem we are given a list ofpotential employees, each of which has some subset of 𝑚 potentialskills, and a number 𝑘. We need to assemble a team of 𝑘 employeessuch that for every skill there would be one member of the team withthis skill.

For example, if Alice has the skills “C programming”, “NANDprogramming” and “Solving Differential Equations”, Bob has theskills “C programming” and “Solving Differential Equations”, andCharlie has the skills “NAND programming” and “Coffee Brewing”,then if we want a team of two people that covers all the four skills, wewould hire Alice and Charlie.

Define the function EMP s.t. on input the skills 𝐿 of all potentialemployees (in the form of a sequence 𝐿 of 𝑛 lists 𝐿1, 
 , 𝐿𝑛, eachcontaining distinct numbers between 0 and 𝑚), and a number 𝑘,EMP(𝐿, 𝑘) = 1 if and only if there is a subset 𝑆 of 𝑘 potential em-ployees such that for every skill 𝑗 in [𝑚], there is an employee in 𝑆 thathas the skill 𝑗.

Prove that EMP is NP complete.

Exercise 15.5 — Balanced max cut. Prove that the “balanced variant” ofthe maximum cut problem is NP-complete, where this is defined asBMC ∶ 0, 1∗ → 0, 1 where for every graph đș = (𝑉 , 𝐾) and 𝑘 ∈ ℕ,BMC(đș, 𝑘) = 1 if and only if there exists a cut 𝑆 in đș cutting at least 𝑘edges such that |𝑆| = |𝑉 |/2.

Exercise 15.6 — Regular expression intersection. Let MANYREGS be the fol-lowing function: On input a list of regular expressions đ‘’đ‘„đ‘0, 
 , exp𝑚(represented as strings in some standard way), output 1 if and only ifthere is a single string đ‘„ ∈ 0, 1∗ that matches all of them. Prove thatMANYREGS is NP-hard.

15.8 BIBLIOGRAPHICAL NOTES

Aaronson’s 120 page survey [Aar16] is a beautiful and extensive ex-position to the P vs NP problem, its importance and status. See alsoas well as Chapter 3 in Wigderson’s excellent book [Wig19]. Johnson[Joh12] gives a survey of the historical development of the theory ofNP completeness. The following web page keeps a catalog of failed

Page 495: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

np, np completeness, and the cook-levin theorem 495

attempts at settling P vs NP. At the time of this writing, it lists about110 papers claiming to resolve the question, of which about 60 claim toprove that P = NP and about 50 claim to prove that P ≠ NP.

Eugene Lawler’s quote on the “mystical power of twoness” wastaken from the wonderful book “The Nature of Computation” byMoore and Mertens. See also this memorial essay on Lawler byLenstra.

Page 496: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 497: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

1 Paul ErdƑs (1913-1996) was one of the most prolificmathematicians of all times. Though he was an athe-ist, ErdƑs often referred to “The Book” in which Godkeeps the most elegant proof of each mathematicaltheorem.

2 The 𝑘-th Ramsey number, denoted as 𝑅(𝑘, 𝑘), is thesmallest number 𝑛 such that for every graph đș on 𝑛vertices, both đș and its complement contain a 𝑘-sizedindependent set. If P = NP then we can compute𝑅(𝑘, 𝑘) in time polynomial in 2𝑘, while otherwise itcan potentially take closer to 222𝑘 steps.

16What if P equals NP?

“You don’t have to believe in God, but you should believe in The Book.”, PaulErdƑs, 1985.1

“No more half measures, Walter”, Mike Ehrmantraut in “Breaking Bad”,2010.

“The evidence in favor of [P ≠ NP] and [ its algebraic counterpart ] is sooverwhelming, and the consequences of their failure are so grotesque, that theirstatus may perhaps be compared to that of physical laws rather than that ofordinary mathematical conjectures.”, Volker Strassen, laudation for LeslieValiant, 1986.

“Suppose aliens invade the earth and threaten to obliterate it in a year’s timeunless human beings can find the [fifth Ramsey number]. We could marshalthe world’s best minds and fastest computers, and within a year we could prob-ably calculate the value. If the aliens demanded the [sixth Ramsey number],however, we would have no choice but to launch a preemptive attack.”, PaulErdƑs, as quoted by Graham and Spencer, 1990.2

We have mentioned that the question of whether P = NP, whichis equivalent to whether there is a polynomial-time algorithm for3SAT, is the great open question of Computer Science. But why is it soimportant? In this chapter, we will try to figure out the implications ofsuch an algorithm.

First, let us get one qualm out of the way. Sometimes people say,“What if P = NP but the best algorithm for 3SAT takes 𝑛1000 time?” Well,𝑛1000 is much larger than, say, 20.001√𝑛 for any input smaller than 250,as large as a harddrive as you will encounter, and so another way tophrase this question is to say “what if the complexity of 3SAT is ex-ponential for all inputs that we will ever encounter, but then growsmuch smaller than that?” To me this sounds like the computer scienceequivalent of asking, “what if the laws of physics change completelyonce they are out of the range of our telescopes?”. Sure, this is a validpossibility, but wondering about it does not sound like the most pro-ductive use of our time.

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Explore the consequences of P = NP‱ Search-to-decision reduction: transform

algorithms that solve decision version tosearch version for NP-complete problems.

‱ Optimization and learning problems‱ Quantifier elimination and solving problems

in the polynomial hierarchy.‱ What is the evidence for P = NP vs P ≠ NP?

Page 498: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

498 introduction to theoretical computer science

So, as the saying goes, we’ll keep an open mind, but not so openthat our brains fall out, and assume from now on that:

‱ There is a mathematical god,

and

‱ She does not “beat around the bush’ ’ or take “half measures”.

What we mean by this is that we will consider two extreme scenar-ios:

‱ 3SAT is very easy: 3SAT has an 𝑂(𝑛) or 𝑂(𝑛2) time algorithm witha not too huge constant (say smaller than 106.)

‱ 3SAT is very hard: 3SAT is exponentially hard and cannot besolved faster than 2𝜖𝑛 for some not too tiny 𝜖 > 0 (say at least10−6). We can even make the stronger assumption that for everysufficiently large 𝑛, the restriction of 3SAT to inputs of length 𝑛cannot be computed by a circuit of fewer than 2𝜖𝑛 gates.

At the time of writing, the fastest known algorithm for 3SAT re-quires more than 20.35𝑛 to solve 𝑛 variable formulas, while we do noteven know how to rule out the possibility that we can compute 3SATusing 10𝑛 gates. To put it in perspective, for the case 𝑛 = 1000 ourlower and upper bounds for the computational costs are apart bya factor of about 10100. As far as we know, it could be the case that1000-variable 3SAT can be solved in a millisecond on a first-generationiPhone, and it can also be the case that such instances require morethan the age of the universe to solve on the world’s fastest supercom-puter.

So far, most of our evidence points to the latter possibility of 3SATbeing exponentially hard, but we have not ruled out the former possi-bility either. In this chapter we will explore some of the consequencesof the “3SAT easy” scenario.

16.1 SEARCH-TO-DECISION REDUCTION

A priori, having a fast algorithm for 3SAT might not seem so impres-sive. Sure, such an algorithm allows us to decide the satisfiability ofnot just 3CNF formulas but also of quadratic equations, as well as findout whether there is a long path in a graph, and solve many other de-cision problems. But this is not typically what we want to do. It’s notenough to know if a formula is satisfiable: we want to discover theactual satisfying assignment. Similarly, it’s not enough to find out if agraph has a long path: we want to actually find the path.

It turns out that if we can solve these decision problems, we cansolve the corresponding search problems as well:

Page 499: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

what if p equals np? 499

Theorem 16.1 — Search vs Decision. Suppose that P = NP. Thenfor every polynomial-time algorithm 𝑉 and 𝑎, 𝑏 ∈ ℕ,there is apolynomial-time algorithm FIND𝑉 such that for every đ‘„ ∈ 0, 1𝑛,if there exists 𝑩 ∈ 0, 1𝑎𝑛𝑏 satisfying 𝑉 (đ‘„đ‘Š) = 1, then FIND𝑉 (đ‘„)finds some string 𝑩â€Č satisfying this condition.

PTo understand what the statement of Theo-rem 16.1 means, let us look at the special case ofthe MAXCUT problem. It is not hard to see that thereis a polynomial-time algorithm VERIFYCUT such thatVERIFYCUT(đș, 𝑘, 𝑆) = 1 if and only if 𝑆 is a subsetof đș’s vertices that cuts at least 𝑘 edges. Theorem 16.1implies that if P = NP then there is a polynomial-timealgorithm FINDCUT that on input đș, 𝑘 outputs a set𝑆 such that VERIFYCUT(đș, 𝑘, 𝑆) = 1 if such a setexists. This means that if P = NP, by trying all valuesof 𝑘 we can find in polynomial time a maximum cutin any given graph. We can use a similar argument toshow that if P = NP then we can find a satisfying as-signment for every satisfiable 3CNF formula, find thelongest path in a graph, solve integer programming,and so and so forth.

Proof Idea:

The idea behind the proof of Theorem 16.1 is simple; let usdemonstrate it for the special case of 3SAT. (In fact, this case is notso “special”− since 3SAT is NP-complete, we can reduce the task ofsolving the search problem for MAXCUT or any other problem inNP to the task of solving it for 3SAT.) Suppose that P = NP and weare given a satisfiable 3CNF formula 𝜑, and we now want to find asatisfying assignment 𝑩 for 𝜑. Define 3SAT0(𝜑) to output 1 if there isa satisfying assignment 𝑩 for 𝜑 such that its first bit is 0, and similarlydefine 3SAT1(𝜑) = 1 if there is a satisfying assignment 𝑩 with 𝑩0 = 1.The key observation is that both 3SAT0 and 3SAT1 are in NP, and so ifP = NP then we can compute them in polynomial time as well. Thuswe can use this to find the first bit of the satisfying assignment. Wecan continue in this way to recover all the bits.⋆Proof of Theorem 16.1. Let 𝑉 be some polynomial time algorithm and𝑎, 𝑏 ∈ ℕ some constants. Define the function STARTSWITH𝑉 asfollows: For every đ‘„ ∈ 0, 1∗ and 𝑧 ∈ 0, 1∗, STARTSWITH𝑉 (đ‘„, 𝑧) =1 if and only if there exists some 𝑩 ∈ 0, 1𝑎𝑛𝑏−|𝑧| (where 𝑛 = |đ‘„|) suchthat 𝑉 (đ‘„đ‘§đ‘Š) = 1. That is, STARTSWITH𝑉 (đ‘„, 𝑧) outputs 1 if there issome string đ‘€ of length 𝑎|đ‘„|𝑏 such that 𝑉 (đ‘„, đ‘€) = 1 and the first |𝑧|

Page 500: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

500 introduction to theoretical computer science

bits of đ‘€ are 𝑧0, 
 , 𝑧ℓ−1. Since, given đ‘„, 𝑩, 𝑧 as above, we can check inpolynomial time if 𝑉 (đ‘„đ‘§đ‘Š) = 1, the function STARTSWITH𝑉 is in NPand hence if P = NP we can compute it in polynomial time.

Now for every such polynomial-time 𝑉 and 𝑎, 𝑏 ∈ ℕ, we can imple-ment FIND𝑉 (đ‘„) as follows:

Algorithm 16.2 — đčđŒđ‘đ·đ‘‰ : Search to decision reduction.

Input: đ‘„ ∈ 0, 1𝑛Output: 𝑧 ∈ 0, 1𝑎𝑛𝑏 s.t. 𝑉 (đ‘„đ‘§) = 1, if such 𝑧 exists. Other-

wise output the empty string.1: Initially 𝑧0 = 𝑧1 = ⋯ = 𝑧𝑎𝑛𝑏−1 = 0.2: for ℓ = 0, 
 , 𝑎𝑛𝑏 − 1 do3: Let 𝑏0 ← 𝑆𝑇 𝐮𝑅𝑇 đ‘†đ‘ŠđŒđ‘‡ đ»đ‘‰ (đ‘„đ‘§0 ⋯ 𝑧ℓ−10).4: Let 𝑏1 ← 𝑆𝑇 𝐮𝑅𝑇 đ‘†đ‘ŠđŒđ‘‡ đ»đ‘‰ (đ‘„đ‘§0 ⋯ 𝑧ℓ−11).5: if 𝑏0 = 𝑏1 = 0 then6: return ””7: # Can’t extend đ‘„đ‘§0 
 𝑧ℓ−1 to input 𝑉 accepts8: end if9: if 𝑏0 = 1 then

10: 𝑧ℓ ← 011: # Can extend đ‘„đ‘§0 
 đ‘„â„“âˆ’1 with 0 to accepting input12: else13: 𝑧ℓ ← 114: # Can extend đ‘„đ‘§0 
 đ‘„â„“âˆ’1 with 1 to accepting input15: end if16: end for17: return 𝑧0, 
 , 𝑧𝑎𝑛𝑏−1

To analyze Algorithm 16.2, note that it makes 2𝑎𝑛𝑏 invocations toSTARTSWITH𝑉 and hence if the latter is polynomial-time, then so isAlgorithm 16.2 Now suppose that đ‘„ is such that there exists some 𝑩satisfying 𝑉 (đ‘„đ‘Š) = 1. We claim that at every step ℓ = 0, 
 , 𝑎𝑛𝑏 − 1, wemaintain the invariant that there exists 𝑩 ∈ 0, 1𝑎𝑛𝑏 whose first ℓ bitsare 𝑧 s.t. 𝑉 (đ‘„đ‘Š) = 1. Note that this claim implies the theorem, since inparticular it means that for ℓ = 𝑎𝑛𝑏 − 1, 𝑧 satisfies 𝑉 (đ‘„đ‘§) = 1.

We prove the claim by induction. For ℓ = 0, this holds vacuously.Now for every ℓ > 0, if the call STARTSWITH𝑉 (đ‘„đ‘§0 ⋯ 𝑧ℓ−10)returns 1, then we are guaranteed the invariant by definition ofSTARTSWITH𝑉 . Now under our inductive hypothesis, there is𝑩ℓ, 
 , 𝑩𝑎𝑛𝑏−1 such that 𝑃(đ‘„đ‘§0, 
 , 𝑧ℓ−1𝑩ℓ, 
 , 𝑩𝑎𝑛𝑏−1) = 1. If the call toSTARTSWITH𝑉 (đ‘„đ‘§0 ⋯ 𝑧ℓ−10) returns 0 then it must be the case that𝑩ℓ = 1, and hence when we set 𝑧ℓ = 1 we maintain the invariant.

Page 501: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

what if p equals np? 501

16.2 OPTIMIZATION

Theorem 16.1 allows us to find solutions for NP problems if P = NP,but it is not immediately clear that we can find the optimal solution.For example, suppose that P = NP, and you are given a graph đș. Canyou find the longest simple path in đș in polynomial time?

PThis is actually an excellent question for you to at-tempt on your own. That is, assuming P = NP, givea polynomial-time algorithm that on input a graph đș,outputs a maximally long simple path in the graph đș.

The answer is Yes. The idea is simple: if P = NP then we can findout in polynomial time if an 𝑛-vertex graph đș contains a simple pathof length 𝑛, and moreover, by Theorem 16.1, if đș does contain such apath, then we can find it. (Can you see why?) If đș does not contain asimple path of length 𝑛, then we will check if it contains a simple pathof length 𝑛 − 1, and continue in this way to find the largest 𝑘 such thatđș contains a simple path of length 𝑘.

The above reasoning was not specifically tailored to finding pathsin graphs. In fact, it can be vastly generalized to proving the followingresult:

Theorem 16.3 — Optimization from P = NP. Suppose that P = NP. Thenfor every polynomial-time computable function 𝑓 ∶ 0, 1∗ → ℕ(identifying 𝑓(đ‘„) with natural numbers via the binary representa-tion) there is a polynomial-time algorithm OPT such that on inputđ‘„ ∈ 0, 1∗,

OPT(đ‘„, 1𝑚) = max𝑩∈0,1𝑚 𝑓(đ‘„, 𝑩) . (16.1)

Moreover under the same assumption, there is a polynomial-time algorithm FINDOPT such that for every đ‘„ ∈ 0, 1∗, FINDOPT(đ‘„, 1𝑚)outputs 𝑩∗ ∈ 0, 1∗ such that 𝑓(đ‘„, 𝑩∗) = max𝑩∈0,1𝑚 𝑓(đ‘„, 𝑩).

PThe statement of Theorem 16.3 is a bit cumbersome.To understand it, think how it would subsume theexample above of a polynomial time algorithm forfinding the maximum length path in a graph. Inthis case the function 𝑓 would be the map that oninput a pair đ‘„, 𝑩 outputs 0 if the pair (đ‘„, 𝑩) does notrepresent some graph and a simple path inside thegraph respectively; otherwise 𝑓(đ‘„, 𝑩) would equalthe length of the path 𝑩 in the graph đ‘„. Since a pathin an 𝑛 vertex graph can be represented by at most

Page 502: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

502 introduction to theoretical computer science

𝑛 log𝑛 bits, for every đ‘„ representing a graph of 𝑛 ver-tices, finding max𝑩∈0,1𝑛 log𝑛 𝑓(đ‘„, 𝑩) corresponds tofinding the length of the maximum simple path in thegraph corresponding to đ‘„, and finding the string 𝑩∗that achieves this maximum corresponds to actuallyfinding the path.

Proof Idea:

The proof follows by generalizing our ideas from the longest pathexample above. Let 𝑓 be as in the theorem statement. If P = NP thenfor every for every string đ‘„ ∈ 0, 1∗ and number 𝑘, we can test inin 𝑝𝑜𝑙𝑩(|đ‘„|, 𝑚) time whether there exists 𝑩 such that 𝑓(đ‘„, 𝑩) ≄ 𝑘, orin other words test whether max𝑩∈0,1𝑚 𝑓(đ‘„, 𝑩) ≄ 𝑘. If 𝑓(đ‘„, 𝑩) is aninteger between 0 and 𝑝𝑜𝑙𝑩(|đ‘„| + |𝑩|) (as is the case in the example oflongest path) then we can just try out all possibilities for 𝑘 to find themaximum number 𝑘 for which max𝑩 𝑓(đ‘„, 𝑩) ≄ 𝑘. Otherwise, we canuse binary search to hone down on the right value. Once we do so, wecan use search-to-decision to actually find the string 𝑩∗ that achievesthe maximum.⋆Proof of Theorem 16.3. For every 𝑓 as in the theorem statement, we candefine the Boolean function đč ∶ 0, 1∗ → 0, 1 as follows.

đč(đ‘„, 1𝑚, 𝑘) = ⎧⎚⎩1 ∃𝑩∈0,1𝑚𝑓(đ‘„, 𝑩) ≄ 𝑘0 otherwise(16.2)

Since 𝑓 is computable in polynomial time, đč is in NP, and so underour assumption that P = NP, đč itself can be computed in polynomialtime. Now, for every đ‘„ and 𝑚, we can compute the largest 𝑘 such thatđč(đ‘„, 1𝑚, 𝑘) = 1 by a binary search. Specifically, we will do this asfollows:

1. We maintain two numbers 𝑎, 𝑏 such that we are guaranteed that𝑎 ≀ max𝑩∈0,1𝑚 𝑓(đ‘„, 𝑩) < 𝑏.2. Initially we set 𝑎 = 0 and 𝑏 = 2𝑇 (𝑛) where 𝑇 (𝑛) is the running time

of 𝑓 . (A function with 𝑇 (𝑛) running time can’t output more than𝑇 (𝑛) bits and so can’t output a number larger than 2𝑇 (𝑛).)3. At each point in time, we compute the midpoint 𝑐 = ⌊(𝑎 + 𝑏)/2⌋)

and let 𝑩 = đč(1𝑛, 𝑐).a. If 𝑩 = 1 then we set 𝑎 = 𝑐 and leave 𝑏 as it is.b. If 𝑩 = 0 then we set 𝑏 = 𝑐 and leave 𝑎 as it is.

4. We then go back to step 3, until 𝑏 ≀ 𝑎 + 1.

Page 503: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

what if p equals np? 503

Since |𝑏 − 𝑎| shrinks by a factor of 2, within log2 2𝑇 (𝑛) = 𝑇 (𝑛)steps, we will get to the point at which 𝑏 ≀ 𝑎 + 1, and then we cansimply output 𝑎. Once we find the maximum value of 𝑘 such thatđč(đ‘„, 1𝑚, 𝑘) = 1, we can use the search to decision reduction of Theo-rem 16.1 to obtain the actual value 𝑩∗ ∈ 0, 1𝑚 such that 𝑓(đ‘„, 𝑩∗) = 𝑘.

Example 16.4 — Integer programming. One application for Theo-rem 16.3 is in solving optimization problems. For example, the taskof linear programming is to find 𝑩 ∈ ℝ𝑛 that maximizes some linearobjective ∑𝑛−1𝑖=0 𝑐𝑖𝑩𝑖 subject to the constraint that 𝑩 satisfies linearinequalities of the form ∑𝑛−1𝑖=0 𝑎𝑖𝑩𝑖 ≀ 𝑐. As we discussed in Sec-tion 12.1.3, there is a known polynomial-time algorithm for linearprogramming. However, if we want to place additional constraintson 𝑩, such as requiring the coordinates of 𝑩 to be integer or 0/1valued then the best-known algorithms run in exponential time inthe worst case. However, if P = NP then Theorem 16.3 tells usthat we would be able to solve all problems of this form in poly-nomial time. For every string đ‘„ that describes a set of constraintsand objective, we will define a function 𝑓 such that if 𝑩 satisfiesthe constraints of đ‘„ then 𝑓(đ‘„, 𝑩) is the value of the objective, andotherwise we set 𝑓(đ‘„, 𝑩) = −𝑀 where 𝑀 is some large number. Wecan then use Theorem 16.3 to compute the 𝑩 that maximizes 𝑓(đ‘„, 𝑩)and that will give us the assignment for the variables that satisfiesour constraints and maximizes the objective. (If the computationresults in 𝑩 such that 𝑓(đ‘„, 𝑩) = −𝑀 then we can double 𝑀 and tryagain; if the true maximum objective is achieved by some string𝑩∗, then eventually 𝑀 will be large enough so that −𝑀 would besmaller than the objective achieved by 𝑩∗, and hence when we runprocedure of Theorem 16.3 we would get a value larger than −𝑀 .)

RRemark 16.5 — Need for binary search.. In many exam-ples, such as the case of finding longest path, we don’tneed to use the binary search step in Theorem 16.3,and can simply enumerate over all possible values for𝑘 until we find the correct one. One example wherewe do need to use this binary search step is in the caseof the problem of finding a maximum length path ina weighted graph. This is the problem where đș is aweighted graph, and every edge of đș is given a weightwhich is a number between 0 and 2𝑘. Theorem 16.3shows that we can find the maximum-weight simplepath in đș (i.e., simple path maximizing the sum of

Page 504: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

504 introduction to theoretical computer science

3 This is often known as Empirical Risk Minimization.

the weights of its edges) in time polynomial in thenumber of vertices and in 𝑘.Beyond just this example there is a vast field of math-ematical optimization that studies problems of thesame form as in Theorem 16.3. In the context of opti-mization, đ‘„ typically denotes a set of constraints oversome variables (that can be Boolean, integer, or realvalued), 𝑩 encodes an assignment to these variables,and 𝑓(đ‘„, 𝑩) is the value of some objective function thatwe want to maximize. Given that we don’t knowefficient algorithms for NP complete problems, re-searchers in optimization research study special casesof functions 𝑓 (such as linear programming andsemidefinite programming) where it is possible tooptimize the value efficiently. Optimization is widelyused in a great many scientific areas including: ma-chine learning, engineering, economics and operationsresearch.

16.2.1 Example: Supervised learningOne classical optimization task is supervised learning. In supervisedlearning we are given a list of examples đ‘„0, đ‘„1, 
 , đ‘„đ‘šâˆ’1 (where wecan think of each đ‘„đ‘– as a string in 0, 1𝑛 for some 𝑛) and the la-bels for them 𝑩0, 
 , 𝑩𝑛−1 (which we will think of simply bits, i.e.,𝑩𝑖 ∈ 0, 1). For example, we can think of the đ‘„đ‘–â€™s as images of ei-ther dogs or cats, for which 𝑩𝑖 = 1 in the former case and 𝑩𝑖 = 0in the latter case. Our goal is to come up with a hypothesis or predic-tor ℎ ∶ 0, 1𝑛 → 0, 1 such that if we are given a new example đ‘„that has an (unknown to us) label 𝑩, then with high probability ℎwill predict the label. That is, with high probability it will hold thatℎ(đ‘„) = 𝑩. The idea in supervised learning is to use the Occam’s Ra-zor principle: the simplest hypothesis that explains the data is likelyto be correct. There are several ways to model this, but one popularapproach is to pick some fairly simple function đ» ∶ 0, 1𝑘+𝑛 → 0, 1.We think of the first 𝑘 inputs as the parameters and the last 𝑛 inputsas the example data. (For example, we can think of the first 𝑘 inputsof đ» as specifying the weights and connections for some neural net-work that will then be applied on the latter 𝑛 inputs.) We can thenphrase the supervised learning problem as finding, given a set of la-beled examples 𝑆 = (đ‘„0, 𝑩0), 
 , (đ‘„đ‘šâˆ’1, 𝑩𝑚−1), the set of parameters𝜃0, 
 , 𝜃𝑘−1 ∈ 0, 1 that minimizes the number of errors made by thepredictor đ‘„ ↩ đ»(𝜃, đ‘„).3

In other words, we can define for every set 𝑆 as above the functionđč𝑆 ∶ 0, 1𝑘 → [𝑚] such that đč𝑆(𝜃) = ∑(đ‘„,𝑩)∈𝑆 |đ»(𝜃, đ‘„) − 𝑩|. Now,finding the value 𝜃 that minimizes đč𝑆(𝜃) is equivalent to solving thesupervised learning problem with respect to đ» . For every polynomial-

Page 505: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

what if p equals np? 505

time computable đ» ∶ 0, 1𝑘+𝑛 → 0, 1, the task of minimizingđč𝑆(𝜃) can be “massaged” to fit the form of Theorem 16.3 and hence ifP = NP, then we can solve the supervised learning problem in greatgenerality. In fact, this observation extends to essentially any learn-ing model, and allows for finding the optimal predictors given theminimum number of examples. (This is in contrast to many currentlearning algorithms, which often rely on having access to an extremelylarge number of examples− far beyond the minimum needed, andin particular far beyond the number of examples humans use for thesame tasks.)

16.2.2 Example: Breaking cryptosystemsWe will discuss cryptography later in this course, but it turns out thatif P = NP then almost every cryptosystem can be efficiently bro-ken. One approach is to treat finding an encryption key as an in-stance of a supervised learning problem. If there is an encryptionscheme that maps a “plaintext” message 𝑝 and a key 𝜃 to a “cipher-text” 𝑐, then given examples of ciphertext/plaintext pairs of theform (𝑐0, 𝑝0), 
 , (𝑐𝑚−1, 𝑝𝑚−1), our goal is to find the key 𝜃 such that𝐾(𝜃, 𝑝𝑖) = 𝑐𝑖 where 𝐾 is the encryption algorithm. While you mightthink getting such “labeled examples” is unrealistic, it turns out (asmany amateur home-brew crypto designers learn the hard way) thatthis is actually quite common in real-life scenarios, and that it is alsopossible to relax the assumption to having more minimal prior infor-mation about the plaintext (e.g., that it is English text). We defer amore formal treatment to Chapter 21.

16.3 FINDING MATHEMATICAL PROOFS

In the context of Gödel’s Theorem, we discussed the notion of a proofsystem (see Section 11.1). Generally speaking, a proof system can bethought of as an algorithm 𝑉 ∶ 0, 1∗ → 0, 1 (known as the verifier)such that given a statement đ‘„ ∈ 0, 1∗ and a candidate proof đ‘€ ∈ 0, 1∗,𝑉 (đ‘„, đ‘€) = 1 if and only if đ‘€ encodes a valid proof for the statement đ‘„.Any type of proof system that is used in mathematics for geometry,number theory, analysis, etc., is an instance of this form. In fact, stan-dard mathematical proof systems have an even simpler form wherethe proof đ‘€ encodes a sequence of lines đ‘€0, 
 , đ‘€đ‘š (each of which isitself a binary string) such that each line đ‘€đ‘– is either an axiom or fol-lows from some prior lines through an application of some inferencerule. For example, Peano’s axioms encode a set of axioms and rulesfor the natural numbers, and one can use them to formalize proofsin number theory. Also, there are some even stronger axiomatic sys-tems, the most popular one being Zermelo–Fraenkel with the Axiomof Choice or ZFC for short. Thus, although mathematicians typically

Page 506: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

506 introduction to theoretical computer science

4 The undecidability of Entscheidungsproblem refersto the uncomputability of the function that maps astatement in first order logic to 1 if and only if thatstatement has a proof.

write their papers in natural language, proofs of number theoristscan typically be translated to ZFC or similar systems, and so in par-ticular the existence of an 𝑛-page proof for a statement đ‘„ implies thatthere exists a string đ‘€ of length 𝑝𝑜𝑙𝑩(𝑛) (in fact often 𝑂(𝑛) or 𝑂(𝑛2))that encodes the proof in such a system. Moreover, because verify-ing a proof simply involves going over each line and checking that itdoes indeed follow from the prior lines, it is fairly easy to do that in𝑂(|đ‘€|) or 𝑂(|đ‘€|2) (where as usual |đ‘€| denotes the length of the proofđ‘€). This means that for every reasonable proof system 𝑉 , the follow-ing function SHORTPROOF𝑉 ∶ 0, 1∗ → 0, 1 is in NP, wherefor every input of the form đ‘„1𝑚, SHORTPROOF𝑉 (đ‘„, 1𝑚) = 1 if andonly if there exists đ‘€ ∈ 0, 1∗ with |đ‘€| ≀ 𝑚 s.t. 𝑉 (đ‘„đ‘€) = 1. Thatis, SHORTPROOF𝑉 (đ‘„, 1𝑚) = 1 if there is a proof (in the system 𝑉 )of length at most 𝑚 bits that đ‘„ is true. Thus, if P = NP, then despiteGödel’s Incompleteness Theorems, we can still automate mathematicsin the sense of finding proofs that are not too long for every statementthat has one. (Frankly speaking, if the shortest proof for some state-ment requires a terabyte, then human mathematicians won’t ever findthis proof either.) For this reason, Gödel himself felt that the questionof whether SHORTPROOF𝑉 has a polynomial time algorithm is ofgreat interest. As Gödel wrote in a letter to John von Neumann in 1956(before the concept of NP or even “polynomial time” was formallydefined):

One can obviously easily construct a Turing machine, which for everyformula đč in first order predicate logic and every natural number 𝑛, al-lows one to decide if there is a proof of đč of length 𝑛 (length = numberof symbols). Let 𝜓(đč , 𝑛) be the number of steps the machine requiresfor this and let 𝜑(𝑛) = maxđč 𝜓(đč , 𝑛). The question is how fast 𝜑(𝑛)grows for an optimal machine. One can show that 𝜑 ≄ 𝑘 ⋅ 𝑛 [for someconstant 𝑘 > 0]. If there really were a machine with 𝜑(𝑛) ∌ 𝑘 ⋅ 𝑛 (oreven ∌ 𝑘 ⋅ 𝑛2), this would have consequences of the greatest importance.Namely, it would obviously mean that in spite of the undecidabilityof the Entscheidungsproblem,4 the mental work of a mathematicianconcerning Yes-or-No questions could be completely replaced by a ma-chine. After all, one would simply have to choose the natural number𝑛 so large that when the machine does not deliver a result, it makes nosense to think more about the problem.

For many reasonable proof systems (including the one that Gödelreferred to), SHORTPROOF𝑉 is in fact NP-complete, and so Gödel canbe thought of as the first person to formulate the P vs NP question.Unfortunately, the letter was only discovered in 1988.

Page 507: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

what if p equals np? 507

5 Since NAND-CIRC programs are equivalent toBoolean circuits, the search problem corresponding to(16.6) known as the circuit minimization problem andis widely studied in Engineering. You can skip aheadto Section 16.4.1 to see a particularly compellingapplication of this.

16.4 QUANTIFIER ELIMINATION (ADVANCED)

If P = NP then we can solve all NP search and optimization problems inpolynomial time. But can we do more? It turns out that the answer isthat Yes we can!

An NP decision problem can be thought of as the task of deciding,given some string đ‘„ ∈ 0, 1∗ the truth of a statement of the form∃𝑩∈0,1𝑝(|đ‘„|)𝑉 (đ‘„đ‘Š) = 1 (16.3)

for some polynomial-time algorithm 𝑉 and polynomial 𝑝 ∶ ℕ → ℕ.That is, we are trying to determine, given some string đ‘„, whetherthere exists a string 𝑩 such that đ‘„ and 𝑩 satisfy some polynomial-timecheckable condition 𝑉 . For example, in the independent set problem,the string đ‘„ represents a graph đș and a number 𝑘, the string 𝑩 repre-sents some subset 𝑆 of đș’s vertices, and the condition that we check iswhether |𝑆| ≄ 𝑘 and there is no edge 𝑱, 𝑣 in đș such that both 𝑱 ∈ 𝑆and 𝑣 ∈ 𝑆.

We can consider more general statements such as checking, given astring đ‘„ ∈ 0, 1∗, the truth of a statement of the form∃𝑩∈0,1𝑝0(|đ‘„|)∀𝑧∈0,1𝑝1(|đ‘„|)𝑉 (đ‘„đ‘Šđ‘§) = 1 , (16.4)

which in words corresponds to checking, given some string đ‘„, whetherthere exists a string 𝑩 such that for every string 𝑧, the triple (đ‘„, 𝑩, 𝑧) sat-isfy some polynomial-time checkable condition. We can also considermore levels of quantifiers such as checking the truth of the statement∃𝑩∈0,1𝑝0(|đ‘„|)∀𝑧∈0,1𝑝1(|đ‘„|)âˆƒđ‘€âˆˆ0,1𝑝2(|đ‘„|)𝑉 (đ‘„đ‘Šđ‘§đ‘€) = 1 (16.5)

and so on and so forth.For example, given an 𝑛-input NAND-CIRC program 𝑃 , we might

want to find the smallest NAND-CIRC program 𝑃 â€Č that computes thesame function as 𝑃 . The question of whether there is such a 𝑃 â€Č thatcan be described by a string of at most 𝑠 bits can be phrased as∃𝑃 â€Č∈0,1đ‘ âˆ€đ‘„âˆˆ0,1𝑛𝑃(đ‘„) = 𝑃 â€Č(đ‘„) (16.6)which has the form (16.4).5 Another example of a statement involving𝑎 levels of quantifiers would be to check, given a chess position đ‘„,whether there is a strategy that guarantees that White wins within 𝑎steps. For example is 𝑎 = 3 we would want to check if given the boardposition đ‘„, there exists a move 𝑩 for White such that for every move 𝑧 forBlack there exists a move đ‘€ for White that ends in a a checkmate.

It turns out that if P = NP then we can solve these kinds of prob-lems as well:

Page 508: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

508 introduction to theoretical computer science

6 For the ease of notation, we assume that all thestrings we quantify over have the same length 𝑚 =𝑝(𝑛), but using simple padding one can show thatthis captures the general case of strings of differentpolynomial lengths.

Theorem 16.6 — Polynomial hierarchy collapse. If P = NP then for every𝑎 ∈ ℕ, polynomial 𝑝 ∶ ℕ → ℕ and polynomial-time algorithm𝑉 , there is a polynomial-time algorithm SOLVE𝑉 ,𝑎 that on inputđ‘„ ∈ 0, 1𝑛 returns 1 if and only if∃𝑩0∈0,1𝑚∀𝑩1∈0,1𝑚 ⋯ 𝒬𝑩𝑎−1∈0,1𝑚𝑉 (đ‘„đ‘Š0𝑩1 ⋯ 𝑩𝑎−1) = 1 (16.7)

where 𝑚 = 𝑝(𝑛) and 𝒬 is either ∃ or ∀ depending on whether 𝑎 isodd or even, respectively. 6

Proof Idea:

To understand the idea behind the proof, consider the special casewhere we want to decide, given đ‘„ ∈ 0, 1𝑛, whether for every 𝑩 ∈0, 1𝑛 there exists 𝑧 ∈ 0, 1𝑛 such that 𝑉 (đ‘„đ‘Šđ‘§) = 1. Consider thefunction đč such that đč(đ‘„đ‘Š) = 1 if there exists 𝑧 ∈ 0, 1𝑛 such that𝑉 (đ‘„đ‘Šđ‘§) = 1. Since 𝑉 runs in polynomial-time đč ∈ NP and hence ifP = NP, then there is an algorithm 𝑉 â€Č that on input đ‘„, 𝑩 outputs 1 ifand only if there exists 𝑧 ∈ 0, 1𝑛 such that 𝑉 (đ‘„đ‘Šđ‘§) = 1. Now wecan see that the original statement we consider is true if and only if forevery 𝑩 ∈ 0, 1𝑛, 𝑉 â€Č(đ‘„đ‘Š) = 1, which means it is false if and only ifthe following condition (∗) holds: there exists some 𝑩 ∈ 0, 1𝑛 suchthat 𝑉 â€Č(đ‘„đ‘Š) = 0. But for every đ‘„ ∈ 0, 1𝑛, the question of whetherthe condition (∗) is itself in NP (as we assumed 𝑉 â€Č can be computedin polynomial time) and hence under the assumption that P = NPwe can determine in polynomial time whether the condition (∗), andhence our original statement, is true.⋆Proof of Theorem 16.6. We prove the theorem by induction. We assumethat there is a polynomial-time algorithm SOLVE𝑉 ,𝑎−1 that can solvethe problem (16.7) for 𝑎 − 1 and use that to solve the problem for 𝑎.For 𝑎 = 1, SOLVE𝑉 ,𝑎−1(đ‘„) = 1 iff 𝑉 (đ‘„) = 1 which is a polynomial-timecomputation since 𝑉 runs in polynomial time. For every đ‘„, 𝑩0, definethe statement đœ‘đ‘„,𝑩0 to be the following:

đœ‘đ‘„,𝑩0 = ∀𝑩1∈0,1𝑚∃𝑩2∈0,1𝑚 ⋯ 𝒬𝑩𝑎−1∈0,1𝑚𝑉 (đ‘„đ‘Š0𝑩1 ⋯ 𝑩𝑎−1) = 1 (16.8)

By the definition of SOLVE𝑉 ,𝑎, for every đ‘„ ∈ 0, 1𝑛, our goal isthat SOLVE𝑉 ,𝑎(đ‘„) = 1 if and only if there exists 𝑩0 ∈ 0, 1𝑚 such thatđœ‘đ‘„,𝑩0 is true.

The negation of đœ‘đ‘„,𝑩0 is the statement

đœ‘đ‘„,𝑩0 = ∃𝑩1∈0,1𝑚∀𝑩2∈0,1𝑚 ⋯ 𝒬𝑩𝑎−1∈0,1𝑚𝑉 (đ‘„đ‘Š0𝑩1 ⋯ 𝑩𝑎−1) = 0 (16.9)

Page 509: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

what if p equals np? 509

7 We do not know whether such loss is inherent.As far as we can tell, it’s possible that the quantifiedboolean formula problem has a linear-time algorithm.We will, however, see later in this course that itsatisfies a notion known as PSPACE-hardness that iseven stronger than NP-hardness.

where 𝒬 is ∃ if 𝒬 was ∀ and 𝒬 is ∀ otherwise. (Please stop and verifythat you understand why this is true, this is a generalization of the factthat if ι is some logical condition then the negation of ∃𝑩∀𝑧ι(𝑩, 𝑧) is∀𝑩∃𝑧¬ι(𝑩, 𝑧).)

The crucial observation is that đœ‘đ‘„,𝑩0 is exactly a statement of theform we consider with 𝑎 − 1 quantifiers instead of 𝑎, and hence byour inductive hypothesis there is some polynomial time algorithm𝑆 that on input đ‘„đ‘Š0 outputs 1 if and only if đœ‘đ‘„,𝑩0 is true. If we let 𝑆be the algorithm that on input đ‘„, 𝑩0 outputs 1 − 𝑆(đ‘„đ‘Š0) then we seethat 𝑆 outputs 1 if and only if đœ‘đ‘„,𝑩0 is true. Hence we can rephrase theoriginal statement (16.7) as follows:∃𝑩0∈0,1𝑚𝑆(đ‘„đ‘Š0) = 1 (16.10)

but since 𝑆 is a polynomial-time algorithm, Eq. (16.10) is clearly astatement in NP and hence under our assumption that P = NP there isa polynomial time algorithm that on input đ‘„ ∈ 0, 1𝑛, will determineif (16.10) is true and so also if the original statement (16.7) is true.

The algorithm of Theorem 16.6 can also solve the search problemas well: find the value 𝑩0 that certifies the truth of (16.7). We notethat while this algorithm is in polynomial time, the exponent of thispolynomial blows up quite fast. If the original NANDSAT algorithmrequired Ω(𝑛2) time, solving 𝑎 levels of quantifiers would require timeΩ(𝑛2𝑎).716.4.1 Application: self improving algorithm for 3SATSuppose that we found a polynomial-time algorithm 𝐮 for 3SAT thatis “good but not great”. For example, maybe our algorithm runs intime 𝑐𝑛2 for some not too small constant 𝑐. However, it’s possiblethat the best possible SAT algorithm is actually much more efficientthan that. Perhaps, as we guessed before, there is a circuit đ¶âˆ— of atmost 106𝑛 gates that computes 3SAT on 𝑛 variables, and we simplyhaven’t discovered it yet. We can use Theorem 16.6 to “bootstrap” ouroriginal “good but not great” 3SAT algorithm to discover the optimalone. The idea is that we can phrase the question of whether thereexists a size 𝑠 circuit that computes 3SAT for all length 𝑛 inputs asfollows: there exists a size ≀ 𝑠 circuit đ¶ such that for every formula 𝜑described by a string of length at most 𝑛, if đ¶(𝜑) = 1 then there existsan assignment đ‘„ to the variables of 𝜑 that satisfies it. One can see thatthis is a statement of the form (16.5) and hence if P = NP we can solveit in polynomial time as well. We can therefore imagine investing hugecomputational resources in running 𝐮 one time to discover the circuitđ¶âˆ— and then using đ¶âˆ— for all further computation.

Page 510: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

510 introduction to theoretical computer science

16.5 APPROXIMATING COUNTING PROBLEMS AND POSTERIORSAMPLING (ADVANCED, OPTIONAL)

Given a Boolean circuit đ¶, if P = NP then we can find an input đ‘„ (ifone exists) such that đ¶(đ‘„) = 1. But what if there is more than one đ‘„like that? Clearly we can’t efficiently output all such đ‘„â€™s; there mightbe exponentially many. But we can get an arbitrarily good multiplica-tive approximation (i.e., a 1Â±đœ– factor for arbitrarily small 𝜖 > 0) for thenumber of such đ‘„â€™s, as well as output a (nearly) uniform member ofthis set. The details are beyond the scope of this book, but this result isformally stated in the following theorem (whose proof is omitted).

Theorem 16.7 — Approximate counting if P = NP. Let 𝑉 ∶ 0, 1∗ → 0, 1be some polynomial-time algorithm, and suppose that P = NP.Then there exists an algorithm COUNT𝑉 that on input đ‘„, 1𝑚, 𝜖,runs in time polynomial in |đ‘„|, 𝑚, 1/𝜖 and outputs a number in[2𝑚 + 1] satisfying(1−𝜖)COUNT𝑉 (đ‘„, 𝑚, 𝜖) ≀ ∣𝑩 ∈ 0, 1𝑚 ∶ 𝑉 (đ‘„đ‘Š) = 1∣ ≀ (1+𝜖)COUNT𝑉 (đ‘„, 𝑚, 𝜖) .

(16.11)

In other words, the algorithm COUNT𝑉 gives an approximationup to a factor of 1 ± 𝜖 for the number of witnesses for đ‘„ with respectto the verifying algorithm 𝑉 . Once again, to understand this theoremit can be useful to see how it implies that if P = NP then there is apolynomial-time algorithm that given a graph đș and a number 𝑘,can compute a number đŸ that is within a 1 ± 0.01 factor equal to thenumber of simple paths in đș of length 𝑘. (That is, đŸ is between 0.99 to1.01 times the number of such paths.)

Posterior sampling and probabilistic programming. The algorithm for count-ing can also be extended to sampling from a given posterior distri-bution. That is, if đ¶ ∶ 0, 1𝑛 → 0, 1𝑚 is a Boolean circuit and𝑩 ∈ 0, 1𝑚, then if P = NP we can sample from (a close approx-imation of) the distribution of uniform đ‘„ ∈ 0, 1𝑛 conditioned onđ¶(đ‘„) = 𝑩. This task is known as posterior sampling and is crucial forBayesian data analysis. These days it is known how to achieve pos-terior sampling only for circuits đ¶ of very special form, and even inthese cases more often than not we do have guarantees on the qualityof the sampling algorithm. The field of making inferences by samplingfrom posterior distribution specified by circuits or programs is knownas probabilistic programming.

Page 511: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

what if p equals np? 511

8 One interesting theory is that P = NP and evolutionhas already discovered this algorithm, which we arealready using without realizing it. At the moment,there seems to be very little evidence for such a sce-nario. In fact, we have some partial results in theother direction showing that, regardless of whetherP = NP, many types of “local search” or “evolution-ary” algorithms require exponential time to solve3SAT and other NP-hard problems.

16.6 WHAT DOES ALL OF THIS IMPLY?

So, what will happen if we have a 106𝑛 algorithm for 3SAT? We havementioned that NP-hard problems arise in many contexts, and indeedscientists, engineers, programmers and others routinely encountersuch problems in their daily work. A better 3SAT algorithm will prob-ably make their lives easier, but that is the wrong place to look forthe most foundational consequences. Indeed, while the invention ofelectronic computers did of course make it easier to do calculationsthat people were already doing with mechanical devices and pen andpaper, the main applications computers are used for today were noteven imagined before their invention.

An exponentially faster algorithm for all NP problems would beno less radical an improvement (and indeed, in some sense wouldbe more) than the computer itself, and it is as hard for us to imaginewhat it would imply as it was for Babbage to envision today’s world.For starters, such an algorithm would completely change the way weprogram computers. Since we could automatically find the “best”(in any measure we chose) program that achieves a certain task, wewould not need to define how to achieve a task, but only specify testsas to what would be a good solution, and could also ensure that aprogram satisfies an exponential number of tests without actuallyrunning them.

The possibility that P = NP is often described as “automatingcreativity”. There is something to that analogy, as we often think ofa creative solution as one that is hard to discover but that, once the“spark” hits, is easy to verify. But there is also an element of hubristo that statement, implying that the most impressive consequence ofsuch an algorithmic breakthrough will be that computers would suc-ceed in doing something that humans already do today. Nevertheless,artificial intelligence, like many other fields, will clearly be greatlyimpacted by an efficient 3SAT algorithm. For example, it is clearlymuch easier to find a better Chess-playing algorithm when, given anyalgorithm 𝑃 , you can find the smallest algorithm 𝑃 â€Č that plays Chessbetter than 𝑃 . Moreover, as we mentioned above, much of machinelearning (and statistical reasoning in general) is about finding “sim-ple” concepts that explain the observed data, and if NP = P, we couldsearch for such concepts automatically for any notion of “simplicity”we see fit. In fact, we could even “skip the middle man” and do anautomatic search for the learning algorithm with smallest general-ization error. Ultimately the field of Artificial Intelligence is abouttrying to “shortcut” billions of years of evolution to obtain artificialprograms that match (or beat) the performance of natural ones, and afast algorithm for NP would provide the ultimate shortcut.8

Page 512: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

512 introduction to theoretical computer science

More generally, a faster algorithm for NP problems would be im-mensely useful in any field where one is faced with computational orquantitative problems− which is basically all fields of science, math,and engineering. This will not only help with concrete problems suchas designing a better bridge, or finding a better drug, but also withaddressing basic mysteries such as trying to find scientific theories or“laws of nature”. In a fascinating talk, physicist Nima Arkani-Hameddiscusses the effort of finding scientific theories in much the same lan-guage as one would describe solving an NP problem, for which thesolution is easy to verify or seems “inevitable”, once found, but thatrequires searching through a huge landscape of possibilities to reach,and that often can get “stuck” at local optima:

“the laws of nature have this amazing feeling of inevitability
 which is associ-ated with local perfection.”

“The classical picture of the world is the top of a local mountain in the space ofideas. And you go up to the top and it looks amazing up there and absolutelyincredible. And you learn that there is a taller mountain out there. Find it,Mount Quantum
. they’re not smoothly connected 
 you’ve got to make ajump to go from classical to quantum 
 This also tells you why we have suchmajor challenges in trying to extend our understanding of physics. We don’thave these knobs, and little wheels, and twiddles that we can turn. We have tolearn how to make these jumps. And it is a tall order. And that’s why things aredifficult.”

Finding an efficient algorithm for NP amounts to always being ableto search through an exponential space and find not just the “local”mountain, but the tallest peak.

But perhaps more than any computational speedups, a fast algo-rithm for NP problems would bring about a new type of understanding.In many of the areas where NP-completeness arises, it is not as mucha barrier for solving computational problems as it is a barrier for ob-taining “closed-form formulas” or other types of more constructivedescriptions of the behavior of natural, biological, social and other sys-tems. A better algorithm for NP, even if it is “merely” 2√𝑛-time, seemsto require obtaining a new way to understand these types of systems,whether it is characterizing Nash equilibria, spin-glass configurations,entangled quantum states, or any of the other questions where NP iscurrently a barrier for analytical understanding. Such new insightswould be very fruitful regardless of their computational utility.

Big Idea 23 If P = NP, we can efficiently solve a fantastic numberof decision, search, optimization, counting, and sampling problemsfrom all areas of human endeavors.

Page 513: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

what if p equals np? 513

9 This inefficiency is not necessarily inherent. Laterin this course we may discuss results in program-checking, interactive proofs, and average-case com-plexity, that can be used for efficient verification ofproofs of related statements. In contrast, the ineffi-ciency of verifying failure of all programs could wellbe inherent.

16.7 CAN P ≠ NP BE NEITHER TRUE NOR FALSE?

The Continuum Hypothesis is a conjecture made by Georg Cantor in1878, positing the non-existence of a certain type of infinite cardinality.(One way to phrase it is that for every infinite subset 𝑆 of the realnumbers ℝ, either there is a one-to-one and onto function 𝑓 ∶ 𝑆 → ℝor there is a one-to-one and onto function 𝑓 ∶ 𝑆 → ℕ.) This wasconsidered one of the most important open problems in set theory,and settling its truth or falseness was the first problem put forward byHilbert in the 1900 address we mentioned before. However, using thetheories developed by Gödel and Turing, in 1963 Paul Cohen provedthat both the Continuum Hypothesis and its negation are consistentwith the standard axioms of set theory (i.e., the Zermelo-Fraenkelaxioms + the Axiom of choice, or “ZFC” for short). Formally, whathe proved is that if ZFC is consistent, then so is ZFC when we assumeeither the continuum hypothesis or its negation.

Today, many (though not all) mathematicians interpret this resultas saying that the Continuum Hypothesis is neither true nor false, butrather is an axiomatic choice that we are free to make one way or theother. Could the same hold for P ≠ NP?

In short, the answer is No. For example, suppose that we are try-ing to decide between the “3SAT is easy” conjecture (there is an 106𝑛time algorithm for 3SAT) and the “3SAT is hard” conjecture (for ev-ery 𝑛, any NAND-CIRC program that solves 𝑛 variable 3SAT takes210−6𝑛 lines). Then, since for 𝑛 = 108, 210−6𝑛 > 106𝑛, this boils downto the finite question of deciding whether or not there is a 1013-lineNAND-CIRC program deciding 3SAT on formulas with 108 variables.If there is such a program then there is a finite proof of its existence,namely the approximately 1TB file describing the program, and forwhich the verification is the (finite in principle though infeasible inpractice) process of checking that it succeeds on all inputs.9 If thereisn’t such a program, then there is also a finite proof of that, thoughany such proof would take longer since we would need to enumer-ate over all programs as well. Ultimately, since it boils down to a finitestatement about bits and numbers; either the statement or its negationmust follow from the standard axioms of arithmetic in a finite numberof arithmetic steps. Thus, we cannot justify our ignorance in distin-guishing between the “3SAT easy” and “3SAT hard” cases by claimingthat this might be an inherently ill-defined question. Similar reason-ing (with different numbers) applies to other variants of the P vs NPquestion. We note that in the case that 3SAT is hard, it may well bethat there is no short proof of this fact using the standard axioms, andthis is a question that people have been studying in various restrictedforms of proof systems.

Page 514: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

514 introduction to theoretical computer science

10 Actually, the computational difficulty of problems ineconomics such as finding optimal (or any) equilibriais quite subtle. Some variants of such problems areNP-hard, while others have a certain “intermediate”complexity.

11 Talk more about coping with NP hardness. Maintwo approaches are heuristics such as SAT solvers thatsucceed on some instances, and proxy measures suchas mathematical relaxations that instead of solvingproblem 𝑋 (e.g., an integer program) solve program𝑋â€Č (e.g., a linear program) that is related to that.Maybe give compressed sensing as an example, andleast square minimization as a proxy for maximumapostoriori probability.

16.8 IS P = NP “IN PRACTICE”?

The fact that a problem is NP-hard means that we believe there is noefficient algorithm that solve it in the worst case. It does not, however,mean that every single instance of the problem is hard. For exam-ple, if all the clauses in a 3SAT instance 𝜑 contain the same variableđ‘„đ‘– (possibly in negated form), then by guessing a value to đ‘„đ‘– we canreduce 𝜑 to a 2SAT instance which can then be efficiently solved. Gen-eralizations of this simple idea are used in “SAT solvers”, which arealgorithms that have solved certain specific interesting SAT formulaswith thousands of variables, despite the fact that we believe SAT tobe exponentially hard in the worst case. Similarly, a lot of problemsarising in economics and machine learning are NP-hard.10 And yetvendors and customers manage to figure out market-clearing prices(as economists like to point out, there is milk on the shelves) and micesucceed in distinguishing cats from dogs. Hence people (and ma-chines) seem to regularly succeed in solving interesting instances ofNP-hard problems, typically by using some combination of guessingwhile making local improvements.

It is also true that there are many interesting instances of NP-hardproblems that we do not currently know how to solve. Across all ap-plication areas, whether it is scientific computing, optimization, con-trol or more, people often encounter hard instances of NP problemson which our current algorithms fail. In fact, as we will see, all of ourdigital security infrastructure relies on the fact that some concrete andeasy-to-generate instances of, say, 3SAT (or, equivalently, any otherNP-hard problem) are exponentially hard to solve.

Thus it would be wrong to say that NP is easy “in practice”, norwould it be correct to take NP-hardness as the “final word” on thecomplexity of a problem, particularly when we have more informa-tion about how any given instance is generated. Understanding boththe “typical complexity” of NP problems, as well as the power andlimitations of certain heuristics (such as various local-search based al-gorithms) is a very active area of research. We will see more on thesetopics later in this course.

11

16.9 WHAT IF P ≠ NP?

So, P = NP would give us all kinds of fantastical outcomes. But westrongly suspect that P ≠ NP, and moreover that there is no much-better-than-brute-force algorithm for 3SAT. If indeed that is the case, isit all bad news?

One might think that impossibility results, telling you that youcannot do something, is the kind of cloud that does not have a silver

Page 515: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

what if p equals np? 515

lining. But in fact, as we already alluded to before, it does. A hard(in a sufficiently strong sense) problem in NP can be used to create acode that cannot be broken, a task that for thousands of years has beenthe dream of not just spies but of many scientists and mathematiciansover the generations. But the complexity viewpoint turned out toyield much more than simple codes, achieving tasks that people hadpreviously not even dared to dream of. These include the notion ofpublic key cryptography, allowing two people to communicate securelywithout ever having exchanged a secret key; electronic cash, allowingprivate and secure transaction without a central authority; and securemultiparty computation, enabling parties to compute a joint function onprivate inputs without revealing any extra information about it. Also,as we will see, computational hardness can be used to replace the roleof randomness in many settings.

Furthermore, while it is often convenient to pretend that computa-tional problems are simply handed to us, and that our job as computerscientists is to find the most efficient algorithm for them, this is nothow things work in most computing applications. Typically even for-mulating the problem to solve is a highly non-trivial task. When wediscover that the problem we want to solve is NP-hard, this might be auseful sign that we used the wrong formulation for it.

Beyond all these, the quest to understand computational hardness− including the discoveries of lower bounds for restricted compu-tational models, as well as new types of reductions (such as thosearising from “probabilistically checkable proofs”) − has already hadsurprising positive applications to problems in algorithm design, aswell as in coding for both communication and storage. This is notsurprising since, as we mentioned before, from group theory to thetheory of relativity, the pursuit of impossibility results has often beenone of the most fruitful enterprises of mankind.

Chapter Recap

‱ The question of whether P = NP is one of themost important and fascinating questions of com-puter science and science at large, touching on allfields of the natural and social sciences, as well asmathematics and engineering.

‱ Our current evidence and understanding supportsthe “SAT hard” scenario that there is no much-better-than-brute-force algorithm for 3SAT or manyother NP-hard problems.

‱ We are very far from proving this, however. Re-searchers have studied proving lower bounds onthe number of gates to compute explicit functionsin restricted forms of circuits, and have made some

Page 516: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

516 introduction to theoretical computer science

advances in this effort, along the way generatingmathematical tools that have found other uses.However, we have made essentially no headwayin proving lower bounds for general models ofcomputation such as Boolean circuits and Turingmachines. Indeed, we currently do not even knowhow to rule out the possibility that for every 𝑛 ∈ ℕ,SAT restricted to 𝑛-length inputs has a Booleancircuit of less than 10𝑛 gates (even though thereexist 𝑛-input functions that require at least 2𝑛/(10𝑛)gates to compute).

‱ Understanding how to cope with this compu-tational intractability, and even benefit from it,comprises much of the research in theoreticalcomputer science.

16.10 EXERCISES

16.11 BIBLIOGRAPHICAL NOTES

As mentioned before, Aaronson’s survey [Aar16] is a great expositionof the P vs NP problem. Another recommended survey by Aaronsonis [Aar05] which discusses the question of whether NP completeproblems could be computed by any physical means.

The paper [BU11] discusses some results about problems in thepolynomial hierarchy.

Page 517: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

17Space bounded computation

PLAN: Example of space bounded algorithms, importance of pre-serving space. The classes L and PSPACE, space hierarchy theorem,PSPACE=NPSPACE, constant space = regular languages.

17.1 EXERCISES

17.2 BIBLIOGRAPHICAL NOTES

Compiled on 8.26.2020 18:10

Page 518: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 519: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

IVRANDOMIZED COMPUTATION

Page 520: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 521: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

18Probability Theory 101

“God doesn’t play dice with the universe”, Albert Einstein

“Einstein was doubly wrong 
 not only does God definitely play dice, but Hesometimes confuses us by throwing them where they can’t be seen.”, StephenHawking

“ ‘The probability of winning a battle has no place in our theory because itdoes not belong to any [random experiment]. Probability cannot be appliedto this problem any more than the physical concept of work can be applied tothe ’work’ done by an actor reciting his part.”, Richard Von Mises, 1928(paraphrased)

“I am unable to see why ‘objectivity’ requires us to interpret every probabilityas a frequency in some random experiment; particularly when in most problemsprobabilities are frequencies only in an imaginary universe invented just for thepurpose of allowing a frequency interpretation.”, E.T. Jaynes, 1976

Before we show how to use randomness in algorithms, let us do aquick review of some basic notions in probability theory. This is notmeant to replace a course on probability theory, and if you have notseen this material before, I highly recommend you look at additionalresources to get up to speed. Fortunately, we will not need many ofthe advanced notions of probability theory, but, as we will see, eventhe so-called “simple” setting of tossing 𝑛 coins can lead to very subtleand interesting issues.

18.1 RANDOM COINS

The nature of randomness and probability is a topic of great philo-sophical, scientific and mathematical depth. Is there actual random-ness in the world, or does it proceed in a deterministic clockwork fash-ion from some initial conditions set at the beginning of time? Doesprobability refer to our uncertainty of beliefs, or to the frequency ofoccurrences in repeated experiments? How can we define probabilityover infinite sets?

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Review the basic notion of probability theory

that we will use.‱ Sample spaces, and in particular the space0, 1𝑛‱ Events, probabilities of unions and

intersections.‱ Random variables and their expectation,

variance, and standard deviation.‱ Independence and correlation for both events

and random variables.‱ Markov, Chebyshev and Chernoff tail bounds

(bounding the probability that a randomvariable will deviate from its expectation).

Page 522: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

522 introduction to theoretical computer science

Figure 18.1: The probabilistic experiment of tossingthree coins corresponds to making 2 × 2 × 2 = 8choices, each with equal probability. In this example,the blue set corresponds to the event 𝐮 = đ‘„ ∈0, 13 | đ‘„0 = 0 where the first coin toss is equalto 0, and the pink set corresponds to the event đ” =đ‘„ ∈ 0, 13 | đ‘„1 = 1 where the second coin toss isequal to 1 (with their intersection having a purplishcolor). As we can see, each of these events contains 4elements (out of 8 total) and so has probability 1/2.The intersection of 𝐮 and đ” contains two elements,and so the probability that both of these events occuris 2/8 = 1/4.

Figure 18.2: The event that if we toss three coinsđ‘„0, đ‘„1, đ‘„2 ∈ 0, 1 then the sum of the đ‘„đ‘–â€™s is evenhas probability 1/2 since it corresponds to exactly 4out of the 8 possible strings of length 3.

These are all important questions that have been studied and de-bated by scientists, mathematicians, statisticians and philosophers.Fortunately, we will not need to deal directly with these questionshere. We will be mostly interested in the setting of tossing 𝑛 random,unbiased and independent coins. Below we define the basic proba-bilistic objects of events and random variables when restricted to thissetting. These can be defined for much more general probabilistic ex-periments or sample spaces, and later on we will briefly discuss howthis can be done. However, the 𝑛-coin case is sufficient for almosteverything we’ll need in this course.

If instead of “heads” and “tails” we encode the sides of each coinby “zero” and “one”, we can encode the result of tossing 𝑛 coins asa string in 0, 1𝑛. Each particular outcome đ‘„ ∈ 0, 1𝑛 is obtainedwith probability 2−𝑛. For example, if we toss three coins, then weobtain each of the 8 outcomes 000, 001, 010, 011, 100, 101, 110, 111with probability 2−3 = 1/8 (see also Fig. 18.1). We can describe theexperiment of tossing 𝑛 coins as choosing a string đ‘„ uniformly atrandom from 0, 1𝑛, and hence we’ll use the shorthand đ‘„ ∌ 0, 1𝑛for đ‘„ that is chosen according to this experiment.

An event is simply a subset 𝐮 of 0, 1𝑛. The probability of 𝐮, de-noted by Prđ‘„âˆŒ0,1𝑛 [𝐮] (or Pr[𝐮] for short, when the sample space isunderstood from the context), is the probability that an đ‘„ chosen uni-formly at random will be contained in 𝐮. Note that this is the same as|𝐮|/2𝑛 (where |𝐮| as usual denotes the number of elements in the set𝐮). For example, the probability that đ‘„ has an even number of onesis Pr[𝐮] where 𝐮 = đ‘„ ∶ ∑𝑛−1𝑖=0 đ‘„đ‘– = 0 mod 2. In the case 𝑛 = 3,𝐮 = 000, 011, 101, 110, and hence Pr[𝐮] = 48 = 12 (see Fig. 18.2). Itturns out this is true for every 𝑛:Lemma 18.1 For every 𝑛 > 0,

Prđ‘„âˆŒ0,1𝑛[𝑛−1∑𝑖=0 đ‘„đ‘– is even ] = 1/2 (18.1)

PTo test your intuition on probability, try to stop hereand prove the lemma on your own.

Proof of Lemma 18.1. We prove the lemma by induction on 𝑛. For thecase 𝑛 = 1 it is clear since đ‘„ = 0 is even and đ‘„ = 1 is odd, and hencethe probability that đ‘„ ∈ 0, 1 is even is 1/2. Let 𝑛 > 1. We assumeby induction that the lemma is true for 𝑛 − 1 and we will prove itfor 𝑛. We split the set 0, 1𝑛 into four disjoint sets 𝐾0, 𝐾1, 𝑂0, 𝑂1,where for 𝑏 ∈ 0, 1, 𝐾𝑏 is defined as the set of đ‘„ ∈ 0, 1𝑛 such that

Page 523: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probability theory 101 523

đ‘„0 ⋯ đ‘„đ‘›âˆ’2 has even number of ones and đ‘„đ‘›âˆ’1 = 𝑏 and similarly 𝑂𝑏 isthe set of đ‘„ ∈ 0, 1𝑛 such that đ‘„0 ⋯ đ‘„đ‘›âˆ’2 has odd number of ones andđ‘„đ‘›âˆ’1 = 𝑏. Since 𝐾0 is obtained by simply extending 𝑛 − 1-length stringwith even number of ones by the digit 0, the size of 𝐾0 is simply thenumber of such 𝑛−1-length strings which by the induction hypothesisis 2𝑛−1/2 = 2𝑛−2. The same reasoning applies for 𝐾1, 𝑂0, and 𝑂1.Hence each one of the four sets 𝐾0, 𝐾1, 𝑂0, 𝑂1 is of size 2𝑛−2. Sinceđ‘„ ∈ 0, 1𝑛 has an even number of ones if and only if đ‘„ ∈ 𝐾0 âˆȘ 𝑂1(i.e., either the first 𝑛 − 1 coordinates sum up to an even number andthe final coordinate is 0 or the first 𝑛 − 1 coordinates sum up to an oddnumber and the final coordinate is 1), we get that the probability thatđ‘„ satisfies this property is

|𝐾0âˆȘ𝑂1|2𝑛 = 2𝑛−2 + 2𝑛−22𝑛 = 12 , (18.2)

using the fact that 𝐾0 and 𝑂1 are disjoint and hence |𝐾0 âˆȘ 𝑂1| =|𝐾0| + |𝑂1|.

We can also use the intersection (∩) and union (âˆȘ) operators totalk about the probability of both event 𝐮 and event đ” happening, orthe probability of event 𝐮 or event đ” happening. For example, theprobability 𝑝 that đ‘„ has an even number of ones and đ‘„0 = 1 is the sameas Pr[𝐮 ∩ đ”] where 𝐮 = đ‘„ ∈ 0, 1𝑛 ∶ ∑𝑛−1𝑖=0 đ‘„đ‘– = 0 mod 2 andđ” = đ‘„ ∈ 0, 1𝑛 ∶ đ‘„0 = 1. This probability is equal to 1/4 for𝑛 > 1. (It is a great exercise for you to pause here and verify that youunderstand why this is the case.)

Because intersection corresponds to considering the logical ANDof the conditions that two events happen, while union correspondsto considering the logical OR, we will sometimes use the ∧ and √operators instead of ∩ and âˆȘ, and so write this probability 𝑝 = Pr[𝐮 âˆ©đ”] defined above also as

Prđ‘„âˆŒ0,1𝑛 [∑𝑖 đ‘„đ‘– = 0 mod 2 ∧ đ‘„0 = 1] . (18.3)

If 𝐮 ⊆ 0, 1𝑛 is an event, then 𝐮 = 0, 1𝑛 ⧔ 𝐮 corresponds to theevent that 𝐮 does not happen. Since |𝐮| = 2𝑛 − |𝐮|, we get that

Pr[𝐮] = |𝐮|2𝑛 = 2𝑛−|𝐮|2𝑛 = 1 − |𝐮|2𝑛 = 1 − Pr[𝐮] (18.4)

This makes sense: since 𝐮 happens if and only if 𝐮 does not happen,the probability of 𝐮 should be one minus the probability of 𝐮.

R

Page 524: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

524 introduction to theoretical computer science

Remark 18.2 — Remember the sample space. While theabove definition might seem very simple and almosttrivial, the human mind seems not to have evolved forprobabilistic reasoning, and it is surprising how oftenpeople can get even the simplest settings of probabilitywrong. One way to make sure you don’t get confusedwhen trying to calculate probability statements isto always ask yourself the following two questions:(1) Do I understand what is the sample space thatthis probability is taken over?, and (2) Do I under-stand what is the definition of the event that we areanalyzing?.For example, suppose that I were to randomize seatingin my course, and then it turned out that studentssitting in row 7 performed better on the final: howsurprising should we find this? If we started out withthe hypothesis that there is something special aboutthe number 7 and chose it ahead of time, then theevent that we are discussing is the event 𝐮 that stu-dents sitting in number 7 had better performance onthe final, and we might find it surprising. However, ifwe first looked at the results and then chose the rowwhose average performance is best, then the eventwe are discussing is the event đ” that there exists somerow where the performance is higher than the over-all average. đ” is a superset of 𝐮, and its probability(even if there is no correlation between sitting andperformance) can be quite significant.

18.1.1 Random variablesEvents correspond to Yes/No questions, but often we want to analyzefiner questions. For example, if we make a bet at the roulette wheel,we don’t want to just analyze whether we won or lost, but also howmuch we’ve gained. A (real valued) random variable is simply a wayto associate a number with the result of a probabilistic experiment.Formally, a random variable is a function 𝑋 ∶ 0, 1𝑛 → ℝ that mapsevery outcome đ‘„ ∈ 0, 1𝑛 to an element 𝑋(đ‘„) ∈ ℝ. For example, thefunction SUM ∶ 0, 1𝑛 → ℝ that maps đ‘„ to the sum of its coordinates(i.e., to ∑𝑛−1𝑖=0 đ‘„đ‘–) is a random variable.

The expectation of a random variable 𝑋, denoted by đ”Œ[𝑋], is theaverage value that this number takes, taken over all draws from theprobabilistic experiment. In other words, the expectation of 𝑋 is de-fined as follows: đ”Œ[𝑋] = âˆ‘đ‘„âˆˆ0,1𝑛 2−𝑛𝑋(đ‘„) . (18.5)

If 𝑋 and 𝑌 are random variables, then we can define 𝑋 + 𝑌 assimply the random variable that maps a point đ‘„ ∈ 0, 1𝑛 to 𝑋(đ‘„) +𝑌 (đ‘„). One basic and very useful property of the expectation is that itis linear:

Page 525: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probability theory 101 525

Lemma 18.3 — Linearity of expectation.đ”Œ[𝑋 + 𝑌 ] = đ”Œ[𝑋] + đ”Œ[𝑌 ] (18.6)

Proof. đ”Œ[𝑋 + 𝑌 ] = âˆ‘đ‘„âˆˆ0,1𝑛 2−𝑛 (𝑋(đ‘„) + 𝑌 (đ‘„)) =âˆ‘đ‘„âˆˆ0,1𝑏 2−𝑛𝑋(đ‘„) + âˆ‘đ‘„âˆˆ0,1𝑏 2−𝑛𝑌 (đ‘„) =đ”Œ[𝑋] + đ”Œ[𝑌 ] (18.7)

Similarly, đ”Œ[𝑘𝑋] = 𝑘 đ”Œ[𝑋] for every 𝑘 ∈ ℝ.Solved Exercise 18.1 — Expectation of sum. Let 𝑋 ∶ 0, 1𝑛 → ℝ be therandom variable that maps đ‘„ ∈ 0, 1𝑛 to đ‘„0 + đ‘„1 + 
 + đ‘„đ‘›âˆ’1. Provethat đ”Œ[𝑋] = 𝑛/2.

Solution:

We can solve this using the linearity of expectation. We can de-fine random variables 𝑋0, 𝑋1, 
 , 𝑋𝑛−1 such that 𝑋𝑖(đ‘„) = đ‘„đ‘–. Sinceeach đ‘„đ‘– equals 1 with probability 1/2 and 0 with probability 1/2,đ”Œ[𝑋𝑖] = 1/2. Since 𝑋 = ∑𝑛−1𝑖=0 𝑋𝑖, by the linearity of expectationđ”Œ[𝑋] = đ”Œ[𝑋0] + đ”Œ[𝑋1] + ⋯ + đ”Œ[𝑋𝑛−1] = 𝑛2 . (18.8)

PIf you have not seen discrete probability before, pleasego over this argument again until you are sure youfollow it; it is a prototypical simple example of thetype of reasoning we will employ again and again inthis course.

If 𝐮 is an event, then 1𝐮 is the random variable such that 1𝐮(đ‘„)equals 1 if đ‘„ ∈ 𝐮, and 1𝐮(đ‘„) = 0 otherwise. Note that Pr[𝐮] = đ”Œ[1𝐮](can you see why?). Using this and the linearity of expectation, wecan show one of the most useful bounds in probability theory:Lemma 18.4 — Union bound. For every two events 𝐮, đ”, Pr[𝐮 âˆȘ đ”] ≀Pr[𝐮] + Pr[đ”]

PBefore looking at the proof, try to see why the unionbound makes intuitive sense. We can also proveit directly from the definition of probabilities and

Page 526: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

526 introduction to theoretical computer science

Figure 18.3: The union bound tells us that the proba-bility of 𝐮 or đ” happening is at most the sum of theindividual probabilities. We can see it by noting thatfor every two sets |𝐮 âˆȘ đ”| ≀ |𝐮| + |đ”| (with equalityonly if 𝐮 and đ” have no intersection).

the cardinality of sets, together with the equation|𝐮 âˆȘ đ”| ≀ |𝐮| + |đ”|. Can you see why the latterequation is true? (See also Fig. 18.3.)

Proof of Lemma 18.4. For every đ‘„, the variable 1𝐮âˆȘđ”(đ‘„) ≀ 1𝐮(đ‘„)+1đ”(đ‘„).Hence, Pr[𝐮âˆȘđ”] = đ”Œ[1𝐮âˆȘđ”] ≀ đ”Œ[1𝐮+1đ”] = đ”Œ[1𝐮]+đ”Œ[1đ”] = Pr[𝐮]+Pr[đ”].

The way we often use this in theoretical computer science is toargue that, for example, if there is a list of 100 bad events that can hap-pen, and each one of them happens with probability at most 1/10000,then with probability at least 1 − 100/10000 = 0.99, no bad eventhappens.

18.1.2 Distributions over stringsWhile most of the time we think of random variables as havingas output a real number, we sometimes consider random vari-ables whose output is a string. That is, we can think of a map𝑌 ∶ 0, 1𝑛 → 0, 1∗ and consider the “random variable” 𝑌 suchthat for every 𝑩 ∈ 0, 1∗, the probability that 𝑌 outputs 𝑩 is equalto 12𝑛 |đ‘„ ∈ 0, 1𝑛 | 𝑌 (đ‘„) = 𝑩|. To avoid confusion, we will typicallyrefer to such string-valued random variables as distributions overstrings. So, a distribution 𝑌 over strings 0, 1∗ can be thought of asa finite collection of strings 𝑩0, 
 , 𝑩𝑀−1 ∈ 0, 1∗ and probabilities𝑝0, 
 , 𝑝𝑀−1 (which are non-negative numbers summing up to one),so that Pr[𝑌 = 𝑩𝑖] = 𝑝𝑖.

Two distributions 𝑌 and 𝑌 â€Č are identical if they assign the sameprobability to every string. For example, consider the following twofunctions 𝑌 , 𝑌 â€Č ∶ 0, 12 → 0, 12. For every đ‘„ ∈ 0, 12, we define𝑌 (đ‘„) = đ‘„ and 𝑌 â€Č(đ‘„) = đ‘„0(đ‘„0 ⊕ đ‘„1) where ⊕ is the XOR operations.Although these are two different functions, they induce the samedistribution over 0, 12 when invoked on a uniform input. The distri-bution 𝑌 (đ‘„) for đ‘„ ∌ 0, 12 is of course the uniform distribution over0, 12. On the other hand 𝑌 â€Č is simply the map 00 ↩ 00, 01 ↩ 01,10 ↩ 11, 11 ↩ 10 which is a permutation of 𝑌 .

18.1.3 More general sample spacesWhile throughout most of this book we assume that the underlyingprobabilistic experiment corresponds to tossing 𝑛 independent coins,all the claims we make easily generalize to sampling đ‘„ from a moregeneral finite or countable set 𝑆 (and not-so-easily generalizes touncountable sets 𝑆 as well). A probability distribution over a finite set𝑆 is simply a function 𝜇 ∶ 𝑆 → [0, 1] such that âˆ‘đ‘„âˆˆđ‘† 𝜇(đ‘„) = 1. Wethink of this as the experiment where we obtain every đ‘„ ∈ 𝑆 with

Page 527: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probability theory 101 527

Figure 18.4: Two events 𝐮 and đ” are independent ifPr[𝐮 ∩ đ”] = Pr[𝐮] ⋅ Pr[đ”]. In the two figures above,the empty đ‘„ × đ‘„ square is the sample space, and 𝐮and đ” are two events in this sample space. In the leftfigure, 𝐮 and đ” are independent, while in the rightfigure they are negatively correlated, since đ” is lesslikely to occur if we condition on 𝐮 (and vice versa).Mathematically, one can see this by noticing that inthe left figure the areas of 𝐮 and đ” respectively are𝑎 ⋅ đ‘„ and 𝑏 ⋅ đ‘„, and so their probabilities are đ‘Žâ‹…đ‘„đ‘„2 = đ‘Žđ‘„and đ‘â‹…đ‘„đ‘„2 = đ‘đ‘„ respectively, while the area of 𝐮 ∩ đ” is𝑎 ⋅ 𝑏 which corresponds to the probability đ‘Žâ‹…đ‘đ‘„2 . In theright figure, the area of the triangle đ” is đ‘â‹…đ‘„2 whichcorresponds to a probability of 𝑏2đ‘„ , but the area of𝐮 ∩ đ” is 𝑏â€Č⋅𝑎2 for some 𝑏â€Č < 𝑏. This means that theprobability of 𝐮 ∩ đ” is 𝑏â€Č⋅𝑎2đ‘„2 < 𝑏2đ‘„ ⋅ đ‘Žđ‘„ , or in other wordsPr[𝐮 ∩ đ”] < Pr[𝐮] ⋅ Pr[đ”].

probability 𝜇(đ‘„), and sometimes denote this as đ‘„ ∌ 𝜇. In particular,tossing 𝑛 random coins corresponds to the probability distribution𝜇 ∶ 0, 1𝑛 → [0, 1] defined as 𝜇(đ‘„) = 2−𝑛 for every đ‘„ ∈ 0, 1𝑛. Anevent 𝐮 is a subset of 𝑆, and the probability of 𝐮, which we denote byPr𝜇[𝐮], is âˆ‘đ‘„âˆˆđŽ 𝜇(đ‘„). A random variable is a function 𝑋 ∶ 𝑆 → ℝ, wherethe probability that 𝑋 = 𝑩 is equal to âˆ‘đ‘„âˆˆđ‘† s.t. 𝑋(đ‘„)=𝑩 𝜇(đ‘„).18.2 CORRELATIONS AND INDEPENDENCE

One of the most delicate but important concepts in probability is thenotion of independence (and the opposing notion of correlations). Subtlecorrelations are often behind surprises and errors in probability andstatistical analysis, and several mistaken predictions have been blamedon miscalculating the correlations between, say, housing prices inFlorida and Arizona, or voter preferences in Ohio and Michigan. Seealso Joe Blitzstein’s aptly named talk “Conditioning is the Soul ofStatistics”. (Another thorny issue is of course the difference betweencorrelation and causation. Luckily, this is another point we don’t need toworry about in our clean setting of tossing 𝑛 coins.)

Two events 𝐮 and đ” are independent if the fact that 𝐮 happensmakes đ” neither more nor less likely to happen. For example, if wethink of the experiment of tossing 3 random coins đ‘„ ∈ 0, 13, and welet 𝐮 be the event that đ‘„0 = 1 and đ” the event that đ‘„0 + đ‘„1 + đ‘„2 ≄ 2,then if 𝐮 happens it is more likely that đ” happens, and hence theseevents are not independent. On the other hand, if we let đ¶ be the eventthat đ‘„1 = 1, then because the second coin toss is not affected by theresult of the first one, the events 𝐮 and đ¶ are independent.

The formal definition is that events 𝐮 and đ” are independent ifPr[𝐮 ∩ đ”] = Pr[𝐮] ⋅ Pr[đ”]. If Pr[𝐮 ∩ đ”] > Pr[𝐮] ⋅ Pr[đ”] then we saythat 𝐮 and đ” are positively correlated, while if Pr[𝐮 ∩ đ”] < Pr[𝐮] ⋅ Pr[đ”]then we say that 𝐮 and đ” are negatively correlated (see Fig. 18.1).

If we consider the above examples on the experiment of choosingđ‘„ ∈ 0, 13 then we can see that

Pr[đ‘„0 = 1] = 12Pr[đ‘„0 + đ‘„1 + đ‘„2 ≄ 2] = Pr[011, 101, 110, 111] = 48 = 12 (18.9)

but

Pr[đ‘„0 = 1 ∧ đ‘„0 +đ‘„1 +đ‘„2 ≄ 2] = Pr[101, 110, 111] = 38 > 12 ⋅ 12 (18.10)

and hence, as we already observed, the events đ‘„0 = 1 and đ‘„0 +đ‘„1 + đ‘„2 ≄ 2 are not independent and in fact are positively correlated.On the other hand, Pr[đ‘„0 = 1 ∧ đ‘„1 = 1] = Pr[110, 111] = 28 = 12 ⋅ 12and hence the events đ‘„0 = 1 and đ‘„1 = 1 are indeed independent.

Page 528: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

528 introduction to theoretical computer science

Figure 18.5: Consider the sample space 0, 1𝑛 andthe events 𝐮, đ”, đ¶, đ·, 𝐾 corresponding to 𝐮: đ‘„0 = 1,đ”: đ‘„1 = 1, đ¶: đ‘„0 + đ‘„1 + đ‘„2 ≄ 2, đ·: đ‘„0 + đ‘„1 + đ‘„2 =0𝑚𝑜𝑑2 and đ·: đ‘„0 + đ‘„1 = 0𝑚𝑜𝑑2. We can see that𝐮 and đ” are independent, đ¶ is positively correlatedwith 𝐮 and positively correlated with đ”, the threeevents 𝐮, đ”, đ· are mutually independent, and whileevery pair out of 𝐮, đ”, 𝐾 is independent, the threeevents 𝐮, đ”, 𝐾 are not mutually independent sincetheir intersection has probability 28 = 14 instead of12 ⋅ 12 ⋅ 12 = 18 .

RRemark 18.5 — Disjointness vs independence. Peoplesometimes confuse the notion of disjointness and in-dependence, but these are actually quite different. Twoevents 𝐮 and đ” are disjoint if 𝐮 ∩ đ” = ∅, which meansthat if 𝐮 happens then đ” definitely does not happen.They are independent if Pr[𝐮 ∩ đ”] = Pr[𝐮]Pr[đ”] whichmeans that knowing that 𝐮 happens gives us no infor-mation about whether đ” happened or not. If 𝐮 and đ”have nonzero probability, then being disjoint impliesthat they are not independent, since in particular itmeans that they are negatively correlated.

Conditional probability: If 𝐮 and đ” are events, and 𝐮 happens withnonzero probability then we define the probability that đ” happensconditioned on 𝐮 to be Pr[đ”|𝐮] = Pr[𝐮 ∩ đ”]/Pr[𝐮]. This correspondsto calculating the probability that đ” happens if we already knowthat 𝐮 happened. Note that 𝐮 and đ” are independent if and only ifPr[đ”|𝐮] = Pr[đ”].More than two events: We can generalize this definition to more thantwo events. We say that events 𝐮1, 
 , 𝐮𝑘 are mutually independentif knowing that any set of them occurred or didn’t occur does notchange the probability that an event outside the set occurs. Formally,the condition is that for every subset đŒ ⊆ [𝑘],

Pr[âˆ§đ‘–âˆˆđŒđŽđ‘–] = âˆđ‘–âˆˆđŒ Pr[𝐮𝑖]. (18.11)

For example, if đ‘„ ∌ 0, 13, then the events đ‘„0 = 1, đ‘„1 = 1 andđ‘„2 = 1 are mutually independent. On the other hand, the eventsđ‘„0 = 1, đ‘„1 = 1 and đ‘„0 + đ‘„1 = 0 mod 2 are not mutuallyindependent, even though every pair of these events is independent(can you see why? see also Fig. 18.5).

18.2.1 Independent random variablesWe say that two random variables 𝑋 ∶ 0, 1𝑛 → ℝ and 𝑌 ∶ 0, 1𝑛 → ℝare independent if for every 𝑱, 𝑣 ∈ ℝ, the events 𝑋 = 𝑱 and 𝑌 = 𝑣are independent. (We use 𝑋 = 𝑱 as shorthand for đ‘„ | 𝑋(đ‘„) = 𝑱.)In other words, 𝑋 and 𝑌 are independent if Pr[𝑋 = 𝑱 ∧ 𝑌 = 𝑣] =Pr[𝑋 = 𝑱]Pr[𝑌 = 𝑣] for every 𝑱, 𝑣 ∈ ℝ. For example, if two randomvariables depend on the result of tossing different coins then they areindependent:Lemma 18.6 Suppose that 𝑆 = 𝑠0, 
 , 𝑠𝑘−1 and 𝑇 = 𝑡0, 
 , 𝑡𝑚−1 aredisjoint subsets of 0, 
 , 𝑛 − 1 and let 𝑋, 𝑌 ∶ 0, 1𝑛 → ℝ be randomvariables such that 𝑋 = đč(đ‘„đ‘ 0 , 
 , đ‘„đ‘ đ‘˜âˆ’1) and 𝑌 = đș(đ‘„đ‘Ą0 , 
 , đ‘„đ‘Ąđ‘šâˆ’1) for

Page 529: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probability theory 101 529

some functions đč ∶ 0, 1𝑘 → ℝ and đș ∶ 0, 1𝑚 → ℝ. Then 𝑋 and 𝑌are independent.

PThe notation in the lemma’s statement is a bit cum-bersome, but at the end of the day, it simply says thatif 𝑋 and 𝑌 are random variables that depend on twodisjoint sets 𝑆 and 𝑇 of coins (for example, 𝑋 mightbe the sum of the first 𝑛/2 coins, and 𝑌 might be thelargest consecutive stretch of zeroes in the second 𝑛/2coins), then they are independent.

Proof of Lemma 18.6. Let 𝑎, 𝑏 ∈ ℝ, and let 𝐮 = đ‘„ ∈ 0, 1𝑘 ∶ đč (đ‘„) = 𝑎and đ” = đ‘„ ∈ 0, 1𝑚 ∶ đč (đ‘„) = 𝑏. Since 𝑆 and 𝑇 are disjoint, we canreorder the indices so that 𝑆 = 0, 
 , 𝑘 − 1 and 𝑇 = 𝑘, 
 , 𝑘 + 𝑚 − 1without affecting any of the probabilities. Hence we can write Pr[𝑋 =𝑎 ∧ 𝑋 = 𝑏] = |đ¶|/2𝑛 where đ¶ = đ‘„0, 
 , đ‘„đ‘›âˆ’1 ∶ (đ‘„0, 
 , đ‘„đ‘˜âˆ’1) ∈𝐮 ∧ (đ‘„đ‘˜, 
 , đ‘„đ‘˜+𝑚−1) ∈ đ”. Another way to write this using stringconcatenation is that đ¶ = đ‘„đ‘Šđ‘§ ∶ đ‘„ ∈ 𝐮, 𝑩 ∈ đ”, 𝑧 ∈ 0, 1𝑛−𝑘−𝑚, andhence |đ¶| = |𝐮||đ”|2𝑛−𝑘−𝑚, which means that|đ¶|2𝑛 = |𝐮|2𝑘 |đ”|2𝑚 2𝑛−𝑘−𝑚2𝑛−𝑘−𝑚 = Pr[𝑋 = 𝑎]Pr[𝑌 = 𝑏]. (18.12)

If 𝑋 and 𝑌 are independent random variables then (letting 𝑆𝑋, 𝑆𝑌denote the sets of all numbers that have positive probability of beingthe output of 𝑋 and 𝑌 , respectively):đ”Œ[XY] = ∑𝑎∈𝑆𝑋,𝑏∈𝑆𝑌 Pr[𝑋 = 𝑎 ∧ 𝑌 = 𝑏] ⋅ 𝑎𝑏 =(1) ∑𝑎∈𝑆𝑋,𝑏∈𝑆𝑌 Pr[𝑋 = 𝑎]Pr[𝑌 = 𝑏] ⋅ 𝑎𝑏 =(2)

( ∑𝑎∈𝑆𝑋 Pr[𝑋 = 𝑎] ⋅ 𝑎) ( ∑𝑏∈𝑆𝑌 Pr[𝑌 = 𝑏] ⋅ 𝑏) =(3)đ”Œ[𝑋] đ”Œ[𝑌 ](18.13)

where the first equality (=(1)) follows from the independence of 𝑋and 𝑌 , the second equality (=(2)) follows by “opening the parenthe-ses” of the righthand side, and the third equality (=(3)) follows fromthe definition of expectation. (This is not an “if and only if”; see Exer-cise 18.3.)

Another useful fact is that if 𝑋 and 𝑌 are independent randomvariables, then so are đč(𝑋) and đș(𝑌 ) for all functions đč, đș ∶ ℝ → ℝ.This is intuitively true since learning đč(𝑋) can only provide us withless information than does learning 𝑋 itself. Hence, if learning 𝑋does not teach us anything about 𝑌 (and so also about đč(𝑌 )) then

Page 530: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

530 introduction to theoretical computer science

neither will learning đč(𝑋). Indeed, to prove this we can write forevery 𝑎, 𝑏 ∈ ℝ:

Pr[đč (𝑋) = 𝑎 ∧ đș(𝑌 ) = 𝑏] = âˆ‘đ‘„ s.t.đč(đ‘„)=𝑎,𝑩 s.t. đș(𝑩)=𝑏 Pr[𝑋 = đ‘„ ∧ 𝑌 = 𝑩] =âˆ‘đ‘„ s.t.đč(đ‘„)=𝑎,𝑩 s.t. đș(𝑩)=𝑏 Pr[𝑋 = đ‘„]Pr[𝑌 = 𝑩] =⎛⎜⎝ âˆ‘đ‘„ s.t.đč(đ‘„)=𝑎 Pr[𝑋 = đ‘„]⎞⎟⎠ ⋅ ⎛⎜⎝ ∑𝑩 s.t.đș(𝑩)=𝑏 Pr[𝑌 = 𝑩]⎞⎟⎠ =

Pr[đč (𝑋) = 𝑎]Pr[đș(𝑌 ) = 𝑏].(18.14)

18.2.2 Collections of independent random variablesWe can extend the notions of independence to more than two randomvariables: we say that the random variables 𝑋0, 
 , 𝑋𝑛−1 are mutuallyindependent if for every 𝑎0, 
 , 𝑎𝑛−1 ∈ ℝ,

Pr [𝑋0 = 𝑎0 ∧ ⋯ ∧ 𝑋𝑛−1 = 𝑎𝑛−1] = Pr[𝑋0 = 𝑎0] ⋯Pr[𝑋𝑛−1 = 𝑎𝑛−1].(18.15)

And similarly, we have thatLemma 18.7 — Expectation of product of independent random variables. If𝑋0, 
 , 𝑋𝑛−1 are mutually independent thenđ”Œ[𝑛−1∏𝑖=0 𝑋𝑖] = 𝑛−1∏𝑖=0 đ”Œ[𝑋𝑖]. (18.16)

Lemma 18.8 — Functions preserve independence. If 𝑋0, 
 , 𝑋𝑛−1 are mu-tually independent, and 𝑌0, 
 , 𝑌𝑛−1 are defined as 𝑌𝑖 = đč𝑖(𝑋𝑖) forsome functions đč0, 
 , đč𝑛−1 ∶ ℝ → ℝ, then 𝑌0, 
 , 𝑌𝑛−1 are mutuallyindependent as well.

PWe leave proving Lemma 18.7 and Lemma 18.8 asExercise 18.6 and Exercise 18.7. It is good idea for youstop now and do these exercises to make sure you arecomfortable with the notion of independence, as wewill use it heavily later on in this course.

18.3 CONCENTRATION AND TAIL BOUNDS

The name “expectation” is somewhat misleading. For example, sup-pose that you and I place a bet on the outcome of 10 coin tosses, whereif they all come out to be 1’s then I pay you 100,000 dollars and other-

Page 531: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probability theory 101 531

Figure 18.6: The probabilities that we obtain a partic-ular sum when we toss 𝑛 = 10, 20, 100, 1000 coinsconverge quickly to the Gaussian/normal distribu-tion.

Figure 18.7: Markov’s Inequality tells us that a non-negative random variable 𝑋 cannot be much largerthan its expectation, with high probability. For exam-ple, if the expectation of 𝑋 is 𝜇, then the probabilitythat 𝑋 > 4𝜇 must be at most 1/4, as otherwise justthe contribution from this part of the sample spacewill be too large.

wise you pay me 10 dollars. If we let 𝑋 ∶ 0, 110 → ℝ be the randomvariable denoting your gain, then we see thatđ”Œ[𝑋] = 2−10 ⋅ 100000 − (1 − 2−10)10 ∌ 90. (18.17)

But we don’t really “expect” the result of this experiment to be foryou to gain 90 dollars. Rather, 99.9% of the time you will pay me 10dollars, and you will hit the jackpot 0.01% of the times.

However, if we repeat this experiment again and again (with freshand hence independent coins), then in the long run we do expect youraverage earning to be close to 90 dollars, which is the reason whycasinos can make money in a predictable way even though everyindividual bet is random. For example, if we toss 𝑛 independent andunbiased coins, then as 𝑛 grows, the number of coins that come upones will be more and more concentrated around 𝑛/2 according to thefamous “bell curve” (see Fig. 18.6).

Much of probability theory is concerned with so called concentrationor tail bounds, which are upper bounds on the probability that a ran-dom variable 𝑋 deviates too much from its expectation. The first andsimplest one of them is Markov’s inequality:

Theorem 18.9 — Markov’s inequality. If 𝑋 is a non-negative randomvariable then for every 𝑘 > 1, Pr[𝑋 ≄ 𝑘 đ”Œ[𝑋]] ≀ 1/𝑘.

PMarkov’s Inequality is actually a very natural state-ment (see also Fig. 18.7). For example, if you knowthat the average (not the median!) household incomein the US is 70,000 dollars, then in particular you candeduce that at most 25 percent of households makemore than 280,000 dollars, since otherwise, even ifthe remaining 75 percent had zero income, the top25 percent alone would cause the average income tobe larger than 70,000 dollars. From this example youcan already see that in many situations, Markov’sinequality will not be tight and the probability of devi-ating from expectation will be much smaller: see theChebyshev and Chernoff inequalities below.

Proof of Theorem 18.9. Let 𝜇 = đ”Œ[𝑋] and define 𝑌 = 1đ‘‹â‰„đ‘˜đœ‡. Thatis, 𝑌 (đ‘„) = 1 if 𝑋(đ‘„) ≄ 𝑘𝜇 and 𝑌 (đ‘„) = 0 otherwise. Note that bydefinition, for every đ‘„, 𝑌 (đ‘„) ≀ 𝑋/(𝑘𝜇). We need to show đ”Œ[𝑌 ] ≀ 1/𝑘.But this follows since đ”Œ[𝑌 ] ≀ đ”Œ[𝑋/𝑘(𝜇)] = đ”Œ[𝑋]/(𝑘𝜇) = 𝜇/(𝑘𝜇) = 1/𝑘.

Page 532: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

532 introduction to theoretical computer science

The averaging principle. While the expectation of a random variable𝑋 is hardly always the “typical value”, we can show that 𝑋 is guar-anteed to achieve a value that is at least its expectation with positiveprobability. For example, if the average grade in an exam is 87 points,at least one student got a grade 87 or more on the exam. This is knownas the averaging principle, and despite its simplicity it is surprisinglyuseful.Lemma 18.10 Let 𝑋 be a random variable, then Pr[𝑋 ≄ đ”Œ[𝑋]] > 0.Proof. Suppose towards the sake of contradiction that Pr[𝑋 < đ”Œ[𝑋]] =1. Then the random variable 𝑌 = đ”Œ[𝑋] − 𝑋 is always positive. Bylinearity of expectation đ”Œ[𝑌 ] = đ”Œ[𝑋] − đ”Œ[𝑋] = 0. Yet by Markov, anon-negative random variable 𝑌 with đ”Œ[𝑌 ] = 0 must equal 0 withprobability 1, since the probability that 𝑌 > 𝑘 ⋅ 0 = 0 is at most 1/𝑘 forevery 𝑘 > 1. Hence we get a contradiction to the assumption that 𝑌 isalways positive.

18.3.1 Chebyshev’s InequalityMarkov’s inequality says that a (non-negative) random variable 𝑋can’t go too crazy and be, say, a million times its expectation, withsignificant probability. But ideally we would like to say that withhigh probability, 𝑋 should be very close to its expectation, e.g., in therange [0.99𝜇, 1.01𝜇] where 𝜇 = đ”Œ[𝑋]. In such a case we say that 𝑋 isconcentrated, and hence its expectation (i.e., mean) will be close to itsmedian and other ways of measuring 𝑋’s “typical value”. Chebyshev’sinequality can be thought of as saying that 𝑋 is concentrated if it has asmall standard deviation.

A standard way to measure the deviation of a random variablefrom its expectation is by using its standard deviation. For a randomvariable 𝑋, we define the variance of 𝑋 as Var[𝑋] = đ”Œ[(𝑋 − 𝜇)2]where 𝜇 = đ”Œ[𝑋]; i.e., the variance is the average squared distanceof 𝑋 from its expectation. The standard deviation of 𝑋 is defined as𝜎[𝑋] = √Var[𝑋]. (This is well-defined since the variance, being anaverage of a square, is always a non-negative number.)

Using Chebyshev’s inequality, we can control the probability thata random variable is too many standard deviations away from itsexpectation.

Theorem 18.11 — Chebyshev’s inequality. Suppose that 𝜇 = đ”Œ[𝑋] and𝜎2 = Var[𝑋]. Then for every 𝑘 > 0, Pr[|𝑋 − 𝜇| ≄ 𝑘𝜎] ≀ 1/𝑘2.Proof. The proof follows from Markov’s inequality. We define therandom variable 𝑌 = (𝑋 − 𝜇)2. Then đ”Œ[𝑌 ] = Var[𝑋] = 𝜎2, and hence

Page 533: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probability theory 101 533

Figure 18.8: In the normal distribution or the Bell curve,the probability of deviating 𝑘 standard deviationsfrom the expectation shrinks exponentially in 𝑘2, andspecifically with probability at least 1 − 2𝑒−𝑘2/2, arandom variable 𝑋 of expectation 𝜇 and standarddeviation 𝜎 satisfies 𝜇−𝑘𝜎 ≀ 𝑋 ≀ 𝜇+𝑘𝜎. This figuregives more precise bounds for 𝑘 = 1, 2, 3, 4, 5, 6.(Image credit:Imran Baghirov)

by Markov the probability that 𝑌 > 𝑘2𝜎2 is at most 1/𝑘2. But clearly(𝑋 − 𝜇)2 ≄ 𝑘2𝜎2 if and only if |𝑋 − 𝜇| ≄ 𝑘𝜎.

One example of how to use Chebyshev’s inequality is the settingwhen 𝑋 = 𝑋1 + ⋯ + 𝑋𝑛 where 𝑋𝑖’s are independent and identicallydistributed (i.i.d for short) variables with values in [0, 1] where eachhas expectation 1/2. Since đ”Œ[𝑋] = ∑𝑖 đ”Œ[𝑋𝑖] = 𝑛/2, we would like tosay that 𝑋 is very likely to be in, say, the interval [0.499𝑛, 0.501𝑛]. Us-ing Markov’s inequality directly will not help us, since it will only tellus that 𝑋 is very likely to be at most 100𝑛 (which we already knew,since it always lies between 0 and 𝑛). However, since 𝑋1, 
 , 𝑋𝑛 areindependent,

Var[𝑋1 + ⋯ + 𝑋𝑛] = Var[𝑋1] + ⋯ + Var[𝑋𝑛] . (18.18)

(We leave showing this to the reader as Exercise 18.8.)For every random variable 𝑋𝑖 in [0, 1], Var[𝑋𝑖] ≀ 1 (if the variable

is always in [0, 1], it can’t be more than 1 away from its expectation),and hence (18.18) implies that Var[𝑋] ≀ 𝑛 and hence 𝜎[𝑋] ≀ √𝑛.For large 𝑛, √𝑛 â‰Ș 0.001𝑛, and in particular if √𝑛 ≀ 0.001𝑛/𝑘, we canuse Chebyshev’s inequality to bound the probability that 𝑋 is not in[0.499𝑛, 0.501𝑛] by 1/𝑘2.18.3.2 The Chernoff boundChebyshev’s inequality already shows a connection between inde-pendence and concentration, but in many cases we can hope fora quantitatively much stronger result. If, as in the example above,𝑋 = 𝑋1 + 
 + 𝑋𝑛 where the 𝑋𝑖’s are bounded i.i.d random variablesof mean 1/2, then as 𝑛 grows, the distribution of 𝑋 would be roughlythe normal or Gaussian distribution− that is, distributed according tothe bell curve (see Fig. 18.6 and Fig. 18.8). This distribution has theproperty of being very concentrated in the sense that the probability ofdeviating 𝑘 standard deviations from the mean is not merely 1/𝑘2 as isguaranteed by Chebyshev, but rather is roughly 𝑒−𝑘2 . Specifically, fora normal random variable 𝑋 of expectation 𝜇 and standard deviation𝜎, the probability that |𝑋 − 𝜇| ≄ 𝑘𝜎 is at most 2𝑒−𝑘2/2. That is, we havean exponential decay of the probability of deviation.

The following extremely useful theorem shows that such expo-nential decay occurs every time we have a sum of independent andbounded variables. This theorem is known under many names in dif-ferent communities, though it is mostly called the Chernoff bound inthe computer science literature:

Page 534: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

534 introduction to theoretical computer science

Theorem 18.12 — Chernoff/Hoeffding bound. If 𝑋0, 
 , 𝑋𝑛−1 are i.i.d ran-dom variables such that 𝑋𝑖 ∈ [0, 1] and đ”Œ[𝑋𝑖] = 𝑝 for every 𝑖, thenfor every 𝜖 > 0

Pr[∣𝑛−1∑𝑖=0 𝑋𝑖 − 𝑝𝑛∣ > 𝜖𝑛] ≀ 2 ⋅ 𝑒−2𝜖2𝑛. (18.19)

We omit the proof, which appears in many texts, and uses Markov’sinequality on i.i.d random variables 𝑌0, 
 , 𝑌𝑛 that are of the form𝑌𝑖 = 𝑒𝜆𝑋𝑖 for some carefully chosen parameter 𝜆. See Exercise 18.11for a proof of the simple (but highly useful and representative) casewhere each 𝑋𝑖 is 0, 1 valued and 𝑝 = 1/2. (See also Exercise 18.12for a generalization.)

RRemark 18.13 — Slight simplification of Chernoff. Since 𝑒is roughly 2.7 (and in particular larger than 2),(18.19) would still be true if we replaced its righthandside with 𝑒−2𝜖2𝑛+1. For 𝑛 > 1/𝜖2, the equation willstill be true if we replaced the righthand side withthe simpler 𝑒−𝜖2𝑛. Hence we will sometimes use theChernoff bound as stating that for 𝑋0, 
 , 𝑋𝑛−1 and 𝑝as above, 𝑛 > 1/𝜖2 then

Pr[∣𝑛−1∑𝑖=0 𝑋𝑖 − 𝑝𝑛∣ > 𝜖𝑛] ≀ 𝑒−𝜖2𝑛. (18.20)

18.3.3 Application: Supervised learning and empirical risk minimizationHere is a nice application of the Chernoff bound. Consider the taskof supervised learning. You are given a set 𝑆 of 𝑛 samples of the form(đ‘„0, 𝑩0), 
 , (đ‘„đ‘›âˆ’1, 𝑩𝑛−1) drawn from some unknown distribution đ·over pairs (đ‘„, 𝑩). For simplicity we will assume that đ‘„đ‘– ∈ 0, 1𝑚 and𝑩𝑖 ∈ 0, 1. (We use here the concept of general distribution over thefinite set 0, 1𝑚+1 as discussed in Section 18.1.3.) The goal is to finda classifier ℎ ∶ 0, 1𝑚 → 0, 1 that will minimize the test error whichis the probability 𝐿(ℎ) that ℎ(đ‘„) ≠ 𝑩 where (đ‘„, 𝑩) is drawn from thedistribution đ·. That is, 𝐿(ℎ) = Pr(đ‘„,𝑩)âˆŒđ·[ℎ(đ‘„) ≠ 𝑩].

One way to find such a classifier is to consider a collection 𝒞 of po-tential classifiers and look at the classifier ℎ in 𝒞 that does best on thetraining set 𝑆. The classifier ℎ is known as the empirical risk minimizer(see also Section 12.1.6) . The Chernoff bound can be used to showthat as long as the number 𝑛 of samples is sufficiently larger than thelogarithm of |𝒞|, the test error 𝐿(ℎ) will be close to its training error

Page 535: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probability theory 101 535

𝑆(ℎ), which is defined as the fraction of pairs (đ‘„đ‘–, 𝑩𝑖) ∈ 𝑆 that it failsto classify. (Equivalently, 𝑆(ℎ) = 1𝑛 ∑𝑖∈[𝑛] |ℎ(đ‘„đ‘–) − 𝑩𝑖|.)

Theorem 18.14 — Generalization of ERM. Let đ· be any distribution overpairs (đ‘„, 𝑩) ∈ 0, 1𝑚+1 and 𝒞 be any set of functions mapping0, 1𝑚 to 0, 1. Then for every 𝜖, 𝛿 > 0, if 𝑛 > log |𝒞| log(1/𝛿)𝜖2 and 𝑆is a set of (đ‘„0, 𝑩0), 
 , (đ‘„đ‘›âˆ’1, 𝑩𝑛−1) samples that are drawn indepen-dently from đ· then

Pr𝑆 [∀ℎ∈𝒞|𝐿(ℎ) − 𝑆(ℎ)| ≀ 𝜖] > 1 − 𝛿 , (18.21)

where the probability is taken over the choice of the set of samples𝑆.In particular if |𝒞| ≀ 2𝑘 and 𝑛 > 𝑘 log(1/𝛿)𝜖2 then with probability at

least 1−𝛿, the classifier ℎ∗ ∈ 𝒞 that minimizes that empirical test er-ror 𝑆(đ¶) satisfies 𝐿(ℎ∗) ≀ 𝑆(ℎ∗) + 𝜖, and hence its test error is atmost 𝜖 worse than its training error.

Proof Idea:

The idea is to combine the Chernoff bound with the union bound.Let 𝑘 = log |𝒞|. We first use the Chernoff bound to show that forevery fixed ℎ ∈ 𝒞, if we choose 𝑆 at random then the probability that|𝐿(ℎ) − 𝑆(ℎ)| > 𝜖 will be smaller than 𝛿2𝑘 . We can then use the unionbound over all the 2𝑘 members of 𝒞 to show that this will be the casefor every ℎ.⋆Proof of Theorem 18.14. Set 𝑘 = log |𝒞| and so 𝑛 > 𝑘 log(1/𝛿)/𝜖2. Westart by making the following claim

CLAIM: For every ℎ ∈ 𝒞, the probability over 𝑆 that |𝐿(ℎ) −𝑆(ℎ)| ≄ 𝜖 is smaller than 𝛿/2𝑘.We prove the claim using the Chernoff bound. Specifically, for ev-

ery such ℎ, let us defined a collection of random variables 𝑋0, 
 , 𝑋𝑛−1as follows:

𝑋𝑖 = ⎧⎚⎩1 ℎ(đ‘„đ‘–) ≠ 𝑩𝑖0 otherwise. (18.22)

Since the samples (đ‘„0, 𝑩0), 
 , (đ‘„đ‘›âˆ’1, 𝑩𝑛−1) are drawn independentlyfrom the same distribution đ·, the random variables 𝑋0, 
 , 𝑋𝑛−1 areindependently and identically distributed. Moreover, for every 𝑖,đ”Œ[𝑋𝑖] = 𝐿(ℎ). Hence by the Chernoff bound (see (18.20)), the proba-bility that | ∑𝑛𝑖=0 𝑋𝑖 −𝑛⋅𝐿(ℎ)| ≄ 𝜖𝑛 is at most 𝑒−𝜖2𝑛 < 𝑒−𝑘 log(1/𝛿) < 𝛿/2𝑘(using the fact that 𝑒 > 2). Since (ℎ) = 1𝑛 ∑𝑖∈[𝑛] 𝑋𝑖, this completesthe proof of the claim.

Page 536: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

536 introduction to theoretical computer science

Given the claim, the theorem follows from the union bound. In-deed, for every ℎ ∈ 𝒞, define the “bad event” đ”â„Ž to be the event (overthe choice of 𝑆) that |𝐿(ℎ) − 𝑆(ℎ)| > 𝜖. By the claim Pr[đ”â„Ž] < 𝛿/2𝑘,and hence by the union bound the probability that the union of đ”â„Ž forall ℎ ∈ ℋ happens is smaller than |𝒞|𝛿/2𝑘 = 𝛿. If for every ℎ ∈ 𝒞, đ”â„Ždoes not happen, it means that for every ℎ ∈ ℋ, |𝐿(ℎ) − 𝑆(ℎ)| ≀ 𝜖,and so the probability of the latter event is larger than 1 − 𝛿 which iswhat we wanted to prove.

Chapter Recap

‱ A basic probabilistic experiment corresponds totossing 𝑛 coins or choosing đ‘„ uniformly at randomfrom 0, 1𝑛.

‱ Random variables assign a real number to everyresult of a coin toss. The expectation of a randomvariable 𝑋 is its average value.

‱ There are several concentration results, also knownas tail bounds showing that under certain condi-tions, random variables deviate significantly fromtheir expectation only with small probability.

18.4 EXERCISES

Exercise 18.1 Suppose that we toss three independent fair coins 𝑎, 𝑏, 𝑐 ∈0, 1. What is the probability that the XOR of 𝑎,𝑏, and 𝑐 is equal to 1?What is the probability that the AND of these three values is equal to1? Are these two events independent?

Exercise 18.2 Give an example of random variables 𝑋, 𝑌 ∶ 0, 13 → ℝsuch that đ”Œ[XY] ≠ đ”Œ[𝑋] đ”Œ[𝑌 ].

Exercise 18.3 Give an example of random variables 𝑋, 𝑌 ∶ 0, 13 → ℝsuch that 𝑋 and 𝑌 are not independent but đ”Œ[XY] = đ”Œ[𝑋] đ”Œ[𝑌 ].

Exercise 18.4 Let 𝑛 be an odd number, and let 𝑋 ∶ 0, 1𝑛 → ℝ be therandom variable defined as follows: for every đ‘„ ∈ 0, 1𝑛, 𝑋(đ‘„) = 1 if∑𝑖=0 đ‘„đ‘– > 𝑛/2 and 𝑋(đ‘„) = 0 otherwise. Prove that đ”Œ[𝑋] = 1/2.

Exercise 18.5 — standard deviation. 1. Give an example for a randomvariable 𝑋 such that 𝑋’s standard deviation is equal to đ”Œ[|𝑋 − đ”Œ[𝑋]|]

Page 537: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probability theory 101 537

1 While you don’t need this to solve this exercise, thisis the function that maps 𝑝 to the entropy (as definedin Exercise 18.9) of the 𝑝-biased coin distribution over0, 1, which is the function 𝜇 ∶ 0, 1 → [0, 1] s.y.𝜇(0) = 1 − 𝑝 and 𝜇(1) = 𝑝.2 Hint: Use Stirling’s formula for approximating thefactorial function.

2. Give an example for a random variable 𝑋 such that 𝑋’s standarddeviation is not equal to đ”Œ[|𝑋 − đ”Œ[𝑋]|]

Exercise 18.6 — Product of expectations. Prove Lemma 18.7

Exercise 18.7 — Transformations preserve independence. Prove Lemma 18.8

Exercise 18.8 — Variance of independent random variables. Prove that if𝑋0, 
 , 𝑋𝑛−1 are independent random variables then Var[𝑋0 + ⋯ +𝑋𝑛−1] = ∑𝑛−1𝑖=0 Var[𝑋𝑖].

Exercise 18.9 — Entropy (challenge). Recall the definition of a distribution𝜇 over some finite set 𝑆. Shannon defined the entropy of a distribution𝜇, denoted by đ»(𝜇), to be âˆ‘đ‘„âˆˆđ‘† 𝜇(đ‘„) log(1/𝜇(đ‘„)). The idea is that if 𝜇is a distribution of entropy 𝑘, then encoding members of 𝜇 will require𝑘 bits, in an amortized sense. In this exercise we justify this definition.Let 𝜇 be such that đ»(𝜇) = 𝑘.

1. Prove that for every one to one function đč ∶ 𝑆 → 0, 1∗,đ”Œđ‘„âˆŒđœ‡ |đč (đ‘„)| ≄ 𝑘.2. Prove that for every 𝜖, there is some 𝑛 and a one-to-one functionđč ∶ 𝑆𝑛 → 0, 1∗, such that đ”Œđ‘„âˆŒđœ‡đ‘› |đč (đ‘„)| ≀ 𝑛(𝑘 + 𝜖), where đ‘„ ∌ 𝜇

denotes the experiments of choosing đ‘„0, 
 , đ‘„đ‘›âˆ’1 each independentlyfrom 𝑆 using the distribution 𝜇.

Exercise 18.10 — Entropy approximation to binomial. Let đ»(𝑝) = 𝑝 log(1/𝑝) +(1 − 𝑝) log(1/(1 − 𝑝)).1 Prove that for every 𝑝 ∈ (0, 1) and 𝜖 > 0, if 𝑛 islarge enough then2 2(đ»(𝑝)−𝜖)𝑛( 𝑛𝑝𝑛) ≀ 2(đ»(𝑝)+𝜖)𝑛 (18.23)

where (𝑛𝑘) is the binomial coefficient 𝑛!𝑘!(𝑛−𝑘)! which is equal to thenumber of 𝑘-size subsets of 0, 
 , 𝑛 − 1.

Exercise 18.11 — Chernoff using Stirling. 1. Prove that Prđ‘„âˆŒ0,1𝑛 [∑ đ‘„đ‘– =𝑘] = (𝑛𝑘)2−𝑛.2. Use this and Exercise 18.10 to prove (an approximate version of)

the Chernoff bound for the case that 𝑋0, 
 , 𝑋𝑛−1 are i.i.d. randomvariables over 0, 1 each equaling 0 and 1 with probability 1/2.That is, prove that for every 𝜖 > 0, and 𝑋0, 
 , 𝑋𝑛−1 as above,Pr[| ∑𝑛−1𝑖=0 𝑋𝑖 − 𝑛2 | > 𝜖𝑛] < 20.1⋅𝜖2𝑛.

Page 538: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

538 introduction to theoretical computer science

3 Hint: Bound the number of tuples 𝑗0, 
 , 𝑗𝑛−1 suchthat every 𝑗𝑖 is even and ∑ 𝑗𝑖 = 𝑘 using the Binomialcoefficient and the fact that in any such tuple there areat most 𝑘/2 distinct indices.4 Hint: Set 𝑘 = 2⌈𝜖2𝑛/1000⌉ and then show that if theevent | ∑ 𝑌𝑖| ≄ 𝜖𝑛 happens then the random variable(∑ 𝑌𝑖)𝑘 is a factor of 𝜖−𝑘 larger than its expectation.

Exercise 18.12 — Poor man’s Chernoff. Exercise 18.11 establishes the Cher-noff bound for the case that 𝑋0, 
 , 𝑋𝑛−1 are i.i.d variables over 0, 1with expectation 1/2. In this exercise we use a slightly differentmethod (bounding the moments of the random variables) to estab-lish a version of Chernoff where the random variables range over [0, 1]and their expectation is some number 𝑝 ∈ [0, 1] that may be differentthan 1/2. Let 𝑋0, 
 , 𝑋𝑛−1 be i.i.d random variables with đ”Œ 𝑋𝑖 = 𝑝 andPr[0 ≀ 𝑋𝑖 ≀ 1] = 1. Define 𝑌𝑖 = 𝑋𝑖 − 𝑝.1. Prove that for every 𝑗0, 
 , 𝑗𝑛−1 ∈ ℕ, if there exists one 𝑖 such that 𝑗𝑖

is odd then đ”Œ[∏𝑛−1𝑖=0 𝑌 𝑗𝑖𝑖 ] = 0.2. Prove that for every 𝑘, đ”Œ[(∑𝑛−1𝑖=0 𝑌𝑖)𝑘] ≀ (10𝑘𝑛)𝑘/2.33. Prove that for every 𝜖 > 0, Pr[| ∑𝑖 𝑌𝑖| ≄ 𝜖𝑛] ≄ 2−𝜖2𝑛/(10000 log1/𝜖).4

Exercise 18.13 — Sampling. Suppose that a country has 300,000,000 citi-zens, 52 percent of which prefer the color “green” and 48 percent ofwhich prefer the color “orange”. Suppose we sample 𝑛 random citi-zens and ask them their favorite color (assume they will answer truth-fully). What is the smallest value 𝑛 among the following choices sothat the probability that the majority of the sample answers “green” isat most 0.05?a. 1,000

b. 10,000

c. 100,000

d. 1,000,000

Exercise 18.14 Would the answer to Exercise 18.13 change if the countryhad 300,000,000,000 citizens?

Exercise 18.15 — Sampling (2). Under the same assumptions as Exer-cise 18.13, what is the smallest value 𝑛 among the following choices sothat the probability that the majority of the sample answers “green” isat most 2−100?a. 1,000

b. 10,000

c. 100,000

Page 539: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probability theory 101 539

d. 1,000,000

e. It is impossible to get such low probability since there are fewerthan 2100 citizens.

18.5 BIBLIOGRAPHICAL NOTES

There are many sources for more information on discrete probability,including the texts referenced in Section 1.9. One particularly recom-mended source for probability is Harvard’s STAT 110 class, whoselectures are available on youtube and whose book is available online.

The version of the Chernoff bound that we stated in Theorem 18.12is sometimes known as Hoeffding’s Inequality. Other variants of theChernoff bound are known as well, but all of them are equally goodfor the applications of this book.

Page 540: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 541: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Figure 19.1: A 1947 entry in the log book of the Har-vard MARK II computer containing an actual bug thatcaused a hardware malfunction. By Courtesy of theNaval Surface Warfare Center.

1 Some texts also talk about “Las Vegas algorithms”that always return the right answer but whose run-ning time is only polynomial on the average. Sincethis Monte Carlo vs Las Vegas terminology is confus-ing, we will not use these terms anymore, and simplytalk about randomized algorithms.

19Probabilistic computation

“in 1946 .. (I asked myself) what are the chances that a Canfield solitaire laidout with 52 cards will come out successfully? After spending a lot of timetrying to estimate them by pure combinatorial calculations, I wondered whethera more practical method 
 might not be to lay it our say one hundred times andsimple observe and count”, Stanislaw Ulam, 1983

“The salient features of our method are that it is probabilistic 
 and with acontrollable miniscule probability of error.”, Michael Rabin, 1977

In early computer systems, much effort was taken to drive outrandomness and noise. Hardware components were prone to non-deterministic behavior from a number of causes, whether it was vac-uum tubes overheating or actual physical bugs causing short circuits(see Fig. 19.1). This motivated John von Neumann, one of the earlycomputing pioneers, to write a paper on how to error correct computa-tion, introducing the notion of redundancy.

So it is quite surprising that randomness turned out not just a hin-drance but also a resource for computation, enabling us to achievetasks much more efficiently than previously known. One of the firstapplications involved the very same John von Neumann. While hewas sick in bed and playing cards, Stan Ulam came up with the ob-servation that calculating statistics of a system could be done muchfaster by running several randomized simulations. He mentioned thisidea to von Neumann, who became very excited about it; indeed, itturned out to be crucial for the neutron transport calculations thatwere needed for development of the Atom bomb and later on the hy-drogen bomb. Because this project was highly classified, Ulam, vonNeumann and their collaborators came up with the codeword “MonteCarlo” for this approach (based on the famous casinos where Ulam’suncle gambled). The name stuck, and randomized algorithms areknown as Monte Carlo algorithms to this day.1

In this chapter, we will see some examples of randomized algo-rithms that use randomness to compute a quantity in a faster or

Compiled on 8.26.2020 18:10

Learning Objectives:‱ See examples of randomized algorithms‱ Get more comfort with analyzing

probabilistic processes and tail bounds‱ Success amplification using tail bounds

Page 542: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

542 introduction to theoretical computer science

simpler way than was known otherwise. We will describe the algo-rithms in an informal / “pseudo-code” way, rather than as NAND-TM, NAND-RAM programs or Turing macines. In Chapter 20 we willdiscuss how to augment the computational models we say before toincorporate the ability to “toss coins”.

19.1 FINDING APPROXIMATELY GOOD MAXIMUM CUTS

We start with the following example. Recall the maximum cut problemof finding, given a graph đș = (𝑉 , 𝐾), the cut that maximizes the num-ber of edges. This problem is NP-hard, which means that we do notknow of any efficient algorithm that can solve it, but randomizationenables a simple algorithm that can cut at least half of the edges:

Theorem 19.1 — Approximating max cut. There is an efficient probabilis-tic algorithm that on input an 𝑛-vertex 𝑚-edge graph đș, outputs acut (𝑆, 𝑆) that cuts at least 𝑚/2 of the edges of đș in expectation.

Proof Idea:

We simply choose a random cut: we choose a subset 𝑆 of vertices bychoosing every vertex 𝑣 to be a member of 𝑆 with probability 1/2 in-dependently. It’s not hard to see that each edge is cut with probability1/2 and so the expected number of cut edges is 𝑚/2.⋆Proof of Theorem 19.1. The algorithm is extremely simple:

Algorithm Random Cut:Input: Graph đș = (𝑉 , 𝐾) with 𝑛 vertices and 𝑚 edges. Denote 𝑉 =𝑣0, 𝑣1, 
 , 𝑣𝑛−1.Operation:

1. Pick đ‘„ uniformly at random in 0, 1𝑛.2. Let 𝑆 ⊆ 𝑉 be the set 𝑣𝑖 ∶ đ‘„đ‘– = 1 , 𝑖 ∈ [𝑛] that includes all vertices

corresponding to coordinates of đ‘„ where đ‘„đ‘– = 1.3. Output the cut (𝑆, 𝑆).We claim that the expected number of edges cut by the algorithm is𝑚/2. Indeed, for every edge 𝑒 ∈ 𝐾, let 𝑋𝑒 be the random variable such

that 𝑋𝑒(đ‘„) = 1 if the edge 𝑒 is cut by đ‘„, and 𝑋𝑒(đ‘„) = 0 otherwise. Forevery such edge 𝑒 = 𝑖, 𝑗, 𝑋𝑒(đ‘„) = 1 if and only if đ‘„đ‘– ≠ đ‘„đ‘—. Since thepair (đ‘„đ‘–, đ‘„đ‘—) obtains each of the values 00, 01, 10, 11 with probability1/4, the probability that đ‘„đ‘– ≠ đ‘„đ‘— is 1/2 and hence đ”Œ[𝑋𝑒] = 1/2. If we let

Page 543: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probabilist ic computation 543

𝑋 be the random variable corresponding to the total number of edgescut by 𝑆, then 𝑋 = ∑𝑒∈𝐾 𝑋𝑒 and hence by linearity of expectationđ”Œ[𝑋] = ∑𝑒∈𝐾 đ”Œ[𝑋𝑒] = 𝑚(1/2) = 𝑚/2 . (19.1)

Randomized algorithms work in the worst case. It is tempting of a random-ized algorithm such as the one of Theorem 19.1 as an algorithm thatworks for a “random input graph” but it is actually much better thanthat. The expectation in this theorem is not taken over the choice ofthe graph, but rather only over the random choices of the algorithm. Inparticular, for every graph đș, the algorithm is guaranteed to cut half ofthe edges of the input graph in expectation. That is,

Big Idea 24 A randomized algorithm outputs the correct valuewith good probability on every possible input.

We will define more formally what “good probability” means inChapter 20 but the crucial point is that this probability is always onlytaken over the random choices of the algorithm, while the input is notchosen at random.

19.1.1 Amplifying the success of randomized algorithmsTheorem 19.1 gives us an algorithm that cuts 𝑚/2 edges in expectation.But, as we saw before, expectation does not immediately imply con-centration, and so a priori, it may be the case that when we run thealgorithm, most of the time we don’t get a cut matching the expecta-tion. Luckily, we can amplify the probability of success by repeatingthe process several times and outputting the best cut we find. Westart by arguing that the probability the algorithm above succeeds incutting at least 𝑚/2 edges is not too tiny.Lemma 19.2 The probability that a random cut in an 𝑚 edge graph cutsat least 𝑚/2 edges is at least 1/(2𝑚).Proof Idea:

To see the idea behind the proof, think of the case that 𝑚 = 1000. Inthis case one can show that we will cut at least 500 edges with proba-bility at least 0.001 (and so in particular larger than 1/(2𝑚) = 1/2000).Specifically, if we assume otherwise, then this means that with proba-bility more than 0.999 the algorithm cuts 499 or fewer edges. But sincewe can never cut more than the total of 1000 edges, given this assump-tion, the highest value the expected number of edges cut is if we cutexactly 499 edges with probability 0.999 and cut 1000 edges with prob-ability 0.001. Yet even in this case the expected number of edges will

Page 544: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

544 introduction to theoretical computer science

be 0.999 ⋅ 499 + 0.001 ⋅ 1000 < 500, which contradicts the fact that we’vecalculated the expectation to be at least 500 in Theorem 19.1.⋆Proof of Lemma 19.2. Let 𝑝 be the probability that we cut at least 𝑚/2edges and suppose, towards a contradiction, that 𝑝 < 1/(2𝑚). Sincethe number of edges cut is an integer, and 𝑚/2 is a multiple of 0.5,by definition of 𝑝, with probability 1 − 𝑝 we cut at most 𝑚/2 − 0.5edges. Moreover, since we can never cut more than 𝑚 edges, underour assumption that 𝑝 < 1/(2𝑚), we can bound the expected numberof edges cut by𝑝𝑚 + (1 − 𝑝)(𝑚/2 − 0.5) ≀ 𝑝𝑚 + 𝑚/2 − 0.5 (19.2)But if 𝑝 < 1/(2𝑚) then 𝑝𝑚 < 0.5 and so the righthand side is smallerthan 𝑚/2, which contradicts the fact that (as proven in Theorem 19.1)the expected number of edges cut is at least 𝑚/2.

19.1.2 Success amplificationLemma 19.2 shows that our algorithm succeeds at least some of thetime, but we’d like to succeed almost all of the time. The approachto do that is to simply repeat our algorithm many times, with freshrandomness each time, and output the best cut we get in one of theserepetitions. It turns out that with extremely high probability we willget a cut of size at least 𝑚/2. For example, if we repeat this experiment2000𝑚 times, then (using the inequality (1 − 1/𝑘)𝑘 ≀ 1/𝑒 ≀ 1/2) wecan show that the probability that we will never cut at least 𝑚/2 edgesis at most (1 − 1/(2𝑚))2000𝑚 ≀ 2−1000 . (19.3)

More generally, the same calculations can be used to show thefollowing lemma:Lemma 19.3 There is an algorithm that on input a graph đș = (𝑉 , 𝐾) anda number 𝑘, runs in time polynomial in |𝑉 | and 𝑘 and outputs a cut(𝑆, 𝑆) such that

Pr[number of edges cut by (𝑆, 𝑆) ≄ |𝐾|/2] ≄ 1 − 2−𝑘 . (19.4)

Proof of Lemma 19.3. The algorithm will work as follows:

Algorithm AMPLIFY RANDOM CUT:Input: Graph đș = (𝑉 , 𝐾) with 𝑛 vertices and 𝑚 edges. Denote 𝑉 =𝑣0, 𝑣1, 
 , 𝑣𝑛−1. Number 𝑘 > 0.Operation:

Page 545: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probabilist ic computation 545

1. Repeat the following 200𝑘𝑚 times:

a. Pick đ‘„ uniformly at random in 0, 1𝑛.b. Let 𝑆 ⊆ 𝑉 be the set 𝑣𝑖 ∶ đ‘„đ‘– = 1 , 𝑖 ∈ [𝑛] that includes all

vertices corresponding to coordinates of đ‘„ where đ‘„đ‘– = 1.c. If (𝑆, 𝑆) cuts at least 𝑚/2 then halt and output (𝑆, 𝑆).

2. Output “failed”

We leave completing the analysis as an exercise to the reader (seeExercise 19.1).

19.1.3 Two-sided amplificationThe analysis above relied on the fact that the maximum cut has onesided error. By this we mean that if we get a cut of size at least 𝑚/2then we know we have succeeded. This is common for randomizedalgorithms, but is not the only case. In particular, consider the task ofcomputing some Boolean function đč ∶ 0, 1∗ → 0, 1. A randomizedalgorithm 𝐮 for computing đč , given input đ‘„, might toss coins and suc-ceed in outputting đč(đ‘„) with probability, say, 0.9. We say that 𝐮 hastwo sided errors if there is positive probability that 𝐮(đ‘„) outputs 1 whenđč(đ‘„) = 0, and positive probability that 𝐮(đ‘„) outputs 0 when đč(đ‘„) = 1.In such a case, to simplify 𝐮’s success, we cannot simply repeat it 𝑘times and output 1 if a single one of those repetitions resulted in 1,nor can we output 0 if a single one of the repetitions resulted in 0. Butwe can output the majority value of these repetitions. By the Chernoffbound (Theorem 18.12), with probability exponentially close to 1 (i.e.,1 − 2Ω(𝑘)), the fraction of the repetitions where 𝐮 will output đč(đ‘„)will be at least, say 0.89, and in such cases we will of course output thecorrect answer.

The above translates into the following theorem

Theorem 19.4 — Two-sided amplification. If đč ∶ 0, 1∗ → 0, 1 is a func-tion such that there is a polynomial-time algorithm 𝐮 satisfying

Pr[𝐮(đ‘„) = đč(đ‘„)] ≄ 0.51 (19.5)

for every đ‘„ ∈ 0, 1∗, then there is a polynomial time algorithm đ”satisfying

Pr[đ”(đ‘„) = đč(đ‘„)] ≄ 1 − 2−|đ‘„| (19.6)for every đ‘„ ∈ 0, 1∗.We omit the proof of Theorem 19.4, since we will prove a more

general result later on in Theorem 20.5.

Page 546: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

546 introduction to theoretical computer science

2 This question does have some significance to prac-tice, since hardware that generates high qualityrandomness at speed is nontrivial to construct.

19.1.4 What does this mean?We have shown a probabilistic algorithm that on any 𝑚 edge graphđș, will output a cut of at least 𝑚/2 edges with probability at least1 − 2−1000. Does it mean that we can consider this problem as “easy”?Should we be somewhat wary of using a probabilistic algorithm, sinceit can sometimes fail?

First of all, it is important to emphasize that this is still a worst caseguarantee. That is, we are not assuming anything about the inputgraph: the probability is only due to the internal randomness of the al-gorithm. While a probabilistic algorithm might not seem as nice as adeterministic algorithm that is guaranteed to give an output, to get asense of what a failure probability of 2−1000 means, note that:

‱ The chance of winning the Massachusetts Mega Million lottery isone over (75)5 ⋅ 15 which is roughly 2−35. So 2−1000 corresponds towinning the lottery about 300 times in a row, at which point youmight not care so much about your algorithm failing.

‱ The chance for a U.S. resident to be struck by lightning is about1/700000, which corresponds to about 2−45 chance that you’ll bestruck by lightning the very second that you’re reading this sen-tence (after which again you might not care so much about thealgorithm’s performance).

‱ Since the earth is about 5 billion years old, we can estimate thechance that an asteroid of the magnitude that caused the dinosaurs’extinction will hit us this very second to be about 2−60. It is quitelikely that even a deterministic algorithm will fail if this happens.

So, in practical terms, a probabilistic algorithm is just as good asa deterministic one. But it is still a theoretically fascinating ques-tion whether randomized algorithms actually yield more power, orwhether is it the case that for any computational problem that can besolved by probabilistic algorithm, there is a deterministic algorithmwith nearly the same performance.2 For example, we will see in Ex-ercise 19.2 that there is in fact a deterministic algorithm that can cutat least 𝑚/2 edges in an 𝑚-edge graph. We will discuss this questionin generality in Chapter 20. For now, let us see a couple of exampleswhere randomization leads to algorithms that are better in some sensethan the known deterministic algorithms.

19.1.5 Solving SAT through randomizationThe 3SAT problem is NP hard, and so it is unlikely that it has a poly-nomial (or even subexponential) time algorithm. But this does notmean that we can’t do at least somewhat better than the trivial 2𝑛 al-gorithm for 𝑛-variable 3SAT. The best known worst-case algorithms

Page 547: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probabilist ic computation 547

3 At the time of this writing, the best known ran-domized algorithms for 3SAT run in time roughly𝑂(1.308𝑛), and the best known deterministic algo-rithms run in time 𝑂(1.3303𝑛) in the worst case.

for 3SAT are randomized, and are related to the following simplealgorithm, variants of which are also used in practice:

Algorithm WalkSAT:Input: An 𝑛 variable 3CNF formula 𝜑.Parameters: 𝑇 , 𝑆 ∈ ℕOperation:

1. Repeat the following 𝑇 steps:a. Choose a random assignment đ‘„ ∈ 0, 1𝑛 and repeat the following

for 𝑆 steps:1. If đ‘„ satisfies 𝜑 then output đ‘„.2. Otherwise, choose a random clause (ℓ𝑖 √ ℓ𝑗 √ ℓ𝑘) that đ‘„ does

not satisfy, choose a random literal in ℓ𝑖, ℓ𝑗, ℓ𝑘 and modify đ‘„ tosatisfy this literal.

2. If all the 𝑇 ⋅ 𝑆 repetitions above did not result in a satisfying assign-ment then output Unsatisfiable

The running time of this algorithm is 𝑆 ⋅ 𝑇 ⋅ 𝑝𝑜𝑙𝑩(𝑛), and so thekey question is how small we can make 𝑆 and 𝑇 so that the proba-bility that WalkSAT outputs Unsatisfiable on a satisfiable formula𝜑 is small. It is known that we can do so with ST = ((4/3)𝑛) =(1.333 
𝑛) (see Exercise 19.4 for a weaker result), but we’ll showbelow a simpler analysis yielding ST = (√3𝑛) = (1.74𝑛), which isstill much better than the trivial 2𝑛 bound.3

Theorem 19.5 — WalkSAT simple analysis. If we set 𝑇 = 100 ⋅ √3𝑛 and𝑆 = 𝑛/2, then the probability we output Unsatisfiable for asatisfiable 𝜑 is at most 1/2.

Proof. Suppose that 𝜑 is a satisfiable formula and let đ‘„âˆ— be a satisfyingassignment for it. For every đ‘„ ∈ 0, 1𝑛, denote by Δ(đ‘„, đ‘„âˆ—) the num-ber of coordinates that differ between đ‘„ and đ‘„âˆ—. The heart of the proofis the following claim:

Claim I: For every đ‘„, đ‘„âˆ— as above, in every local improvement step,the value Δ(đ‘„, đ‘„âˆ—) is decreased by one with probability at least 1/3.

Proof of Claim I: Since đ‘„âˆ— is a satisfying assignment, if đ¶ is a clausethat đ‘„ does not satisfy, then at least one of the variables involve in đ¶must get different values in đ‘„ and đ‘„âˆ—. Thus when we change đ‘„ by oneof the three literals in the clause, we have probability at least 1/3 ofdecreasing the distance.

The second claim is that our starting point is not that bad:Claim 2: With probability at least 1/2 over a random đ‘„ ∈ 0, 1𝑛,Δ(đ‘„, đ‘„âˆ—) ≀ 𝑛/2.Proof of Claim II: Consider the map FLIP ∶ 0, 1𝑛 → 0, 1𝑛 that

simply “flips” all the bits of its input from 0 to 1 and vice versa. That

Page 548: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

548 introduction to theoretical computer science

Figure 19.2: For every đ‘„âˆ— ∈ 0, 1𝑛, we can sort allstrings in 0, 1𝑛 according to their distance fromđ‘„âˆ— (top to bottom in the above figure), where we let𝐮 = đ‘„ ∈ 0, 1𝑛 | 𝑑𝑖𝑠𝑡(đ‘„, đ‘„âˆ— ≀ 𝑛/2 be the “tophalf” of strings. If we define FLIP ∶ 0, 1𝑛 → 0, 1to be the map that “flips” the bits of a given string đ‘„then it maps every đ‘„ ∈ 𝐮 to an output FLIP(đ‘„) ∈ 𝐮in a one-to-one way, and so it demonstrates that|𝐮| ≀ |𝐮| which implies that Pr[𝐮] ≄ Pr[𝐮] and hencePr[𝐮] ≄ 1/2.

Figure 19.3: The bipartite matching problem in thegraph đș = (𝐿âˆȘ𝑅, 𝐾) can be reduced to the minimum𝑠, 𝑡 cut problem in the graph đșâ€Č obtained by addingvertices 𝑠, 𝑡 to đș, connecting 𝑠 with 𝐿 and connecting𝑡 with 𝑅.

is, FLIP(đ‘„0, 
 , đ‘„đ‘›âˆ’1) = (1âˆ’đ‘„0, 
 , 1âˆ’đ‘„đ‘›âˆ’1). Clearly FLIP is one to one.Moreover, if đ‘„ is of distance 𝑘 to đ‘„âˆ—, then FLIP(đ‘„) is distance 𝑛 − 𝑘 tođ‘„âˆ—. Now let đ” be the “bad event” in which đ‘„ is of distance > 𝑛/2 fromđ‘„âˆ—. Then the set 𝐮 = FLIP(đ”) = FLIP(đ‘„) ∶ đ‘„ ∈ 0, 1𝑛 satisfies|𝐮| = |đ”| and that if đ‘„ ∈ 𝐮 then đ‘„ is of distance < 𝑛/2 from đ‘„âˆ—. Since𝐮 and đ” are disjoint events, Pr[𝐮] + Pr[đ”] ≀ 1. Since they have thesame cardinality, they have the same probability and so we get that2Pr[đ”] ≀ 1 or Pr[đ”] ≀ 1/2. (See also Fig. 19.2).

Claims I and II imply that each of the 𝑇 iterations of the outer loopsucceeds with probability at least 1/2 ⋅ √3−𝑛. Indeed, by Claim II,the original guess đ‘„ will satisfy Δ(đ‘„, đ‘„âˆ—) ≀ 𝑛/2 with probabilityPr[Δ(đ‘„, đ‘„âˆ—) ≀ 𝑛/2] ≄ 1/2. By Claim I, even conditioned on all thehistory so far, for each of the 𝑆 = 𝑛/2 steps of the inner loop we haveprobability at least ≄ 1/3 of being “lucky” and decreasing the distance(i.e. the output of Δ) by one. The chance we will be lucky in all 𝑛/2steps is hence at least (1/3)𝑛/2 = √3−𝑛.

Since any single iteration of the outer loop succeeds with probabil-ity at least 12 ⋅ √3−𝑛, the probability that we never do so in 𝑇 = 100√3𝑛repetitions is at most (1 − 12√3𝑛 )100⋅√3𝑛 ≀ (1/𝑒)50.

19.1.6 Bipartite matchingThe matching problem is one of the canonical optimization problems,arising in all kinds of applications: matching residents with hospitals,kidney donors with patients, flights with crews, and many others.One prototypical variant is bipartite perfect matching. In this problem,we are given a bipartite graph đș = (𝐿 âˆȘ 𝑅, 𝐾) which has 2𝑛 verticespartitioned into 𝑛-sized sets 𝐿 and 𝑅, where all edges have one end-point in 𝐿 and the other in 𝑅. The goal is to determine whether thereis a perfect matching, a subset 𝑀 ⊆ 𝐾 of 𝑛 disjoint edges. That is, 𝑀matches every vertex in 𝐿 to a unique vertex in 𝑅.

The bipartite matching problem turns out to have a polynomial-time algorithm, since we can reduce finding a matching in đș to find-ing a maximum flow (or equivalently, minimum cut) in a relatedgraph đșâ€Č (see Fig. 19.3). However, we will see a different probabilisticalgorithm to determine whether a graph contains such a matching.

Let us label đș’s vertices as 𝐿 = ℓ0, 
 , ℓ𝑛−1 and 𝑅 = 𝑟0, 
 , 𝑟𝑛−1.A matching 𝑀 corresponds to a permutation 𝜋 ∈ 𝑆𝑛 (i.e., one-to-oneand onto function 𝜋 ∶ [𝑛] → [𝑛]) where for every 𝑖 ∈ [𝑛], we define 𝜋(𝑖)to be the unique 𝑗 such that 𝑀 contains the edge ℓ𝑖, 𝑟𝑗. Define an𝑛 × 𝑛 matrix 𝐮 = 𝐮(đș) where 𝐮𝑖,𝑗 = 1 if and only if the edge ℓ𝑖, 𝑟𝑗is present and 𝐮𝑖,𝑗 = 0 otherwise. The correspondence betweenmatchings and permutations implies the following claim:

Page 549: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probabilist ic computation 549

4 The sign of a permutation 𝜋 ∶ [𝑛] → [𝑛], denoted by𝑠𝑖𝑔𝑛(𝜋), can be defined in several equivalent ways,one of which is that 𝑠𝑖𝑔𝑛(𝜋) = (−1)đŒđ‘đ‘‰ (𝜋) whereINV(𝑝𝑖) = |(đ‘„, 𝑩) ∈ [𝑛] | đ‘„ < 𝑩 ∧ 𝜋(đ‘„) > 𝜋(𝑩) (i.e.,INV(𝜋) is the number of pairs of elements that areinverted by 𝜋). The importance of the term 𝑠𝑖𝑔𝑛(𝜋) isthat it makes 𝑃 equal to the determinant of the matrix(đ‘„đ‘–,𝑗) and hence efficiently computable.

Figure 19.4: A degree 𝑑 curve in one variable canhave at most 𝑑 roots. In higher dimensions, a 𝑛-variate degree-𝑑 polynomial can have an infinitenumber roots though the set of roots will be an 𝑛 − 1dimensional surface. Over a finite field đ”œ, an 𝑛-variatedegree 𝑑 polynomial has at most 𝑑|đ”œ|𝑛−1 roots.

Lemma 19.6 — Matching polynomial. Define 𝑃 = 𝑃(đș) to be the polynomialmapping ℝ𝑛2 to ℝ where𝑃(đ‘„0,0, 
 , đ‘„đ‘›âˆ’1,𝑛−1) = ∑𝜋∈𝑆𝑛 (𝑛−1∏𝑖=0 𝑠𝑖𝑔𝑛(𝜋)𝐮𝑖,𝜋(𝑖)) 𝑛−1∏𝑖=0 đ‘„đ‘–,𝜋(𝑖) (19.7)

Then đș has a perfect matching if and only if 𝑃 is not identically zero.That is, đș has a perfect matching if and only if there exists some as-signment đ‘„ = (đ‘„đ‘–,𝑗)𝑖,𝑗∈[𝑛] ∈ ℝ𝑛2 such that 𝑃(đ‘„) ≠ 0.4Proof. If đș has a perfect matching 𝑀∗, then let 𝜋∗ be the permutationcorresponding to 𝑀 and let đ‘„âˆ— ∈ â„€đ‘›2 defined as follows: đ‘„đ‘–,𝑗 = 1 if𝑗 = 𝜋(𝑖) and đ‘„đ‘–,𝑗 = 0. Note that for every 𝜋 ≠ 𝜋∗, ∏𝑛−1𝑖=0 đ‘„đ‘–,𝜋(𝑖) = 0 but∏𝑛−1𝑖=0 đ‘„âˆ—đ‘–,𝜋∗(𝑖) = 1. Hence 𝑃(đ‘„âˆ—) will equal ∏𝑛−1𝑖=0 𝐮𝑖,𝜋∗(𝑖). But since 𝑀∗ isa perfect matching in đș, ∏𝑛−1𝑖=0 𝐮𝑖,𝜋∗(𝑖) = 1.

On the other hand, suppose that 𝑃 is not identically zero. By (19.7),this means that at least one of the terms ∏𝑛−1𝑖=0 𝐮𝑖,𝜋(𝑖) is not equal tozero. But then this permutation 𝜋 must be a perfect matching in đș.

As we’ve seen before, for every đ‘„ ∈ ℝ𝑛2 , we can compute 𝑃(đ‘„)by simply computing the determinant of the matrix 𝐮(đ‘„), which isobtained by replacing 𝐮𝑖,𝑗 with 𝐮𝑖,đ‘—đ‘„đ‘–,𝑗. This reduces testing perfectmatching to the zero testing problem for polynomials: given some poly-nomial 𝑃(⋅), test whether 𝑃 is identically zero or not. The intuitionbehind our randomized algorithm for zero testing is the following:

If a polynomial is not identically zero, then it can’t have “too many” roots.

This intuition sort of makes sense. For one variable polynomi-als, we know that a nonzero linear function has at most one root, aquadratic function (e.g., a parabola) has at most two roots, and gener-ally a degree 𝑑 equation has at most 𝑑 roots. While in more than onevariable there can be an infinite number of roots (e.g., the polynomialđ‘„0 + 𝑩0 vanishes on the line 𝑩 = âˆ’đ‘„) it is still the case that the set ofroots is very “small” compared to the set of all inputs. For example,the root of a bivariate polynomial form a curve, the roots of a three-variable polynomial form a surface, and more generally the roots of an𝑛-variable polynomial are a space of dimension 𝑛 − 1.

This intuition leads to the following simple randomized algorithm:

To decide if 𝑃 is identically zero, choose a “random” input đ‘„ and check if𝑃(đ‘„) ≠ 0.This makes sense: if there are only “few” roots, then we expect that

with high probability the random input đ‘„ is not going to be one ofthose roots. However, to transform this into an actual algorithm, we

Page 550: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

550 introduction to theoretical computer science

need to make both the intuition and the notion of a “random” inputprecise. Choosing a random real number is quite problematic, espe-cially when you have only a finite number of coins at your disposal,and so we start by reducing the task to a finite setting. We will use thefollowing result:

Theorem 19.7 — Schwartz–Zippel lemma. For every integer 𝑞, and poly-nomial 𝑃 ∶ ℝ𝑛 → ℝ with integer coefficients. If 𝑃 has degree atmost 𝑑 and is not identically zero, then it has at most 𝑑𝑞𝑛−1 roots inthe set [𝑞]𝑛 = (đ‘„0, 
 , đ‘„đ‘›âˆ’1) ∶ đ‘„đ‘– ∈ 0, 
 , 𝑞 − 1.We omit the (not too complicated) proof of Theorem 19.7. We

remark that it holds not just over the real numbers but over any fieldas well. Since the matching polynomial 𝑃 of Lemma 19.6 has degree atmost 𝑛, Theorem 19.7 leads directly to a simple algorithm for testing ifit is nonzero:

Algorithm Perfect-Matching:Input: Bipartite graph đș on 2𝑛 vertices ℓ0, 
 , ℓ𝑛−1, 𝑟0, 
 , 𝑟𝑛−1.Operation:

1. For every 𝑖, 𝑗 ∈ [𝑛], choose đ‘„đ‘–,𝑗 independently at random from[2𝑛] = 0, 
 2𝑛 − 1.2. Compute the determinant of the matrix 𝐮(đ‘„) whose (𝑖, 𝑗)𝑡ℎ entry

equals đ‘„đ‘–,𝑗 if the edge ℓ𝑖, 𝑟𝑗 is present and 0 otherwise.3. Output no perfect matching if this determinant is zero, and out-

put perfect matching otherwise.

This algorithm can be improved further (e.g., see Exercise 19.5).While it is not necessarily faster than the cut-based algorithms for per-fect matching, it does have some advantages. In particular, it is moreamenable for parallelization. (However, it also has the significant dis-advantage that it does not produce a matching but only states that oneexists.) The Schwartz–Zippel Lemma, and the associated zero testingalgorithm for polynomials, is widely used across computer science,including in several settings where we have no known deterministicalgorithm matching their performance.

Chapter Recap

‱ Using concentration results, we can amplify inpolynomial time the success probability of a prob-abilistic algorithm from a mere 1/𝑝(𝑛) to 1 − 2−𝑞(𝑛)for every polynomials 𝑝 and 𝑞.

‱ There are several randomized algorithms that arebetter in various senses (e.g., simpler, faster, orother advantages) than the best known determinis-tic algorithm for the same problem.

Page 551: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

probabilist ic computation 551

5 TODO: add exercise to give a deterministic max cutalgorithm that gives 𝑚/2 edges. Talk about greedyapproach.

6 Hint: Think of đ‘„ ∈ 0, 1𝑛 as choosing 𝑘 numbers𝑩1, 
 , 𝑩𝑘 ∈ 0, 
 , 2⌈log𝑀⌉ − 1. Output the first suchnumber that is in 0, 
 , 𝑀 − 1.

19.2 EXERCISES

Exercise 19.1 — Amplification for max cut. Prove Lemma 19.3

Exercise 19.2 — Deterministic max cut algorithm. 5

Exercise 19.3 — Simulating distributions using coins. Our model for proba-bility involves tossing 𝑛 coins, but sometimes algorithm require sam-pling from other distributions, such as selecting a uniform number in0, 
 , 𝑀 − 1 for some 𝑀 . Fortunately, we can simulate this with anexponentially small probability of error: prove that for every 𝑀 , if 𝑛 >𝑘⌈log𝑀⌉, then there is a function đč ∶ 0, 1𝑛 → 0, 
 , 𝑀 − 1 âˆȘ ⊄such that (1) The probability that đč(đ‘„) = ⊄ is at most 2−𝑘 and (2) thedistribution of đč(đ‘„) conditioned on đč(đ‘„) ≠ ⊄ is equal to the uniformdistribution over 0, 
 , 𝑀 − 1.6

Exercise 19.4 — Better walksat analysis. 1. Prove that for every 𝜖 > 0, if𝑛 is large enough then for every đ‘„âˆ— ∈ 0, 1𝑛 Prđ‘„âˆŒ0,1𝑛 [Δ(đ‘„, đ‘„âˆ—) â‰€đ‘›/3] ≀ 2−(1âˆ’đ»(1/3)−𝜖)𝑛 where đ»(𝑝) = 𝑝 log(1/𝑝)+(1−𝑝) log(1/(1−𝑝))is the same function as in Exercise 18.10.

2. Prove that 21âˆ’đ»(1/4)+(1/4) log3 = (3/2).3. Use the above to prove that for every 𝛿 > 0 and large enough 𝑛, if

we set 𝑇 = 1000 ⋅ (3/2 + 𝛿)𝑛 and 𝑆 = 𝑛/4 in the WalkSAT algorithmthen for every satisfiable 3CNF 𝜑, the probability that we outputunsatisfiable is at most 1/2.

Exercise 19.5 — Faster bipartite matching (challenge). (to be completed: im-prove the matching algorithm by working modulo a prime)

19.3 BIBLIOGRAPHICAL NOTES

The books of Motwani and Raghavan [MR95] and Mitzenmacher andUpfal [MU17] are two excellent resources for randomized algorithms.Some of the history of the discovery of Monte Carlo algorithm is cov-ered here.

19.4 ACKNOWLEDGEMENTS

Page 552: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 553: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Figure 20.1: A mechanical coin tosser built for PercyDiaconis by Harvard technicians Steve Sansone andRick Haggerty

20Modeling randomized computation

“Any one who considers arithmetical methods of producing random digits is, ofcourse, in a state of sin.” John von Neumann, 1951.

So far we have described randomized algorithms in an informalway, assuming that an operation such as “pick a string đ‘„ ∈ 0, 1𝑛”can be done efficiently. We have neglected to address two questions:

1. How do we actually efficiently obtain random strings in the physi-cal world?

2. What is the mathematical model for randomized computations,and is it more powerful than deterministic computation?

The first question is of both practical and theoretical importance,but for now let’s just say that there are various physical sources of“random” or “unpredictable” data. A user’s mouse movements andtyping pattern, (non solid state) hard drive and network latency,thermal noise, and radioactive decay have all been used as sources forrandomness (see discussion in Section 20.8). For example, many Intelchips come with a random number generator built in. One can evenbuild mechanical coin tossing machines (see Fig. 20.1).

In this chapter we focus on the second question: formally modelingprobabilistic computation and studying its power. We will show that:

1. We can define the class BPP that captures all Boolean functions thatcan be computed in polynomial time by a randomized algorithm.Crucially BPP is still very much a worst case class of computation:the probability is only over the choice of the random coins of thealgorithm, as opposed to the choice of the input.

2. We can amplify the success probability of randomized algorithms,and as a result the class BPP would be identical if we changedthe required success probability to any number 𝑝 that lies strictlybetween 1/2 and 1 (and in fact any number in the range 1/2+1/𝑞(𝑛)to 1 − 2−𝑞(𝑛) for any polynomial 𝑞(𝑛)).

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Formal definition of probabilistic polynomial

time: the class BPP.‱ Proof that every function in BPP can be

computed by 𝑝𝑜𝑙𝑩(𝑛)-sized NAND-CIRCprograms/circuits.

‱ Relations between BPP and NP.‱ Pseudorandom generators

Page 554: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

554 introduction to theoretical computer science

3. Though, as is the case for P and NP, there is much we do not knowabout the class BPP, we can establish some relations between BPPand the other complexity classes we saw before. In particular wewill show that P ⊆ BPP ⊆ EXP and BPP ⊆ P/poly.

4. While the relation between BPP and NP is not known, we can showthat if P = NP then BPP = P.

5. We also show that the concept of NP completeness applies equallywell if we use randomized algorithms as our model of “efficientcomputation”. That is, if a single NP complete problem has a ran-domized polynomial-time algorithm, then all of NP can be com-puted in polynomial-time by randomized algorithms.

6. Finally we will discuss the question of whether BPP = P and showsome of the intriguing evidence that the answer might actually be“Yes” using the concept of pseudorandom generators.

20.1 MODELING RANDOMIZED COMPUTATION

Modeling randomized computation is actually quite easy. We canadd the following operations to any programming language such asNAND-TM, NAND-RAM, NAND-CIRC etc..:foo = RAND()

where foo is a variable. The result of applying this operation is thatfoo is assigned a random bit in 0, 1. (Every time the RAND operationis invoked it returns a fresh independent random bit.) We call theprogramming languages that are augmented with this extra operationRNAND-TM, RNAND-RAM, and RNAND-CIRC respectively.

Similarly, we can easily define randomized Turing machines asTuring machines in which the transition function 𝛿 gets as an extrainput (in addition to the current state and symbol read from the tape)a bit 𝑏 that in each step is chosen at random ∈0, 1. Of course thefunction can ignore this bit (and have the same output regardless ofwhether 𝑏 = 0 or 𝑏 = 1) and hence randomized Turing machinesgeneralize deterministic Turing machines.

We can use the RAND() operation to define the notion of a functionbeing computed by a randomized 𝑇 (𝑛) time algorithm for every nicetime bound 𝑇 ∶ ℕ → ℕ, as well as the notion of a finite function beingcomputed by a size 𝑆 randomized NAND-CIRC program (or, equiv-alently, a randomized circuit with 𝑆 gates that correspond to eitherthe NAND or coin-tossing operations). However, for simplicity wewill not define randomized computation in full generality, but simplyfocus on the class of functions that are computable by randomizedalgorithms running in polynomial time, which by historical conventionis known as BPP:

Page 555: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling randomized computation 555

Definition 20.1 — The class BPP. Let đč ∶ 0, 1∗ → 0, 1. We say thatđč ∈ BPP if there exist constants 𝑎, 𝑏 ∈ ℕ and an RNAND-TMprogram 𝑃 such that for every đ‘„ ∈ 0, 1∗, on input đ‘„, the program𝑃 halts within at most 𝑎|đ‘„|𝑏 steps and

Pr[𝑃 (đ‘„) = đč(đ‘„)] ≄ 23 (20.1)

where this probability is taken over the result of the RAND opera-tions of 𝑃 .

Note that the probability in (20.1) is taken only over the ran-dom choices in the execution of 𝑃 and not over the choice of the in-put đ‘„. In particular, as discussed in Big Idea 24, BPP is still a worstcase complexity class, in the sense that if đč is in BPP then there is apolynomial-time randomized algorithm that computes đč with proba-bility at least 2/3 on every possible (and not just random) input.

The same polynomial-overhead simulation of NAND-RAM pro-grams by NAND-TM programs we saw in Theorem 13.5 extends torandomized programs as well. Hence the class BPP is the same re-gardless of whether it is defined via RNAND-TM or RNAND-RAMprograms. Similarly, we could have just as well defined BPP usingrandomized Turing machines.

Because of these equivalences, below we will use the name “poly-nomial time randomized algorithm” to denote a computation that can bemodeled by a polynomial-time RNAND-TM program, RNAND-RAMprogram, or a randomized Turing machine (or any programming lan-guage that includes a coin tossing operation). Since all these modelsare equivalent up to polynomial factors, you can use your favoritemodel to capture polynomial-time randomized algorithms withoutany loss in generality.Solved Exercise 20.1 — Choosing from a set. Modern programming lan-guages often involve not just the ability to toss a random coin in 0, 1but also to choose an element at random from a set 𝑆. Show that youcan emulate this primitive using coin tossing. Specifically, show thatthere is randomized algorithm 𝐮 that on input a set 𝑆 of 𝑚 strings oflength 𝑛, runs in time 𝑝𝑜𝑙𝑩(𝑛, 𝑚) and outputs either an element đ‘„ ∈ 𝑆or “fail” such that

1. Let 𝑝 be the probability that 𝐮 outputs “fail”, then 𝑝 < 2−𝑛 (anumber small enough that it can be ignored).

2. For every đ‘„ ∈ 𝑆, the probability that 𝐮 outputs đ‘„ is exactly 1−𝑝𝑚(and so the output is uniform over 𝑆 if we ignore the tiny probabil-ity of failure)

Page 556: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

556 introduction to theoretical computer science

Figure 20.2: The two equivalent views of random-ized algorithms. We can think of such an algorithmas having access to an internal RAND() operationthat outputs a random independent value in 0, 1whenever it is invoked, or we can think of it as a de-terministic algorithm that in addition to the standardinput đ‘„ ∈ 0, 1𝑛 obtains an additional auxiliaryinput 𝑟 ∈ 0, 1𝑚 that is chosen uniformly at random.

Solution:

If the size of 𝑆 is a power of two, that is 𝑚 = 2ℓ for some ℓ ∈ 𝑁 ,then we can choose a random element in 𝑆 by tossing ℓ coins toobtain a string đ‘€ ∈ 0, 1ℓ and then output the 𝑖-th element of 𝑆where 𝑖 is the number whose binary representation is đ‘€.

If 𝑆 is not a power of two, then our first attempt will be to letℓ = ⌈log𝑚⌉ and do the same, but then output the 𝑖-th element of𝑆 if 𝑖 ∈ [𝑚] and output “fail” otherwise. Conditioned on not out-putting “fail”, this element is distributed uniformly in 𝑆. However,in the worst case, 2ℓ can be almost 2𝑚 and so the probability of failmight be close to half. To reduce the failure probability, we canrepeat the experiment above 𝑛 times. Specifically, we will use thefollowing algorithm

Algorithm 20.2 — Sample from set.

Input: Set 𝑆 = đ‘„0, 
 , đ‘„đ‘šâˆ’1 with đ‘„đ‘– ∈ 0, 1𝑛 for all𝑖 ∈ [𝑚].Output: Either đ‘„ ∈ 𝑆 or ”fail”1: Let ℓ ← ⌈log𝑚⌉2: for 𝑗 = 0, 1, 
 , 𝑛 − 1 do3: Pick đ‘€ ∌ 0, 1ℓ4: Let 𝑖 ∈ [2ℓ] be number whose binary representa-

tion is đ‘€.5: if 𝑖 < 𝑚 then6: return đ‘„đ‘–7: end if8: end for9: return ”fail”

Conditioned on not failing, the output of Algorithm 20.2 is uni-formly distributed in 𝑆. However, since 2ℓ < 2𝑚, the probabilityof failure in each iteration is less than 1/2 and so the probability offailure in all of them is at most (1/2)𝑛 = 2−𝑛.

20.1.1 An alternative view: random coins as an “extra input”While we presented randomized computation as adding an extra“coin tossing” operation to our programs, we can also model this asbeing given an additional extra input. That is, we can think of a ran-domized algorithm 𝐮 as a deterministic algorithm 𝐮â€Č that takes twoinputs đ‘„ and 𝑟 where the second input 𝑟 is chosen at random from0, 1𝑚 for some 𝑚 ∈ ℕ (see Fig. 20.2). The equivalence to the Defini-tion 20.1 is shown in the following theorem:

Page 557: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling randomized computation 557

Theorem 20.3 — Alternative characterization of BPP. Let đč ∶ 0, 1∗ →0, 1. Then đč ∈ BPP if and only if there exists 𝑎, 𝑏 ∈ ℕ andđș ∶ 0, 1∗ → 0, 1 such that đș is in P and for every đ‘„ ∈ 0, 1∗,Prđ‘ŸâˆŒ0,1𝑎|đ‘„|𝑏 [đș(đ‘„đ‘Ÿ) = đč(đ‘„)] ≄ 23 . (20.2)

Proof Idea:

The idea behind the proof is that, as illustrated in Fig. 20.2, we cansimply replace sampling a random coin with reading a bit from theextra “random input” 𝑟 and vice versa. To prove this rigorously weneed to work through some slightly cumbersome formal notation.This might be one of those proofs that is easier to work out on yourown than to read.⋆Proof of Theorem 20.3. We start by showing the “only if” direction.Let đč ∈ BPP and let 𝑃 be an RNAND-TM program that computesđč as per Definition 20.1, and let 𝑎, 𝑏 ∈ ℕ be such that on every inputof length 𝑛, the program 𝑃 halts within at most 𝑎𝑛𝑏 steps. We willconstruct a polynomial-time algorithm that 𝑃 â€Č such that for everyđ‘„ ∈ 0, 1𝑛, if we set 𝑚 = 𝑎𝑛𝑏, then

Prđ‘ŸâˆŒ0,1𝑚[𝑃 â€Č(đ‘„đ‘Ÿ) = 1] = Pr[𝑃 (đ‘„) = 1] , (20.3)

where the probability in the righthand side is taken over the RAND()operations in 𝑃 . In particular this means that if we define đș(đ‘„đ‘Ÿ) =𝑃 â€Č(đ‘„đ‘Ÿ) then the function đș satisfies the conditions of (20.2).

The algorithm 𝑃 â€Č will be very simple: it simulates the program 𝑃 ,maintaining a counter 𝑖 initialized to 0. Every time that 𝑃 makes aRAND() operation, the program 𝑃 â€Č will supply the result from 𝑟𝑖 andincrement 𝑖 by one. We will never “run out” of bits, since the runningtime of 𝑃 is at most 𝑎𝑛𝑏 and hence it can make at most this number ofRNAND() calls. The output of 𝑃 â€Č(đ‘„đ‘Ÿ) for a random 𝑟 ∌ 0, 1𝑚 will bedistributed identically to the output of 𝑃(đ‘„).

For the other direction, given a function đș ∈ P satisfying the condi-tion (20.2) and a NAND-TM 𝑃 â€Č that computes đș in polynomial time,we can construct an RNAND-TM program 𝑃 that computes đč in poly-nomial time. On input đ‘„ ∈ 0, 1𝑛, the program 𝑃 will simply use theRNAND() instruction 𝑎𝑛𝑏 times to fill an array R[0] , 
, R[𝑎𝑛𝑏 − 1] andthen execute the original program 𝑃 â€Č on input đ‘„đ‘Ÿ where 𝑟𝑖 is the 𝑖-thelement of the array R. Once again, it is clear that if 𝑃 â€Č runs in polyno-mial time then so will 𝑃 , and for every input đ‘„ and 𝑟 ∈ 0, 1𝑎𝑛𝑏 , theoutput of 𝑃 on input đ‘„ and where the coin tosses outcome is 𝑟 is equalto 𝑃 â€Č(đ‘„đ‘Ÿ).

Page 558: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

558 introduction to theoretical computer science

RRemark 20.4 — Definitions of BPP and NP. The char-acterization of BPP Theorem 20.3 is reminiscent ofthe characterization of NP in Definition 15.1, withthe randomness in the case of BPP playing the roleof the solution in the case of NP. However, there areimportant differences between the two:

‱ The definition of NP is “one sided”: đč(đ‘„) = 1 ifthere exists a solution đ‘€ such that đș(đ‘„đ‘€) = 1 andđč(đ‘„) = 0 if for every string đ‘€ of the appropriatelength, đș(đ‘„đ‘€) = 0. In contrast, the characteriza-tion of BPP is symmetric with respect to the casesđč(đ‘„) = 0 and đč(đ‘„) = 1.

‱ The relation between NP and BPP is not immedi-ately clear. It is not known whether BPP ⊆ NP,NP ⊆ BPP, or these two classes are incomparable.It is however known (with a non-trivial proof) thatif P = NP then BPP = P (see Theorem 20.11).

‱ Most importantly, the definition of NP is “inef-fective,” since it does not yield a way of actuallyfinding whether there exists a solution among theexponentially many possibilities. By contrast, thedefinition of BPP gives us a way to compute thefunction in practice by simply choosing the secondinput at random.

”Random tapes”. Theorem 20.3 motivates sometimes considering therandomness of an RNAND-TM (or RNAND-RAM) program as anextra input. As such, if 𝐮 is a randomized algorithm that on inputs oflength 𝑛 makes at most 𝑚 coin tosses, we will often use the notation𝐮(đ‘„; 𝑟) (where đ‘„ ∈ 0, 1𝑛 and 𝑟 ∈ 0, 1𝑚) to refer to the result ofexecuting đ‘„ when the coin tosses of 𝐮 correspond to the coordinatesof 𝑟. This second, or “auxiliary,” input is sometimes referred to asa “random tape.” This terminology originates from the model ofrandomized Turing machines.

20.1.2 Success amplification of two-sided error algorithmsThe number 2/3 might seem arbitrary, but as we’ve seen in Chapter 19it can be amplified to our liking:

Theorem 20.5 — Amplification. Let đč ∶ 0, 1∗ → 0, 1 be a Booleanfunction such that there is a polynomial 𝑝 ∶ ℕ → ℕ and apolynomial-time randomized algorithm 𝐮 satisfying that for ev-

Page 559: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling randomized computation 559

Figure 20.3: If đč ∈ BPP then there is randomizedpolynomial-time algorithm 𝑃 with the followingproperty: In the case đč(đ‘„) = 0 two thirds of the“population” of random choices satisfy 𝑃(đ‘„; 𝑟) = 0and in the case đč(đ‘„) = 1 two thirds of the populationsatisfy 𝑃(đ‘„; 𝑟) = 1. We can think of amplification asa form of “polling” of the choices of randomness. Bythe Chernoff bound, if we poll a sample of 𝑂( log(1/𝛿)𝜖2 )random choices 𝑟, then with probability at least1 − 𝛿, the fraction of 𝑟’s in the sample satisfying𝑃(đ‘„; 𝑟) = 1 will give us an estimate of the fraction ofthe population within an 𝜖 margin of error. This is thesame calculation used by pollsters to determine theneeded sample size in their polls.

ery đ‘„ ∈ 0, 1𝑛,Pr[𝐮(đ‘„) = đč(đ‘„)] ≄ 12 + 1𝑝(𝑛) . (20.4)

Then for every polynomial 𝑞 ∶ ℕ → ℕ there is a polynomial-timerandomized algorithm đ” satisfying for every đ‘„ ∈ 0, 1𝑛,

Pr[đ”(đ‘„) = đč(đ‘„)] ≄ 1 − 2−𝑞(𝑛) . (20.5)

Big Idea 25 We can amplify the success of randomized algorithmsto a value that is arbitrarily close to 1.

Proof Idea:

The proof is the same as we’ve seen before in the case of maximumcut and other examples. We use the Chernoff bound to argue that if𝐮 computes đč with probability at least 12 + 𝜖 and we run it 𝑂(𝑘/𝜖2)times, each time using fresh and independent random coins, then theprobability that the majority of the answers will not be correct will beless than 2−𝑘. Amplification can be thought of as a “polling” of thechoices for randomness for the algorithm (see Fig. 20.3).⋆Proof of Theorem 20.5. Let 𝐮 be an algorithm satisfying (20.4). Set𝜖 = 1𝑝(𝑛) and 𝑘 = 𝑞(𝑛) where 𝑝, 𝑞 are the polynomials in the theoremstatement. We can run 𝑃 on input đ‘„ for 𝑡 = 10𝑘/𝜖2 times, using freshrandomness in each execution, and compute the outputs 𝑩0, 
 , 𝑩𝑡−1.We output the value 𝑩 that appeared the largest number of times. Let𝑋𝑖 be the random variable that is equal to 1 if 𝑩𝑖 = đč(đ‘„) and equal to0 otherwise. The random variables 𝑋0, 
 , 𝑋𝑡−1 are i.i.d. and satisfyđ”Œ[𝑋𝑖] = Pr[𝑋𝑖 = 1] ≄ 1/2 + 𝜖, and hence by linearity of expectationđ”Œ[∑𝑡−1𝑖=0 𝑋𝑖] ≄ 𝑡(1/2 + 𝜖). For the plurality value to be incorrect, it musthold that ∑𝑡−1𝑖=0 𝑋𝑖 ≀ 𝑡/2, which means that ∑𝑡−1𝑖=0 𝑋𝑖 is at least 𝜖𝑡 farfrom its expectation. Hence by the Chernoff bound (Theorem 18.12),the probability that the plurality value is not correct is at most 2𝑒−𝜖2𝑡,which is smaller than 2−𝑘 for our choice of 𝑡.

20.2 BPP AND NP COMPLETENESS

Since “noisy processes” abound in nature, randomized algorithms canbe realized physically, and so it is reasonable to propose BPP ratherthan P as our mathematical model for “feasible” or “tractable” com-putation. One might wonder if this makes all the previous chapters

Page 560: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

560 introduction to theoretical computer science

irrelevant, and in particular if the theory of NP completeness stillapplies to probabilistic algorithms. Fortunately, the answer is Yes:

Theorem 20.6 — NP hardness and BPP. Suppose that đč is NP-hard andđč ∈ BPP. Then NP ⊆ BPP.

Before seeing the proof, note that Theorem 20.6 implies that if therewas a randomized polynomial time algorithm for any NP-completeproblem such as 3SAT, ISET etc., then there would be such an algo-rithm for every problem in NP. Thus, regardless of whether our modelof computation is deterministic or randomized algorithms, NP com-plete problems retain their status as the “hardest problems in NP.”

Proof Idea:

The idea is to simply run the reduction as usual, and plug it intothe randomized algorithm instead of a deterministic one. It wouldbe an excellent exercise, and a way to reinforce the definitions of NP-hardness and randomized algorithms, for you to work out the prooffor yourself. However for the sake of completeness, we include thisproof below.⋆Proof of Theorem 20.6. Suppose that đč is NP-hard and đč ∈ BPP.We will now show that this implies that NP ⊆ BPP. Let đș ∈ NP.By the definition of NP-hardness, it follows that đș â‰€đ‘ đč , or that inother words there exists a polynomial-time computable function 𝑅 ∶0, 1∗ → 0, 1∗ such that đș(đ‘„) = đč(𝑅(đ‘„)) for every đ‘„ ∈ 0, 1∗. Nowif đč is in BPP then there is a polynomial-time RNAND-TM program 𝑃such that

Pr[𝑃 (𝑩) = đč(𝑩)] ≄ 2/3 (20.6)

for every 𝑩 ∈ 0, 1∗ (where the probability is taken over the randomcoin tosses of 𝑃 ). Hence we can get a polynomial-time RNAND-TMprogram 𝑃 â€Č to compute đș by setting 𝑃 â€Č(đ‘„) = 𝑃(𝑅(đ‘„)). By (20.6)Pr[𝑃 â€Č(đ‘„) = đč(𝑅(đ‘„))] ≄ 2/3 and since đč(𝑅(đ‘„)) = đș(đ‘„) this implies thatPr[𝑃 â€Č(đ‘„) = đș(đ‘„)] ≄ 2/3, which proves that đș ∈ BPP.

Most of the results we’ve seen about NP hardness, including thesearch to decision reduction of Theorem 16.1, the decision to optimiza-tion reduction of Theorem 16.3, and the quantifier elimination resultof Theorem 16.6, all carry over in the same way if we replace P withBPP as our model of efficient computation. Thus if NP ⊆ BPP thenwe get essentially all of the strange and wonderful consequences ofP = NP. Unsurprisingly, we cannot rule out this possibility. In fact,unlike P = EXP, which is ruled out by the time hierarchy theorem, we

Page 561: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling randomized computation 561

1 At the time of this writing, the largest “natural” com-plexity class which we can’t rule out being containedin BPP is the class NEXP, which we did not definein this course, but corresponds to non deterministicexponential time. See this paper for a discussion ofthis question.

Figure 20.4: Some possibilities for the relations be-tween BPP and other complexity classes. Mostresearchers believe that BPP = P and that theseclasses are not powerful enough to solve NP-completeproblems, let alone all problems in EXP. However,we have not even been able yet to rule out the possi-bility that randomness is a “silver bullet” that allowsexponential speedup on all problems, and henceBPP = EXP. As we’ve already seen, we also can’trule out that P = NP. Interestingly, in the latter case,P = BPP.

don’t even know how to rule out the possibility that BPP = EXP! Thusa priori it’s possible (though seems highly unlikely) that randomnessis a magical tool that allows us to speed up arbitrary exponential timecomputation.1 Nevertheless, as we discuss below, it is believed thatrandomization’s power is much weaker and BPP lies in much more“pedestrian” territory.

20.3 THE POWER OF RANDOMIZATION

A major question is whether randomization can add power to compu-tation. Mathematically, we can phrase this as the following question:does BPP = P? Given what we’ve seen so far about the relations ofother complexity classes such as P and NP, or NP and EXP, one mightguess that:

1. We do not know the answer to this question.

2. But we suspect that BPP is different than P.

One would be correct about the former, but wrong about the latter.As we will see, we do in fact have reasons to believe that BPP = P.This can be thought of as supporting the extended Church Turing hy-pothesis that deterministic polynomial-time Turing machines capturewhat can be feasibly computed in the physical world.

We now survey some of the relations that are known betweenBPP and other complexity classes we have encountered. (See alsoFig. 20.4.)

20.3.1 Solving BPP in exponential timeIt is not hard to see that if đč is in BPP then it can be computed inexponential time.

Theorem 20.7 — Simulating randomized algorithms in exponential time.

BPP ⊆ EXP

PThe proof of Theorem 20.7 readily follows by enumer-ating over all the (exponentially many) choices for therandom coins. We omit the formal proof, as doing itby yourself is an excellent way to get comfortable withDefinition 20.1.

20.3.2 Simulating randomized algorithms by circuitsWe have seen in Theorem 13.12 that if đč is in P, then there is a polyno-mial 𝑝 ∶ ℕ → ℕ such that for every 𝑛, the restriction đč𝑛 of đč to inputs

Page 562: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

562 introduction to theoretical computer science

0, 1𝑛 is in SIZE(𝑝(𝑛)). (In other words, that P ⊆ P/poly.) A priori it isnot at all clear that the same holds for a function in BPP, but this doesturn out to be the case.

Figure 20.5: The possible guarantees for a random-ized algorithm 𝐮 computing some function đč . Inthe tables above, the columns correspond to differ-ent inputs and the rows to different choices of therandom tape. A cell at position 𝑟, đ‘„ is colored greenif 𝐮(đ‘„; 𝑟) = đč(đ‘„) (i.e., the algorithm outputs thecorrect answer) and red otherwise. The standard BPPguarantee corresponds to the middle figure, wherefor every input đ‘„, at least two thirds of the choices𝑟 for a random tape will result in 𝐮 computing thecorrect value. That is, every column is colored greenin at least two thirds of its coordinates. In the leftfigure we have an “average case” guarantee wherethe algorithm is only guaranteed to output the correctanswer with probability two thirds over a randominput (i.e., at most one third of the total entries of thetable are colored red, but there could be an all redcolumn). The right figure corresponds to the “offlineBPP” case, with probability at least two thirds overthe random choice 𝑟, 𝑟 will be good for every input.That is, at least two thirds of the rows are all green.Theorem 20.8 (BPP ⊆ P/poly) is proven by amplify-ing the success of a BPP algorithm until we have the“offline BPP” guarantee, and then hardwiring thechoice of the randomness 𝑟 to obtain a nonuniformdeterministic algorithm.

Theorem 20.8 — Randomness does not help for non uniform computation.

BPP ⊆ P/poly.That is, for every đč ∈ BPP, there exist some 𝑎, 𝑏 ∈ ℕ such that

for every 𝑛 > 0, đč𝑛 ∈ SIZE(𝑎𝑛𝑏) where đč𝑛 is the restriction of đč toinputs in 0, 1𝑛.Proof Idea:

The idea behind the proof is that we can first amplify by repetitionthe probability of success from 2/3 to 1 − 0.1 ⋅ 2−𝑛. This will allow us toshow that for every 𝑛 ∈ ℕ there exists a single fixed choice of “favorablecoins” which is a string 𝑟 of length polynomial in 𝑛 such that if 𝑟 isused for the randomness then we output the right answer on all ofthe possible 2𝑛 inputs. We can then use the standard “unravelling theloop” technique to transform an RNAND-TM program to an RNAND-CIRC program, and “hardwire” the favorable choice of random coinsto transform the RNAND-CIRC program into a plain old deterministicNAND-CIRC program.⋆Proof of Theorem 20.8. Suppose that đč ∈ BPP. Let 𝑃 be a polynomial-time RNAND-TM program that computes đč as per Definition 20.1.Using Theorem 20.5, we can amplify the success probability of 𝑃 toobtain an RNAND-TM program 𝑃 â€Č that is at most a factor of 𝑂(𝑛)

Page 563: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling randomized computation 563

slower (and hence still polynomial time) such that for every đ‘„ ∈0, 1𝑛Prđ‘ŸâˆŒ0,1𝑚[𝑃 â€Č(đ‘„; 𝑟) = đč(đ‘„)] ≄ 1 − 0.1 ⋅ 2−𝑛 , (20.7)

where 𝑚 is the number of coin tosses that 𝑃 â€Č uses on inputs oflength 𝑛. We use the notation 𝑃 â€Č(đ‘„; 𝑟) to denote the execution of 𝑃 â€Čon input đ‘„ and when the result of the coin tosses corresponds to thestring 𝑟.

For every đ‘„ ∈ 0, 1𝑛, define the “bad” event đ”đ‘„ to hold if 𝑃 â€Č(đ‘„) ≠đč(đ‘„), where the sample space for this event consists of the coins of 𝑃 â€Č.Then by (20.7), Pr[đ”đ‘„] ≀ 0.1 ⋅ 2−𝑛 for every đ‘„ ∈ 0, 1𝑛. Since thereare 2𝑛 many such đ‘„â€™s, by the union bound we see that the probabilitythat the union of the events đ”đ‘„đ‘„âˆˆ0,1𝑛 is at most 0.1. This means thatif we choose 𝑟 ∌ 0, 1𝑚, then with probability at least 0.9 it will bethe case that for every đ‘„ ∈ 0, 1𝑛, đč(đ‘„) = 𝑃 â€Č(đ‘„; 𝑟). (Indeed, otherwisethe event đ”đ‘„ would hold for some đ‘„.) In particular, because of themere fact that the the probability of âˆȘđ‘„âˆˆ0,1đ‘›đ”đ‘„ is smaller than 1, thismeans that there exists a particular 𝑟∗ ∈ 0, 1𝑚 such that𝑃 â€Č(đ‘„; 𝑟∗) = đč(đ‘„) (20.8)

for every đ‘„ ∈ 0, 1𝑛.Now let us use the standard “unravelling the loop” the technique

and transform 𝑃 â€Č into a NAND-CIRC program 𝑄 of polynomial in𝑛 size, such that 𝑄(đ‘„đ‘Ÿ) = 𝑃 â€Č(đ‘„; 𝑟) for every đ‘„ ∈ 0, 1𝑛 and 𝑟 ∈0, 1𝑚. Then by “hardwiring” the values 𝑟∗0, 
 , 𝑟∗𝑚−1 in place of thelast 𝑚 inputs of 𝑄, we obtain a new NAND-CIRC program 𝑄𝑟∗ thatsatisfies by (20.8) that 𝑄𝑟∗(đ‘„) = đč(đ‘„) for every đ‘„ ∈ 0, 1𝑛. Thisdemonstrates that đč𝑛 has a polynomial sized NAND-CIRC program,hence completing the proof of Theorem 20.8.

20.4 DERANDOMIZATION

The proof of Theorem 20.8 can be summarized as follows: we canreplace a 𝑝𝑜𝑙𝑩(𝑛)-time algorithm that tosses coins as it runs with analgorithm that uses a single set of coin tosses 𝑟∗ ∈ 0, 1𝑝𝑜𝑙𝑩(𝑛) whichwill be good enough for all inputs of size 𝑛. Another way to say it isthat for the purposes of computing functions, we do not need “online”access to random coins and can generate a set of coins “offline” aheadof time, before we see the actual input.

But this does not really help us with answering the question ofwhether BPP equals P, since we still need to find a way to generatethese “offline” coins in the first place. To derandomize an RNAND-TM program we will need to come up with a single deterministic

Page 564: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

564 introduction to theoretical computer science

2 One amusing anecdote is a recent case where scam-mers managed to predict the imperfect “pseudo-random generator” used by slot machines to cheatcasinos. Unfortunately we don’t know the details ofhow they did it, since the case was sealed.

algorithm that will work for all input lengths. That is, unlike in thecase of RNAND-CIRC programs, we cannot choose for every inputlength 𝑛 some string 𝑟∗ ∈ 0, 1𝑝𝑜𝑙𝑩(𝑛) to use as our random coins.

Can we derandomize randomized algorithms, or does randomnessadd an inherent extra power for computation? This is a fundamentallyinteresting question but is also of practical significance. Ever sincepeople started to use randomized algorithms during the Manhattanproject, they have been trying to remove the need for randomness andreplace it with numbers that are selected through some deterministicprocess. Throughout the years this approach has often been usedsuccessfully, though there have been a number of failures as well.2

A common approach people used over the years was to replacethe random coins of the algorithm by a “randomish looking” stringthat they generated through some arithmetic progress. For example,one can use the digits of 𝜋 for the random tape. Using these type ofmethods corresponds to what von Neumann referred to as a “stateof sin”. (Though this is a sin that he himself frequently committed,as generating true randomness in sufficient quantity was and still isoften too expensive.) The reason that this is considered a “sin” is thatsuch a procedure will not work in general. For example, it is easy tomodify any probabilistic algorithm 𝐮 such as the ones we have seen inChapter 19, to an algorithm 𝐮â€Č that is guaranteed to fail if the randomtape happens to equal the digits of 𝜋. This means that the procedure“replace the random tape by the digits of 𝜋” does not yield a generalway to transform a probabilistic algorithm to a deterministic one thatwill solve the same problem. Of course, this procedure does not alwaysfail, but we have no good way to determine when it fails and whenit succeeds. This reasoning is not specific to 𝜋 and holds for everydeterministically produced string, whether it obtained by 𝜋, 𝑒, theFibonacci series, or anything else.

An algorithm that checks if its random tape is equal to 𝜋 and thenfails seems to be quite silly, but this is but the “tip of the iceberg” for avery serious issue. Time and again people have learned the hard waythat one needs to be very careful about producing random bits usingdeterministic means. As we will see when we discuss cryptography,many spectacular security failures and break-ins were the result ofusing “insufficiently random” coins.

20.4.1 Pseudorandom generatorsSo, we can’t use any single string to “derandomize” a probabilisticalgorithm. It turns out however, that we can use a collection of stringsto do so. Another way to think about it is that rather than trying toeliminate the need for randomness, we start by focusing on reducing the

Page 565: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling randomized computation 565

Figure 20.6: A pseudorandom generator đș mapsa short string 𝑠 ∈ 0, 1ℓ into a long string 𝑟 ∈0, 1𝑚 such that an small program/circuit 𝑃 cannotdistinguish between the case that it is provided arandom input 𝑟 ∌ 0, 1𝑚 and the case that itis provided a “pseudorandom” input of the form𝑟 = đș(𝑠) where 𝑠 ∌ 0, 1ℓ. The short string 𝑠is sometimes called the seed of the pseudorandomgenerator, as it is a small object that can be thought asyielding a large “tree of randomness”.

amount of randomness needed. (Though we will see that if we reducethe randomness sufficiently, we can eventually get rid of it altogether.)

We make the following definition:

Definition 20.9 — Pseudorandom generator. A function đș ∶ 0, 1ℓ →0, 1𝑚 is a (𝑇 , 𝜖)-pseudorandom generator if for every circuit đ¶ with𝑚 inputs, one output, and at most 𝑇 gates,∣ Prđ‘ âˆŒ0,1ℓ[đ¶(đș(𝑠)) = 1] − Prđ‘ŸâˆŒ0,1𝑚[đ¶(𝑟) = 1]∣ < 𝜖 (20.9)

PThis is a definition that’s worth reading more thanonce, and spending some time to digest it. Note that ittakes several parameters:

‱ 𝑇 is the limit on the number of gates of the circuitđ¶ that the generator needs to “fool”. The larger 𝑇is, the stronger the generator.

‱ 𝜖 is how close is the output of the pseudorandomgenerator to the true uniform distribution over0, 1𝑚. The smaller 𝜖 is, the stronger the generator.

‱ ℓ is the input length and 𝑚 is the output length.If ℓ ≄ 𝑚 then it is trivial to come up with sucha generator: on input 𝑠 ∈ 0, 1ℓ, we can output𝑠0, 
 , 𝑠𝑚−1. In this case Prđ‘ âˆŒ0,1ℓ [𝑃 (đș(𝑠)) = 1]will simply equal Pr𝑟∈0,1𝑚 [𝑃 (𝑟) = 1], no matterhow many lines 𝑃 has. So, the smaller ℓ is and thelarger 𝑚 is, the stronger the generator, and to getanything non-trivial, we need 𝑚 > ℓ.

Furthermore note that although our eventual goal is tofool probabilistic randomized algorithms that take anunbounded number of inputs, Definition 20.9 refers tofinite and deterministic NAND-CIRC programs.

We can think of a pseudorandom generator as a “randomnessamplifier.” It takes an input 𝑠 of ℓ bits chosen at random and ex-pands these ℓ bits into an output 𝑟 of 𝑚 > ℓ pseudorandom bits. If𝜖 is small enough then the pseudorandom bits will “look random”to any NAND-CIRC program that is not too big. Still, there are twoquestions we haven’t answered:

‱ What reason do we have to believe that pseudorandom generators withnon-trivial parameters exist?

‱ Even if they do exist, why would such generators be useful to derandomizerandomized algorithms? After all, Definition 20.9 does not involve

Page 566: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

566 introduction to theoretical computer science

RNAND-TM or RNAND-RAM programs, but rather deterministicNAND-CIRC programs with no randomness and no loops.

We will now (partially) answer both questions. For the first ques-tion, let us come clean and confess we do not know how to prove thatinteresting pseudorandom generators exist. By interesting we meanpseudorandom generators that satisfy that 𝜖 is some small constant(say 𝜖 < 1/3), 𝑚 > ℓ, and the function đș itself can be computed in𝑝𝑜𝑙𝑩(𝑚) time. Nevertheless, Lemma 20.12 (whose statement and proofis deferred to the end of this chapter) shows that if we only drop thelast condition (polynomial-time computability), then there do in factexist pseudorandom generators where 𝑚 is exponentially larger than ℓ.

PAt this point you might want to skip ahead and look atthe statement of Lemma 20.12. However, since its proofis somewhat subtle, I recommend you defer reading ituntil you’ve finished reading the rest of this chapter.

20.4.2 From existence to constructivityThe fact that there exists a pseudorandom generator does not meanthat there is one that can be efficiently computed. However, it turnsout that we can turn complexity “on its head” and use the assumednon existence of fast algorithms for problems such as 3SAT to obtainpseudorandom generators that can then be used to transform random-ized algorithms into deterministic ones. This is known as the Hardnessvs Randomness paradigm. A number of results along those lines, mostof which are outside the scope of this course, have led researchers tobelieve the following conjecture:

Optimal PRG conjecture: There is a polynomial-time computablefunction PRG ∶ 0, 1∗ → 0, 1 that yields an exponentially securepseudorandom generator.Specifically, there exists a constant 𝛿 > 0 such that for every ℓ and𝑚 < 2𝛿ℓ, if we define đș ∶ 0, 1ℓ → 0, 1𝑚 as đș(𝑠)𝑖 = PRG(𝑠, 𝑖) for every𝑠 ∈ 0, 1ℓ and 𝑖 ∈ [𝑚], then đș is a (2𝛿ℓ, 2−𝛿ℓ) pseudorandom generator.

PThe “optimal PRG conjecture” is worth while readingmore than once. What it posits is that we can obtain(𝑇 , 𝜖) pseudorandom generator đș such that everyoutput bit of đș can be computed in time polynomialin the length ℓ of the input, where 𝑇 is exponentiallylarge in ℓ and 𝜖 is exponentially small in ℓ. (Note thatwe could not hope for the entire output to be com-

Page 567: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling randomized computation 567

3 A pseudorandom generator of the form we posit,where each output bit can be computed individuallyin time polynomial in the seed length, is commonlyknown as a pseudorandom function generator. For moreon the many interesting results and connections in thestudy of pseudorandomness, see this monograph of SalilVadhan.

putable in ℓ, as just writing the output down will taketoo long.)To understand why we call such a pseudorandomgenerator “optimal,” it is a great exercise to convinceyourself that, for example, there does not exist a(21.1ℓ, 2−1.1ℓ) pseudorandom generator (in fact, thenumber 𝛿 in the conjecture must be smaller than 1). Tosee that we can’t have 𝑇 ≫ 2ℓ, note that if we allow aNAND-CIRC program with much more than 2ℓ linesthen this NAND-CIRC program could “hardwire” in-side it all the outputs of đș on all its 2ℓ inputs, and usethat to distinguish between a string of the form đș(𝑠)and a uniformly chosen string in 0, 1𝑚. To see thatwe can’t have 𝜖 â‰Ș 2−ℓ, note that by guessing the input𝑠 (which will be successful with probability 2−2ℓ), wecan obtain a small (i.e., 𝑂(ℓ) line) NAND-CIRC pro-gram that achieves a 2−ℓ advantage in distinguishing apseudorandom and uniform input. Working out thesedetails is a highly recommended exercise.

We emphasize again that the optimal PRG conjecture is, as its nameimplies, a conjecture, and we still do not know how to prove it. In par-ticular, it is stronger than the conjecture that P ≠ NP. But we do havesome evidence for its truth. There is a spectrum of different types ofpseudorandom generators, and there are weaker assumptions thanthe optimal PRG conjecture that suffice to prove that BPP = P. Inparticular this is known to hold under the assumption that there existsa function đč ∈ TIME(2𝑂(𝑛)) and 𝜖 > 0 such that for every sufficientlylarge 𝑛, đč𝑛 is not in SIZE(2𝜖𝑛). The name “Optimal PRG conjecture”is non standard. This conjecture is sometimes known in the literatureas the existence of exponentially strong pseudorandom functions.3

20.4.3 Usefulness of pseudorandom generatorsWe now show that optimal pseudorandom generators are indeed veryuseful, by proving the following theorem:

Theorem 20.10 — Derandomization of BPP. Suppose that the optimalPRG conjecture is true. Then BPP = P.

Proof Idea:

The optimal PRG conjecture tells us that we can achieve exponentialexpansion of ℓ truly random coins into as many as 2𝛿ℓ “pseudorandomcoins.” Looked at from the other direction, it allows us to reduce theneed for randomness by taking an algorithm that uses 𝑚 coins andconverting it into an algorithm that only uses 𝑂(log𝑚) coins. Now analgorithm of the latter type by can be made fully deterministic by enu-merating over all the 2𝑂(log𝑚) (which is polynomial in 𝑚) possibilitiesfor its random choices.

Page 568: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

568 introduction to theoretical computer science

⋆We now proceed with the proof details.

Proof of Theorem 20.10. Let đč ∈ BPP and let 𝑃 be a NAND-TM pro-gram and 𝑎, 𝑏, 𝑐, 𝑑 constants such that for every đ‘„ ∈ 0, 1𝑛, 𝑃(đ‘„)runs in at most 𝑐 ⋅ 𝑛𝑑 steps and Prđ‘ŸâˆŒ0,1𝑚 [𝑃 (đ‘„; 𝑟) = đč(đ‘„)] ≄ 2/3.By “unrolling the loop” and hardwiring the input đ‘„, we can obtainfor every input đ‘„ ∈ 0, 1𝑛 a NAND-CIRC program đ‘„đ‘„ of at most,say, 𝑇 = 10𝑐 ⋅ 𝑛𝑑 lines, that takes 𝑚 bits of input and such that𝑄(𝑟) = 𝑃(đ‘„; 𝑟).

Now suppose that đș ∶ 0, 1ℓ → 0, 1 is a (𝑇 , 0.1) pseudorandomgenerator. Then we could deterministically estimate the probability𝑝(đ‘„) = Prđ‘ŸâˆŒ0,1𝑚 [đ‘„đ‘„(𝑟) = 1] up to 0.1 accuracy in time 𝑂(𝑇 ⋅ 2ℓ ⋅ 𝑚 ⋅𝑐𝑜𝑠𝑡(đș)) where 𝑐𝑜𝑠𝑡(đș) is the time that it takes to compute a singleoutput bit of đș.

The reason is that we know that 𝑝(đ‘„) = Prđ‘ âˆŒ0,1ℓ [đ‘„đ‘„(đș(𝑠)) =1] will give us such an estimate for 𝑝(đ‘„), and we can compute theprobability 𝑝(đ‘„) by simply trying all 2ℓ possibillites for 𝑠. Now, underthe optimal PRG conjecture we can set 𝑇 = 2𝛿ℓ or equivalently ℓ =1𝛿 log𝑇 , and our total computation time is polynomial in 2ℓ = 𝑇 1/𝛿.Since 𝑇 ≀ 10𝑐 ⋅ 𝑛𝑑, this running time will be polynomial in 𝑛.

This completes the proof, since we are guaranteed thatPrđ‘ŸâˆŒ0,1𝑚 [đ‘„đ‘„(𝑟) = đč(đ‘„)] ≄ 2/3, and hence estimating theprobability 𝑝(đ‘„) to within 0.1 accuracy is sufficient to compute đč(đ‘„).

20.5 P = NP AND BPP VS PTwo computational complexity questions that we cannot settle are:

‱ Is P = NP? Where we believe the answer is negative.

‱ Is BPP = P? Where we believe the answer is positive.

However we can say that the “conventional wisdom” is correct onat least one of these questions. Namely, if we’re wrong on the firstcount, then we’ll be right on the second one:

Theorem 20.11 — Sipser–Gács Theorem. If P = NP then BPP = P.

PBefore reading the proof, it is instructive to thinkwhy this result is not “obvious.” If P = NP thengiven any randomized algorithm 𝐮 and input đ‘„,we will be able to figure out in polynomial time ifthere is a string 𝑟 ∈ 0, 1𝑚 of random coins for 𝐮

Page 569: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling randomized computation 569

Figure 20.7: If đč ∈ BPP then through amplification wecan ensure that there is an algorithm 𝐮 to computeđč on 𝑛-length inputs and using 𝑚 coins such thatPr𝑟∈0,1𝑚 [𝐮(đ‘„đ‘Ÿ) ≠ đč(đ‘„)] â‰Ș 1/𝑝𝑜𝑙𝑩(𝑚). Henceif đč(đ‘„) = 1 then almost all of the 2𝑚 choices for 𝑟will cause 𝐮(đ‘„đ‘Ÿ) to output 1, while if đč(đ‘„) = 0 then𝐮(đ‘„đ‘Ÿ) = 0 for almost all 𝑟’s. To prove the Sipser–GĂĄcs Theorem we consider several “shifts” of the set𝑆 ⊆ 0, 1𝑚 of the coins 𝑟 such that 𝐮(đ‘„đ‘Ÿ) = 1. Ifđč(đ‘„) = 1 then we can find a set of 𝑘 shifts 𝑠0, 
 , 𝑠𝑘−1for which âˆȘ𝑖∈[𝑘](𝑆 ⊕ 𝑠𝑖) = 0, 1𝑚. If đč(đ‘„) = 0 thenfor every such set |𝑐𝑱𝑝𝑖∈[𝑘]𝑆𝑖| ≀ 𝑘|𝑆| â‰Ș 2𝑚. We canphrase the question of whether there is such a set ofshift using a constant number of quantifiers, and socan solve it in polynomial time if P = NP.

such that 𝐮(đ‘„đ‘Ÿ) = 1. The problem is that even ifPr𝑟∈0,1𝑚 [𝐮(đ‘„đ‘Ÿ) = đč(đ‘„)] ≄ 0.9999, it can still be thecase that even when đč(đ‘„) = 0 there exists a string 𝑟such that 𝐮(đ‘„đ‘Ÿ) = 1.The proof is rather subtle. It is much more importantthat you understand the statement of the theorem thanthat you follow all the details of the proof.

Proof Idea:

The construction follows the “quantifier elimination” idea whichwe have seen in Theorem 16.6. We will show that for every đč ∈ BPP,we can reduce the question of some input đ‘„ satisfies đč(đ‘„) = 1 to thequestion of whether a formula of the form ∃𝑱∈0,1𝑚∀𝑣∈0,1𝑘𝑃(𝑱, 𝑣)is true, where 𝑚, 𝑘 are polynomial in the length of đ‘„ and 𝑃 ispolynomial-time computable. By Theorem 16.6, if P = NP then we candecide in polynomial time whether such a formula is true or false.

The idea behind this construction is that using amplification wecan obtain a randomized algorithm 𝐮 for computing đč using 𝑚 coinssuch that for every đ‘„ ∈ 0, 1𝑛, if đč(đ‘„) = 0 then the set 𝑆 ⊆ 0, 1𝑚of coins that make 𝐮 output 1 is extremely tiny, and if đč(đ‘„) = 1 thenit is very large. Now in the case đč(đ‘„) = 1, one can show that thismeans that there exists a small number 𝑘 of “shifts” 𝑠0, 
 , 𝑠𝑘−1 suchthat the union of the sets 𝑆 ⊕ 𝑠𝑖 (i.e., sets of the form 𝑠 ⊕ 𝑠𝑖 | 𝑠 ∈ 𝑆)covers 0, 1𝑚, while in the case đč(đ‘„) = 0 this union will always be ofsize at most 𝑘|𝑆| which is much smaller than 2𝑚. We can express thecondition that there exists 𝑠0, 
 , 𝑠𝑘−1 such that âˆȘ𝑖∈[𝑘](𝑆 ⊕ 𝑠𝑖) = 0, 1𝑚as a statement with a constant number of quantifiers.⋆Proof of Theorem 20.11. Let đč ∈ BPP. Using Theorem 20.5, thereexists a polynomial-time algorithm 𝐮 such that for every đ‘„ ∈ 0, 1𝑛,Prđ‘„âˆˆ0,1𝑚 [𝐮(đ‘„đ‘Ÿ) = đč(đ‘„)] ≄ 1 − 2−𝑛 where 𝑚 is polynomial in 𝑛. Inparticular (since an exponential dominates a polynomial, and we canalways assume 𝑛 is sufficiently large), it holds that

Prđ‘„âˆˆ0,1𝑚[𝐮(đ‘„đ‘Ÿ) = đč(đ‘„)] ≄ 1 − 110𝑚2 . (20.10)

Let đ‘„ ∈ 0, 1𝑛, and let đ‘†đ‘„ ⊆ 0, 1𝑚 be the set 𝑟 ∈ 0, 1𝑚 âˆ¶đŽ(đ‘„đ‘Ÿ) = 1. By our assumption, if đč(đ‘„) = 0 then |đ‘†đ‘„| ≀ 110𝑚2 2𝑚 and ifđč(đ‘„) = 1 then |đ‘†đ‘„| ≄ (1 − 110𝑚2 )2𝑚.For a set 𝑆 ⊆ 0, 1𝑚 and a string 𝑠 ∈ 0, 1𝑚, we define the set𝑆 ⊕ 𝑠 to be 𝑟 ⊕ 𝑠 ∶ 𝑟 ∈ 𝑆 where ⊕ denotes the XOR operation. That

is, 𝑆 ⊕ 𝑠 is the set 𝑆 “shifted” by 𝑠. Note that |𝑆 ⊕ 𝑠| = |𝑆|. (Pleasemake sure that you see why this is true.)

The heart of the proof is the following two claims:

Page 570: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

570 introduction to theoretical computer science

CLAIM I: For every subset 𝑆 ⊆ 0, 1𝑚, if |𝑆| ≀ 11000𝑚 2𝑚, then forevery 𝑠0, 
 , 𝑠100𝑚−1 ∈ 0, 1𝑚, âˆȘ𝑖∈[100𝑚](𝑆 ⊕ 𝑠𝑖) ⊊ 0, 1𝑚.

CLAIM II: For every subset 𝑆 ⊆ 0, 1𝑚, if |𝑆| ≄ 12 2𝑚 then thereexist a set of string 𝑠0, 
 , 𝑠100𝑚−1 such that âˆȘ𝑖∈[100𝑚](𝑆 ⊕ 𝑠𝑖) = 0, 1𝑚.

CLAIM I and CLAIM II together imply the theorem. Indeed, theymean that under our assumptions, for every đ‘„ ∈ 0, 1𝑛, đč(đ‘„) = 1 ifand only if∃𝑠0,
,𝑠100𝑚−1∈0,1𝑚 âˆȘ𝑖∈[100𝑚] (đ‘†đ‘„ ⊕ 𝑠𝑖) = 0, 1𝑚 (20.11)

which we can re-write as

∃𝑠0,
,𝑠100𝑚−1∈0,1đ‘šâˆ€đ‘€âˆˆ0,1𝑚(đ‘€ ∈ (đ‘†đ‘„âŠ•đ‘ 0)âˆšđ‘€ ∈ (đ‘†đ‘„âŠ•đ‘ 1)∹⋯ đ‘€ ∈ (đ‘†đ‘„âŠ•đ‘ 100𝑚−1))(20.12)

or equivalently

∃𝑠0,
,𝑠100𝑚−1∈0,1đ‘šâˆ€đ‘€âˆˆ0,1𝑚(𝐮(đ‘„(đ‘€âŠ•đ‘ 0)) = 1∹𝐮(đ‘„(đ‘€âŠ•đ‘ 1)) = 1∹⋯∹𝐮(đ‘„(đ‘€âŠ•đ‘ 100𝑚−1)) = 1)(20.13)

which (since 𝐮 is computable in polynomial time) is exactly thetype of statement shown in Theorem 16.6 to be decidable in polyno-mial time if P = NP.

We see that all that is left is to prove CLAIM I and CLAIM II.CLAIM I follows immediately from the fact that

âˆȘ𝑖∈[100𝑚−1]|đ‘†đ‘„ ⊕ 𝑠𝑖| ≀ 100𝑚−1∑𝑖=0 |đ‘†đ‘„ ⊕ 𝑠𝑖| = 100𝑚−1∑𝑖=0 |đ‘†đ‘„| = 100𝑚|đ‘†đ‘„| .(20.14)

To prove CLAIM II, we will use a technique known as the prob-abilistic method (see the proof of Lemma 20.12 for a more extensivediscussion). Note that this is a completely different use of probabilitythan in the theorem statement, we just use the methods of probabilityto prove an existential statement.

Proof of CLAIM II: Let 𝑆 ⊆ 0, 1𝑚 with |𝑆| ≄ 0.5 ⋅ 2𝑚 be asin the claim’s statement. Consider the following probabilistic ex-periment: we choose 100𝑚 random shifts 𝑠0, 
 , 𝑠100𝑚−1 indepen-dently at random in 0, 1𝑚, and consider the event GOOD thatâˆȘ𝑖∈[100𝑚](𝑆 ⊕ 𝑠𝑖) = 0, 1𝑚. To prove CLAIM II it is enough to showthat Pr[GOOD] > 0, since that means that in particular there must existshifts 𝑠0, 
 , 𝑠100𝑚−1 that satisfy this condition.

For every 𝑧 ∈ 0, 1𝑚, define the event BAD𝑧 to hold if 𝑧 ∉âˆȘ𝑖∈[100𝑚−1](𝑆 ⊕ 𝑠𝑖). The event GOOD holds if BAD𝑧 fails for every𝑧 ∈ 0, 1𝑚, and so our goal is to prove that Pr[âˆȘ𝑧∈0,1𝑚BAD𝑧] < 1. Bythe union bound, to show this, it is enough to show that Pr[BAD𝑧] <

Page 571: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling randomized computation 571

4 The condition of independence here is subtle. Itis not the case that all of the 2𝑚 × 100𝑚 eventsBAD𝑖𝑧𝑧∈0,1𝑚,𝑖∈[100𝑚] are mutually independent.Only for a fixed 𝑧 ∈ 0, 1𝑚, the 100𝑚 events of theform BAD𝑖𝑧 are mutually independent.

5 There is a whole (highly recommended) book byAlon and Spencer devoted to this method.

2−𝑚 for every 𝑧 ∈ 0, 1𝑚. Define the event BAD𝑖𝑧 to hold if 𝑧 ∉ 𝑆 ⊕ 𝑠𝑖.Since every shift 𝑠𝑖 is chosen independently, for every fixed 𝑧 theevents BAD0𝑧, 
 ,BAD100𝑚−1𝑧 are mutually independent,4 and hence

Pr[BAD𝑧] = Pr[âˆ©đ‘–âˆˆ[100𝑚−1]BAD𝑖𝑧] = 100𝑚−1∏𝑖=0 Pr[BAD𝑖𝑧] . (20.15)

So this means that the result will follow by showing thatPr[BAD𝑖𝑧] ≀ 12 for every 𝑧 ∈ 0, 1𝑚 and 𝑖 ∈ [100𝑚] (as that wouldallow to bound the righthand side of (20.15) by 2−100𝑚). In otherwords, we need to show that for every 𝑧 ∈ 0, 1𝑚 and set 𝑆 ⊆ 0, 1𝑚with |𝑆| ≄ 12 2𝑚,

Pr𝑠∈0,1𝑚[𝑧 ∈ 𝑆 ⊕ 𝑠] ≄ 12 . (20.16)

To show this, we observe that 𝑧 ∈ 𝑆 ⊕ 𝑠 if and only if 𝑠 ∈ 𝑆 ⊕ 𝑧 (canyou see why). Hence we can rewrite the probability on the lefthandside of (20.16) as Pr𝑠∈0,1𝑚 [𝑠 ∈ 𝑆⊕𝑧] which simply equals |𝑆⊕𝑧|/2𝑚 =|𝑆|/2𝑚 ≄ 1/2! This concludes the proof of CLAIM I and hence ofTheorem 20.11.

20.6 NON-CONSTRUCTIVE EXISTENCE OF PSEUDORANDOM GEN-ERATORS (ADVANCED, OPTIONAL)

We now show that, if we don’t insist on constructivity of pseudoran-dom generators, then we can show that there exists pseudorandomgenerators with output that exponentially larger in the input length.Lemma 20.12 — Existence of inefficient pseudorandom generators. There issome absolute constant đ¶ such that for every 𝜖, 𝑇 , if ℓ > đ¶(log𝑇 +log(1/𝜖)) and 𝑚 ≀ 𝑇 , then there is an (𝑇 , 𝜖) pseudorandom generatorđș ∶ 0, 1ℓ → 0, 1𝑚.

Proof Idea:

The proof uses an extremely useful technique known as the “prob-abilistic method” which is not too hard mathematically but can beconfusing at first.5 The idea is to give a “non constructive” proof ofexistence of the pseudorandom generator đș by showing that if đș waschosen at random, then the probability that it would be a valid (𝑇 , 𝜖)pseudorandom generator is positive. In particular this means thatthere exists a single đș that is a valid (𝑇 , 𝜖) pseudorandom generator.The probabilistic method is just a proof technique to demonstrate theexistence of such a function. Ultimately, our goal is to show the exis-tence of a deterministic function đș that satisfies the condition.⋆

Page 572: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

572 introduction to theoretical computer science

The above discussion might be rather abstract at this point, butwould become clearer after seeing the proof.

Proof of Lemma 20.12. Let 𝜖, 𝑇 , ℓ, 𝑚 be as in the lemma’s statement. Weneed to show that there exists a function đș ∶ 0, 1ℓ → 0, 1𝑚 that“fools” every 𝑇 line program 𝑃 in the sense of (20.9). We will showthat this follows from the following claim:

Claim I: For every fixed NAND-CIRC program 𝑃 , if we pick đș ∶0, 1ℓ → 0, 1𝑚 at random then the probability that (20.9) is violatedis at most 2−𝑇 2 .

Before proving Claim I, let us see why it implies Lemma 20.12. Wecan identify a function đș ∶ 0, 1ℓ → 0, 1𝑚 with its “truth table”or simply the list of evaluations on all its possible 2ℓ inputs. Sinceeach output is an 𝑚 bit string, we can also think of đș as a string in0, 1𝑚⋅2ℓ . We define â„±đ‘šâ„“ to be the set of all functions from 0, 1ℓ to0, 1𝑚. As discussed above we can identify â„±đ‘šâ„“ with 0, 1𝑚⋅2ℓ andchoosing a random function đș ∌ â„±đ‘šâ„“ corresponds to choosing arandom 𝑚 ⋅ 2ℓ-long bit string.

For every NAND-CIRC program 𝑃 let đ”đ‘ƒ be the event that, if wechoose đș at random from â„±đ‘šâ„“ then (20.9) is violated with respect tothe program 𝑃 . It is important to understand what is the sample spacethat the event đ”đ‘ƒ is defined over, namely this event depends on thechoice of đș and so đ”đ‘ƒ is a subset of â„±đ‘šâ„“ . An equivalent way to definethe event đ”đ‘ƒ is that it is the subset of all functions mapping 0, 1ℓ to0, 1𝑚 that violate (20.9), or in other words:

đ”đ‘ƒ = ⎧⎚⎩đș ∈ â„±đ‘šâ„“ ∣ ∣ 12ℓ ∑𝑠∈0,1ℓ 𝑃(đș(𝑠)) − 12𝑚 ∑𝑟∈0,1𝑚 𝑃(𝑟)∣ > đœ–âŽ«âŽŹâŽ­(20.17)

(We’ve replaced here the probability statements in (20.9) with theequivalent sums so as to reduce confusion as to what is the samplespace that đ”đ‘ƒ is defined over.)

To understand this proof it is crucial that you pause here and seehow the definition of đ”đ‘ƒ above corresponds to (20.17). This may welltake re-reading the above text once or twice, but it is a good exerciseat parsing probabilistic statements and learning how to identify thesample space that these statements correspond to.

Now, we’ve shown in Theorem 5.2 that up to renaming variables(which makes no difference to program’s functionality) there are2𝑂(𝑇 log𝑇 ) NAND-CIRC programs of at most 𝑇 lines. Since 𝑇 log𝑇 <𝑇 2 for sufficiently large 𝑇 , this means that if Claim I is true, thenby the union bound it holds that the probability of the union ofđ”đ‘ƒ over all NAND-CIRC programs of at most 𝑇 lines is at most2𝑂(𝑇 log𝑇 )2−𝑇 2 < 0.1 for sufficiently large 𝑇 . What is important for

Page 573: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling randomized computation 573

us about the number 0.1 is that it is smaller than 1. In particular thismeans that there exists a single đș∗ ∈ â„±đ‘šâ„“ such that đș∗ does not violate(20.9) with respect to any NAND-CIRC program of at most 𝑇 lines,but that precisely means that đș∗ is a (𝑇 , 𝜖) pseudorandom generator.

Hence to conclude the proof of Lemma 20.12, it suffices to proveClaim I. Choosing a random đș ∶ 0, 1ℓ → 0, 1𝑚 amounts to choos-ing 𝐿 = 2ℓ random strings 𝑩0, 
 , 𝑩𝐿−1 ∈ 0, 1𝑚 and letting đș(đ‘„) = đ‘Šđ‘„(identifying 0, 1ℓ and [𝐿] via the binary representation). This meansthat proving the claim amounts to showing that for every fixed func-tion 𝑃 ∶ 0, 1𝑚 → 0, 1, if 𝐿 > 2đ¶(log𝑇 +log 𝜖) (which by setting đ¶ > 4,we can ensure is larger than 10𝑇 2/𝜖2) then the probability that∣ 1𝐿 𝐿−1∑𝑖=0 𝑃(𝑩𝑖) − Prđ‘ âˆŒ0,1𝑚[𝑃 (𝑠) = 1]∣ > 𝜖 (20.18)

is at most 2−𝑇 2 .(20.18) follows directly from the Chernoff bound. Indeed, if we

let for every 𝑖 ∈ [𝐿] the random variable 𝑋𝑖 denote 𝑃(𝑩𝑖), thensince 𝑩0, 
 , 𝑩𝐿−1 is chosen independently at random, these are in-dependently and identically distributed random variables with meanđ”Œđ‘ŠâˆŒ0,1𝑚 [𝑃 (𝑩)] = Prđ‘ŠâˆŒ0,1𝑚 [𝑃 (𝑩) = 1] and hence the probability thatthey deviate from their expectation by 𝜖 is at most 2 ⋅ 2−𝜖2𝐿/2.

Figure 20.8: The relation between BPP and the othercomplexity classes that we have seen. We know thatP ⊆ BPP ⊆ EXP and BPP ⊆ P/poly but we don’tknow how BPP compares with NP and can’t rule outeven BPP = EXP. Most evidence points out to thepossibliity that BPP = P.

Chapter Recap

‱ We can model randomized algorithms by eitheradding a special “coin toss” operation or assumingan extra randomly chosen input.

‱ The class BPP contains the set of Boolean func-tions that can be computed by polynomial timerandomized algorithms.

‱ BPP is a worst case class of computation: a ran-domized algorithm to compute a function mustcompute it correctly with high probability on everyinput.

Page 574: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

574 introduction to theoretical computer science

‱ We can amplify the success probability of random-ized algorithm from any value strictly larger than1/2 into a success probability that is exponentiallyclose to 1.

‱ We know that P ⊆ BPP ⊆ EXP.‱ We also know that BPP ⊆ P/poly.‱ The relation between BPP and NP is not known,

but we do know that if P = NP then BPP = P.‱ Pseudorandom generators are objects that take

a short random “seed” and expand it to a muchlonger output that “appears random” for effi-cient algorithms. We conjecture that exponentiallystrong pseudorandom generators exist. Under thisconjecture, BPP = P.

20.7 EXERCISES

20.8 BIBLIOGRAPHICAL NOTES

In this chapter we ignore the issue of how we actually get randombits in practice. The output of many physical processes, whether itis thermal heat, network and hard drive latency, user typing pat-tern and mouse movements, and more can be thought of as a binarystring sampled from some distribution 𝜇 that might have significantunpredictability (or entropy) but is not necessarily the uniform distri-bution over 0, 1𝑛. Indeed, as this paper shows, even (real-world)coin tosses do not have exactly the distribution of a uniformly randomstring. Therefore, to use the resulting measurements for randomizedalgorithms, one typically needs to apply a “distillation” or random-ness extraction process to the raw measurements to transform themto the uniform distribution. Vadhan’s book [Vad+12] is an excellentsource for more discussion on both randomness extractors and pseu-dorandom generators.

The name BPP stands for “bounded probability polynomial time”.This is an historical accident: this class probably should have beencalled RP or PP but both names were taken by other classes.

The proof of Theorem 20.8 actually yields more than its statement.We can use the same “unrolling the loop” arguments we’ve used be-fore to show that the restriction to 0, 1𝑛 of every function in BPPis also computable by a polynomial-size RNAND-CIRC program(i.e., NAND-CIRC program with the RAND operation). Like in the Pvs SIZE(𝑝𝑜𝑙𝑩(𝑛)) case, there are also functions outside BPP whoserestrictions can be computed by polynomial-size RNAND-CIRC pro-grams. Nevertheless the proof of Theorem 20.8 shows that even suchfunctions can be computed by polynomial sized NAND-CIRC pro-

Page 575: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

modeling randomized computation 575

grams without using the rand operations. This can be phrased assaying that BPSIZE(𝑇 (𝑛)) ⊆ SIZE(𝑂(𝑛𝑇 (𝑛))) (where BPSIZE isdefined in the natural way using RNAND progams). The strongerversion of Theorem 20.8 we mentioned can be phrased as saying thatBPP/poly = P/poly.

Page 576: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 577: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

VADVANCED TOPICS

Page 578: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 579: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

21Cryptography

“Human ingenuity cannot concoct a cipher which human ingenuity cannotresolve.”, Edgar Allen Poe, 1841

“A good disguise should not reveal the person’s height”, Shafi Goldwasserand Silvio Micali, 1982

““Perfect Secrecy” is defined by requiring of a system that after a cryptogramis intercepted by the enemy the a posteriori probabilities of this cryptogram rep-resenting various messages be identically the same as the a priori probabilitiesof the same messages before the interception. It is shown that perfect secrecy ispossible but requires, if the number of messages is finite, the same number ofpossible keys.”, Claude Shannon, 1945

“We stand today on the brink of a revolution in cryptography.”, WhitfeldDiffie and Martin Hellman, 1976

Cryptography - the art or science of “secret writing” - has beenaround for several millennia, and for almost all of that time EdgarAllan Poe’s quote above held true. Indeed, the history of cryptographyis littered with the figurative corpses of cryptosystems believed secureand then broken, and sometimes with the actual corpses of those whohave mistakenly placed their faith in these cryptosystems.

Yet, something changed in the last few decades, which is the “revo-lution” alluded to (and to a large extent initiated by) Diffie and Hell-man’s 1976 paper quoted above. New cryptosystems have been foundthat have not been broken despite being subjected to immense effortsinvolving both human ingenuity and computational power on a scalethat completely dwarves the “code breakers” of Poe’s time. Even moreamazingly, these cryptosystem are not only seemingly unbreakable,but they also achieve this under much harsher conditions. Not only dotoday’s attackers have more computational power but they also havemore data to work with. In Poe’s age, an attacker would be lucky ifthey got access to more than a few encryptions of known messages.These days attackers might have massive amounts of data- terabytes

Compiled on 8.26.2020 18:10

Learning Objectives:‱ Definition of perfect secrecy‱ The one-time pad encryption scheme‱ Necessity of long keys for perfect secrecy‱ Computational secrecy and the derandomized

one-time pad.‱ Public key encryption‱ A taste of advanced topics

Page 580: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

580 introduction to theoretical computer science

Figure 21.1: Snippet from encrypted communicationbetween queen Mary and Sir Babington

Figure 21.2: XKCD’s take on the added security ofusing uncommon symbols

or more - at their disposal. In fact, with public key encryption, an at-tacker can generate as many ciphertexts as they wish.

The key to this success has been a clearer understanding of bothhow to define security for cryptographic tools and how to relate thissecurity to concrete computational problems. Cryptography is a vastand continuously changing topic, but we will touch on some of theseissues in this chapter.

21.1 CLASSICAL CRYPTOSYSTEMS

A great many cryptosystems have been devised and broken through-out the ages. Let us recount just some of these stories. In 1587, Marythe queen of Scots, and the heir to the throne of England, wanted toarrange the assassination of her cousin, queen Elisabeth I of England,so that she could ascend to the throne and finally escape the housearrest under which she had been for the last 18 years. As part of thiscomplicated plot, she sent a coded letter to Sir Anthony Babington.

Mary used what’s known as a substitution cipher where each letteris transformed into a different obscure symbol (see Fig. 21.1). At afirst look, such a letter might seem rather inscrutable- a meaninglesssequence of strange symbols. However, after some thought, one mightrecognize that these symbols repeat several times and moreover thatdifferent symbols repeat with different frequencies. Now it doesn’ttake a large leap of faith to assume that perhaps each symbol corre-sponds to a different letter and the more frequent symbols correspondto letters that occur in the alphabet with higher frequency. From thisobservation, there is a short gap to completely breaking the cipher,which was in fact done by queen Elisabeth’s spies who used the de-coded letters to learn of all the co-conspirators and to convict queenMary of treason, a crime for which she was executed. Trusting in su-perficial security measures (such as using “inscrutable” symbols) is atrap that users of cryptography have been falling into again and againover the years. (As in many things, this is the subject of a great XKCDcartoon, see Fig. 21.2.)

The Vigenùre cipher is named after Blaise de Vigenùre who de-scribed it in a book in 1586 (though it was invented earlier by Bellaso).The idea is to use a collection of substitution cyphers - if there are 𝑛different ciphers then the first letter of the plaintext is encoded withthe first cipher, the second with the second cipher, the 𝑛𝑡ℎ with the𝑛𝑡ℎ cipher, and then the 𝑛 + 1𝑠𝑡 letter is again encoded with the firstcipher. The key is usually a word or a phrase of 𝑛 letters, and the𝑖𝑡ℎ substitution cipher is obtained by shifting each letter 𝑘𝑖 positionsin the alphabet. This “flattens” the frequencies and makes it muchharder to do frequency analysis, which is why this cipher was consid-ered “unbreakable” for 300+ years and got the nickname “le chiffre

Page 581: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 581

Figure 21.3: Confederate Cipher Disk for implement-ing the VigenĂšre cipher

Figure 21.4: Confederate encryption of the message“Gen’l Pemberton: You can expect no help from thisside of the river. Let Gen’l Johnston know, if possible,when you can attack the same point on the enemy’slines. Inform me also and I will endeavor to make adiversion. I have sent some caps. I subjoin a despatchfrom General Johnston.”

Figure 21.5: In the Enigma mechanical cipher the secretkey would be the settings of the rotors and internalwires. As the operator types up their message, theencrypted version appeared in the display area above,and the internal state of the cipher was updated (andso typing the same letter twice would generally resultin two different letters output). Decrypting followsthe same process: if the sender and receiver are usingthe same key then typing the ciphertext would resultin the plaintext appearing in the display.1 Here is a nice exercise: compute (up to an orderof magnitude) the probability that a 50-letter longmessage composed of random letters will end up notcontaining the letter “L”.

indĂ©chiffrable” (“the unbreakable cipher”). Nevertheless, CharlesBabbage cracked the VigenĂšre cipher in 1854 (though he did not pub-lish it). In 1863 Friedrich Kasiski broke the cipher and published theresult. The idea is that once you guess the length of the cipher, youcan reduce the task to breaking a simple substitution cipher which canbe done via frequency analysis (can you see why?). Confederate gen-erals used VigenĂšre regularly during the civil war, and their messageswere routinely cryptanalzed by Union officers.

The Enigma cipher was a mechanical cipher (looking like a type-writer, see Fig. 21.5) where each letter typed would get mapped into adifferent letter depending on the (rather complicated) key and currentstate of the machine which had several rotors that rotated at differentpaces. An identically wired machine at the other end could be usedto decrypt. Just as many ciphers in history, this has also been believedby the Germans to be “impossible to break” and even quite late in thewar they refused to believe it was broken despite mounting evidenceto that effect. (In fact, some German generals refused to believe itwas broken even after the war.) Breaking Enigma was an heroic effortwhich was initiated by the Poles and then completed by the British atBletchley Park, with Alan Turing (of the Turing machines) playing akey role. As part of this effort the Brits built arguably the world’s firstlarge scale mechanical computation devices (though they looked moresimilar to washing machines than to iPhones). They were also helpedalong the way by some quirks and errors of the German operators. Forexample, the fact that their messages ended with “Heil Hitler” turnedout to be quite useful.

Here is one entertaining anecdote: the Enigma machine wouldnever map a letter to itself. In March 1941, Mavis Batey, a cryptana-lyst at Bletchley Park received a very long message that she tried todecrypt. She then noticed a curious property— the message did notcontain the letter “L”.1 She realized that the probability that no “L”’sappeared in the message is too small for this to happen by chance.Hence she surmised that the original message must have been com-posed only of L’s. That is, it must have been the case that the operator,perhaps to test the machine, have simply sent out a message where herepeatedly pressed the letter “L”. This observation helped her decodethe next message, which helped inform of a planned Italian attack andsecure a resounding British victory in what became known as “theBattle of Cape Matapan”. Mavis also helped break another Enigmamachine. Using the information she provided, the Brits were ableto feed the Germans with the false information that the main alliedinvasion would take place in Pas de Calais rather than on Normandy.

In the words of General Eisenhower, the intelligence from Bletchleypark was of “priceless value”. It made a huge difference for the Allied

Page 582: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

582 introduction to theoretical computer science

Figure 21.6: A private-key encryption scheme is apair of algorithms 𝐾, đ· such that for every key𝑘 ∈ 0, 1𝑛 and plaintext đ‘„ ∈ 0, 1𝐿(𝑛), 𝑩 = 𝐾𝑘(đ‘„)is a ciphertext of length đ¶(𝑛). The encryption schemeis valid if for every such 𝑩, đ·đ‘˜(𝑩) = đ‘„. That is, thedecryption of an encryption of đ‘„ is đ‘„, as long as bothencryption and decryption use the same key.

war effort, thereby shortening World War II and saving millions oflives. See also this interview with Sir Harry Hinsley.

21.2 DEFINING ENCRYPTION

Many of the troubles that cryptosystem designers faced over history(and still face!) can be attributed to not properly defining or under-standing what are the goals they want to achieve in the first place. Letus focus on the setting of private key encryption. (This is also known as“symmetric encryption”; for thousands of years, “private key encryp-tion” was synonymous with encryption and only in the 1970’s wasthe concept of public key encryption invented, see Definition 21.11.) Asender (traditionally called “Alice”) wants to send a message (knownalso as a plaintext) đ‘„ ∈ 0, 1∗ to a receiver (traditionally called “Bob”).They would like their message to be kept secret from an adversarywho listens in or “eavesdrops” on the communication channel (and istraditionally called “Eve”).

Alice and Bob share a secret key 𝑘 ∈ 0, 1∗. (While the letter 𝑘is often used elsewhere in the book to denote a natural number, inthis chapter we use it to denote the string corresponding to a secretkey.) Alice uses the key 𝑘 to “scramble” or encrypt the plaintext đ‘„ intoa ciphertext 𝑩, and Bob uses the key 𝑘 to “unscramble” or decrypt theciphertext 𝑩 back into the plaintext đ‘„. This motivates the followingdefinition which attempts to capture what it means for an encryptionscheme to be valid or “make sense”, regardless of whether or not it issecure:

Definition 21.1 — Valid encryption scheme. Let 𝐿 ∶ ℕ → ℕ and đ¶ ∶ ℕ → ℕbe two functions mapping natural numbers to natural numbers.A pair of polynomial-time computable functions (𝐾, đ·) map-ping strings to strings is a valid private key encryption scheme (orencryption scheme for short) with plaintext length function 𝐿(⋅) andciphertext length function đ¶(⋅) if for every 𝑛 ∈ ℕ, 𝑘 ∈ 0, 1𝑛 andđ‘„ ∈ 0, 1𝐿(𝑛), |𝐾𝑘(đ‘„)| = đ¶(𝑛) andđ·(𝑘, 𝐾(𝑘, đ‘„)) = đ‘„ . (21.1)

We will often write the first input (i.e., the key) to the encryp-tion and decryption as a subscript and so can write (21.1) also asđ·đ‘˜(𝐾𝑘(đ‘„)) = đ‘„.Solved Exercise 21.1 — Lengths of ciphertext and plaintext. Prove that forevery valid encryption scheme (𝐾, đ·) with functions 𝐿, đ¶. đ¶(𝑛) â‰„đż(𝑛) for every 𝑛.

Page 583: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 583

2 The actual quote is “Il faut qu’il n’exige pas lesecret, et qu’il puisse sans inconvĂ©nient tomber entreles mains de l’ennemi” loosely translated as “Thesystem must not require secrecy and can be stolen bythe enemy without causing trouble”. According toSteve Bellovin the NSA version is “assume that thefirst copy of any device we make is shipped to theKremlin”.

Solution:

For every fixed key 𝑘 ∈ 0, 1𝑛, the equation (21.1) implies thatthe map 𝑩 ↩ đ·đ‘˜(𝑩) inverts the map đ‘„ ↩ 𝐾𝑘(đ‘„), which in partic-ular means that the map đ‘„ ↩ 𝐾𝑘(đ‘„) must be one to one. Henceits codomain must be at least as large as its domain, and since itsdomain is 0, 1𝐿(𝑛) and its codomain is 0, 1đ¶(𝑛) it follows thatđ¶(𝑛) ≄ 𝐿(𝑛).

Since the ciphertext length is always at least the plaintext length(and in most applications it is not much longer than that), we typi-cally focus on the plaintext length as the quantity to optimize in anencryption scheme. The larger 𝐿(𝑛) is, the better the scheme, since itmeans we need a shorter secret key to protect messages of the samelength.

21.3 DEFINING SECURITY OF ENCRYPTION

Definition 21.1 says nothing about the security of 𝐾 and đ·, and evenallows the trivial encryption scheme that ignores the key altogetherand sets 𝐾𝑘(đ‘„) = đ‘„ for every đ‘„. Defining security is not a trivial matter.

PYou would appreciate the subtleties of defining secu-rity of encryption more if at this point you take a fiveminute break from reading, and try (possibly with apartner) to brainstorm on how you would mathemat-ically define the notion that an encryption scheme issecure, in the sense that it protects the secrecy of theplaintext đ‘„.

Throughout history, many attacks on cryptosystems were rootedin the cryptosystem designers’ reliance on “security throughobscurity”— trusting that the fact their methods are not known totheir enemy will protect them from being broken. This is a faultyassumption - if you reuse a method again and again (even with adifferent key each time) then eventually your adversaries will figureout what you are doing. And if Alice and Bob meet frequently in asecure location to decide on a new method, they might as well takethe opportunity to exchange their secrets. These considerations ledAuguste Kerckhoffs in 1883 to state the following principle:

A cryptosystem should be secure even if everything about the system, except thekey, is public knowledge.2

Why is it OK to assume the key is secret and not the algorithm?Because we can always choose a fresh key. But of course that won’t

Page 584: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

584 introduction to theoretical computer science

help us much if our key is “1234” or “passw0rd!”. In fact, if you useany deterministic algorithm to choose the key then eventually youradversary will figure this out. Therefore for security we must choosethe key at random and can restate Kerckhoffs’s principle as follows:

There is no secrecy without randomness

This is such a crucial point that is worth repeating:

Big Idea 26 There is no secrecy without randomness.

At the heart of every cryptographic scheme there is a secret key,and the secret key is always chosen at random. A corollary of thatis that to understand cryptography, you need to know probabilitytheory.

RRemark 21.2 — Randomness in the real world. Choos-ing the secrets for cryptography requires generatingrandomness, which is often done by measuring some“unpredictable” or “high entropy” data, and thenapplying hash functions to the result to “extract” auniformly random string. Great care must be taken indoing this, and randomness generators often turn outto be the Achilles heel of secure systems.In 2006 a programmer removed a line of code from theprocedure to generate entropy in OpenSSL packagedistributed by Debian since it caused a warning insome automatic verification code. As a result for twoyears (until this was discovered) all the randomnessgenerated by this procedure used only the processID as an “unpredictable” source. This means that allcommunication done by users in that period is fairlyeasily breakable (and in particular, if some entitiesrecorded that communication they could break it alsoretroactively). See XKCD’s take on that incident.In 2012 two separate teams of researchers scanned alarge number of RSA keys on the web and found outthat about 4 percent of them are easy to break. Themain issue were devices such as routers, internet-connected printers and such. These devices sometimesrun variants of Linux- a desktop operating system-but without a hard drive, mouse or keyboard, theydon’t have access to many of the entropy sources thatdesktop have. Coupled with some good old fashionedignorance of cryptography and software bugs, this ledto many keys that are downright trivial to break, seethis blog post and this web page for more details.Since randomness is so crucial to security, breakingthe procedure to generate randomness can lead to acomplete break of the system that uses this random-ness. Indeed, the Snowden documents, combined with

Page 585: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 585

observations of Shumow and Ferguson, strongly sug-gest that the NSA has deliberately inserted a trapdoorin one of the pseudorandom generators published bythe National Institute of Standards and Technologies(NIST). Fortunately, this generator wasn’t widelyadapted but apparently the NSA did pay 10 milliondollars to RSA security so the latter would make thisgenerator their default option in their products.

21.4 PERFECT SECRECY

If you think about encryption scheme security for a while, you mightcome up with the following principle for defining security: “Anencryption scheme is secure if it is not possible to recover the key 𝑘 from𝐾𝑘(đ‘„)”. However, a moment’s thought shows that the key is not reallywhat we’re trying to protect. After all, the whole point of an encryp-tion is to protect the confidentiality of the plaintext đ‘„. So, we can try todefine that “an encryption scheme is secure if it is not possible to recover theplaintext đ‘„ from 𝐾𝑘(đ‘„)”. Yet it is not clear what this means either. Sup-pose that an encryption scheme reveals the first 10 bits of the plaintextđ‘„. It might still not be possible to recover đ‘„ completely, but on an in-tuitive level, this seems like it would be extremely unwise to use suchan encryption scheme in practice. Indeed, often even partial informationabout the plaintext is enough for the adversary to achieve its goals.

The above thinking led Shannon in 1945 to formalize the notion ofperfect secrecy, which is that an encryption reveals absolutely nothingabout the message. There are several equivalent ways to define it, butperhaps the cleanest one is the following:

Definition 21.3 — Perfect secrecy. A valid encryption scheme (𝐾, đ·)with plaintext length 𝐿(⋅) is perfectly secret if for every 𝑛 ∈ ℕ andplaintexts đ‘„, đ‘„â€Č ∈ 0, 1𝐿(𝑛), the following two distributions 𝑌 and𝑌 â€Č over 0, 1∗ are identical:

‱ 𝑌 is obtained by sampling 𝑘 ∌ 0, 1𝑛 and outputting 𝐾𝑘(đ‘„).‱ 𝑌 â€Č is obtained by sampling 𝑘 ∌ 0, 1𝑛 and outputting 𝐾𝑘(đ‘„â€Č).

PThis definition might take more than one readingto parse. Try to think of how this condition wouldcorrespond to your intuitive notion of “learning noinformation” about đ‘„ from observing 𝐾𝑘(đ‘„), and toShannon’s quote in the beginning of this chapter.

Page 586: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

586 introduction to theoretical computer science

Figure 21.7: For any key length 𝑛, we can visualize anencryption scheme (𝐾, đ·) as a graph with a vertexfor every one of the 2𝐿(𝑛) possible plaintexts and forevery one of the ciphertexts in 0, 1∗ of the form𝐾𝑘(đ‘„) for 𝑘 ∈ 0, 1𝑛 and đ‘„ ∈ 0, 1𝐿(𝑛). For everyplaintext đ‘„ and key 𝑘, we add an edge labeled 𝑘between đ‘„ and 𝐾𝑘(đ‘„). By the validity condition, if wepick any fixed key 𝑘, the map đ‘„ ↩ 𝐾𝑘(đ‘„) must beone-to-one. The condition of perfect secrecy simplycorresponds to requiring that every two plaintextsđ‘„ and đ‘„â€Č have exactly the same set of neighbors (ormulti-set, if there are parallel edges).

In particular, suppose that you knew ahead of timethat Alice sent either an encryption of đ‘„ or an en-cryption of đ‘„â€Č. Would you learn anything new fromobserving the encryption of the message that Aliceactually sent? It may help you to look at Fig. 21.7.

21.4.1 Example: Perfect secrecy in the battlefieldTo understand Definition 21.3, suppose that Alice sends only one oftwo possible messages: “attack” or “retreat”, which we denote by đ‘„0and đ‘„1 respectively, and that she sends each one of those messageswith probability 1/2. Let us put ourselves in the shoes of Eve, theeavesdropping adversary. A priori we would have guessed that Alicesent either đ‘„0 or đ‘„1 with probability 1/2. Now we observe 𝑩 = 𝐾𝑘(đ‘„đ‘–)where 𝑘 is a uniformly chosen key in 0, 1𝑛. How does this newinformation cause us to update our beliefs on whether Alice sent theplaintext đ‘„0 or the plaintext đ‘„1?

PBefore reading the next paragraph, you might wantto try the analysis yourself. You may find it useful tolook at the Wikipedia entry on Bayesian Inference orthese MIT lecture notes.

Let us define 𝑝0(𝑩) to be the probability (taken over 𝑘 ∌ 0, 1𝑛)that 𝑩 = 𝐾𝑘(đ‘„0) and similarly 𝑝1(𝑩) to be Prđ‘˜âˆŒ0,1𝑛 [𝑩 = 𝐾𝑘(đ‘„1)].Note that, since Alice chooses the message to send at random, oura priori probability for observing 𝑩 is 12 𝑝0(𝑩) + 12 𝑝1(𝑩). However,as per Definition 21.3, the perfect secrecy condition guarantees that𝑝0(𝑩) = 𝑝1(𝑩)! Let us denote the number 𝑝0(𝑩) = 𝑝1(𝑩) by 𝑝. By theformula for conditional probability, the probability that Alice sent themessage đ‘„0 conditioned on our observation 𝑩 is simply

Pr[𝑖 = 0|𝑩 = 𝐾𝑘(đ‘„đ‘–)] = Pr[𝑖 = 0 ∧ 𝑩 = 𝐾𝑘(đ‘„đ‘–)]Pr[𝑩 = 𝐾𝑘(đ‘„)] . (21.2)

(The equation (21.2) is a special case of Bayes’ rule which, althougha simple restatement of the formula for conditional probability, isan extremely important and widely used tool in statistics and dataanalysis.)

Since the probability that 𝑖 = 0 and 𝑩 is the ciphertext 𝐾𝑘(0) is equalto 12 ⋅ 𝑝0(𝑩), and the a priori probability of observing 𝑩 is 12 𝑝0(𝑩) +12 𝑝1(𝑩), we can rewrite (21.2) as

Pr[𝑖 = 0|𝑩 = 𝐾𝑘(đ‘„đ‘–)] = 12 𝑝0(𝑩)12 𝑝0(𝑩) + 12 𝑝1(𝑩) = 𝑝𝑝 + 𝑝 = 12 (21.3)

Page 587: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 587

Figure 21.8: A perfectly secret encryption schemefor two-bit keys and messages. The blue verticesrepresent plaintexts and the red vertices representciphertexts, each edge mapping a plaintext đ‘„ to a ci-phertext 𝑩 = 𝐾𝑘(đ‘„) is labeled with the correspondingkey 𝑘. Since there are four possible keys, the degree ofthe graph is four and it is in fact a complete bipartitegraph. The encryption scheme is valid in the sensethat for every 𝑘 ∈ 0, 12, the map đ‘„ ↩ 𝐾𝑘(đ‘„) isone-to-one, which in other words means that the setof edges labeled with 𝑘 is a matching.

using the fact that 𝑝0(𝑩) = 𝑝1(𝑩) = 𝑝. This means that observing theciphertext 𝑩 did not help us at all! We still would not be able to guesswhether Alice sent “attack” or “retreat” with better than 50/50 odds!

This example can be vastly generalized to show that perfect secrecyis indeed “perfect” in the sense that observing a ciphertext gives Eveno additional information about the plaintext beyond her a priori knowl-edge.

21.4.2 Constructing perfectly secret encryptionPerfect secrecy is an extremely strong condition, and implies that aneavesdropper does not learn any information from observing the ci-phertext. You might think that an encryption scheme satisfying such astrong condition will be impossible, or at least extremely complicated,to achieve. However it turns out we can in fact obtain perfectly secretencryption scheme fairly easily. Such a scheme for two-bit messages isillustrated in Fig. 21.8

In fact, this can be generalized to any number of bits:

Theorem 21.4 — One Time Pad (Vernam 1917, Shannon 1949). There is a per-fectly secret valid encryption scheme (𝐾, đ·) with 𝐿(𝑛) = đ¶(𝑛) = 𝑛.

Proof Idea:

Our scheme is the one-time pad also known as the “Vernam Ci-pher”, see Fig. 21.9. The encryption is exceedingly simple: to encrypta message đ‘„ ∈ 0, 1𝑛 with a key 𝑘 ∈ 0, 1𝑛 we simply output đ‘„ ⊕ 𝑘where ⊕ is the bitwise XOR operation that outputs the string corre-sponding to XORing each coordinate of đ‘„ and 𝑘.⋆Proof of Theorem 21.4. For two binary strings 𝑎 and 𝑏 of the samelength 𝑛, we define 𝑎 ⊕ 𝑏 to be the string 𝑐 ∈ 0, 1𝑛 such that𝑐𝑖 = 𝑎𝑖 + 𝑏𝑖 mod 2 for every 𝑖 ∈ [𝑛]. The encryption scheme(𝐾, đ·) is defined as follows: 𝐾𝑘(đ‘„) = đ‘„ ⊕ 𝑘 and đ·đ‘˜(𝑩) = 𝑩 ⊕ 𝑘.By the associative law of addition (which works also modulo two),đ·đ‘˜(𝐾𝑘(đ‘„)) = (đ‘„ ⊕ 𝑘) ⊕ 𝑘 = đ‘„ ⊕ (𝑘 ⊕ 𝑘) = đ‘„ ⊕ 0𝑛 = đ‘„, using the factthat for every bit 𝜎 ∈ 0, 1, 𝜎 + 𝜎 mod 2 = 0 and 𝜎 + 0 = 𝜎 mod 2.Hence (𝐾, đ·) form a valid encryption.

To analyze the perfect secrecy property, we claim that for everyđ‘„ ∈ 0, 1𝑛, the distribution đ‘Œđ‘„ = 𝐾𝑘(đ‘„) where 𝑘 ∌ 0, 1𝑛 is simplythe uniform distribution over 0, 1𝑛, and hence in particular thedistributions đ‘Œđ‘„ and đ‘Œđ‘„â€Č are identical for every đ‘„, đ‘„â€Č ∈ 0, 1𝑛. Indeed,for every particular 𝑩 ∈ 0, 1𝑛, the value 𝑩 is output by đ‘Œđ‘„ if andonly if 𝑩 = đ‘„ ⊕ 𝑘 which holds if and only if 𝑘 = đ‘„ ⊕ 𝑩. Since 𝑘 ischosen uniformly at random in 0, 1𝑛, the probability that 𝑘 happens

Page 588: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

588 introduction to theoretical computer science

Figure 21.9: In the one time pad encryption scheme weencrypt a plaintext đ‘„ ∈ 0, 1𝑛 with a key 𝑘 ∈ 0, 1𝑛by the ciphertext đ‘„ ⊕ 𝑘 where ⊕ denotes the bitwiseXOR operation.

to equal đ‘„ ⊕ 𝑩 is exactly 2−𝑛, which means that every string 𝑩 is outputby đ‘Œđ‘„ with probability 2−𝑛.

PThe argument above is quite simple but is worthreading again. To understand why the one-time padis perfectly secret, it is useful to envision it as a bi-partite graph as we’ve done in Fig. 21.8. (In fact theencryption scheme of Fig. 21.8 is precisely the one-time pad for 𝑛 = 2.) For every 𝑛, the one-time padencryption scheme corresponds to a bipartite graphwith 2𝑛 vertices on the “left side” corresponding to theplaintexts in 0, 1𝑛 and 2𝑛 vertices on the “right side”corresponding to the ciphertexts 0, 1𝑛. For everyđ‘„ ∈ 0, 1𝑛 and 𝑘 ∈ 0, 1𝑛, we connect đ‘„ to the vertex𝑩 = 𝐾𝑘(đ‘„) with an edge that we label with 𝑘. One cansee that this is the complete bipartite graph, whereevery vertex on the left is connected to all vertices onthe right. In particular this means that for every leftvertex đ‘„, the distribution on the ciphertexts obtainedby taking a random 𝑘 ∈ 0, 1𝑛 and going to theneighbor of đ‘„ on the edge labeled 𝑘 is the uniform dis-tribution over 0, 1𝑛. This ensures the perfect secrecycondition.

21.5 NECESSITY OF LONG KEYS

So, does Theorem 21.4 give the final word on cryptography, andmeans that we can all communicate with perfect secrecy and livehappily ever after? No it doesn’t. While the one-time pad is efficient,and gives perfect secrecy, it has one glaring disadvantage: to commu-nicate 𝑛 bits you need to store a key of length 𝑛. In contrast, practicallyused cryptosystems such as AES-128 have a short key of 128 bits (i.e.,16 bytes) that can be used to protect terabytes or more of communica-tion! Imagine that we all needed to use the one time pad. If that wasthe case, then if you had to communicate with 𝑚 people, you wouldhave to maintain (securely!) 𝑚 huge files that are each as long as thelength of the maximum total communication you expect with that per-son. Imagine that every time you opened an account with Amazon,Google, or any other service, they would need to send you in the mail(ideally with a secure courier) a DVD full of random numbers, andevery time you suspected a virus, you’d need to ask all these servicesfor a fresh DVD. This doesn’t sound so appealing.

This is not just a theoretical issue. The Soviets have used the one-time pad for their confidential communication since before the 1940’s.In fact, even before Shannon’s work, the U.S. intelligence already

Page 589: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 589

Figure 21.10: Gene Grabeel, who founded the U.S.Russian SigInt program on 1 Feb 1943. Photo taken in1942, see Page 7 in the Venona historical study.

Figure 21.11: An encryption scheme where the num-ber of keys is smaller than the number of plaintextscorresponds to a bipartite graph where the degree issmaller than the number of vertices on the left side.Together with the validity condition this implies thatthere will be two left vertices đ‘„, đ‘„â€Č with non-identicalneighborhoods, and hence the scheme does not satisfyperfect secrecy.

knew in 1941 that the one-time pad is in principle “unbreakable” (seepage 32 in the Venona document). However, it turned out that thehassle of manufacturing so many keys for all the communication tookits toll on the Soviets and they ended up reusing the same keys formore than one message. They did try to use them for completely dif-ferent receivers in the (false) hope that this wouldn’t be detected. TheVenona Project of the U.S. Army was founded in February 1943 byGene Grabeel (see Fig. 21.10), a former home economics teacher fromMadison Heights, Virgnia and Lt. Leonard Zubko. In October 1943,they had their breakthrough when it was discovered that the Russianswere reusing their keys. In the 37 years of its existence, the project hasresulted in a treasure chest of intelligence, exposing hundreds of KGBagents and Russian spies in the U.S. and other countries, includingJulius Rosenberg, Harry Gold, Klaus Fuchs, Alger Hiss, Harry DexterWhite and many others.

Unfortunately it turns out that such long keys are necessary forperfect secrecy:

Theorem 21.5 — Perfect secrecy requires long keys. For every perfectlysecret encryption scheme (𝐾, đ·) the length function 𝐿 satisfies𝐿(𝑛) ≀ 𝑛.

Proof Idea:

The idea behind the proof is illustrated in Fig. 21.11. We define agraph between the plaintexts and ciphertexts, where we put an edgebetween plaintext đ‘„ and ciphertext 𝑩 if there is some key 𝑘 such that𝑩 = 𝐾𝑘(đ‘„). The degree of this graph is at most the number of potentialkeys. The fact that the degree is smaller than the number of plaintexts(and hence of ciphertexts) implies that there would be two plaintextsđ‘„ and đ‘„â€Č with different sets of neighbors, and hence the distributionof a ciphertext corresponding to đ‘„ (with a random key) will not beidentical to the distribution of a ciphertext corresponding to đ‘„â€Č.⋆Proof of Theorem 21.5. Let 𝐾, đ· be a valid encryption scheme withmessages of length 𝐿 and key of length 𝑛 < 𝐿. We will show that(𝐾, đ·) is not perfectly secret by providing two plaintexts đ‘„0, đ‘„1 ∈0, 1𝐿 such that the distributions đ‘Œđ‘„0 and đ‘Œđ‘„1 are not identical, wheređ‘Œđ‘„ is the distribution obtained by picking 𝑘 ∌ 0, 1𝑛 and outputting𝐾𝑘(đ‘„).

We choose đ‘„0 = 0𝐿. Let 𝑆0 ⊆ 0, 1∗ be the set of all ciphertextsthat have nonzero probability of being output in đ‘Œđ‘„0 . That is, 𝑆0 =𝑩 | ∃𝑘∈0,1𝑛𝑩 = 𝐾𝑘(đ‘„0). Since there are only 2𝑛 keys, we know that|𝑆0| ≀ 2𝑛.

Page 590: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

590 introduction to theoretical computer science

We will show the following claim:Claim I: There exists some đ‘„1 ∈ 0, 1𝐿 and 𝑘 ∈ 0, 1𝑛 such that𝐾𝑘(đ‘„1) ∉ 𝑆0.Claim I implies that the string 𝐾𝑘(đ‘„1) has positive probability of

being output by đ‘Œđ‘„1 and zero probability of being output by đ‘Œđ‘„0 andhence in particular đ‘Œđ‘„0 and đ‘Œđ‘„1 are not identical. To prove Claim I, justchoose a fixed 𝑘 ∈ 0, 1𝑛. By the validity condition, the map đ‘„ ↩𝐾𝑘(đ‘„) is a one to one map of 0, 1𝐿 to 0, 1∗ and hence in particularthe image of this map which is the set đŒđ‘˜ = 𝑩 | âˆƒđ‘„âˆˆ0,1𝐿𝑩 = 𝐾𝑘(đ‘„)has size at least (in fact exactly) 2𝐿. Since |𝑆0| ≀ 2𝑛 < 2𝐿, this meansthat |đŒđ‘˜| > |𝑆0| and so in particular there exists some string 𝑩 in đŒđ‘˜ ⧔ 𝑆0.But by the definition of đŒđ‘˜ this means that there is some đ‘„ ∈ 0, 1𝐿such that 𝐾𝑘(đ‘„) ∉ 𝑆0 which concludes the proof of Claim I and henceof Theorem 21.5.

21.6 COMPUTATIONAL SECRECY

To sum up the previous episodes, we now know that:

‱ It is possible to obtain a perfectly secret encryption scheme with keylength the same as the plaintext.

and

‱ It is not possible to obtain such a scheme with key that is even asingle bit shorter than the plaintext.

How does this mesh with the fact that, as we’ve already seen, peo-ple routinely use cryptosystems with a 16 byte (i.e., 128 bit) key butmany terabytes of plaintext? The proof of Theorem 21.5 does give infact a way to break all these cryptosystems, but an examination of thisproof shows that it only yields an algorithm with time exponential inthe length of the key. This motivates the following relaxation of perfectsecrecy to a condition known as “computational secrecy”. Intuitively,an encryption scheme is computationally secret if no polynomial timealgorithm can break it. The formal definition is below:

Definition 21.6 — Computational secrecy. Let (𝐾, đ·) be a valid encryp-tion scheme where for keys of length 𝑛, the plaintexts are of length𝐿(𝑛) and the ciphertexts are of length 𝑚(𝑛). We say that (𝐾, đ·) iscomputationally secret if for every polynomial 𝑝 ∶ ℕ → ℕ, and large

Page 591: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 591

enough 𝑛, if 𝑃 is an 𝑚(𝑛)-input and single output NAND-CIRCprogram of at most 𝑝(𝑛) lines, and đ‘„0, đ‘„1 ∈ 0, 1𝐿(𝑛) then

∣ đ”Œđ‘˜âˆŒ0,1𝑛[𝑃 (𝐾𝑘(đ‘„0))] − đ”Œđ‘˜âˆŒ0,1𝑛[𝑃 (𝐾𝑘(đ‘„1))]∣ < 1𝑝(𝑛) (21.4)

PDefinition 21.6 requires a second or third read andsome practice to truly understand. One excellent exer-cise to make sure you follow it is to see that if we allow𝑃 to be an arbitrary function mapping 0, 1𝑚(𝑛) to0, 1, and we replace the condition in (21.4) that thelefthand side is smaller than 1𝑝(𝑛) with the conditionthat it is equal to 0 then we get the perfect secrecycondition of Definition 21.3. Indeed if the distributions𝐾𝑘(đ‘„0) and 𝐾𝑘(đ‘„1) are identical then applying anyfunction 𝑃 to them we get the same expectation. Onthe other hand, if the two distributions above give adifferent probability for some element 𝑩∗ ∈ 0, 1𝑚(𝑛),then the function 𝑃(𝑩) that outputs 1 iff 𝑩 = 𝑩∗ willhave a different expectation under the former distribu-tion than under the latter.

Definition 21.6 raises two natural questions:

‱ Is it strong enough to ensure that a computationally secret encryp-tion scheme protects the secrecy of messages that are encryptedwith it?

‱ It is weak enough that, unlike perfect secrecy, it is possible to obtaina computationally secret encryption scheme where the key is muchsmaller than the message?

To the best of our knowledge, the answer to both questions is Yes.This is just one example of a much broader phenomenon. We canuse computational hardness to achieve many cryptographic goals,including some goals that have been dreamed about for millenia, andother goals that people have not even dared to imagine.

Big Idea 27 Computational hardness is necessary and sufficient foralmost all cryptographic applications.

Regarding the first question, it is not hard to show that if, for ex-ample, Alice uses a computationally secret encryption algorithm toencrypt either “attack” or “retreat” (each chosen with probability

Page 592: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

592 introduction to theoretical computer science

Figure 21.12: In a stream cipher or “derandomizedone-time pad” we use a pseudorandom generatorđș ∶ 0, 1𝑛 → 0, 1𝐿 to obtain an encryption schemewith a key length of 𝑛 and plaintexts of length 𝐿.We encrypt the plaintext đ‘„ ∈ 0, 1𝐿 with key𝑘 ∈ 0, 1𝑛 by the ciphertext đ‘„ ⊕ đș(𝑘).

1/2), then as long as she’s restricted to polynomial-time algorithms, anadversary Eve will not be able to guess the message with probabilitybetter than, say, 0.51, even after observing its encrypted form. (Weomit the proof, but it is an excellent exercise for you to work it out onyour own.)

To answer the second question we will show that under the sameassumption we used for derandomizing BPP, we can obtain a com-putationally secret cryptosystem where the key is almost exponentiallysmaller than the plaintext.

21.6.1 Stream ciphers or the “derandomized one-time pad”It turns out that if pseudorandom generators exist as in the optimalPRG conjecture, then there exists a computationally secret encryptionscheme with keys that are much shorter than the plaintext. The con-struction below is known as a stream cipher, though perhaps a bettername is the “derandomized one-time pad”. It is widely used in prac-tice with keys on the order of a few tens or hundreds of bits protectingmany terabytes or even petabytes of communication.

We start by recalling the notion of a pseudorandom generator, as de-fined in Definition 20.9. For this chapter, we will fix a special case ofthe definition:

Definition 21.7 — Cryptographic pseudorandom generator. Let 𝐿 ∶ ℕ → ℕ besome function. A cryptographic pseudorandom generator with stretch𝐿(⋅) is a polynomial-time computable function đș ∶ 0, 1∗ → 0, 1∗such that:

‱ For every 𝑛 ∈ ℕ and 𝑠 ∈ 0, 1𝑛, |đș(𝑠)| = 𝐿(𝑛).‱ For every polynomial 𝑝 ∶ ℕ → ℕ and 𝑛 large enough, if đ¶ is a cir-

cuit of 𝐿(𝑛) inputs, one output, and at most 𝑝(𝑛) gates then∣ Prđ‘ âˆŒ0,1ℓ[đ¶(đș(𝑠)) = 1] − Prđ‘ŸâˆŒ0,1𝑚[đ¶(𝑟) = 1]∣ < 1𝑝(𝑛) . (21.5)

In this chapter we will call a cryptographic pseudorandom gener-ator simply a pseudorandom generator or PRG for short. The optimalPRG conjecture of Section 20.4.2 implies that there is a pseudoran-dom generator that can “fool” circuits of exponential size and wherethe gap in probabilities is at most one over an exponential quantity.Since exponential grow faster than every polynomial, the optimal PRGconjecture implies the following:

The crypto PRG conjecture: For every 𝑎 ∈ ℕ, there is a cryptographicpseudorandom generator with 𝐿(𝑛) = 𝑛𝑎.

Page 593: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 593

The crypto PRG conjecture is a weaker conjecture than the optimalPRG conjecture, but it too (as we will see) is still stronger than theconjecture that P ≠ NP.

Theorem 21.8 — Derandomized one-time pad. Suppose that the cryptoPRG conjecture is true. Then for every constant 𝑎 ∈ ℕ there is acomputationally secret encryption scheme (𝐾, đ·) with plaintextlength 𝐿(𝑛) at least 𝑛𝑎.

Proof Idea:

The proof is illustrated in Fig. 21.12. We simply take the one-timepad on 𝐿 bit plaintexts, but replace the key with đș(𝑘) where 𝑘 is astring in 0, 1𝑛 and đș ∶ 0, 1𝑛 → 0, 1𝐿 is a pseudorandom gen-erator. Since the one time pad cannot be broken, an adversary thatbreaks the derandomized one-time pad can be used to distinguishbetween the output of the pseudorandom generator and the uniformdistribution.⋆Proof of Theorem 21.8. Let đș ∶ 0, 1𝑛 → 0, 1𝐿 for 𝐿 = 𝑛𝑎 be therestriction to input length 𝑛 of the pseudorandom generator đș whoseexistence we are guaranteed from the crypto PRG conjecture. Wenow define our encryption scheme as follows: given key 𝑘 ∈ 0, 1𝑛and plaintext đ‘„ ∈ 0, 1𝐿, the encryption 𝐾𝑘(đ‘„) is simply đ‘„ ⊕ đș(𝑘).To decrypt a string 𝑩 ∈ 0, 1𝑚 we output 𝑩 ⊕ đș(𝑘). This is a validencryption since đș is computable in polynomial time and (đ‘„ ⊕ đș(𝑘)) ⊕đș(𝑘) = đ‘„ ⊕ (đș(𝑘) ⊕ đș(𝑘)) = đ‘„ for every đ‘„ ∈ 0, 1𝐿.

Computational secrecy follows from the condition of a pseudo-random generator. Suppose, towards a contradiction, that there isa polynomial 𝑝, NAND-CIRC program 𝑄 of at most 𝑝(𝐿) lines andđ‘„, đ‘„â€Č ∈ 0, 1𝐿(𝑛) such that∣ đ”Œđ‘˜âˆŒ0,1𝑛[𝑄(𝐾𝑘(đ‘„))] − đ”Œđ‘˜âˆŒ0,1𝑛[𝑄(𝐾𝑘(đ‘„â€Č))]∣ > 1𝑝(𝐿) . (21.6)

(We use here the simple fact that for a 0, 1-valued random variable𝑋, Pr[𝑋 = 1] = đ”Œ[𝑋].)By the definition of our encryption scheme, this means that∣ đ”Œđ‘˜âˆŒ0,1𝑛[𝑄(đș(𝑘) ⊕ đ‘„)] − đ”Œđ‘˜âˆŒ0,1𝑛[𝑄(đș(𝑘) ⊕ đ‘„â€Č)]∣ > 1𝑝(𝐿) . (21.7)

Now since (as we saw in the security analysis of the one-time pad),for every strings đ‘„, đ‘„â€Č ∈ 0, 1𝐿, the distribution 𝑟 ⊕ đ‘„ and 𝑟 ⊕ đ‘„â€Č areidentical, where 𝑟 ∌ 0, 1𝐿. Henceđ”Œđ‘ŸâˆŒ0,1𝐿[𝑄(𝑟 ⊕ đ‘„)] = đ”Œđ‘ŸâˆŒ0,1𝐿[𝑄(𝑟 ⊕ đ‘„â€Č)] . (21.8)

Page 594: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

594 introduction to theoretical computer science

By plugging (21.8) into (21.7) we can derive that∣ đ”Œđ‘˜âˆŒ0,1𝑛[𝑄(đș(𝑘) ⊕ đ‘„)] − đ”Œđ‘ŸâˆŒ0,1𝐿[𝑄(𝑟 ⊕ đ‘„)] + đ”Œđ‘ŸâˆŒ0,1𝐿[𝑄(𝑟 ⊕ đ‘„â€Č)] − đ”Œđ‘˜âˆŒ0,1𝑛[𝑄(đș(𝑘) ⊕ đ‘„â€Č)]∣ > 1𝑝(𝐿) .(21.9)

(Please make sure that you can see why this is true.)Now we can use the triangle inequality that |𝐮 + đ”| ≀ |𝐮| + |đ”| for

every two numbers 𝐮, đ”, applying it for 𝐮 = đ”Œđ‘˜âˆŒ0,1𝑛 [𝑄(đș(𝑘) ⊕ đ‘„)] âˆ’đ”Œđ‘ŸâˆŒ0,1𝐿 [𝑄(đ‘ŸâŠ•đ‘„)] and đ” = đ”Œđ‘ŸâˆŒ0,1𝐿 [𝑄(đ‘ŸâŠ•đ‘„â€Č)]âˆ’đ”Œđ‘˜âˆŒ0,1𝑛 [𝑄(đș(𝑘)âŠ•đ‘„â€Č)]to derive∣ đ”Œđ‘˜âˆŒ0,1𝑛[𝑄(đș(𝑘) ⊕ đ‘„)] − đ”Œđ‘ŸâˆŒ0,1𝐿[𝑄(𝑟 ⊕ đ‘„)]∣+∣ đ”Œđ‘ŸâˆŒ0,1𝐿[𝑄(𝑟 ⊕ đ‘„â€Č)] − đ”Œđ‘˜âˆŒ0,1𝑛[𝑄(đș(𝑘) ⊕ đ‘„â€Č)]∣ > 1𝑝(𝐿) .

(21.10)In particular, either the first term or the second term of the

lefthand-side of (21.10) must be at least 12𝑝(𝐿) . Let us assume the firstcase holds (the second case is analyzed in exactly the same way).Then we get that∣ đ”Œđ‘˜âˆŒ0,1𝑛[𝑄(đș(𝑘) ⊕ đ‘„)] − đ”Œđ‘ŸâˆŒ0,1𝐿[𝑄(𝑟 ⊕ đ‘„)]∣ > 12𝑝(𝐿) . (21.11)

But if we now define the NAND-CIRC program đ‘ƒđ‘„ that on input𝑟 ∈ 0, 1𝐿 outputs 𝑄(đ‘ŸâŠ•đ‘„) then (since XOR of 𝐿 bits can be computedin 𝑂(𝐿) lines), we get that đ‘ƒđ‘„ has 𝑝(𝐿) + 𝑂(𝐿) lines and by (21.11) itcan distinguish between an input of the form đș(𝑘) and an input of theform 𝑟 ∌ 0, 1𝑘 with advantage better than 12𝑝(𝐿) . Since a polynomialis dominated by an exponential, if we make 𝐿 large enough, this willcontradict the (2𝛿𝑛, 2−𝛿𝑛) security of the pseudorandom generator đș.

RRemark 21.9 — Stream ciphers in practice. The twomost widely used forms of (private key) encryptionschemes in practice are stream ciphers and block ciphers.(To make things more confusing, a block cipher isalways used in some mode of operation and someof these modes effectively turn a block cipher intoa stream cipher.) A block cipher can be thought asa sort of a “random invertible map” from 0, 1𝑛 to0, 1𝑛, and can be used to construct a pseudorandomgenerator and from it a stream cipher, or to encryptdata directly using other modes of operations. Thereare a great many other security notions and consider-ations for encryption schemes beyond computationalsecrecy. Many of those involve handling scenariossuch as chosen plaintext, man in the middle, and cho-sen ciphertext attacks, where the adversary is not justmerely a passive eavesdropper but can influence thecommunication in some way. While this chapter is

Page 595: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 595

meant to give you some taste of the ideas behind cryp-tography, there is much more to know before applyingit correctly to obtain secure applications, and a greatmany people have managed to get it wrong.

21.7 COMPUTATIONAL SECRECY AND NPWe’ve also mentioned before that an efficient algorithm for NP couldbe used to break all cryptography. We now give an example of howthis can be done:

Theorem 21.10 — Breaking encryption using NP algorithm. If P = NPthen there is no computationally secret encryption scheme with𝐿(𝑛) > 𝑛.

Furthermore, for every valid encryption scheme (𝐾, đ·) with𝐿(𝑛) > 𝑛 + 100 there is a polynomial 𝑝 such that for every largeenough 𝑛 there exist đ‘„0, đ‘„1 ∈ 0, 1𝐿(𝑛) and a 𝑝(𝑛)-line NAND-CIRC program EVE s.t.

Prđ‘–âˆŒ0,1,đ‘˜âˆŒ0,1𝑛[EVE(𝐾𝑘(đ‘„đ‘–)) = 𝑖] ≄ 0.99 . (21.12)

Note that the “furthermore” part is extremely strong. It meansthat if the plaintext is even a little bit larger than the key, then we canalready break the scheme in a very strong way. That is, there will bea pair of messages đ‘„0, đ‘„1 (think of đ‘„0 as “sell” and đ‘„1 as “buy”) andan efficient strategy for Eve such that if Eve gets a ciphertext 𝑩 thenshe will be able to tell whether 𝑩 is an encryption of đ‘„0 or đ‘„1 withprobability very close to 1. (We model breaking the scheme as Eveoutputting 0 or 1 corresponding to whether the message sent was đ‘„0or đ‘„1. Note that we could have just as well modified Eve to output đ‘„0instead of 0 and đ‘„1 instead of 1. The key point is that a priori Eve onlyhad a 50/50 chance of guessing whether Alice sent đ‘„0 or đ‘„1 but afterseeing the ciphertext this chance increases to better than 99/1.) Thecondition P = NP can be relaxed to NP ⊆ BPP and even the weakercondition NP ⊆ P/poly with essentially the same proof.Proof Idea:

The proof follows along the lines of Theorem 21.5 but this timepaying attention to the computational aspects. If P = NP then forevery plaintext đ‘„ and ciphertext 𝑩, we can efficiently tell whether thereexists 𝑘 ∈ 0, 1𝑛 such that 𝐾𝑘(đ‘„) = 𝑩. So, to prove this result we needto show that if the plaintexts are long enough, there would exist a pairđ‘„0, đ‘„1 such that the probability that a random encryption of đ‘„1 also isa valid encryption of đ‘„0 will be very small. The details of how to showthis are below.

Page 596: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

596 introduction to theoretical computer science

⋆Proof of Theorem 21.10. We focus on showing only the “furthermore”part since it is the more interesting and the other part follows by es-sentially the same proof.

Suppose that (𝐾, đ·) is such an encryption, let 𝑛 be large enough,and let đ‘„0 = 0𝐿(𝑛). For every đ‘„ ∈ 0, 1𝐿(𝑛) we define đ‘†đ‘„ to be the setof all valid encryption of đ‘„. That is đ‘†đ‘„ = 𝑩 | ∃𝑘∈0,1𝑛𝑩 = 𝐾𝑘(đ‘„). Asin the proof of Theorem 21.5, since there are 2𝑛 keys 𝑘, |đ‘†đ‘„| ≀ 2𝑛 forevery đ‘„ ∈ 0, 1𝐿(𝑛).

We denote by 𝑆0 the set đ‘†đ‘„0 . We define our algorithm EVE to out-put 0 on input 𝑩 ∈ 0, 1∗ if 𝑩 ∈ 𝑆0 and to output 1 otherwise. Thiscan be implemented in polynomial time if P = NP, since the key 𝑘can serve the role of an efficiently verifiable solution. (Can you seewhy?) Clearly Pr[EVE(𝐾𝑘(đ‘„0)) = 0] = 1 and so in the case that EVEgets an encryption of đ‘„0 then she guesses correctly with probability1. The remainder of the proof is devoted to showing that there ex-ists đ‘„1 ∈ 0, 1𝐿(𝑛) such that Pr[EVE(𝐾𝑘(đ‘„1)) = 0] ≀ 0.01, whichwill conclude the proof by showing that EVE guesses wrongly withprobability at most 12 0 + 12 0.01 < 0.01.

Consider now the following probabilistic experiment (which wedefine solely for the sake of analysis). We consider the sample spaceof choosing đ‘„ uniformly in 0, 1𝐿(𝑛) and define the random variable𝑍𝑘(đ‘„) to equal 1 if and only if 𝐾𝑘(đ‘„) ∈ 𝑆0. For every 𝑘, the map đ‘„ ↩𝐾𝑘(đ‘„) is one-to-one, which means that the probability that 𝑍𝑘 = 1is equal to the probability that đ‘„ ∈ 𝐾−1𝑘 (𝑆0) which is |𝑆0|2𝐿(𝑛) . So by thelinearity of expectation đ”Œ[∑𝑘∈0,1𝑛 𝑍𝑘] ≀ 2𝑛|𝑆0|2𝐿(𝑛) ≀ 22𝑛2𝐿(𝑛) .

We will now use the following extremely simple but useful factknown as the averaging principle (see also Lemma 18.10): for everyrandom variable 𝑍, if đ”Œ[𝑍] = 𝜇, then with positive probability 𝑍 ≀ 𝜇.(Indeed, if 𝑍 > 𝜇 with probability one, then the expected value of 𝑍will have to be larger than 𝜇, just like you can’t have a class in whichall students got A or A- and yet the overall average is B+.) In our caseit means that with positive probability ∑𝑘∈0,1𝑛 𝑍𝑘 ≀ 22𝑛2𝐿(𝑛) . In otherwords, there exists some đ‘„1 ∈ 0, 1𝐿(𝑛) such that ∑𝑘∈0,1𝑛 𝑍𝑘(đ‘„1) ≀22𝑛2𝐿(𝑛) . Yet this means that if we choose a random 𝑘 ∌ 0, 1𝑛, thenthe probability that 𝐾𝑘(đ‘„1) ∈ 𝑆0 is at most 12𝑛 ⋅ 22𝑛2𝐿(𝑛) = 2𝑛−𝐿(𝑛).So, in particular if we have an algorithm EVE that outputs 0 if đ‘„ ∈𝑆0 and outputs 1 otherwise, then Pr[EVE(𝐾𝑘(đ‘„0)) = 0] = 1 andPr[EVE(𝐾𝑘(đ‘„1)) = 0] ≀ 2𝑛−𝐿(𝑛) which will be smaller than 2−10 < 0.01if 𝐿(𝑛) ≄ 𝑛 + 10.

Page 597: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 597

In retrospect Theorem 21.10 is perhaps not surprising. After all, aswe’ve mentioned before it is known that the Optimal PRG conjecture(which is the basis for the derandomized one-time pad encryption) isfalse if P = NP (and in fact even if NP ⊆ BPP or even NP ⊆ P/poly).21.8 PUBLIC KEY CRYPTOGRAPHY

People have been dreaming about heavier-than-air flight since at leastthe days of Leonardo Da Vinci (not to mention Icarus from the greekmythology). Jules Verne wrote with rather insightful details aboutgoing to the moon in 1865. But, as far as I know, in all the thousandsof years people have been using secret writing, until about 50 yearsago no one has considered the possibility of communicating securelywithout first exchanging a shared secret key.

Yet in the late 1960’s and early 1970’s, several people started toquestion this “common wisdom”. Perhaps the most surprising ofthese visionaries was an undergraduate student at Berkeley namedRalph Merkle. In the fall of 1974 Merkle wrote in a project proposalfor his computer security course that while “it might seem intuitivelyobvious that if two people have never had the opportunity to prear-range an encryption method, then they will be unable to communicatesecurely over an insecure channel
 I believe it is false”. The projectproposal was rejected by his professor as “not good enough”. Merklelater submitted a paper to the communication of the ACM where heapologized for the lack of references since he was unable to find anymention of the problem in the scientific literature, and the only sourcewhere he saw the problem even raised was in a science fiction story.The paper was rejected with the comment that “Experience shows thatit is extremely dangerous to transmit key information in the clear.”Merkle showed that one can design a protocol where Alice and Bobcan use 𝑇 invocations of a hash function to exchange a key, but anadversary (in the random oracle model, though he of course didn’tuse this name) would need roughly 𝑇 2 invocations to break it. Heconjectured that it may be possible to obtain such protocols wherebreaking is exponentially harder than using them, but could not think ofany concrete way to doing so.

We only found out much later that in the late 1960’s, a few yearsbefore Merkle, James Ellis of the British Intelligence agency GCHQwas having similar thoughts. His curiosity was spurred by an oldWorld-War II manuscript from Bell labs that suggested the followingway that two people could communicate securely over a phone line.Alice would inject noise to the line, Bob would relay his messages,and then Alice would subtract the noise to get the signal. The idea isthat an adversary over the line sees only the sum of Alice’s and Bob’ssignals, and doesn’t know what came from what. This got James Ellis

Page 598: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

598 introduction to theoretical computer science

thinking whether it would be possible to achieve something like thatdigitally. As Ellis later recollected, in 1970 he realized that in princi-ple this should be possible, since he could think of an hypotheticalblack box đ” that on input a “handle” đ›Œ and plaintext đ‘„ would give a“ciphertext” 𝑩 and that there would be a secret key đ›œ correspondingto đ›Œ, such that feeding đ›œ and 𝑩 to the box would recover đ‘„. However,Ellis had no idea how to actually instantiate this box. He and otherskept giving this question as a puzzle to bright new recruits until oneof them, Clifford Cocks, came up in 1973 with a candidate solutionloosely based on the factoring problem; in 1974 another GCHQ re-cruit, Malcolm Williamson, came up with a solution using modularexponentiation.

But among all those thinking of public key cryptography, probablythe people who saw the furthest were two researchers at Stanford,Whit Diffie and Martin Hellman. They realized that with the adventof electronic communication, cryptography would find new applica-tions beyond the military domain of spies and submarines, and theyunderstood that in this new world of many users and point to pointcommunication, cryptography will need to scale up. Diffie and Hell-man envisioned an object which we now call “trapdoor permutation”though they called “one way trapdoor function” or sometimes simply“public key encryption”. Though they didn’t have full formal defini-tions, their idea was that this is an injective function that is easy (e.g.,polynomial-time) to compute but hard (e.g., exponential-time) to in-vert. However, there is a certain trapdoor, knowledge of which wouldallow polynomial time inversion. Diffie and Hellman argued that us-ing such a trapdoor function, it would be possible for Alice and Bobto communicate securely without ever having exchanged a secret key. Butthey didn’t stop there. They realized that protecting the integrity ofcommunication is no less important than protecting its secrecy. Thusthey imagined that Alice could “run encryption in reverse” in order tocertify or sign messages.

At the point, Diffie and Hellman were in a position not unlikephysicists who predicted that a certain particle should exist but with-out any experimental verification. Luckily they met Ralph Merkle,and his ideas about a probabilistic key exchange protocol, together witha suggestion from their Stanford colleague John Gill, inspired themto come up with what today is known as the Diffie Hellman Key Ex-change (which unbeknownst to them was found two years earlier atGCHQ by Malcolm Williamson). They published their paper “NewDirections in Cryptography” in 1976, and it is considered to havebrought about the birth of modern cryptography.

The Diffie-Hellman Key Exchange is still widely used today forsecure communication. However, it still felt short of providing Diffie

Page 599: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 599

Figure 21.13: Top left: Ralph Merkle, Martin Hellmanand Whit Diffie, who together came up in 1976with the concept of public key encryption and a keyexchange protocol. Bottom left: Adi Shamir, Ron Rivest,and Leonard Adleman who, following Diffie andHellman’s paper, discovered the RSA function thatcan be used for public key encryption and digitalsignatures. Interestingly, one can see the equationP = NP on the blackboard behind them. Right: JohnGill, who was the first person to suggest to Diffie andHellman that they use modular exponentiation as aneasy-to-compute but hard-to-invert function.

Figure 21.14: In a public key encryption, Alice generatesa private/public keypair (𝑒, 𝑑), publishes 𝑒 and keeps𝑑 secret. To encrypt a message for Alice, one onlyneeds to know 𝑒. To decrypt it we need to know 𝑑.

and Hellman’s elusive trapdoor function. This was done the next yearby Rivest, Shamir and Adleman who came up with the RSA trapdoorfunction, which through the framework of Diffie and Hellman yieldednot just encryption but also signatures. (A close variant of the RSAfunction was discovered earlier by Clifford Cocks at GCHQ, thoughas far as I can tell Cocks, Ellis and Williamson did not realize theapplication to digital signatures.) From this point on began a flurry ofadvances in cryptography which hasn’t died down till this day.

21.8.1 Defining public key encryptionA public key encryption consists of a triple of algorithms:

‱ The key generation algorithm, which we denote by đŸđ‘’đ‘Šđș𝑒𝑛 or KG forshort, is a randomized algorithm that outputs a pair of strings (𝑒, 𝑑)where 𝑒 is known as the public (or encryption) key, and 𝑑 is knownas the private (or decryption) key. The key generation algorithm getsas input 1𝑛 (i.e., a string of ones of length 𝑛). We refer to 𝑛 as thesecurity parameter of the scheme. The bigger we make 𝑛, the moresecure the encryption will be, but also the less efficient it will be.

‱ The encryption algorithm, which we denote by 𝐾, takes the encryp-tion key 𝑒 and a plaintext đ‘„, and outputs the ciphertext 𝑩 = 𝐾𝑒(đ‘„).

‱ The decryption algorithm, which we denote by đ·, takes the decryp-tion key 𝑑 and a ciphertext 𝑩, and outputs the plaintext đ‘„ = đ·đ‘‘(𝑩).We now make this a formal definition:

Definition 21.11 — Public Key Encryption. A computationally secret publickey encryption with plaintext length 𝐿 ∶ ℕ → ℕ is a triple of ran-domized polynomial-time algorithms (KG, 𝐾, đ·) that satisfy thefollowing conditions:

‱ For every 𝑛, if (𝑒, 𝑑) is output by KG(1𝑛) with positive proba-bility, and đ‘„ ∈ 0, 1𝐿(𝑛), then đ·đ‘‘(𝐾𝑒(đ‘„)) = đ‘„ with probabilityone.

‱ For every polynomial 𝑝, and sufficiently large 𝑛, if 𝑃 is a NAND-CIRC program of at most 𝑝(𝑛) lines then for every đ‘„, đ‘„â€Č ∈0, 1𝐿(𝑛), |đ”Œ[𝑃 (𝑒, 𝐾𝑒(đ‘„))] − đ”Œ[𝑃 (𝑒, 𝐾𝑒(đ‘„â€Č))]| < 1/𝑝(𝑛), wherethis probability is taken over the coins of KG and 𝐾.

Definition 21.11 allows 𝐾 and đ· to be randomized algorithms. Infact, it turns out that it is necessary for 𝐾 to be randomized to obtaincomputational secrecy. It also turns out that, unlike the private keycase, we can transform a public-key encryption that works for mes-sages that are only one bit long into a public-key encryption scheme

Page 600: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

600 introduction to theoretical computer science

that can encrypt arbitrarily long messages, and in particular messagesthat are longer than the key. In particular this means that we cannot ob-tain a perfectly secret public-key encryption scheme even for one-bitlong messages (since it would imply a perfectly secret public-key, andhence in particular private-key, encryption with messages longer thanthe key).

We will not give full constructions for public key encryptionschemes in this chapter, but will mention some of the ideas thatunderlie the most widely used schemes today. These generally belongto one of two families:

‱ Group theoretic constructions based on problems such as integer factor-ing and the discrete logarithm over finite fields or elliptic curves.

‱ Lattice/coding based constructions based on problems such as theclosest vector in a lattice or bounded distance decoding.

Group-theory based encryptions such as the RSA cryptosystem, theDiffie-Hellman protocol, and Elliptic-Curve Cryptography, are cur-rently more widely implemented. But the lattice/coding schemes arerecently on the rise, particularly because the known group theoreticencryption schemes can be broken by quantum computers, which wediscuss in Chapter 23.

21.8.2 Diffie-Hellman key exchangeAs just one example of how public key encryption schemes are con-structed, let us now describe the Diffie-Hellman key exchange. Wedescribe the Diffie-Hellman protocol in a somewhat of an informallevel, without presenting a full security analysis.

The computational problem underlying the Diffie Hellman protocolis the discrete logarithm problem. Let’s suppose that 𝑔 is some integer.We can compute the map đ‘„ ↩ đ‘”đ‘„ and also its inverse 𝑩 ↩ log𝑔 𝑩. (Forexample, we can compute a logarithm is by binary search: start withsome interval [đ‘„đ‘šđ‘–đ‘›, đ‘„đ‘šđ‘Žđ‘„] that is guaranteed to contain log𝑔 𝑩. We canthen test whether the interval’s midpoint đ‘„đ‘šđ‘–đ‘‘ satisfies đ‘”đ‘„đ‘šđ‘–đ‘‘ > 𝑩, andbased on that halve the size of the interval.)

However, suppose now that we use modular arithmetic and workmodulo some prime number 𝑝. If 𝑝 has 𝑛 binary digits and 𝑔 is in [𝑝]then we can compute the map đ‘„ ↩ đ‘”đ‘„ mod 𝑝 in time polynomial in 𝑛.(This is not trivial, and is a great exercise for you to work this out; as ahint, start by showing that one can compute the map 𝑘 ↩ 𝑔2𝑘 mod 𝑝using 𝑘 modular multiplications modulo 𝑝, if you’re stumped, youcan look up this Wikipedia entry.) On the other hand, because of the“wraparound” property of modular arithmetic, we cannot run binarysearch to find the inverse of this map (known as the discrete logarithm).

Page 601: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 601

In fact, there is no known polynomial-time algorithm for computingthis discrete logarithm map (𝑔, đ‘„, 𝑝) ↩ log𝑔 đ‘„ mod 𝑝, where we definelog𝑔 đ‘„ mod 𝑝 as the number 𝑎 ∈ [𝑝] such that 𝑔𝑎 = đ‘„ mod 𝑝.

The Diffie-Hellman protocol for Bob to send a message to Alice is asfollows:

‱ Alice: Chooses 𝑝 to be a random 𝑛 bit long prime (which can bedone by choosing random numbers and running a primality testingalgorithm on them), and 𝑔 and 𝑎 at random in [𝑝]. She sends to Bobthe triple (𝑝, 𝑔, 𝑔𝑎 mod 𝑝).

‱ Bob: Given the triple (𝑝, 𝑔, ℎ), Bob sends a message đ‘„ ∈ 0, 1𝐿to Alice by choosing 𝑏 at random in [𝑝], and sending to Alice thepair (𝑔𝑏 mod 𝑝, 𝑟𝑒𝑝(ℎ𝑏 mod 𝑝) ⊕ đ‘„) where 𝑟𝑒𝑝 ∶ [𝑝] → 0, 1∗is some “representation function” that maps [𝑝] to 0, 1𝐿. (Thefunction 𝑟𝑒𝑝 does not need to be one-to-one and you can think of𝑟𝑒𝑝(𝑧) as simply outputting 𝐿 of the bits of 𝑧 in the natural binaryrepresentation, it does need to satisfy certain technical conditionswhich we omit in this description.)

‱ Alice: Given 𝑔â€Č, 𝑧, Alice recovers đ‘„ by outputting 𝑟𝑒𝑝(𝑔â€Č𝑎 mod 𝑝) ⊕𝑧.The correctness of the protocol follows from the simple fact that(𝑔𝑎)𝑏 = (𝑔𝑏)𝑎 for every 𝑔, 𝑎, 𝑏 and this still holds if we work modulo𝑝. Its security relies on the computational assumption that computing

this map is hard, even in a certain “average case” sense (this computa-tional assumption is known as the Decisional Diffie Hellman assump-tion). The Diffie-Hellman key exchange protocol can be thought of asa public key encryption where the Alice’s first message is the publickey, and Bob’s message is the encryption.

One can think of the Diffie-Hellman protocol as being based ona “trapdoor pseudorandom generator” whereas the triple 𝑔𝑎, 𝑔𝑏, 𝑔𝑎𝑏looks “random” to someone that doesn’t know 𝑎, but someone thatdoes know 𝑎 can see that raising the second element to the 𝑎-th poweryields the third element. The Diffie-Hellman protocol can be describedabstractly in the context of any finite Abelian group for which we canefficiently compute the group operation. It has been implementedon other groups than numbers modulo 𝑝, and in particular EllipticCurve Cryptography (ECC) is obtained by basing the Diffie Hell-man on elliptic curve groups which gives some practical advantages.Another common group theoretic basis for key-exchange/public keyencryption protocol is the RSA function. A big disadvantage of Diffie-Hellman (both the modular arithmetic and elliptic curve variants)and RSA is that both schemes can be broken in polynomial time by a

Page 602: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

602 introduction to theoretical computer science

quantum computer. We will discuss quantum computing later in thiscourse.

21.9 OTHER SECURITY NOTIONS

There is a great deal to cryptography beyond just encryption schemes,and beyond the notion of a passive adversary. A central objectiveis integrity or authentication: protecting communications from beingmodified by an adversary. Integrity is often more fundamental thansecrecy: whether it is a software update or viewing the news, youmight often not care about the communication being secret as much asthat it indeed came from its claimed source. Digital signature schemesare the analog of public key encryption for authentication, and arewidely used (in particular as the basis for public key certificates) toprovide a foundation of trust in the digital world.

Similarly, even for encryption, we often need to ensure securityagainst active attacks, and so notions such as non-malleability andadaptive chosen ciphertext security have been proposed. An encryp-tion scheme is only as secure as the secret key, and mechanisms tomake sure the key is generated properly, and is protected against re-fresh or even compromise (i.e., forward secrecy) have been studied aswell. Hopefully this chapter provides you with some appreciation forcryptography as an intellectual field, but does not imbue you with afalse self confidence in implementing it.

Cryptographic hash functions is another widely used tool with a va-riety of uses, including extracting randomness from high entropysources, achieving hard-to-forge short “digests” of files, protectingpasswords, and much more.

21.10 MAGIC

Beyond encryption and signature schemes, cryptographers have man-aged to obtain objects that truly seem paradoxical and “magical”. Webriefly discuss some of these objects. We do not give any details, buthopefully this will spark your curiosity to find out more.

21.10.1 Zero knowledge proofsOn October 31, 1903, the mathematician Frank Nelson Cole,gave an hourlong lecture to a meeting of the American Mathe-matical Society where he did not speak a single word. Rather,he calculated on the board the value 267 − 1 which is equal to147, 573, 952, 589, 676, 412, 927, and then showed that this number isequal to 193, 707, 721 × 761, 838, 257, 287. Cole’s proof showed that267 − 1 is not a prime, but it also revealed additional information,namely its actual factors. This is often the case with proofs: they teachus more than just the validity of the statements.

Page 603: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 603

In Zero Knowledge Proofs we try to achieve the opposite effect. Wewant a proof for a statement 𝑋 where we can rigorously show that theproofs reveals absolutely no additional information about 𝑋 beyond thefact that it is true. This turns out to be an extremely useful object fora variety of tasks including authentication, secure protocols, voting,anonymity in cryptocurrencies, and more. Constructing these ob-jects relies on the theory of NP completeness. Thus this theory thatoriginally was designed to give a negative result (show that some prob-lems are hard) ended up yielding positive applications, enabling us toachieve tasks that were not possible otherwise.

21.10.2 Fully homomorphic encryptionSuppose that we are given a bit-by-bit encryption of a string𝐾𝑘(đ‘„0), 
 , 𝐾𝑘(đ‘„đ‘›âˆ’1). By design, these ciphertexts are supposed tobe “completely unscrutable” and we should not be able to extractany information about đ‘„đ‘–â€™s from it. However, already in 1978, Rivest,Adleman and Dertouzos observed that this does not imply that wecould not manipulate these encryptions. For example, it turns out thesecurity of an encryption scheme does not immediately rule out theability to take a pair of encryptions 𝐾𝑘(𝑎) and 𝐾𝑘(𝑏) and computefrom them 𝐾𝑘(𝑎NAND𝑏) without knowing the secret key 𝑘. But do thereexist encryption schemes that allow such manipulations? And if so, isthis a bug or a feature?

Rivest et al already showed that such encryption schemes couldbe immensely useful, and their utility has only grown in the age ofcloud computing. After all, if we can compute NAND then we canuse this to run any algorithm 𝑃 on the encrypted data, and map𝐾𝑘(đ‘„0), 
 , 𝐾𝑘(đ‘„đ‘›âˆ’1) to 𝐾𝑘(𝑃 (đ‘„0, 
 , đ‘„đ‘›âˆ’1)). For example, a clientcould store their secret data đ‘„ in encrypted form on the cloud, andhave the cloud provider perform all sorts of computation on thesedata without ever revealing to the provider the private key, and sowithout the provider ever learning any information about the secretdata.

The question of existence of such a scheme took much longer timeto resolve. Only in 2009 Craig Gentry gave the first construction ofan encryption scheme that allows to compute a universal basis ofgates on the data (known as a Fully Homomorphic Encryption scheme incrypto parlance). Gentry’s scheme left much to be desired in terms ofefficiency, and improving upon it has been the focus of an intensiveresearch program that has already seen significant improvements.

21.10.3 Multiparty secure computationCryptography is about enabling mutually distrusting parties toachieve a common goal. Perhaps the most general primitive achiev-

Page 604: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

604 introduction to theoretical computer science

ing this objective is secure multiparty computation. The idea in securemultiparty computation is that 𝑛 parties interact together to computesome function đč(đ‘„0, 
 , đ‘„đ‘›âˆ’1) where đ‘„đ‘– is the private input of the 𝑖-thparty. The crucial point is that there is no commonly trusted party orauthority and that nothing is revealed about the secret data beyond thefunction’s output. One example is an electronic voting protocol whereonly the total vote count is revealed, with the privacy of the individualvoters protected, but without having to trust any authority to eithercount the votes correctly or to keep information confidential. Anotherexample is implementing a second price (aka Vickrey) auction where𝑛 − 1 parties submit bids to an item owned by the 𝑛-th party, and theitem goes to the highest bidder but at the price of the second highest bid.Using secure multiparty computation we can implement second priceauction in a way that will ensure the secrecy of the numerical valuesof all bids (including even the top one) except the second highest one,and the secrecy of the identity of all bidders (including even the sec-ond highest bidder) except the top one. We emphasize that such aprotocol requires no trust even in the auctioneer itself, that will alsonot learn any additional information. Secure multiparty computationcan be used even for computing randomized processes, with one exam-ple being playing Poker over the net without having to trust any serverfor correct shuffling of cards or not revealing the information.

Chapter Recap

‱ We can formally define the notion of security of anencryption scheme.

‱ Perfect secrecy ensures that an adversary does notlearn anything about the plaintext from the cipher-text, regardless of their computational powers.

‱ The one-time pad is a perfectly secret encryptionwith the length of the key equaling the length ofthe message. No perfectly secret encryption canhave key shorter than the message.

‱ Computational secrecy can be as good as perfectsecrecy since it ensures that the advantage thatcomputationally bounded adversaries gain fromobserving the ciphertext is exponentially small. Ifthe optimal PRG conjecture is true then there existsa computationally secret encryption scheme withmessages that can be (almost) exponentially biggerthan the key.

‱ There are many cryptographic tools that go well be-yond private key encryption. These include publickey encryption, digital signatures and hash functions,as well as more “magical” tools such as multipartysecure computation, fully homomorphic encryption, zeroknowledge proofs, and many others.

Page 605: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

cryptography 605

21.11 EXERCISES

21.12 BIBLIOGRAPHICAL NOTES

Much of this text is taken from my lecture notes on cryptography.Shannon’s manuscript was written in 1945 but was classified, and a

partial version was only published in 1949. Still it has revolutionizedcryptography, and is the forerunner to much of what followed.

The Venona project’s history is described in this document. Asidefrom Grabeel and Zubko, credit to the discovery that the Soviets werereusing keys is shared by Lt. Richard Hallock, Carrie Berry, FrankLewis, and Lt. Karl Elmquist, and there are others that have madeimportant contribution to this project. See pages 27 and 28 in thedocument.

In a 1955 letter to the NSA that only recently came forward, JohnNash proposed an “unbreakable” encryption scheme. He wrote “Ihope my handwriting, etc. do not give the impression I am just a crank orcircle-squarer
. The significance of this conjecture [that certain encryptionschemes are exponentially secure against key recovery attacks] .. is that it isquite feasible to design ciphers that are effectively unbreakable.”. John Nashmade seminal contributions in mathematics and game theory, and wasawarded both the Abel Prize in mathematics and the Nobel MemorialPrize in Economic Sciences. However, he has struggled with mentalillness throughout his life. His biography, A Beautiful Mind was madeinto a popular movie. It is natural to compare Nash’s 1955 letter to theNSA to Gödel’s letter to von Neumann we mentioned before. Fromthe theoretical computer science point of view, the crucial differenceis that while Nash informally talks about exponential vs polynomialcomputation time, he does not mention the word “Turing Machine”or other models of computation, and it is not clear if he is aware or notthat his conjecture can be made mathematically precise (assuming aformalization of “sufficiently complex types of enciphering”).

The definition of computational secrecy we use is the notion ofcomputational indistinguishability (known to be equivalent to semanticsecurity) that was given by Goldwasser and Micali in 1982.

Although they used a different terminology, Diffie and Hellmanalready made clear in their paper that their protocol can be used asa public key encryption, with the first message being put in a “pub-lic file”. In 1985, ElGamal showed how to obtain a signature schemebased on the Diffie Hellman ideas, and since he described the Diffie-Hellman encryption scheme in the same paper, the public key encryp-tion scheme originally proposed by Diffie and Hellman is sometimesalso known as ElGamal encryption.

My survey contains a discussion on the different types of public keyassumptions. While the standard elliptic curve cryptographic schemes

Page 606: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

606 introduction to theoretical computer science

are as susceptible to quantum computers as Diffie-Hellman and RSA,their main advantage is that the best known classical algorithms forcomputing discrete logarithms over elliptic curve groups take time 2𝜖𝑛for some 𝜖 > 0 where 𝑛 is the number of bits to describe a group ele-ment. In contrast, for the multiplicative group modulo a prime 𝑝 thebest algorithm take time 2𝑂(𝑛1/3𝑝𝑜𝑙𝑩𝑙𝑜𝑔(𝑛)) which means that (assum-ing the known algorithms are optimal) we need to set the prime to bebigger (and so have larger key sizes with corresponding overhead incommunication and computation) to get the same level of security.

Zero-knowledge proofs were constructed by Goldwasser, Micali,and Rackoff in 1982, and their wide applicability was shown (usingthe theory of NP completeness) by Goldreich, Micali, and Wigdersonin 1986.

Two party and multiparty secure computation protocols were con-structed (respectively) by Yao in 1982 and Goldreich, Micali, andWigderson in 1987. The latter work gave a general transformationfrom security against passive adversaries to security against activeadversaries using zero knowledge proofs.

Page 607: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

22Proofs and algorithms

“Let’s not try to define knowledge, but try to define zero-knowledge.”, ShafiGoldwasser.

Proofs have captured human imagination for thousands of years,ever since the publication of Euclid’s Elements, a book second only tothe bible in the number of editions printed.

Plan:

‱ Proofs and algorithms

‱ Interactive proofs

‱ Zero knowledge proofs

‱ Propositions as types, Coq and other proof assistants.

22.1 EXERCISES

22.2 BIBLIOGRAPHICAL NOTES

Compiled on 8.26.2020 18:10

Page 608: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 609: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

23Quantum computing

“We always have had (secret, secret, close the doors!) 
 a great deal of diffi-culty in understanding the world view that quantum mechanics represents 
It has not yet become obvious to me that there’s no real problem. 
 Can I learnanything from asking this question about computers–about this may or maynot be mystery as to what the world view of quantum mechanics is?” , RichardFeynman, 1981

“The only difference between a probabilistic classical world and the equationsof the quantum world is that somehow or other it appears as if the probabilitieswould have to go negative”, Richard Feynman, 1981

There were two schools of natural philosophy in ancient Greece.Aristotle believed that objects have an essence that explains their behav-ior, and a theory of the natural world has to refer to the reasons (or “fi-nal cause” to use Aristotle’s language) as to why they exhibit certainphenomena. Democritus believed in a purely mechanistic explanationof the world. In his view, the universe was ultimately composed ofelementary particles (or Atoms) and our observed phenomena arisefrom the interactions between these particles according to some localrules. Modern science (arguably starting with Newton) has embracedDemocritus’ point of view, of a mechanistic or “clockwork” universeof particles and forces acting upon them.

While the classification of particles and forces evolved with time,to a large extent the “big picture” has not changed from Newton tillEinstein. In particular it was held as an axiom that if we knew fullythe current state of the universe (i.e., the particles and their propertiessuch as location and velocity) then we could predict its future state atany point in time. In computational language, in all these theories thestate of a system with 𝑛 particles could be stored in an array of 𝑂(𝑛)numbers, and predicting the evolution of the system can be done byrunning some efficient (e.g., 𝑝𝑜𝑙𝑩(𝑛) time) deterministic computationon this array.

Compiled on 8.26.2020 18:10

Learning Objectives:‱ See main aspects in which quantum

mechanics differs from local deterministictheories.

‱ Model of quantum circuits, or equivalentlyQNAND-CIRC programs

‱ The complexity class BQP and what we knowabout its relation to other classes

‱ Ideas behind Shor’s Algorithm and theQuantum Fourier Transform

Page 610: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

610 introduction to theoretical computer science

Figure 23.1: In the “double baseball experiment” weshoot baseballs from a gun at a soft wall through ahard barrier that has one or two slits open in it. Thereis only “constructive interference” in the sense thatthe dent in each position in the wall when both slitsare open is the sum of the dents when each slit isopen on its own.

Figure 23.2: The setup of the double slit experimentin the case of photon or electron guns. We see alsodestructive interference in the sense that there aresome positions on the wall that get fewer hits whenboth slits are open than they get when only one of theslits is open. See also this video.

23.1 THE DOUBLE SLIT EXPERIMENT

Alas, in the beginning of the 20th century, several experimental re-sults were calling into question this “clockwork” or “billiard ball”theory of the world. One such experiment is the famous double slit ex-periment. Here is one way to describe it. Suppose that we buy one ofthose baseball pitching machines, and aim it at a soft plastic wall, butput a metal barrier with a single slit between the machine and the plasticwall (see Fig. 23.1). If we shoot baseballs at the plastic wall, then someof the baseballs would bounce off the metal barrier, while some wouldmake it through the slit and dent the wall. If we now carve out an ad-ditional slit in the metal barrier then more balls would get through,and so the plastic wall would be even more dented.

So far this is pure common sense, and it is indeed (to my knowl-edge) an accurate description of what happens when we shoot base-balls at a plastic wall. However, this is not the same when we shootphotons. Amazingly, if we shoot with a “photon gun” (i.e., a laser) ata wall equipped with photon detectors through some barrier, then(as shown in Fig. 23.2) in some positions of the wall we will see fewerhits when the two slits are open than when only one of them is!. Inparticular there are positions in the wall that are hit when the first slitis open, hit when the second gun is open, but are not hit at all when bothslits are open!.

It seems as if each photon coming out of the gun is aware of theglobal setup of the experiment, and behaves differently if two slits areopen than if only one is. If we try to “catch the photon in the act” andplace a detector right next to each slit so we can see exactly the patheach photon takes then something even more bizarre happens. Themere fact that we measure the path changes the photon’s behavior, andnow this “destructive interference” pattern is gone and the numberof times a position is hit when two slits are open is the sum of thenumber of times it is hit when each slit is open.

PYou should read the paragraphs above more thanonce and make sure you appreciate how truly mindboggling these results are.

23.2 QUANTUM AMPLITUDES

The double slit and other experiments ultimately forced scientists toaccept a very counterintuitive picture of the world. It is not merelyabout nature being randomized, but rather it is about the probabilitiesin some sense “going negative” and cancelling each other!

Page 611: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 611

To see what we mean by this, let us go back to the baseball exper-iment. Suppose that the probability a ball passes through the left slitis 𝑝𝐿 and the probability that it passes through the right slit is 𝑝𝑅.Then, if we shoot 𝑁 balls out of each gun, we expect the wall will behit (𝑝𝐿 + 𝑝𝑅)𝑁 times. In contrast, in the quantum world of photonsinstead of baseballs, it can sometimes be the case that in both the firstand second case the wall is hit with positive probabilities 𝑝𝐿 and 𝑝𝑅respectively but somehow when both slits are open the wall (or a par-ticular position in it) is not hit at all. It’s almost as if the probabilitiescan “cancel each other out”.

To understand the way we model this in quantum mechanics, it ishelpful to think of a “lazy evaluation” approach to probability. Wecan think of a probabilistic experiment such as shooting a baseballthrough two slits in two different ways:‱ When a ball is shot, “nature” tosses a coin and decides if it will go

through the left slit (which happens with probability 𝑝𝐿), right slit(which happens with probability 𝑝𝑅), or bounce back. If it passesthrough one of the slits then it will hit the wall. Later we can look atthe wall and find out whether or not this event happened, but thefact that the event happened or not is determined independently ofwhether or not we look at the wall.

‱ The other viewpoint is that when a ball is shot, “nature” computesthe probabilities 𝑝𝐿 and 𝑝𝑅 as before, but does not yet “toss thecoin” and determines what happened. Only when we actuallylook at the wall, nature tosses a coin and with probability 𝑝𝐿 + 𝑝𝑅ensures we see a dent. That is, nature uses “lazy evaluation”, andonly determines the result of a probabilistic experiment when wedecide to measure it.While the first scenario seems much more natural, the end result

in both is the same (the wall is hit with probability 𝑝𝐿 + 𝑝𝑅) and sothe question of whether we should model nature as following the firstscenario or second one seems like asking about the proverbial tree thatfalls in the forest with no one hearing about it.

However, when we want to describe the double slit experimentwith photons rather than baseballs, it is the second scenario that lendsitself better to a quantum generalization. Quantum mechanics as-sociates a number đ›Œ known as an amplitude with each probabilisticexperiment. This number đ›Œ can be negative, and in fact even complex.We never observe the amplitudes directly, since whenever we mea-sure an event with amplitude đ›Œ, nature tosses a coin and determinesthat the event happens with probability |đ›Œ|2. However, the sign (orin the complex case, phase) of the amplitudes can affect whether twodifferent events have constructive or destructive interference.

Page 612: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

612 introduction to theoretical computer science

Specifically, consider an event that can either occur or not (e.g. “de-tector number 17 was hit by a photon”). In classical probability, wemodel this by a probability distribution over the two outcomes: a pairof non-negative numbers 𝑝 and 𝑞 such that 𝑝 + 𝑞 = 1, where 𝑝 corre-sponds to the probability that the event occurs and 𝑞 corresponds tothe probability that the event does not occur. In quantum mechanics,we model this also by pair of numbers, which we call amplitudes. Thisis a pair of (potentially negative or even complex) numbers đ›Œ and đ›œsuch that |đ›Œ|2 + |đ›œ|2 = 1. The probability that the event occurs is |đ›Œ|2and the probability that it does not occur is |đ›œ|2. In isolation, thesenegative or complex numbers don’t matter much, since we anywaysquare them to obtain probabilities. But the interaction of positive andnegative amplitudes can result in surprising cancellations where some-how combining two scenarios where an event happens with positiveprobability results in a scenario where it never does.

PIf you don’t find the above description confusing andunintuitive, you probably didn’t get it. Please makesure to re-read the above paragraphs until you arethoroughly confused.

Quantum mechanics is a mathematical theory that allows us tocalculate and predict the results of the double-slit and many other ex-periments. If you think of quantum mechanics as an explanation as towhat “really” goes on in the world, it can be rather confusing. How-ever, if you simply “shut up and calculate” then it works amazinglywell at predicting experimental results. In particular, in the doubleslit experiment, for any position in the wall, we can compute num-bers đ›Œ and đ›œ such that photons from the first and second slit hit thatposition with probabilities |đ›Œ|2 and |đ›œ|2 respectively. When we openboth slits, the probability that the position will be hit is proportionalto |đ›Œ + đ›œ|2, and so in particular, if đ›Œ = âˆ’đ›œ then it will be the case that,despite being hit when either slit one or slit two are open, the positionis not hit at all when they both are. If you are confused by quantummechanics, you are not alone: for decades people have been trying tocome up with explanations for “the underlying reality” behind quan-tum mechanics, including Bohmian Mechanics, Many Worlds andothers. However, none of these interpretations have gained universalacceptance and all of those (by design) yield the same experimentalpredictions. Thus at this point many scientists prefer to just ignore thequestion of what is the “true reality” and go back to simply “shuttingup and calculating”.

Page 613: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 613

RRemark 23.1 — Complex vs real, other simplifications. If(like the author) you are a bit intimidated by complexnumbers, don’t worry: you can think of all ampli-tudes as real (though potentially negative) numberswithout loss of understanding. All the “magic” ofquantum computing already arises in this case, andso we will often restrict attention to real amplitudes inthis chapter.We will also only discuss so-called pure quantumstates, and not the more general notion of mixed states.Pure states turn out to be sufficient for understandingthe algorithmic aspects of quantum computing.More generally, this chapter is not meant to be a com-plete description of quantum mechanics, quantuminformation theory, or quantum computing, but ratherillustrate the main points where these differ fromclassical computing.

23.2.1 Linear algebra quick reviewLinear algebra underlies much of quantum mechanics, and so youwould do well to review some of the basic notions such as vectors,matrices, and linear subspaces. The operations in quantum mechanicscan be represented as linear functions over the complex numbers, butwe stick to the real numbers in this chapter. This does not cause muchloss in understanding but does allow us to simplify our notation andeliminate the use of the complex conjugate.

The main notions we use are:

‱ A function đč ∶ ℝ𝑁 → ℝ𝑁 is linear if đč(đ›Œđ‘ą + đ›œđ‘Ł) = đ›Œđč(𝑱) + đ›œđč(𝑣) forevery đ›Œ, đ›œ ∈ ℝ and 𝑱, 𝑣 ∈ ℝ𝑁 .

‱ The inner product of two vectors 𝑱, 𝑣 ∈ ℝ𝑁 can be defined as ⟹𝑱, đ‘ŁâŸ© =∑𝑖∈[𝑁] 𝑱𝑖𝑣𝑖. (There can be different inner products but we stickto this one.) The norm of a vector 𝑱 ∈ ℝ𝑁 is defined as ‖𝑱‖ =√⟹𝑱, đ‘ąâŸ© = √∑𝑖∈[𝑁] 𝑱2𝑖 . We say that 𝑱 is a unit vector if ‖𝑱‖ = 1.

‱ Two vectors 𝑱, 𝑣 ∈ ℝ𝑁 are orthogonal if ⟹𝑱, đ‘ŁâŸ© = 0. An orthonormalbasis for ℝ𝑁 is a set of 𝑁 vectors 𝑣0, 𝑣1, 
 , 𝑣𝑁−1 such that ‖𝑣𝑖‖ = 1for every 𝑖 ∈ [𝑁] and ⟹𝑣𝑖, đ‘Łđ‘—âŸ© = 0 for every 𝑖 ≠ 𝑗. A canoncialexample is the standard basis 𝑒0, 
 , 𝑒𝑁−1, where 𝑒𝑖 is the vector thathas zeroes in all cooordinates except the 𝑖-th coordinate in whichits value is 1. A quirk of the quantum mechanics literature is that𝑒𝑖 is often denoted by |đ‘–âŸ©. We often consider the case 𝑁 = 2𝑛, inwhich case we identify [𝑁] with 0, 1𝑛 and for every đ‘„ ∈ 0, 1𝑛,we denote the standard basis element corresponding to the đ‘„-thcoordinate by |đ‘„âŸ©.

Page 614: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

614 introduction to theoretical computer science

1 If you are extremely paranoid about Alice and Bobcommunicating with one another, you can coordinatewith your assistant to perform the experiment exactlyat the same time, and make sure that the roomsare sufficiently far apart (e.g., are on two differentcontinents, or maybe even one is on the moon andanother is on earth) so that Alice and Bob couldn’tcommunicate to each other in time the results of theirrespective coins even if they do so at the speed oflight.

‱ If 𝑱 is a vector in ℝ𝑛 and 𝑣0, 
 , 𝑣𝑁−1 is an orthonormal basis forℝ𝑁 , then there are coefficients đ›Œ0, 
 , đ›Œđ‘âˆ’1 such that 𝑱 = đ›Œ0𝑣0 +⋯ + đ›Œđ‘âˆ’1𝑣𝑁−1. Consequently, the value đč(𝑱) is determined by thevalues đč(𝑣0), 
, đč(𝑣𝑁−1). Moreover, ‖𝑱‖ = √∑𝑖∈[𝑁] đ›Œ2𝑖 .

‱ We can represent a linear function đč ∶ ℝ𝑁 → ℝ𝑁 as an 𝑁 × 𝑁matrix 𝑀(đč) where the coordinate in the 𝑖-th row and 𝑗-th columnof 𝑀(đč) (that is 𝑀(đč)𝑖,𝑗) is equal to ⟹𝑒𝑖, đč (𝑒𝑗)⟩ or equivalently the𝑖-th coordinate of đč(𝑒𝑗).

‱ A linear function đč ∶ ℝ𝑁 → ℝ𝑁 such that ‖đč(𝑱)‖ = ‖𝑱‖ for every𝑱 is called unitary. It can be shown that a function đč is unitary ifand only if 𝑀(đč)𝑀(đč)⊀ = đŒ where ⊀ is the transpose operator(in the complex case the conjugate transpose) and đŒ is the 𝑁 × 𝑁identity matrix that has 1’s on the diagonal and zeroes everywhereelse. (For every two matrices 𝐮, đ”, we use đŽđ” to denote the matrixproduct of 𝐮 and đ”.) Another equivalent characterization of thiscondition is that 𝑀(đč)⊀ = 𝑀(đč)−1 and yet another is that both therows and columns of 𝑀(đč) form an orthonormal basis.

23.3 BELL’S INEQUALITY

There is something weird about quantum mechanics. In 1935 Einstein,Podolsky and Rosen (EPR) tried to pinpoint this issue by highlightinga previously unrealized corollary of this theory. They showed thatthe idea that nature does not determine the results of an experimentuntil it is measured results in so called “spooky action at a distance”.Namely, making a measurement of one object may instantaneouslyeffect the state (i.e., the vector of amplitudes) of another object in theother end of the universe.

Since the vector of amplitudes is just a mathematical abstraction,the EPR paper was considered to be merely a thought experiment forphilosophers to be concerned about, without bearing on experiments.This changed when in 1965 John Bell showed an actual experimentto test the predictions of EPR and hence pit intuitive common senseagainst quantum mechanics. Quantum mechanics won: it turns outthat it is in fact possible to use measurements to create correlationsbetween the states of objects far removed from one another that cannotbe explained by any prior theory. Nonetheless, since the results ofthese experiments are so obviously wrong to anyone that has ever satin an armchair, that there are still a number of Bell denialists arguingthat this can’t be true and quantum mechanics is wrong.

So, what is this Bell’s Inequality? Suppose that Alice and Bob tryto convince you they have telepathic ability, and they aim to prove itvia the following experiment. Alice and Bob will be in separate closed

Page 615: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 615

rooms.1 You will interrogate Alice and your associate will interrogateBob. You choose a random bit đ‘„ ∈ 0, 1 and your associate choosesa random 𝑩 ∈ 0, 1. We let 𝑎 be Alice’s response and 𝑏 be Bob’sresponse. We say that Alice and Bob win this experiment if 𝑎 ⊕ 𝑏 =đ‘„ ∧ 𝑩. In other words, Alice and Bob need to output two bits thatdisagree if đ‘„ = 𝑩 = 1 and agree otherwise.

Now if Alice and Bob are not telepathic, then they need to agree inadvance on some strategy. It’s not hard for Alice and Bob to succeedwith probability 3/4: just always output the same bit. Moreover, bydoing some case analysis, we can show that no matter what strategythey use, Alice and Bob cannot succeed with higher probability thanthat:

Theorem 23.2 — Bell’s Inequality. For every two functions 𝑓, 𝑔 ∶ 0, 1 →0, 1, Prđ‘„,𝑩∈0,1[𝑓(đ‘„) ⊕ 𝑔(𝑩) = đ‘„ ∧ 𝑩] ≀ 3/4.Proof. Since the probability is taken over all four choices of đ‘„, 𝑩 ∈0, 1, the only way the theorem can be violated if if there exist twofunctions 𝑓, 𝑔 that satisfy 𝑓(đ‘„) ⊕ 𝑔(𝑩) = đ‘„ ∧ 𝑩 (23.1)

for all the four choices of đ‘„, 𝑩 ∈ 0, 12. Let’s plug in all these fourchoices and see what we get (below we use the equalities 𝑧 ⊕ 0 = 𝑧,𝑧 ∧ 0 = 0 and 𝑧 ∧ 1 = 𝑧):𝑓(0) ⊕ 𝑔(0) = 0 (plugging in đ‘„ = 0, 𝑩 = 0)𝑓(0) ⊕ 𝑔(1) = 0 (plugging in đ‘„ = 0, 𝑩 = 1)𝑓(1) ⊕ 𝑔(0) = 0 (plugging in đ‘„ = 1, 𝑩 = 0)𝑓(1) ⊕ 𝑔(1) = 1 (plugging in đ‘„ = 1, 𝑩 = 1) (23.2)

If we XOR together the first and second equalities we get 𝑔(0) ⊕𝑔(1) = 0 while if we XOR together the third and fourth equalities weget 𝑔(0) ⊕ 𝑔(1) = 1, thus obtaining a contradiction.

RRemark 23.3 — Randomized strategies. Theorem 23.2above assumes that Alice and Bob use deterministicstrategies 𝑓 and 𝑔 respectively. More generally, Aliceand Bob could use a randomized strategy, or equiva-lently, each could choose 𝑓 and 𝑔 from some distri-butions ℱ and 𝒱 respectively. However the averagingprinciple (Lemma 18.10) implies that if all possibledeterministic strategies succeed with probability atmost 3/4, then the same is true for all randomizedstrategies.

Page 616: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

616 introduction to theoretical computer science

2 More accurately, one either has to give up on a“billiard ball type” theory of the universe or believein telepathy (believe it or not, some scientists went forthe latter option).

An amazing experimentally verified fact is that quantum mechanicsallows for “telepathy”.2 Specifically, it has been shown that using theweirdness of quantum mechanics, there is in fact a strategy for Aliceand Bob to succeed in this game with probability larger than 3/4 (infact, they can succeed with probability about 0.85, see Lemma 23.5).

23.4 QUANTUM WEIRDNESS

Some of the counterintuitive properties that arise from quantum me-chanics include:

‱ Interference - As we’ve seen, quantum amplitudes can “cancel eachother out”.

‱ Measurement - The idea that amplitudes are negative as long as“no one is looking” and “collapse” (by squaring them) to positiveprobabilities when they are measured is deeply disturbing. Indeed,as shown by EPR and Bell, this leads to various strange outcomessuch as “spooky actions at a distance”, where we can create corre-lations between the results of measurements in places far removed.Unfortunately (or fortunately?) these strange outcomes have beenconfirmed experimentally.

‱ Entanglement - The notion that two parts of the system could beconnected in this weird way where measuring one will affect theother is known as quantum entanglement.

As counter-intuitive as these concepts are, they have been experi-mentally confirmed, so we just have to live with them.

The discussion in this chapter of quantum mechanics in general andquantum computing in particular is quite brief and superficial, the“bibliographical notes” section (Section 23.13) contains references andlinks to many other resources that cover this material in more depth.

23.5 QUANTUM COMPUTING AND COMPUTATION - AN EXECUTIVESUMMARY

One of the strange aspects of the quantum-mechanical picture of theworld is that unlike in the billiard ball example, there is no obviousalgorithm to simulate the evolution of 𝑛 particles over 𝑡 time periodsin 𝑝𝑜𝑙𝑩(𝑛, 𝑡) steps. In fact, the natural way to simulate 𝑛 quantum par-ticles will require a number of steps that is exponential in 𝑛. This is ahuge headache for scientists that actually need to do these calculationsin practice.

In the 1981, physicist Richard Feynman proposed to “turn thislemon to lemonade” by making the following almost tautologicalobservation:

Page 617: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 617

3 As its title suggests, Feynman’s lecture was actuallyfocused on the other side of simulating physics witha computer. However, he mentioned that as a “sideremark” one could wonder if it’s possible to simulatephysics with a new kind of computer - a “quantumcomputer” which would “not [be] a Turing machine,but a machine of a different kind”. As far as I know,Feynman did not suggest that such a computer couldbe useful for computations completely outside thedomain of quantum simulation. Indeed, he wasmore interested in the question of whether quantummechanics could be simulated by a classical computer.

4 This “95 percent” is a figure of speech, but not com-pletely so. At the time of this writing, cryptocurrencymining electricity consumption is estimated to useup at least 70Twh or 0.3 percent of the world’s pro-duction, which is about 2 to 5 percent of the totalenergy usage for the computing industry. All thecurrent cryptocurrencies will be broken by quantumcomputers. Also, for many web servers the TLS pro-tocol (which is based on the current non-lattice basedsystems would be completely broken by quantumcomputing) is responsible for about 1 percent of theCPU usage.

If a physical system cannot be simulated by a computer in 𝑇 steps, thesystem can be considered as performing a computation that would takemore than 𝑇 steps.

So, he asked whether one could design a quantum system suchthat its outcome 𝑩 based on the initial condition đ‘„ would be somefunction 𝑩 = 𝑓(đ‘„) such that (a) we don’t know how to efficientlycompute in any other way, and (b) is actually useful for something.3In 1985, David Deutsch formally suggested the notion of a quantumTuring machine, and the model has been since refined in works ofDeutsch, Josza, Bernstein and Vazirani. Such a system is now knownas a quantum computer.

For a while these hypothetical quantum computers seemed usefulfor one of two things. First, to provide a general-purpose mecha-nism to simulate a variety of the real quantum systems that peoplecare about, such as various interactions inside molecules in quan-tum chemistry. Second, as a challenge to the Physical Extended ChurchTuring Thesis which says that every physically realizable computa-tion device can be modeled (up to polynomial overhead) by Turingmachines (or equivalently, NAND-TM / NAND-RAM programs).

Quantum chemistry is important (and in particular understand-ing it can be a bottleneck for designing new materials, drugs, andmore), but it is still a rather niche area within the broader context ofcomputing (and even scientific computing) applications. Hence for awhile most researchers (to the extent they were aware of it), thoughtof quantum computers as a theoretical curiosity that has little bear-ing to practice, given that this theoretical “extra power” of quantumcomputer seemed to offer little advantage in the majority of the prob-lems people want to solve in areas such as combinatorial optimization,machine learning, data structures, etc..

To some extent this is still true today. As far as we know, quantumcomputers, if built, will not provide exponential speed ups for 95%of the applications of computing.4 In particular, as far as we know,quantum computers will not help us solve NP complete problems inpolynomial or even sub-exponential time, though Grover’s algorithm (Remark 23.4) does yield a quadratic advantage in many cases.

However, there is one cryptography-sized exception: In 1994 PeterShor showed that quantum computers can solve the integer factoringand discrete logarithm in polynomial time. This result has capturedthe imagination of a great many people, and completely energized re-search into quantum computing. This is both because the hardness ofthese particular problems provides the foundations for securing sucha huge part of our communications (and these days, our economy),as well as it was a powerful demonstration that quantum computers

Page 618: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

618 introduction to theoretical computer science

5 Of course, given that we’re still hearing of attacksexploiting “export grade” cryptography that wassupposed to disappear in 1990’s, I imagine thatwe’ll still have products running 1024 bit RSA wheneveryone has a quantum laptop.

could turn out to be useful for problems that a-priori seemed to havenothing to do with quantum physics.

As we’ll discuss later, at the moment there are several intensiveefforts to construct large scale quantum computers. It seems safeto say that, as far as we know, in the next five years or so there willnot be a quantum computer large enough to factor, say, a 1024 bitnumber. On the other hand, it does seem quite likely that in the verynear future there will be quantum computers which achieve some taskexponentially faster than the best-known way to achieve the sametask with a classical computer. When and if a quantum computer isbuilt that is strong enough to break reasonable parameters of DiffieHellman, RSA and elliptic curve cryptography is anybody’s guess. Itcould also be a “self destroying prophecy” whereby the existence ofa small-scale quantum computer would cause everyone to shift awayto lattice-based crypto which in turn will diminish the motivationto invest the huge resources needed to build a large scale quantumcomputer.5

RRemark 23.4 — Quantum computing and NP. Despitepopular accounts of quantum computers as havingvariables that can take “zero and one at the sametime” and therefore can “explore an exponential num-ber of possibilities simultaneously”, their true poweris much more subtle and nuanced. In particular, as faras we know, quantum computers do not enable us tosolve NP complete problems such as 3SAT in polyno-mial or even sub-exponential time. However, Grover’ssearch algorithm does give a more modest advan-tage (namely, quadratic) for quantum computersover classical ones for problems in NP. In particular,due to Grover’s search algorithm, we know that the𝑘-SAT problem for 𝑛 variables can be solved in time𝑂(2𝑛/2𝑝𝑜𝑙𝑩(𝑛)) on a quantum computer for every 𝑘.In contrast, the best known algorithms for 𝑘-SAT on aclassical computer take roughly 2(1− 1𝑘 )𝑛 steps.

Big Idea 28 Quantum computers are not a panacea and are un-likely to solve NP complete problems, but they can provide exponen-tial speedups to certain structured problems.

23.6 QUANTUM SYSTEMS

Before we talk about quantum computing, let us recall how we phys-ically realize “vanilla” or classical computing. We model a logical bit

Page 619: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 619

that can equal 0 or a 1 by some physical system that can be in one oftwo states. For example, it might be a wire with high or low voltage,charged or uncharged capacitor, or even (as we saw) a pipe with orwithout a flow of water, or the presence or absence of a soldier crab. Aclassical system of 𝑛 bits is composed of 𝑛 such “basic systems”, eachof which can be in either a “zero” or “one” state. We can model thestate of such a system by a string 𝑠 ∈ 0, 1𝑛. If we perform an op-eration such as writing to the 17-th bit the NAND of the 3rd and 5thbits, this corresponds to applying a local function to 𝑠 such as setting𝑠17 = 1 − 𝑠3 ⋅ 𝑠5.

In the probabilistic setting, we would model the state of the systemby a distribution. For an individual bit, we could model it by a pair ofnon-negative numbers đ›Œ, đ›œ such that đ›Œ + đ›œ = 1, where đ›Œ is the prob-ability that the bit is zero and đ›œ is the probability that the bit is one.For example, applying the negation (i.e., NOT) operation to this bitcorresponds to mapping the pair (đ›Œ, đ›œ) to (đ›œ, đ›Œ) since the probabilitythat NOT(𝜎) is equal to 1 is the same as the probability that 𝜎 is equalto 0. This means that we can think of the NOT function as the linearmap 𝑁 ∶ ℝ2 → ℝ2 such that 𝑁 (đ›Œđ›œ) = (đ›œđ›Œ) or equivalently as the

matrix (0 11 0).

If we think of the 𝑛-bit system as a whole, then since the 𝑛 bits cantake one of 2𝑛 possible values, we model the state of the system as avector 𝑝 of 2𝑛 probabilities. For every 𝑠 ∈ 0, 1𝑛, we denote by 𝑒𝑠the 2𝑛 dimensional vector that has 1 in the coordinate correspond-ing to 𝑠 (identifying it with a number in [2𝑛]), and so can write 𝑝 as∑𝑠∈0,1𝑛 𝑝𝑠𝑒𝑠 where 𝑝𝑠 is the probability that the system is in the state𝑠.

Applying the operation above of setting the 17-th bit to the NANDof the 3rd and 5th bits, corresponds to transforming the vector 𝑝 tothe vector đč𝑝 where đč ∶ ℝ2𝑛 → ℝ2𝑛 is the linear map that maps 𝑒𝑠 to𝑒𝑠0⋯𝑠16(1−𝑠3⋅𝑠5)𝑠18⋯𝑠𝑛−1 . (Since 𝑒𝑠𝑠∈0,1𝑛 is a basis for 𝑅2𝑛 , it suffices todefine the map đč on vectors of this form.)

PPlease make sure you understand why performing theoperation will take a system in state 𝑝 to a system inthe state đč𝑝. Understanding the evolution of proba-bilistic systems is a prerequisite to understanding theevolution of quantum systems.If your linear algebra is a bit rusty, now would be agood time to review it, and in particular make sureyou are comfortable with the notions of matrices, vec-tors, (orthogonal and orthonormal) bases, and norms.

Page 620: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

620 introduction to theoretical computer science

23.6.1 Quantum amplitudesIn the quantum setting, the state of an individual bit (or “qubit”,to use quantum parlance) is modeled by a pair of numbers (đ›Œ, đ›œ)such that |đ›Œ|2 + |đ›œ|2 = 1. While in general these numbers can becomplex, for the rest of this chapter, we will often assume they arereal (though potentially negative), and hence often drop the absolutevalue operator. (This turns out not to make much of a difference inexplanatory power.) As before, we think of đ›Œ2 as the probability thatthe bit equals 0 and đ›œ2 as the probability that the bit equals 1. As wedid before, we can model the NOT operation by the map 𝑁 ∶ ℝ2 → ℝ2where 𝑁(đ›Œ, đ›œ) = (đ›œ, đ›Œ).

Following quantum tradition, instead of using 𝑒0 and 𝑒1 as we didabove, from now on we will denote the vector (1, 0) by |0⟩ and thevector (0, 1) by |1⟩ (and moreover, think of these as column vectors).This is known as the Dirac “ket” notation. This means that NOT isthe unique linear map 𝑁 ∶ ℝ2 → ℝ2 that satisfies 𝑁|0⟩ = |1⟩ and𝑁|1⟩ = |0⟩. In other words, in the quantum case, as in the probabilisticcase, NOT corresponds to the matrix

𝑁 = (0 11 0) . (23.3)

In classical computation, we typically think that there are onlytwo operations that we can do on a single bit: keep it the same ornegate it. In the quantum setting, a single bit operation correspondsto any linear map OP ∶ ℝ2 → ℝ2 that is norm preserving in the sense

that for every đ›Œ, đ›œ, if we apply OP to the vector (đ›Œđ›œ) then we obtain

a vector (đ›Œâ€Čđ›œâ€Č) such that đ›Œâ€Č2 + đ›œâ€Č2 = đ›Œ2 + đ›œ2. Such a linear map

OP corresponds to a unitary two by two matrix. (As we mentioned,quantum mechanics actually models states as vectors with complexcoordinates; however, this does not make any qualitative difference toour discussion.) Keeping the bit the same corresponds to the matrixđŒ = (1 00 1) and (as we’ve seen) the NOT operations corresponds to

the matrix 𝑁 = (0 11 0). But there are other operations we can use

as well. One such useful operation is the Hadamard operation, whichcorresponds to the matrix

đ» = 1√2 (+1 +1+1 −1) . (23.4)

Page 621: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 621

In fact it turns out that Hadamard is all that we need to add to aclassical universal basis to achieve the full power of quantum comput-ing.

23.6.2 Quantum systems: an executive summaryIf you ignore the physics and philosophy, for the purposes of under-standing the model of quantum computers, all you need to knowabout quantum systems is the following. The state of a quantum systemof 𝑛 qubits is modeled by an 2𝑛 dimensional vector 𝜓 of unit norm(i.e., squares of all coordinates sums up to 1), which we write as𝜓 = âˆ‘đ‘„âˆˆ0,1𝑛 đœ“đ‘„|đ‘„âŸ© where |đ‘„âŸ© is the column vector that has 0 in allcoordinates except the one corresponding to đ‘„ (identifying 0, 1𝑛with the numbers 0, 
 , 2𝑛 − 1). We use the convention that if 𝑎, 𝑏are strings of lengths 𝑘 and ℓ respectively then we can write the 2𝑘+ℓdimensional vector with 1 in the 𝑎𝑏-th coordinate and zero elsewherenot just as |đ‘Žđ‘âŸ© but also as |đ‘ŽâŸ©|đ‘âŸ©. In particular, for every đ‘„ ∈ 0, 1𝑛, wecan write the vector |đ‘„âŸ© also as |đ‘„0⟩|đ‘„1⟩ ⋯ |đ‘„đ‘›âˆ’1⟩. This notation satisfiescertain nice distributive laws such as |đ‘ŽâŸ©(|đ‘âŸ© + |𝑏â€Č⟩)|đ‘âŸ© = |đ‘Žđ‘đ‘âŸ© + |𝑎𝑏â€Čđ‘âŸ©.

A quantum operation on such a system is modeled by a 2𝑛 × 2𝑛unitary matrix 𝑈 (one that satisfies UU⊀ = đŒ where đ‘ˆâŠ€ is the transposeoperation, or conjugate transpose for complex matrices). If the systemis in state 𝜓 and we apply to it the operation 𝑈 , then the new state ofthe system is 𝑈𝜓.

When we measure an 𝑛-qubit system in a state 𝜓 = âˆ‘đ‘„âˆˆ0,1𝑛 đœ“đ‘„|đ‘„âŸ©,then we observe the value đ‘„ ∈ 0, 1𝑛 with probability |đœ“đ‘„|2. In thiscase, the system collapses to the state |đ‘„âŸ©.23.7 ANALYSIS OF BELL’S INEQUALITY (OPTIONAL)

Now that we have the notation in place, we can show a strategy forAlice and Bob to display “quantum telepathy” in Bell’s Game. Re-call that in the classical case, Alice and Bob can succeed in the “BellGame” with probability at most 3/4 = 0.75. We now show that quan-tum mechanics allows them to succeed with probability at least 0.8.(The strategy we show is not the best one. Alice and Bob can in factsucceed with probability cos2(𝜋/8) ∌ 0.854.)Lemma 23.5 There is a 2-qubit quantum state 𝜓 ∈ ℂ4 so that if Alicehas access to the first qubit of 𝜓, can manipulate and measure it andoutput 𝑎 ∈ 0, 1 and Bob has access to the second qubit of 𝜓 and canmanipulate and measure it and output 𝑏 ∈ 0, 1 then Pr[𝑎 ⊕ 𝑏 =đ‘„ ∧ 𝑩] ≄ 0.8.

Page 622: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

622 introduction to theoretical computer science

Proof. Alice and Bob will start by preparing a 2-qubit quantum systemin the state 𝜓 = 1√2 |00⟩ + 1√2 |11⟩ (23.5)

(this state is known as an EPR pair). Alice takes the first qubitof the system to her room, and Bob takes the second qubit to hisroom. Now, when Alice receives đ‘„ if đ‘„ = 0 she does nothing andif đ‘„ = 1 she applies the unitary map 𝑅−𝜋/8 to her qubit where𝑅𝜃 = (𝑐𝑜𝑠𝜃 − sin 𝜃

sin 𝜃 cos 𝜃 ) is the unitary operation corresponding to

rotation in the plane with angle 𝜃. When Bob receives 𝑩, if 𝑩 = 0 hedoes nothing and if 𝑩 = 1 he applies the unitary map 𝑅𝜋/8 to his qubit.Then each one of them measures their qubit and sends this as theirresponse.

Recall that to win the game Bob and Alice want their outputs tobe more likely to differ if đ‘„ = 𝑩 = 1 and to be more likely to agreeotherwise. We will split the analysis in one case for each of the fourpossible values of đ‘„ and 𝑩.

Case 1: đ‘„ = 0 and 𝑩 = 0. If đ‘„ = 𝑩 = 0 then the state does notchange. Because the state 𝜓 is proportional to |00⟩ + |11⟩, the measure-ments of Bob and Alice will always agree (if Alice measures 0 then thestate collapses to |00⟩ and so Bob measures 0 as well, and similarly for1). Hence in the case đ‘„ = 𝑩 = 1, Alice and Bob always win.

Case 2: đ‘„ = 0 and 𝑩 = 1. If đ‘„ = 0 and 𝑩 = 1 then after Alicemeasures her bit, if she gets 0 then the system collapses to the state|00⟩, in which case after Bob performs his rotation, his qubit is inthe state cos(𝜋/8)|0⟩ + sin(𝜋/8)|1⟩. Thus, when Bob measures hisqubit, he will get 0 (and hence agree with Alice) with probabilitycos2(𝜋/8) ≄ 0.85. Similarly, if Alice gets 1 then the system collapsesto |11⟩, in which case after rotation Bob’s qubit will be in the state− sin(𝜋/8)|0⟩ + cos(𝜋/8)|1⟩ and so once again he will agree with Alicewith probability cos2(𝜋/8).

The analysis for Case 3, where đ‘„ = 1 and 𝑩 = 0, is completelyanalogous to Case 2. Hence Alice and Bob will agree with probabilitycos2(𝜋/8) in this case as well. (To show this we use the observationthat the result of this experiment is the same regardless of the orderin which Alice and Bob apply their rotations and measurements; thisrequires a proof but is not very hard to show.)

Case 4: đ‘„ = 1 and 𝑩 = 1. For the case that đ‘„ = 1 and 𝑩 = 1,after both Alice and Bob perform their rotations, the state will beproportional to 𝑅−𝜋/8|0âŸ©đ‘…đœ‹/8|0⟩ + 𝑅−𝜋/8|1âŸ©đ‘…đœ‹/8|1⟩ . (23.6)

Page 623: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 623

Intuitively, since we rotate one state by 45 degrees and the otherstate by -45 degrees, they will become orthogonal to each other, andthe measurements will behave like independent coin tosses that agreewith probability 1/2. However, for the sake of completeness, we nowshow the full calculation.

Opening up the coefficients and using cos(âˆ’đ‘„) = cos(đ‘„) andsin(âˆ’đ‘„) = − sin(đ‘„), we can see that (23.6) is proportional to

cos2(𝜋/8)|00⟩ + cos(𝜋/8) sin(𝜋/8)|01⟩− sin(𝜋/8) cos(𝜋/8)|10⟩ + sin2(𝜋/8)|11⟩− sin2(𝜋/8)|00⟩ + sin(𝜋/8) cos(𝜋/8)|01⟩− cos(𝜋/8) sin(𝜋/8)|10⟩ + cos2(𝜋/8)|11⟩ . (23.7)

Using the trigonometric identities 2 sin(đ›Œ) cos(đ›Œ) = sin(2đ›Œ) andcos2(đ›Œ) − sin2(đ›Œ) = cos(2đ›Œ), we see that the probability of getting anyone of |00⟩, |10⟩, |01⟩, |11⟩ is proportional to cos(𝜋/4) = sin(𝜋/4) = 1√2 .Hence all four options for (𝑎, 𝑏) are equally likely, which mean that inthis case 𝑎 = 𝑏 with probability 0.5.

Taking all the four cases together, the overall probability of winningthe game is 14 ⋅ 1 + 12 ⋅ 0.85 + 14 ⋅ 0.5 = 0.8.

RRemark 23.6 — Quantum vs probabilistic strategies. Itis instructive to understand what is it about quan-tum mechanics that enabled this gain in Bell’sInequality. For this, consider the following anal-ogous probabilistic strategy for Alice and Bob.They agree that each one of them output 0 if heor she get 0 as input and outputs 1 with prob-ability 𝑝 if they get 1 as input. In this case onecan see that their success probability would be14 ⋅ 1 + 12 (1 − 𝑝) + 14 [2𝑝(1 − 𝑝)] = 0.75 − 0.5𝑝2 ≀ 0.75.The quantum strategy we described above can bethought of as a variant of the probabilistic strategy forparameter 𝑝 set to sin2(𝜋/8) = 0.15. But in the caseđ‘„ = 𝑩 = 1, instead of disagreeing only with probability2𝑝(1 − 𝑝) = 1/4, the existence of the so called “neg-ative probabilities’ ’ in the quantum world allowedus to rotate the state in opposing directions to achievedestructive interference and hence a higher probabilityof disagreement, namely sin2(𝜋/4) = 0.5.

Page 624: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

624 introduction to theoretical computer science

6 Readers familiar with quantum computing shouldnote that đ‘ˆđ‘đŽđ‘đ· is a close variant of the so calledToffoli gate and so QNAND-CIRC programs corre-spond to quantum circuits with the Hadamard andToffoli gates.

23.8 QUANTUM COMPUTATION

Recall that in the classical setting, we modeled computation as ob-tained by a sequence of basic operations. We had two types of computa-tional models:

‱ Non uniform models of computation such as Boolean circuits andNAND-CIRC programs, where a finite function 𝑓 ∶ 0, 1𝑛 → 0, 1is computable in size 𝑇 if it can be expressed as a combination of𝑇 basic operations (gates in a circuit or lines in a NAND-CIRCprogram)

‱ Uniform models of computation such as Turing machines and NAND-TM programs, where an infinite function đč ∶ 0, 1∗ → 0, 1 iscomputable in time 𝑇 (𝑛) if there is a single algorithm that on inputđ‘„ ∈ 0, 1𝑛 evaluates đč(đ‘„) using at most 𝑇 (𝑛) basic steps.

When considering efficient computation, we defined the class P toconsist of all infinite functions đč ∶ 0, 1∗ → 0, 1 that can be com-puted by a Turing machine or NAND-TM program in time 𝑝(𝑛) forsome polynomial 𝑝(⋅). We defined the class P/poly to consists of allinfinite functions đč ∶ 0, 1∗ → 0, 1 such that for every 𝑛, the re-striction đč𝑛 of đč to 0, 1𝑛 can be computed by a Boolean circuit orNAND-CIRC program of size at most 𝑝(𝑛) for some polynomial 𝑝(⋅).

We will do the same for quantum computation, focusing mostly onthe non uniform setting of quantum circuits, since that is simpler, andalready illustrates the important differences with classical computing.

23.8.1 Quantum circuitsA quantum circuit is analogous to a Boolean circuit, and can be de-scribed as a directed acyclic graph. One crucial difference that theout degree of every vertex in a quantum circuit is at most one. This isbecause we cannot “reuse” quantum states without measuring them(which collapses their “probabilities”). Therefore, we cannot use thesame qubit as input for two different gates. (This is known as the NoCloning Theorem.) Another more technical difference is that to ex-press our operations as unitary matrices, we will need to make sure allour gates are reversible. This is not hard to ensure. For example, in thequantum context, instead of thinking of NAND as a (non reversible)map from 0, 12 to 0, 1, we will think of it as the reversible mapon three qubits that maps 𝑎, 𝑏, 𝑐 to 𝑎, 𝑏, 𝑐 ⊕ NAND(𝑎, 𝑏) (i.e., flip thelast bit if NAND of the first two bits is 1). Equivalently, the NANDoperation corresponds to the 8 × 8 unitary matrix đ‘ˆđ‘đŽđ‘đ· such that(identifying 0, 13 with [8]) for every 𝑎, 𝑏, 𝑐 ∈ 0, 1, if |đ‘Žđ‘đ‘âŸ© is thebasis element with 1 in the 𝑎𝑏𝑐-th coordinate and zero elsewhere, thenđ‘ˆđ‘đŽđ‘đ·|đ‘Žđ‘đ‘âŸ© = |𝑎𝑏(𝑐 ⊕ NAND(𝑎, 𝑏))⟩.6 If we order the rows and

Page 625: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 625

columns as 000, 001, 010, 
 , 111, then đ‘ˆđ‘đŽđ‘đ· can be written as thefollowing matrix:

đ‘ˆđ‘đŽđ‘đ· =⎛⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎝

0 1 0 0 0 0 0 01 0 0 0 0 0 0 00 0 0 1 0 0 0 00 0 1 0 0 0 0 00 0 0 0 0 1 0 00 0 0 0 1 0 0 00 0 0 0 0 0 1 00 0 0 0 0 0 0 1

⎞⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎠(23.8)

If we have an 𝑛 qubit system, then for 𝑖, 𝑗, 𝑘 ∈ [𝑛], we will denoteby 𝑈 𝑖,𝑗,đ‘˜đ‘đŽđ‘đ· as the 2𝑛 × 2𝑛 unitary matrix that corresponds to applyingđ‘ˆđ‘đŽđ‘đ· to the 𝑖-th, 𝑗-th, and 𝑘-th bits, leaving the others intact. That is,for every 𝑣 = âˆ‘đ‘„âˆˆ0,1𝑛 đ‘Łđ‘„|đ‘„âŸ©, 𝑈 𝑖,𝑗,đ‘˜đ‘đŽđ‘đ·đ‘Ł = âˆ‘đ‘„âˆˆ0,1𝑛 đ‘Łđ‘„|đ‘„0 ⋯ đ‘„đ‘˜âˆ’1(đ‘„đ‘˜ ⊕NAND(đ‘„đ‘–, đ‘„đ‘—))đ‘„đ‘˜+1 ⋯ đ‘„đ‘›âˆ’1⟩.

As mentioned above, we will also use the Hadamard or HAD oper-ation, A quantum circuit is obtained by applying a sequence of đ‘ˆđ‘đŽđ‘đ·and HAD gates, where a HAD gates corresponding to applying thematrix đ» = 1√2 (+1 +1+1 −1) . (23.9)

Another way to write define đ» is that for 𝑏 ∈ 0, 1, đ»|đ‘âŸ© = 1√2 |0⟩ +1√2 (−1)𝑏|1⟩. We define HAD𝑖 to be the 2𝑛 × 2𝑛 unitary matrix thatapplies HAD to the 𝑖-th qubit and leaves the others intact. Using theket notation, we can write this as

HAD𝑖 âˆ‘đ‘„âˆˆ0,1𝑛 đ‘Łđ‘„|đ‘„âŸ© = 1√2 âˆ‘đ‘„âˆˆ0,1𝑛 |đ‘„0 ⋯ đ‘„đ‘–âˆ’1⟩ (|0⟩ + (−1)đ‘„đ‘– |1⟩) |đ‘„đ‘–+1 ⋯ đ‘„đ‘›âˆ’1⟩ .(23.10)

A quantum circuit is obtained by composing these basic operationson some 𝑚 qubits. If 𝑚 ≄ 𝑛, we use a circuit to compute a function𝑓 ∶ 0, 1𝑛 → 0, 1:‱ On input đ‘„, we initialize the system to hold đ‘„0, 
 , đ‘„đ‘›âˆ’1 in the first 𝑛

qubits, and initialize all remaining 𝑚 − 𝑛 qubits to zero.

‱ We execute each elementary operation one by one: at every step weapply to the current state either an operation of the form 𝑈 𝑖,𝑗,đ‘˜đ‘đŽđ‘đ· oran operation of the form HAD𝑖 for 𝑖, 𝑗, 𝑘 ∈ [𝑚].

‱ At the end of the computation, we measure the system, and outputthe result of the last qubit (i.e. the qubit in location 𝑚 − 1). (Forsimplicity we restrict attention to functions with a single bit ofoutput, though the definition of quantum circuits naturally extendsto circuits with multiple outputs.)

Page 626: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

626 introduction to theoretical computer science

‱ We say that the circuit computes the function 𝑓 if the probability thatthis output equals 𝑓(đ‘„) is at least 2/3. Note that this probabilityis obtained by summing up the squares of the amplitudes of allcoordinates in the final state of the system corresponding to vectors|đ‘ŠâŸ© where 𝑩𝑚−1 = 𝑓(đ‘„).Formally we define quantum circuits as follows:

Definition 23.7 — Quantum circuit. Let 𝑠 ≄ 𝑚 ≄ 𝑛. A quantum circuit of𝑛 inputs, 𝑚 − 𝑛 auxiliary bits, and 𝑠 gates over the đ‘ˆđ‘đŽđ‘đ·,HADbasis is a sequence of 𝑠 unitary 2𝑚 × 2𝑚 matrices 𝑈0, 
 , 𝑈𝑠−1 suchthat each matrix 𝑈ℓ is either of the form NAND𝑖,𝑗,𝑘 for 𝑖, 𝑗, 𝑘 ∈ [𝑚]or HAD𝑖 for 𝑖 ∈ [𝑚].

A quantum circuit computes a function 𝑓 ∶ 0, 1𝑛 → 0, 1 if thefollowing is true for every đ‘„ ∈ 0, 1𝑛:

Let 𝑣 be the vector𝑣 = 𝑈𝑠−1𝑈𝑠−2 ⋯ 𝑈1𝑈0|đ‘„0đ‘šâˆ’đ‘›âŸ© (23.11)

and write 𝑣 as ∑𝑩∈0,1𝑚 𝑣𝑩|đ‘ŠâŸ©. Then∑𝑩∈0,1𝑚 s.t. 𝑩𝑚−1=𝑓(đ‘„) |𝑣𝑩|2 ≄ 23 . (23.12)

PPlease stop here and see that this definition makessense to you.

Big Idea 29 Just as we did with classical computation, we can de-fine mathematical models for quantum computation, and representquantum algorithms as binary strings.

Once we have the notion of quantum circuits, we can define thequantum analog of P/poly (i.e., the class of functions computable bypolynomial size quantum circuits) as follows:

Definition 23.8 — BQP/poly. Let đč ∶ 0, 1∗ → 0, 1. We say thatđč ∈ BQP/poly if there exists some polynomial 𝑝 ∶ ℕ → ℕ such thatfor every 𝑛 ∈ ℕ, if đč𝑛 is the restriction of đč to inputs of length 𝑛,then there is a quantum circuit of size at most 𝑝(𝑛) that computesđč𝑛.

Page 627: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 627

RRemark 23.9 — The obviously exponential fallacy. Apriori it might seem “obvious” that quantum com-puting is exponentially powerful, since to perform aquantum computation on 𝑛 bits we need to maintainthe 2𝑛 dimensional state vector and apply 2𝑛 × 2𝑛 ma-trices to it. Indeed popular descriptions of quantumcomputing (too) often say something along the linesthat the difference between quantum and classicalcomputer is that a classical bit can either be zero orone while a qubit can be in both states at once, andso in many qubits a quantum computer can performexponentially many computations at once.Depending on how you interpret it, this descriptionis either false or would apply equally well to proba-bilistic computation, even though we’ve already seenthat every randomized algorithm can be simulated bya similar-sized circuit, and in fact we conjecture thatBPP = P.Moreover, this “obvious” approach for simulating aquantum computation will take not just exponentialtime but exponential space as well, while can be shownthat using a simple recursive formula one can calcu-late the final quantum state using polynomial space (inphysics this is known as “Feynman path integrals”).So, the exponentially long vector description by itselfdoes not imply that quantum computers are exponen-tially powerful. Indeed, we cannot prove that they are(i.e., we have not been able to rule out the possibilitythat every QNAND-CIRC program could be simu-lated by a NAND-CIRC program/ Boolean circuit withpolynomial overhead), but we do have some problems(integer factoring most prominently) for which theydo provide exponential speedup over the currentlybest known classical (deterministic or probabilistic)algorithms.

23.8.2 QNAND-CIRC programs (optional)Just like in the classical case, there is an equivalence between circuitsand straight-line programs, and so we can define the programminglanguage QNAND-CIRC that is the quantum analog of our NAND-CIRC programming language. To do so, we only add a single op-eration: HAD(foo) which applies the single-bit operation đ» to thevariable foo. We also use the following interpretation to make NANDreversible: foo = NAND(bar,blah)means that we modify foo to bethe XOR of its original value and the NAND of bar and blah. (Inother words, apply the 8 by 8 unitary transformation đ‘ˆđ‘đŽđ‘đ· definedabove to the three qubits corresponding to foo, bar and blah.) If foois initialized to zero then this makes no difference.

Page 628: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

628 introduction to theoretical computer science

If 𝑃 is a QNAND-CIRC program with 𝑛 input variables, ℓworkspace variables, and 𝑚 output variables, then running it on theinput đ‘„ ∈ 0, 1𝑛 corresponds to setting up a system with 𝑛 + 𝑚 + ℓqubits and performing the following process:1. We initialize the input variables X[0] 
 X[𝑛 − 1] to đ‘„0, 
 , đ‘„đ‘›âˆ’1 and

all other variables to 0.2. We execute the program line by line, applying the corresponding

physical operation đ» or đ‘ˆđ‘đŽđ‘đ· to the qubits that are referred to bythe line.

3. We measure the output variables Y[0], 
, Y[𝑚 − 1] and outputthe result (if there is more than one output then we measure morevariables).

23.8.3 Uniform computationJust as in the classical case, we can define uniform computationalmodels for quantum computing as well. We will let BQP be thequantum analog to P and BPP: the class of all Boolean functionsđč ∶ 0, 1∗ → 0, 1 that can be computed by quantum algorithmsin polynomial time. There are several equivalent ways to define BQP.For example, there is a computational model of Quantum TuringMachines that can be used to define BQP just as standard Turingmachines are used to define P. Another alternative is to define theQNAND-TM programming language to be QNAND-CIRC augmentedwith loops and arrays just like NAND-TM is obtained from NAND-CIRC. Once again, we can define BQP using QNAND-TM programsanalogously to the way P can be defined using NAND-TM programs.However, we use the following equivalent definition (which is alsothe one most popular in the literature):

Definition 23.10 — The class BQP. Let đč ∶ 0, 1∗ → 0, 1. We say thatđč ∈ BQP if there exists a polynomial time NAND-TM program 𝑃such that for every 𝑛, 𝑃(1𝑛) is the description of a quantum circuitđ¶đ‘› that computes the restriction of đč to 0, 1𝑛.

PDefinition 23.10 is the quantum analog of the alter-native characterization of P that appears in SolvedExercise 13.4. One way to verify that you’ve under-stood Definition 23.10 it to see that you can prove(1) P ⊆ BQP and in fact the stronger statementBPP ⊆ BQP, (2) BQP ⊆ EXP, and (3) For everyNP-complete function đč , if đč ∈ BQP then NP ⊆ BQP.Exercise 23.1 asks you to work these out.

Page 629: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 629

Figure 23.3: Superconducting quantum computerprototype at Google. Image credit: Google / MITTechnology Review.

The relation between NP and BQP is not known (see also Re-mark 23.4). It is widely believed that NP ⊈ BQP, but there is noconsensus whether or not BQP ⊆ NP. It is quite possible that thesetwo classes are incomparable, in the sense that NP ⊈ BQP (and in par-ticular no NP-complete function belongs to BQP) but also BQP ⊈ NP(and there are some interesting candidates for such problems).

It can be shown that QNANDEVAL (evaluating a quantum circuiton an input) is computable by a polynomial size QNAND-CIRC pro-gram, and moreover this program can even be generated uniformlyand hence QNANDEVAL is in BQP. This allows us to “port” manyof the results of classical computational complexity into the quantumrealm, including the notions of a universal quantum Turing machine,as well as all of the uncomputability results. There is even a quantumanalog of the Cook-Levin Theorem.

RRemark 23.11 — Restricting attention to circuits. Becausethe non uniform model is a little cleaner to work with,in the rest of this chapter we mostly restrict attentionto this model, though all the algorithms we discusscan be implemented using uniform algorithms as well.

23.9 PHYSICALLY REALIZING QUANTUM COMPUTATION

To realize quantum computation one needs to create a system with 𝑛independent binary states (i.e., “qubits”), and be able to manipulatesmall subsets of two or three of these qubits to change their state.While by the way we defined operations above it might seem that oneneeds to be able to perform arbitrary unitary operations on these twoor three qubits, it turns out that there are several choices for universalsets - a small constant number of gates that generate all others. Thebiggest challenge is how to keep the system from being measured andcollapsing to a single classical combination of states. This is sometimesknown as the coherence time of the system. The threshold theorem saysthat there is some absolute constant level of errors 𝜏 so that if errorsare created at every gate at rate smaller than 𝜏 then we can recoverfrom those and perform arbitrary long computations. (Of course thereare different ways to model the errors and so there are actually severalthreshold theorems corresponding to various noise models).

There have been several proposals to build quantum computers:

‱ Superconducting quantum computers use superconducting electriccircuits to do quantum computation. This is the direction wherethere has been most recent progress towards “beating” classicalcomputers.

Page 630: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

630 introduction to theoretical computer science

Figure 23.4: Top: A periodic function. Bottom: Ana-periodic function.

‱ Trapped ion quantum computers Use the states of an ion to sim-ulate a qubit. People have made some recent advances on thesecomputers too. While it’s not at all clear that’s the right measur-ing yard, the current best implementation of Shor’s algorithm (forfactoring 15) is done using an ion-trap computer.

‱ Topological quantum computers use a different technology. Topo-logical qubits are more stable by design and hence error correctionis less of an issue, but constructing them is extremely challenging.

These approaches are not mutually exclusive and it could be thatultimately quantum computers are built by combining all of themtogether. In the near future, it seems that we will not be able to achievefull fledged large scale universal quantum computers, but rather morerestricted machines, sometimes called “Noisy Intermediate-ScaleQuantum Computers” or “NISQ”. See this article by John Preskil forsome of the progress and applications of such more restricted devices.

23.10 SHOR’S ALGORITHM: HEARING THE SHAPE OF PRIME FAC-TORS

Bell’s Inequality is a powerful demonstration that there is some-thing very strange going on with quantum mechanics. But couldthis “strangeness” be of any use to solve computational problems notdirectly related to quantum systems? A priori, one could guess theanswer is no. In 1994 Peter Shor showed that one would be wrong:

Theorem 23.12 — Shor’s Algorithm. There is a polynomial-time quan-tum algorithm that on input an integer 𝑀 (represented in basetwo), outputs the prime factorization of 𝑀 .

Another way to state Theorem 23.12 is that if we defineFACTORING ∶ 0, 1∗ → 0, 1 to be the function that on input apair of numbers (𝑀, 𝑋) outputs 1 if and only if 𝑀 has a factor 𝑃 suchthat 2 ≀ 𝑃 ≀ 𝑋, then FACTORING is in BQP. This is an exponentialimprovement over the best known classical algorithms, which takeroughly 2(𝑛1/3) time, where the notation hides factors that arepolylogarithmic in 𝑛. While we will not prove Theorem 23.12 in thischapter, we will sketch some of the ideas behind the proof.

23.10.1 Period findingAt the heart of Shor’s Theorem is an efficient quantum algorithm forfinding periods of a given function. For example, a function 𝑓 ∶ ℝ → ℝis periodic if there is some ℎ > 0 such that 𝑓(đ‘„ + ℎ) = 𝑓(đ‘„) for every đ‘„(e.g., see Fig. 23.4).

Page 631: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 631

Figure 23.5: Left: The air-pressure when playing a“C Major” chord as a function of time. Right: Thecoefficients of the Fourier transform of the same func-tion, we can see that it is the sum of three frequenciescorresponding to the C, E and G notes (261.63, 329.63and 392 Hertz respectively). Credit: Bjarke Mþnsted’sQuora answer.

Figure 23.6: If 𝑓 is a periodic function then when werepresent it in the Fourier transform, we expect thecoefficients corresponding to wavelengths that donot evenly divide the period to be very small, as theywould tend to “cancel out”.

Musical notes yield one type of periodic function. When you pullon a string on a musical instrument, it vibrates in a repeating pattern.Hence, if we plot the speed of the string (and so also the speed ofthe air around it) as a function of time, it will correspond to someperiodic function. The length of the period is known as the wave lengthof the note. The frequency is the number of times the function repeatsitself within a unit of time. For example, the “Middle C” note hasa frequency of 261.63 Hertz, which means its period is 1/(261.63)seconds.

If we play a chord by playing several notes at once, we get a morecomplex periodic function obtained by combining the functions ofthe individual notes (see Fig. 23.5). The human ear contains manysmall hairs, each of which is sensitive to a narrow band of frequencies.Hence when we hear the sound corresponding to a chord, the hairs inour ears actually separate it out to the components corresponding toeach frequency.

It turns out that (essentially) every periodic function 𝑓 ∶ ℝ → ℝcan be decomposed into a sum of simple wave functions (namelyfunctions of the form đ‘„ ↩ sin(đœƒđ‘„) or đ‘„ ↩ cos(đœƒđ‘„)). This is known asthe Fourier Transform (see Fig. 23.6). The Fourier transform makes iteasy to compute the period of a given function: it will simply be theleast common multiple of the periods of the constituent waves.

23.10.2 Shor’s Algorithm: A bird’s eye viewOn input an integer 𝑀 , Shor’s algorithm outputs the prime factoriza-tion of 𝑀 in time that is polynomial in log𝑀 . The main steps in thealgorithm are the following:

Step 1: Reduce to period finding. The first step in the algorithm is topick a random 𝐮 ∈ 0, 1 
 , 𝑀 − 1 and define the function đč𝐮 ∶0, 1𝑚 → 0, 1𝑚 as đč𝐮(đ‘„) = đŽđ‘„( mod 𝑀) where we identify thestring đ‘„ ∈ 0, 1𝑚 with an integer using the binary representation,and similarly represent the integer đŽđ‘„( mod 𝑀) as a string. (We willchoose 𝑚 to be some polynomial in log𝑀 and so in particular 0, 1𝑚is a large enough set to represent all the numbers in 0, 1, 
 , 𝑀 − 1).

Some not-too-hard (though somewhat technical) calculations showthat: (1) The function đč𝐮 is periodic (i.e., there is some integer 𝑝𝐮 suchthat đč𝐮(đ‘„ + 𝑝𝐮) = đč𝐮(đ‘„) for “almost” every đ‘„) and more importantly(2) If we can recover the period 𝑝𝐮 of đč𝐮 for several randomly cho-sen 𝐮’s, then we can recover the factorization of 𝑀 . (We’ll ignore the“almost” qualifier in the discussion below; it causes some annoying,yet ultimately manageable, technical issues in the full-fledged algo-rithm.) Hence, factoring 𝑀 reduces to finding out the period of thefunction đč𝐮. Exercise 23.2 asks you to work out this for the related

Page 632: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

632 introduction to theoretical computer science

task of computing the discrete logarithm (which underlies the securityof the Diffie-Hellman key exchange and elliptic curve cryptography).Step 2: Period finding via the Quantum Fourier Transform. Using a simpletrick known as “repeated squaring”, it is possible to compute themap đ‘„ ↩ đč𝐮(đ‘„) in time polynomial in 𝑚, which means we can alsocompute this map using a polynomial number of NAND gates,and soin particular we can generate in polynomial quantum time a quantumstate 𝜌 that is (up to normalization) equal toâˆ‘đ‘„âˆˆ0,1𝑚 |đ‘„âŸ©|đč𝐮(đ‘„)⟩ . (23.13)

In particular, if we were to measure the state 𝜌, we would get a ran-dom pair of the form (đ‘„, 𝑩) where 𝑩 = đč𝐮(đ‘„). So far, this is not at allimpressive. After all, we did not need the power of quantum comput-ing to generate such pairs: we could simply generate a random đ‘„ andthen compute đč𝐮(đ‘„).

Another way to describe the state 𝜌 is that the coefficient of |đ‘„âŸ©|đ‘ŠâŸ© in𝜌 is proportional to 𝑓𝐮,𝑩(đ‘„) where 𝑓𝐮,𝑩 ∶ 0, 1𝑚 → ℝ is the functionsuch that 𝑓𝐮,𝑩(đ‘„) = ⎧⎚⎩1 𝑩 = đŽđ‘„( mod 𝑀)0 otherwise

. (23.14)

The magic of Shor’s algorithm comes from a procedure knownas the Quantum Fourier Transform. It allows to change the state 𝜌 intothe state 𝜌 where the coefficient of |đ‘„âŸ©|đ‘ŠâŸ© is now proportional to theđ‘„-th Fourier coefficient of 𝑓𝐮,𝑩. In other words, if we measure the state𝜌, we will obtain a pair (đ‘„, 𝑩) such that the probability of choosing đ‘„is proportional to the square of the weight of the frequency đ‘„ in therepresentation of the function 𝑓𝐮,𝑩. Since for every 𝑩, the function𝑓𝐮,𝑩 has the period 𝑝𝐮, it can be shown that the frequency đ‘„ will be(almost) a multiple of 𝑝𝐮. If we make several such samples 𝑩0, 
 , 𝑩𝑘and obtain the frequencies đ‘„1, 
 , đ‘„đ‘˜, then the true period 𝑝𝐮 dividesall of them, and it can be shown that it is going to be in fact the greatestcommon divisor (g.c.d.) of all these frequencies: a value which can becomputed in polynomial time.

As mentioned above, we can recover the factorization of 𝑀 fromthe periods of đč𝐮0 , 
 , đč𝐮𝑡 for some randomly chosen 𝐮0, 
 , 𝐮𝑡 in0, 
 , 𝑀 − 1 and 𝑡 which is polynomial in log𝑀 .

The resulting algorithm can be described in a high (and somewhatinaccurate) level as follows:

Shor’s Algorithm: (sketch)Input: Number 𝑀 ∈ ℕ.Output: Prime factorization of 𝑀 .Operations:

Page 633: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 633

1. Repeat the following 𝑘 = 𝑝𝑜𝑙𝑩(log𝑀) number of times:a. Choose 𝐮 ∈ 0, 
 , 𝑀 − 1 at random, and let 𝑓𝐮 ∶ â„€đ‘€ → â„€đ‘€ be

the map đ‘„ ↩ đŽđ‘„ mod 𝑀 .b. For 𝑡 = 𝑝𝑜𝑙𝑩(log𝑀), repeat 𝑡 times the following step: Quantum

Fourier Transform to create a quantum state |đœ“âŸ© over 𝑝𝑜𝑙𝑩(log(𝑚))qubits, such that if we measure |đœ“âŸ© we obtain a pair of strings(𝑗, 𝑩) with probability proportional to the square of the coefficientcorresponding to the wave function đ‘„ ↩ cos(đ‘„đœ‹đ‘—/𝑀) or đ‘„ ↩sin(đ‘„đœ‹đ‘—/𝑀) in the Fourier transform of the function 𝑓𝐮,𝑩 ∶ â„€đ‘š →0, 1 defined as 𝑓𝐮,𝑩(đ‘„) = 1 iff 𝑓𝐮(đ‘„) = 𝑩.

c. If 𝑗1, 
 , 𝑗𝑡 are the coefficients we obtained in the previous step,then the least common multiple of 𝑀/𝑗1, 
 , 𝑀/𝑗𝑡 is likely to bethe period of the function 𝑓𝐮.

2. If we let 𝐮0, 
 , 𝐮𝑘−1 and 𝑝0, 
 , 𝑝𝑘−1 be the numbers we chose inthe previous step and the corresponding periods of the functions𝑓𝐮0 , 
 , 𝑓𝐮𝑘−1 then we can use classical results in number theory toobtain from these a non-trivial prime factor 𝑄 of 𝑀 (if such exists).We can now run the algorithm again with the (smaller) input 𝑀/𝑄to obtain all other factors.

Reducing factoring to order finding is cumbersome, but can bedone in polynomial time using a classical computer. The key quantumingredient in Shor’s algorithm is the quantum fourier transform.

RRemark 23.13 — Quantum Fourier Transform. Despiteits name, the Quantum Fourier Transform does notactually give a way to compute the Fourier Trans-form of a function 𝑓 ∶ 0, 1𝑚 → ℝ. This would beimpossible to do in time polynomial in 𝑚, as simplywriting down the Fourier Transform would require 2𝑚coefficients. Rather the Quantum Fourier Transformgives a quantum state where the amplitude correspond-ing to an element (think: frequency) ℎ is equal tothe corresponding Fourier coefficient. This allows tosample from a distribution where ℎ is drawn withprobability proportional to the square of its Fouriercoefficient. This is not the same as computing theFourier transform, but is good enough for recoveringthe period.

23.11 QUANTUM FOURIER TRANSFORM (ADVANCED, OPTIONAL)

The above description of Shor’s algorithm skipped over the implemen-tation of the main quantum ingredient: the Quantum Fourier Transformalgorithm. In this section we discuss the ideas behind this algorithm.We will be rather brief and imprecise. Section 23.13 contain referencesto sources of more information about this topic.

Page 634: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

634 introduction to theoretical computer science

To understand the Quantum Fourier Transform, we need to betterunderstand the Fourier Transform itself. In particular, we will needto understand how it applies not just to functions whose input is areal number but to functions whose domain can be any arbitrarycommutative group. Therefore we now take a short detour to (verybasic) group theory, and define the notion of periodic functions overgroups.

RRemark 23.14 — Group theory. While we define the con-cepts we use, some background in group or numbertheory will be very helpful for fully understandingthis section. In particular we will use the notion offinite commutative (a.k.a. Abelian) groups. These aredefined as follows.

‱ A finite group đ”Ÿ is a pair (đș, ⋆) where đș is a finiteset of elements and ⋆ is a binary operation mappinga pair 𝑔, ℎ of elements in đș to the element 𝑔 ⋆ ℎ in đș.We often identify đ”Ÿ with the set đș of its elements,and so use notation such as 𝑔 ∈ đ”Ÿ to indicate that 𝑔is an element of đ”Ÿ and |đ”Ÿ| to denote the number ofelements in đ”Ÿ.

‱ The operation ⋆ satisfies the sort of properties thata product operation does, namely, it is associative(i.e., (𝑔 ⋆ ℎ) ⋆ 𝑓 = 𝑔 ⋆ (ℎ ⋆ 𝑓)) and there is someelement 1 such that 𝑔 ⋆ 1 = 𝑔 for all 𝑔, and forevery 𝑔 ∈ đ”Ÿ there exists an element 𝑔−1 such that𝑔 ⋆ 𝑔−1 = 1.

‱ A group is called commutative (also known asAbelian) if 𝑔 ⋆ ℎ = ℎ ⋆ 𝑔 for all 𝑔, ℎ ∈ đ”Ÿ.

The Fourier transform is a deep and vast topic, on which we willbarely touch upon here. Over the real numbers, the Fourier trans-form of a function 𝑓 is obtained by expressing 𝑓 in the form ∑ 𝑓(đ›Œ)đœ’đ›Œwhere the đœ’đ›Œâ€™s are “wave functions” (e.g. sines and cosines). How-ever, it turns out that the same notion exists for every Abelian group đ”Ÿ.Specifically, for every such group đ”Ÿ, if 𝑓 is a function mapping đ”Ÿ to ℂ,then we can write 𝑓 as 𝑓 = âˆ‘đ‘”âˆˆđ”Ÿ 𝑓(𝑔)𝜒𝑔 , (23.15)

where the 𝜒𝑔’s are functions mapping đ”Ÿ to ℂ that are analogs ofthe “wave functions” for the group đ”Ÿ and for every 𝑔 ∈ đ”Ÿ, 𝑓(𝑔) is acomplex number known as the Fourier coefficient of 𝑓 corresponding to𝑔. Specifically, the equation (23.15) means that if we think of 𝑓 as a|đ”Ÿ| dimensional vector over the complex numbers, then we can writethis vector as a sum (with certain coefficients) of the vectors đœ’đ‘”đ‘”âˆˆđ”Ÿ.

Page 635: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 635

The representation (23.15) is known as the Fourier expansion or Fouriertransform of 𝑓 , the numbers ( 𝑓(𝑔))đ‘”âˆˆđ”Ÿ are known as the Fourier coef-ficients of 𝑓 and the functions (𝜒𝑔)đ‘”âˆˆđ”Ÿ are known as the Fourier char-acters. The central property of the Fourier characters is that they arehomomorphisms of the group into the complex numbers, in the sensethat for every đ‘„, đ‘„â€Č ∈ đ”Ÿ, 𝜒𝑔(đ‘„ ⋆ đ‘„â€Č) = 𝜒𝑔(đ‘„)𝜒𝑔(đ‘„â€Č), where ⋆ is the groupoperation. One corollary of this property is that if 𝜒𝑔(ℎ) = 1 then 𝜒𝑔is ℎ periodic in the sense that 𝜒𝑔(đ‘„ ⋆ ℎ) = 𝜒𝑔(đ‘„) for every đ‘„. It turnsout that if 𝑓 is periodic with minimal period ℎ, then the only Fouriercharacters that have non zero coefficients in the expression (23.15)are those that are ℎ periodic as well. This can be used to recover theperiod of 𝑓 from its Fourier expansion.

23.11.1 Quantum Fourier Transform over the Boolean Cube: Simon’sAlgorithm

We now describe the simplest setting of the Quantum Fourier Trans-form: the group 0, 1𝑛 with the XOR operation, which we’ll denoteby (0, 1𝑛, ⊕). (Since XOR is equal to addition modulo two, thisgroup is also often denoted as (â„€2)𝑛.) It can be shown that the Fouriertransform over (0, 1𝑛, ⊕) corresponds to expressing 𝑓 ∶ 0, 1𝑛 → ℂas 𝑓 = ∑𝑩∈0,1 𝑓(𝑩)𝜒𝑩 (23.16)

where 𝜒𝑩 ∶ 0, 1𝑛 → ℂ is defined as 𝜒𝑩(đ‘„) = (−1)∑𝑖 đ‘Šđ‘–đ‘„đ‘– and𝑓(𝑩) = 1√2𝑛 âˆ‘đ‘„âˆˆ0,1𝑛 𝑓(đ‘„)(−1)∑𝑖 đ‘Šđ‘–đ‘„đ‘– .The Quantum Fourier Transform over (0, 1𝑛, ⊕) is actually quite

simple:

Theorem 23.15 — QFT Over the Boolean Cube. Let 𝜌 = âˆ‘đ‘„âˆˆ0,1𝑛 𝑓(đ‘„)|đ‘„âŸ©be a quantum state where 𝑓 ∶ 0, 1𝑛 → ℂ is some function satisfy-ing âˆ‘đ‘„âˆˆ0,1𝑛 |𝑓(đ‘„)|2 = 1. Then we can use 𝑛 gates to transform 𝜌 tothe state ∑𝑩∈0,1𝑛 𝑓(𝑩)|đ‘ŠâŸ© (23.17)

where 𝑓 = ∑𝑩 𝑓(𝑩)𝜒𝑩 and 𝜒𝑩 ∶ 0, 1𝑛 → ℂ is the function𝜒𝑩(đ‘„) = −1∑ đ‘„đ‘–đ‘Šđ‘– .Proof Idea:

The idea behind the proof is that the Hadamard operation corre-sponds to the Fourier transform over the group 0, 1𝑛 (with the XORoperations). To show this, we just need to do the calculations.⋆

Page 636: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

636 introduction to theoretical computer science

Proof of Theorem 23.15. We can express the Hadamard operation HADas follows:

HAD|đ‘ŽâŸ© = 1√2 (|0⟩ + (−1)𝑎|1⟩) . (23.18)We are given the state 𝜌 = âˆ‘đ‘„âˆˆ0,1𝑛 𝑓(đ‘„)|đ‘„âŸ© . (23.19)

Now suppose that we apply the HAD operation to each of the 𝑛qubits. We can see that we get the state2−𝑛/2 âˆ‘đ‘„âˆˆ0,1𝑛 𝑓(đ‘„) 𝑛−1∏𝑖=0(|0⟩ + (−1)đ‘„đ‘– |1⟩) . (23.20)

We can now use the distributive law and open up a term of theform 𝑓(đ‘„)(|0⟩ + (−1)đ‘„0 |1⟩) ⋯ (|0⟩ + (−1)đ‘„đ‘›âˆ’1 |1⟩) (23.21)

to the following sum over 2𝑛 terms:𝑓(đ‘„) ∑𝑩∈0,1𝑛(−1)∑ đ‘Šđ‘–đ‘„đ‘– |đ‘ŠâŸ© . (23.22)

(If you find the above confusing, try to work out explicitly thiscalculation for 𝑛 = 3; namely show that (|0⟩ + (−1)đ‘„0 |1⟩)(|0⟩ +(−1)đ‘„1 |1⟩)(|0⟩+(−1)đ‘„2 |1⟩) is the same as the sum over 23 terms |000⟩+(−1)đ‘„2 |001⟩ + ⋯ + (−1)đ‘„0+đ‘„1+đ‘„2 |111⟩.)

By changing the order of summations, we see that the final state is∑𝑩∈0,1𝑛 2−𝑛/2( âˆ‘đ‘„âˆˆ0,1𝑛 𝑓(đ‘„)(−1)∑ đ‘„đ‘–đ‘Šđ‘–)|đ‘ŠâŸ© (23.23)

which exactly corresponds to 𝜌.

23.11.2 From Fourier to Period finding: Simon’s Algorithm (advanced,optional)

Using Theorem 23.15 it is not hard to get an algorithm that can recovera string ℎ∗ ∈ 0, 1𝑛 given a circuit that computes a function đč ∶0, 1𝑛 → 0, 1∗ that is ℎ∗ periodic in the sense that đč(đ‘„) = đč(đ‘„â€Č) fordistinct đ‘„, đ‘„â€Č if and only if đ‘„â€Č = đ‘„ ⊕ ℎ∗. The key observation is that ifwe compute the state âˆ‘đ‘„âˆˆ0,1𝑛 |đ‘„âŸ©|đč (đ‘„)⟩, and perform the QuantumFourier transform on the first 𝑛 qubits, then we would get a state suchthat the only basis elements with nonzero coefficients would be of theform |đ‘ŠâŸ© where ∑ 𝑩𝑖ℎ∗𝑖 = 0( mod 2) (23.24)

Page 637: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 637

So, by measuring the state, we can obtain a sample of a random𝑩 satisfying (23.24). But since (23.24) is a linear equation modulo 2about the unknown 𝑛 variables ℎ∗0, 
 , ℎ∗𝑛−1, if we repeat this proce-dure to get 𝑛 such equations, we will have at least as many equationsas variables and (it can be shown that) this will suffice to recover ℎ∗.

This result is known as Simon’s Algorithm, and it preceded andinspired Shor’s algorithm.

23.11.3 From Simon to Shor (advanced, optional)Theorem 23.15 seemed to really use the special bit-wise structure ofthe group 0, 1𝑛, and so one could wonder if it can be extended toother groups. However, it turns out that we can in fact achieve such ageneralization.

The key step in Shor’s algorithm is to implement the Fourier trans-form for the group â„€đż which is the set of numbers 0, 
 , 𝐿 − 1 withthe operation being addition modulo 𝐿. In this case it turns out thatthe Fourier characters are the functions 𝜒𝑩(đ‘„) = đœ”đ‘Šđ‘„ where 𝜔 = 𝑒2𝜋𝑖/𝐿(𝑖 here denotes the complex number

√−1). The 𝑩-th Fourier coeffi-cient of a function 𝑓 ∶ â„€đż → ℂ is𝑓(𝑩) = 1√𝐿 âˆ‘đ‘„âˆˆâ„€đż 𝑓(đ‘„)đœ”đ‘„đ‘Š . (23.25)

The key to implementing the Quantum Fourier Transform for suchgroups is to use the same recursive equations that enable the classicalFast Fourier Transform (FFT) algorithm. Specifically, consider the casethat 𝐿 = 2ℓ. We can separate the sum over đ‘„ in (23.25) to the termscorresponding to even đ‘„â€™s (of the form đ‘„ = 2𝑧) and odd đ‘„â€™s (of theform đ‘„ = 2𝑧 + 1) to obtain𝑓(𝑩) = 1√𝐿 ∑𝑧∈𝑍𝐿/2 𝑓(2𝑧)(𝜔2)𝑩𝑧 + 𝜔𝑩√𝐿 âˆ‘đ‘§âˆˆâ„€đż/2 𝑓(2𝑧 + 1)(𝜔2)𝑩𝑧 (23.26)

which reduces computing the Fourier transform of 𝑓 over the groupâ„€2ℓ to computing the Fourier transform of the functions 𝑓𝑒𝑣𝑒𝑛 and𝑓𝑜𝑑𝑑 (corresponding to the applying 𝑓 to only the even and odd đ‘„â€™srespectively) which have 2ℓ−1 inputs that we can identify with thegroup â„€2ℓ−1 = â„€đż/2.

Specifically, the Fourier characters of the group â„€đż/2 are the func-tions 𝜒𝑩(đ‘„) = 𝑒2𝜋𝑖/(𝐿/2)đ‘Šđ‘„ = (𝜔2)đ‘Šđ‘„ for every đ‘„, 𝑩 ∈ â„€đż/2. Moreover,since 𝜔𝐿 = 1, (𝜔2)𝑩 = (𝜔2)𝑩 mod 𝐿/2 for every 𝑩 ∈ ℕ. Thus (23.26)translates into𝑓(𝑩) = 𝑓𝑒𝑣𝑒𝑛(𝑩 mod 𝐿/2) + 𝜔𝑩 𝑓𝑜𝑑𝑑(𝑩 mod 𝐿/2) . (23.27)

This observation is usually used to obtain a fast (e.g. 𝑂(𝐿 log𝐿))time to compute the Fourier transform in a classical setting, but it can

Page 638: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

638 introduction to theoretical computer science

be used to obtain a quantum circuit of 𝑝𝑜𝑙𝑩(log𝐿) gates to transform astate of the form âˆ‘đ‘„âˆˆâ„€đż 𝑓(đ‘„)|đ‘„âŸ© to a state of the form âˆ‘đ‘Šâˆˆâ„€đż 𝑓(𝑩)|đ‘ŠâŸ©.

The case that 𝐿 is not an exact power of two causes some complica-tions in both the classical case of the Fast Fourier Transform and thequantum setting of Shor’s algorithm. However, it is possible to handlethese. The idea is that we can embed 𝑍𝐿 in the group â„€đŽâ‹…đż for anyinteger 𝐮, and we can find an integer 𝐮 such that 𝐮 ⋅ 𝐿 will be closeenough to a power of 2 (i.e., a number of the form 2𝑚 for some 𝑚), sothat if we do the Fourier transform over the group â„€2𝑚 then we willnot introduce too many errors.

Figure 23.7: Conjectured status of BQP with respect toother complexity classes. We know that P ⊆ BPP ⊆BQP and BQP ⊆ PSPACE ⊆ EXP. It is not known ifany of these inclusions are strict though it is believedthat they are. The relation between BQP and NP isunknown but they are believed to be incomparable,and that NP-complete problems can not be solved inpolynomial time by quantum computers. However, itis possible that BQP contains NP and even PSPACE,and it is also possible that quantum computersoffer no super-polynomial speedups and that P =BQP. The class “NISQ” above is not a well definedcomplexity class, but rather captures the currentstatus of quantum devices, which seem to be able tosolve a set of computational tasks that is incomparablewith the set of tasks solvable by classical computers.The diagram is also inaccurate in the sense that at themoment the “quantum supremacy” tasks on whichsuch devices seem to offer exponential speedupsdo not correspond to Boolean functions/ decisionproblems. Chapter Recap

‱ The state of an 𝑛-qubit quantum system can bemodeled as a 2𝑛 dimensional vector

‱ An operation on the state corresponds to applyinga unitary matrix to this vector.

‱ Quantum circuits are obtained by composing basicoperations such as HAD and đ‘ˆđ‘đŽđ‘đ·.

‱ We can use quantum circuits to define the classesBQP/poly and BQP which are the quantum analogsof P/poly and BPP respectively.

‱ There are some problems for which the best knownquantum algorithm is exponentially faster thanthe best known, but quantum computing is not apanacea. In particular, as far as we know, quantumcomputers could still require exponential time tosolve NP-complete problems such as SAT.

Page 639: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

quantum computing 639

7 You can use đ‘ˆđ‘đŽđ‘đ· to simulate NAND gates.

8 Use the alternative characterization of P as in SolvedExercise 13.4.9 You can use the HAD gate to simulate a coin toss.

10 In exponential time simulating quantum computa-tion boils down to matrix multiplication.11 If a reduction can be implemented in P it can beimplemented in BQP as well.

12 We are given ℎ = đ‘”đ‘„ and need to recover đ‘„. Todo so we can compute the order of various elementsof the form ℎ𝑎𝑔𝑏. The order of such an element isa number 𝑐 satisfying 𝑐(đ‘„đ‘Ž + 𝑏) = 0 (mod |đ”Ÿ|).With a few random examples we will get a non trivialequation on đ‘„ (where 𝑐 is not zero modulo |đ”Ÿ|) andthen we can use our knowledge of 𝑎, 𝑏, 𝑐 to recover đ‘„.

23.12 EXERCISES

Exercise 23.1 — Quantum and classical complexity class relations. Prove thefollowing relations between quantum complexity classes and classicalones:

1. P/poly ⊆ BQP/poly. See footnote for hint.7

2. P ⊆ BQP. See footnote for hint.8

3. BPP ⊆ BQP. See footnote for hint.9

4. BQP ⊆ EXP. See footnote for hint.10

5. If SAT ∈ BQP then NP ⊆ BQP. See footnote for hint.11

Exercise 23.2 — Discrete logarithm from order finding. Show a probabilisticpolynomial time classical algorithm that given an Abelian finite groupđ”Ÿ (in the form of an algorithm that computes the group operation),a generator 𝑔 for the group, and an element ℎ ∈ đ”Ÿ, as well as access toa black box that on input 𝑓 ∈ đ”Ÿ outputs the order of 𝑓 (the smallest 𝑎such that 𝑓𝑎 = 1), computes the discrete logarithm of ℎ with respect to𝑔. That is the algorithm should output a number đ‘„ such that đ‘”đ‘„ = ℎ.See footnote for hint.12

23.13 BIBLIOGRAPHICAL NOTES

An excellent gentle introduction to quantum computation is given inMermin’s book [Mer07]. In particular the first 100 pages (Chapter1 to 4) of [Mer07] cover all the material of this chapter in a muchmore comprehensive way. This material is also covered in the first5 chapters of De-Wolf’s online lecture notes. For a more condensedexposition, the chapter on quantum computation in my book withArora (see draft here) is one relatively short source that containsfull descriptions of Grover’s, Simon’s and Shor’s algorithms. Thisblog post of Aaronson contains a high level explanation of Shor’salgorithm which ends with links to several more detailed expositions.Chapters 9 and 10 in Aaronson’s book [Aar13] give an informal buthighly informative introduction to the topics of this chapter and muchmore. Chapter 10 in Avi Wigderson’s book also provides a high leveloverview of quantum computing. Other recommended resourcesinclude Andrew Childs’ lecture notes on quantum algorithms, aswell as the lecture notes of Umesh Vazirani, John Preskill, and JohnWatrous.

There are many excellent videos available online covering some ofthese materials. The videos of Umesh Vazirani’s EdX course are an

Page 640: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

640 introduction to theoretical computer science

accessible and recommended introduction to quantum computing.Regarding quantum mechanics in general, this video illustrates thedouble slit experiment, this Scientific American video is a nice ex-position of Bell’s Theorem. This talk and panel moderated by BrianGreene discusses some of the philosophical and technical issuesaround quantum mechanics and its so called “measurement prob-lem”. The Feynman lecture on the Fourier Transform and quantummechanics in general are very much worth reading. The Fourier trans-form is covered in these videos of Dr. Chris Geoscience, Clare Zhangand Vi Hart. See also Kelsey Houston-Edwards’s video on Shor’s Al-gorithm.

The form of Bell’s game we discuss in Section 23.3 was given byClauser, Horne, Shimony, and Holt.

The Fast Fourier Transform, used as a component in Shor’s algo-rithm, is one of the most widely used algorithms invented. The storiesof its discovery by Gauss in trying to calculate asteroid orbits andrediscovery by Tukey during the cold war are fascinating as well.

The image in Fig. 23.2 is taken from Wikipedia.Thanks to Scott Aaronson for many helpful comments about this

chapter.

Page 641: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

VIAPPENDICES

Page 642: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE
Page 643: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

Bibliography

[Aar05] Scott Aaronson. “NP-complete problems and physicalreality”. In: ACM Sigact News 36.1 (2005). Available onhttps://arxiv.org/abs/quant-ph/0502072, pp. 30–52.

[Aar13] Scott Aaronson. Quantum computing since Democritus.Cambridge University Press, 2013.

[Aar16] Scott Aaronson. “P =? NP”. In: Open problems in mathe-matics. Available on https://www.scottaaronson.com/papers/pnp.pdf. Springer, 2016, pp. 1–122.

[Aar20] Scott Aaronson. “The Busy Beaver Frontier”. In: SIGACTNews (2020). Available on https://www.scottaaronson.com/papers/bb.pdf.

[AKS04] Manindra Agrawal, Neeraj Kayal, and Nitin Saxena.“PRIMES is in P”. In: Annals of mathematics (2004),pp. 781–793.

[Asp18] James Aspens. Notes on Discrete Mathematics. Onlinetextbook for CS 202. Available on http://www.cs.yale.edu/homes/aspnes/classes/202/notes.pdf. 2018.

[Bar84] H. P. Barendregt. The lambda calculus : its syntax andsemantics. Amsterdam New York New York, N.Y: North-Holland Sole distributors for the U.S.A. and Canada,Elsevier Science Pub. Co, 1984. isbn: 0444875085.

[Bjo14] Andreas Bjorklund. “Determinant sums for undirectedhamiltonicity”. In: SIAM Journal on Computing 43.1(2014), pp. 280–299.

[BlĂ€13] Markus BlĂ€ser. Fast Matrix Multiplication. Graduate Sur-veys 5. Theory of Computing Library, 2013, pp. 1–60.doi : 10 . 4086/ toc .gs . 2013 .005. url: http : //www.theoryofcomputing.org/library.html.

[Boo47] George Boole. The mathematical analysis of logic. Philo-sophical Library, 1847.

Compiled on 8.26.2020 18:10

Page 644: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

644 introduction to theoretical computer science

[BU11] David Buchfuhrer and Christopher Umans. “The com-plexity of Boolean formula minimization”. In: Journal ofComputer and System Sciences 77.1 (2011), pp. 142–153.

[Bur78] Arthur W Burks. “Booke review: Charles S. Peirce, Thenew elements of mathematics”. In: Bulletin of the Ameri-can Mathematical Society 84.5 (1978), pp. 913–918.

[Cho56] Noam Chomsky. “Three models for the description oflanguage”. In: IRE Transactions on information theory 2.3(1956), pp. 113–124.

[Chu41] Alonzo Church. The calculi of lambda-conversion. Prince-ton London: Princeton University Press H. Milford,Oxford University Press, 1941. isbn: 978-0-691-08394-0.

[CM00] Bruce Collier and James MacLachlan. Charles Babbage:And the engines of perfection. Oxford University Press,2000.

[Coh08] Paul Cohen. Set theory and the continuum hypothesis. Mine-ola, N.Y: Dover Publications, 2008. isbn: 0486469212.

[Coh81] Danny Cohen. “On holy wars and a plea for peace”. In:Computer 14.10 (1981), pp. 48–54.

[Coo66] SA Cook. “On the minimum computation time for mul-tiplication”. In: Doctoral dissertation, Harvard UniversityDepartment of Mathematics, Cambridge, Mass. 1 (1966).

[Coo87] James W Cooley. “The re-discovery of the fast Fouriertransform algorithm”. In: Microchimica Acta 93.1-6(1987), pp. 33–45.

[Cor+09] Thomas H. Cormen et al. Introduction to Algorithms, 3rdEdition. MIT Press, 2009. isbn: 978-0-262-03384-8. url:http://mitpress.mit.edu/books/introduction-algorithms.

[CR73] Stephen A Cook and Robert A Reckhow. “Time boundedrandom access machines”. In: Journal of Computer andSystem Sciences 7.4 (1973), pp. 354–375.

[CRT06] Emmanuel J Candes, Justin K Romberg, and Terence Tao.“Stable signal recovery from incomplete and inaccuratemeasurements”. In: Communications on Pure and AppliedMathematics: A Journal Issued by the Courant Institute ofMathematical Sciences 59.8 (2006), pp. 1207–1223.

[CT06] Thomas M. Cover and Joy A. Thomas. “Elements ofinformation theory 2nd edition”. In: Willey-Interscience:NJ (2006).

[Dau90] Joseph Warren Dauben. Georg Cantor: His mathematics andphilosophy of the infinite. Princeton University Press, 1990.

Page 645: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

BIBLIOGRAPHY 645

[De 47] Augustus De Morgan. Formal logic: or, the calculus ofinference, necessary and probable. Taylor and Walton, 1847.

[Don06] David L Donoho. “Compressed sensing”. In: IEEE Trans-actions on information theory 52.4 (2006), pp. 1289–1306.

[DPV08] Sanjoy Dasgupta, Christos H. Papadimitriou, and UmeshV. Vazirani. Algorithms. McGraw-Hill, 2008. isbn: 978-0-07-352340-8.

[Ell10] Jordan Ellenberg. “Fill in the blanks: Using math to turnlo-res datasets into hi-res samples”. In: Wired Magazine18.3 (2010), pp. 501–509.

[Ern09] Elizabeth Ann Ernst. “Optimal combinational multi-level logic synthesis”. Available on https://deepblue.lib .umich .edu/handle/2027 .42/62373. PhD thesis.University of Michigan, 2009.

[Fle18] Margaret M. Fleck. Building Blocks for Theoretical Com-puter Science. Online book, available at http://mfleck.cs.illinois.edu/building-blocks/. 2018.

[FĂŒr07] Martin FĂŒrer. “Faster integer multiplication”. In: Pro-ceedings of the 39th Annual ACM Symposium on Theory ofComputing, San Diego, California, USA, June 11-13, 2007.2007, pp. 57–66.

[FW93] Michael L Fredman and Dan E Willard. “Surpassingthe information theoretic bound with fusion trees”.In: Journal of computer and system sciences 47.3 (1993),pp. 424–436.

[GKS17] Daniel GĂŒnther, Ágnes Kiss, and Thomas Schneider.“More efficient universal circuit constructions”. In: Inter-national Conference on the Theory and Application of Cryp-tology and Information Security. Springer. 2017, pp. 443–470.

[Gom+08] Carla P Gomes et al. “Satisfiability solvers”. In: Founda-tions of Artificial Intelligence 3 (2008), pp. 89–134.

[Gra05] Judith Grabiner. The origins of Cauchy’s rigorous cal-culus. Mineola, N.Y: Dover Publications, 2005. isbn:9780486438153.

[Gra83] Judith V Grabiner. “Who gave you the epsilon? Cauchyand the origins of rigorous calculus”. In: The AmericanMathematical Monthly 90.3 (1983), pp. 185–194.

[Hag98] Torben Hagerup. “Sorting and searching on the wordRAM”. In: Annual Symposium on Theoretical Aspects ofComputer Science. Springer. 1998, pp. 366–398.

Page 646: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

646 introduction to theoretical computer science

[Hal60] Paul R Halmos. Naive set theory. Republished in 2017 byCourier Dover Publications. 1960.

[Har41] GH Hardy. “A Mathematician’s Apology”. In: (1941).[HJB85] Michael T Heideman, Don H Johnson, and C Sidney

Burrus. “Gauss and the history of the fast Fourier trans-form”. In: Archive for history of exact sciences 34.3 (1985),pp. 265–277.

[HMU14] John Hopcroft, Rajeev Motwani, and Jeffrey Ullman.Introduction to automata theory, languages, and compu-tation. Harlow, Essex: Pearson Education, 2014. isbn:1292039051.

[Hof99] Douglas Hofstadter. Gödel, Escher, Bach : an eternal goldenbraid. New York: Basic Books, 1999. isbn: 0465026567.

[Hol01] Jim Holt. “The Ada perplex: how Byron’s daughter cameto be celebrated as a cybervisionary”. In: The New Yorker5 (2001), pp. 88–93.

[Hol18] Jim Holt. When Einstein walked with Gödel : excursions tothe edge of thought. New York: Farrar, Straus and Giroux,2018. isbn: 0374146705.

[HU69] John E Hopcroft and Jeffrey D Ullman. “Formal lan-guages and their relation to automata”. In: (1969).

[HU79] John E. Hopcroft and Jeffrey D. Ullman. Introduction toAutomata Theory, Languages and Computation. Addison-Wesley, 1979. isbn: 0-201-02988-X.

[HV19] David Harvey and Joris Van Der Hoeven. “Integer multi-plication in time O(n log n)”. working paper or preprint.Mar. 2019. url: https://hal.archives-ouvertes.fr/hal-02070778.

[Joh12] David S Johnson. “A brief history of NP-completeness,1954–2012”. In: Documenta Mathematica (2012), pp. 359–376.

[Juk12] Stasys Jukna. Boolean function complexity: advances andfrontiers. Vol. 27. Springer Science & Business Media,2012.

[Kar+97] David R. Karger et al. “Consistent Hashing and RandomTrees: Distributed Caching Protocols for Relieving HotSpots on the World Wide Web”. In: Proceedings of theTwenty-Ninth Annual ACM Symposium on the Theory ofComputing, El Paso, Texas, USA, May 4-6, 1997. 1997,pp. 654–663. doi : 10.1145/258533.258660. url: https://doi.org/10.1145/258533.258660.

Page 647: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

BIBLIOGRAPHY 647

[Kar95] ANATOLII ALEXEEVICH Karatsuba. “The complexityof computations”. In: Proceedings of the Steklov Institute ofMathematics-Interperiodica Translation 211 (1995), pp. 169–183.

[Kle91] Israel Kleiner. “Rigor and Proof in Mathematics: AHistorical Perspective”. In: Mathematics Magazine 64.5(1991), pp. 291–314. issn: 0025570X, 19300980. url:http://www.jstor.org/stable/2690647.

[Kle99] Jon M Kleinberg. “Authoritative sources in a hyper-linked environment”. In: Journal of the ACM (JACM) 46.5(1999), pp. 604–632.

[Koz97] Dexter Kozen. Automata and computability. New York:Springer, 1997. isbn: 978-3-642-85706-5.

[KT06] Jon M. Kleinberg and Éva Tardos. Algorithm design.Addison-Wesley, 2006. isbn: 978-0-321-37291-8.

[Kun18] Jeremy Kun. A programmer’s introduction to mathematics.Middletown, DE: CreateSpace Independent PublishingPlatform, 2018. isbn: 1727125452.

[Liv05] Mario Livio. The equation that couldn’t be solved : howmathematical genius discovered the language of symmetry.New York: Simon & Schuster, 2005. isbn: 0743258207.

[LLM18] Eric Lehman, Thomson F. Leighton, and Albert R. Meyer.Mathematics for Computer Science. 2018.

[LMS16] Helger Lipmaa, Payman Mohassel, and Seyed SaeedSadeghian. “Valiant’s Universal Circuit: Improvements,Implementation, and Applications.” In: IACR CryptologyePrint Archive 2016 (2016), p. 17.

[Lup58] O Lupanov. “A circuit synthesis method”. In: Izv. Vuzov,Radiofizika 1.1 (1958), pp. 120–130.

[Lup84] Oleg B. Lupanov. Asymptotic complexity bounds for controlcircuits. In Russian. MSU, 1984.

[Lus+08] Michael Lustig et al. “Compressed sensing MRI”. In:IEEE signal processing magazine 25.2 (2008), pp. 72–82.

[LĂŒt02] Jesper LĂŒtzen. “Between Rigor and Applications: De-velopments in the Concept of Function in MathematicalAnalysis”. In: The Cambridge History of Science. Ed. byMary JoEditor Nye. Vol. 5. The Cambridge History ofScience. Cambridge University Press, 2002, pp. 468–487.doi : 10.1017/CHOL9780521571999.026.

Page 648: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

648 introduction to theoretical computer science

[LZ19] Harry Lewis and Rachel Zax. Essential Discrete Mathemat-ics for Computer Science. Princeton University Press, 2019.isbn: 9780691190617.

[Maa85] Wolfgang Maass. “Combinatorial lower bound argu-ments for deterministic and nondeterministic Turingmachines”. In: Transactions of the American MathematicalSociety 292.2 (1985), pp. 675–693.

[Mer07] N David Mermin. Quantum computer science: an introduc-tion. Cambridge University Press, 2007.

[MM11] Cristopher Moore and Stephan Mertens. The nature ofcomputation. Oxford University Press, 2011.

[MP43] Warren S McCulloch and Walter Pitts. “A logical calcu-lus of the ideas immanent in nervous activity”. In: Thebulletin of mathematical biophysics 5.4 (1943), pp. 115–133.

[MR95] Rajeev Motwani and Prabhakar Raghavan. Randomizedalgorithms. Cambridge university press, 1995.

[MU17] Michael Mitzenmacher and Eli Upfal. Probability andcomputing: randomization and probabilistic techniques inalgorithms and data analysis. Cambridge university press,2017.

[Neu45] John von Neumann. “First Draft of a Report on the ED-VAC”. In: (1945). Reprinted in the IEEE Annals of theHistory of Computing journal, 1993.

[NS05] Noam Nisan and Shimon Schocken. The elements of com-puting systems: building a modern computer from first princi-ples. MIT press, 2005.

[Pag+99] Lawrence Page et al. The PageRank citation ranking: Bring-ing order to the web. Tech. rep. Stanford InfoLab, 1999.

[Pie02] Benjamin Pierce. Types and programming languages. Cam-bridge, Mass: MIT Press, 2002. isbn: 0262162091.

[Ric53] Henry Gordon Rice. “Classes of recursively enumerablesets and their decision problems”. In: Transactions of theAmerican Mathematical Society 74.2 (1953), pp. 358–366.

[Rog96] Yurii Rogozhin. “Small universal Turing machines”. In:Theoretical Computer Science 168.2 (1996), pp. 215–240.

[Ros19] Kenneth Rosen. Discrete mathematics and its applications.New York, NY: McGraw-Hill, 2019. isbn: 125967651x.

[RS59] Michael O Rabin and Dana Scott. “Finite automata andtheir decision problems”. In: IBM journal of research anddevelopment 3.2 (1959), pp. 114–125.

Page 649: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

BIBLIOGRAPHY 649

[Sav98] John E Savage. Models of computation. Vol. 136. Availableelectronically at http://cs.brown.edu/people/jsavage/book/. Addison-Wesley Reading, MA, 1998.

[Sch05] Alexander Schrijver. “On the history of combinatorialoptimization (till 1960)”. In: Handbooks in operationsresearch and management science 12 (2005), pp. 1–68.

[Sha38] Claude E Shannon. “A symbolic analysis of relay andswitching circuits”. In: Electrical Engineering 57.12 (1938),pp. 713–723.

[Sha79] Adi Shamir. “Factoring numbers in O (logn) arith-metic steps”. In: Information Processing Letters 8.1 (1979),pp. 28–31.

[She03] Saharon Shelah. “Logical dreams”. In: Bulletin of theAmerican Mathematical Society 40.2 (2003), pp. 203–228.

[She13] Henry Maurice Sheffer. “A set of five independent pos-tulates for Boolean algebras, with application to logicalconstants”. In: Transactions of the American mathematicalsociety 14.4 (1913), pp. 481–488.

[She16] Margot Shetterly. Hidden figures : the American dream andthe untold story of the Black women mathematicians whohelped win the space race. New York, NY: William Morrow,2016. isbn: 9780062363602.

[Sin97] Simon Singh. Fermat’s enigma : the quest to solve the world’sgreatest mathematical problem. New York: Walker, 1997.isbn: 0385493622.

[Sip97] Michael Sipser. Introduction to the theory of computation.PWS Publishing Company, 1997. isbn: 978-0-534-94728-6.

[Sob17] Dava Sobel. The Glass Universe : How the Ladies of theHarvard Observatory Took the Measure of the Stars. NewYork: Penguin Books, 2017. isbn: 9780143111344.

[Sol14] Daniel Solow. How to read and do proofs : an introductionto mathematical thought processes. Hoboken, New Jersey:John Wiley & Sons, Inc, 2014. isbn: 9781118164020.

[SS71] Arnold Schönhage and Volker Strassen. “Schnelle mul-tiplikation grosser zahlen”. In: Computing 7.3-4 (1971),pp. 281–292.

[Ste87] Dorothy Stein. Ada : a life and a legacy. Cambridge, Mass:MIT Press, 1987. isbn: 0262691167.

[Str69] Volker Strassen. “Gaussian elimination is not optimal”.In: Numerische mathematik 13.4 (1969), pp. 354–356.

Page 650: INTRODUCTIONTO THEORETICAL COMPUTERSCIENCE

650 introduction to theoretical computer science

[Swa02] Doron Swade. The difference engine : Charles Babbage andthe quest to build the first computer. New York: PenguinBooks, 2002. isbn: 0142001449.

[Tho84] Ken Thompson. “Reflections on trusting trust”. In: Com-munications of the ACM 27.8 (1984), pp. 761–763.

[Too63] Andrei L Toom. “The complexity of a scheme of func-tional elements realizing the multiplication of integers”.In: Soviet Mathematics Doklady. Vol. 3. 4. 1963, pp. 714–716.

[Tur37] Alan M Turing. “On computable numbers, with an ap-plication to the Entscheidungsproblem”. In: Proceedingsof the London mathematical society 2.1 (1937), pp. 230–265.

[Vad+12] Salil P Vadhan et al. “Pseudorandomness”. In: Founda-tions and Trends¼ in Theoretical Computer Science 7.1–3(2012), pp. 1–336.

[Val76] Leslie G Valiant. “Universal circuits (preliminary re-port)”. In: Proceedings of the eighth annual ACM sympo-sium on Theory of computing. ACM. 1976, pp. 196–203.

[Wan57] Hao Wang. “A variant to Turing’s theory of computingmachines”. In: Journal of the ACM (JACM) 4.1 (1957),pp. 63–92.

[Weg87] Ingo Wegener. The complexity of Boolean functions. Vol. 1.BG Teubner Stuttgart, 1987.

[Wer74] PJ Werbos. “Beyond regression: New tools for predictionand analysis in the behavioral sciences. Ph. D. thesis,Harvard University, Cambridge, MA, 1974.” In: (1974).

[Wig19] Avi Wigderson. Mathematics and Computation. Draftavailable on https://www.math.ias.edu/avi/book.Princeton University Press, 2019.

[Wil09] Ryan Williams. “Finding paths of length k in 𝑂∗(2𝑘)time”. In: Information Processing Letters 109.6 (2009),pp. 315–318.

[WN09] Damien Woods and Turlough Neary. “The complex-ity of small universal Turing machines: A survey”. In:Theoretical Computer Science 410.4-5 (2009), pp. 443–450.

[WR12] Alfred North Whitehead and Bertrand Russell. Principiamathematica. Vol. 2. University Press, 1912.