1. Intrinsic Hardness
Understanding the limits of efficient computation.
2. Hardness as a Shield
Modern Cryptography relies on hard problems!
3. Coping with Limits
Mapping the landscape reveals alternatives:
The Church–Turing Thesis
Every physically realizable computation can be simulated by a standard Turing machine.
Crucial insight: Code is just data.
We can sort all binary strings lexicographically: M_1, M_2, M_3, M_4, \dots
Every string encodes some TM. (Invalid syntax maps to a dummy machine that rejects immediately.)
Every program is an integer; every integer is a program.
Can one machine execute any algorithm?
┌──────────────────────────────┐
<M>, x ───────►│ Universal Turing Machine U ├───────► M(x)
│ │
│ Tape 1: Code <M> │
│ Tape 2: Simulated Tape │
│ Tape 3: State of M │
└──────────────────────────────┘
Theorem (Turing 1936)
There exists a fixed Universal Turing Machine \mathcal{U} such that for every machine M and input x: \mathcal{U}(\langle M \rangle, x) = M(x) If M(x) halts, \mathcal{U}(\langle M \rangle, x) halts with the identical output. If M(x) loops, \mathcal{U} loops.
How much does universal emulation cost?
Using two tapes and binary search addressing:
Hennie–Stearns Simulation (1966)
If M halts in T steps on input x, a 2-tape Universal TM simulates it in: O(T \log T) \text{ steps}
Takeaway for Complexity
Universal simulation incurs only an almost linear time overhead.
A polynomial runtime remains a polynomial runtime!
How do we prove that certain problems are impossible for any machine?
Consider an infinite grid where:
| Machine | x_1 | x_2 | x_3 | x_4 | \dots |
|---|---|---|---|---|---|
| M_1 | 0 | 1 | 0 | 0 | \dots |
| M_2 | 1 | 1 | 1 | 0 | \dots |
| M_3 | 0 | 0 | 0 | 1 | \dots |
| M_4 | 1 | 0 | 1 | 1 | \dots |
Define a new language D: On input x_i, flip the diagonal element! x_i \in D \iff M_i(x_i) \text{ does not accept}
Proof by Contradiction
Suppose some Turing machine M_d decides D.
x_d \in D \iff M_d(x_d) \text{ accepts} \quad (\text{by definition of } M_d \text{ deciding } D)
\text{Yet by definition of } D: \quad x_d \in D \iff M_d(x_d) \text{ does not accept!}
\text{Accepts} \iff \text{Does not accept} \quad \implies \mathbf{Contradiction!}
D cannot have any row in the table. D is uncomputable.
Diagonalization proves uncomputability (\text{HALT} \notin \mathbf{R}).
Can we use it inside complexity to show more time buys more computational power?
Does granting n^{100} time allow us to solve strictly more problems than n^2 time?
\mathbf{DTIME}(n^2) \stackrel{?}{\subsetneq} \mathbf{DTIME}(n^{100})
A machine with more time must simulate machines with less time, but it must abort them before they exceed their clock!
To diagonalize within time bounds, we introduce a clocked simulation:
Input: <M>, x
│
├─► Start clock for t(|x|) steps
│
├─► Universal Simulator U runs M(x)
│
├─── If M(x) halts within t(|x|) steps:
│ Output OPPOSITE of M(x)
│
└─── If clock expires before M halts:
REJECT and abort
Time Hierarchy Theorem (Hartmanis & Stearns 1965)
For any time-constructible functions t_1(n) and t_2(n) satisfying: t_1(n) \log(t_1(n)) = o(t_2(n)) we have: \mathbf{DTIME}(t_1(n)) \subsetneq \mathbf{DTIME}(t_2(n))
What does the Time Hierarchy imply about polynomial time vs. exponential time?
\mathbf{P} = \bigcup_{k \ge 1} \mathbf{DTIME}(n^k) \qquad \text{vs.} \qquad \mathbf{EXP} = \bigcup_{c \ge 1} \mathbf{DTIME}(2^{n^c})
Corollary: P is Strictly Contained in EXP
\mathbf{P} \subsetneq \mathbf{EXP}
Diagonalization is a profound tool, but it has a fundamental boundary:
CS G526: Advanced Algorithms & ComplexityTulasimohan Molli