4.6.22 · D2Theory of Computation

Visual walkthrough — P — polynomial time

2,571 words12 min readBack to topic

Parent: P — polynomial time · this page rebuilds the central claim — "a problem is in P when we can bound its step-count by a polynomial in the input's length" — from absolute zero, one picture at a time.

We are going to prove, in slow motion, why the same problem (deciding whether a number is prime) can look "easy" and yet fail to be a proof that it lives in P — and what a real P-proof looks like. Along the way every word (input, length, step, polynomial, exponential) gets earned before it is used.


Step 1 — What is an "input", and what is its size?

WHAT. A computer never sees a "number" or a "graph" directly. It sees a string of symbols you typed to describe it — a row of boxes, each holding one character (a or a , say). The input is that row of boxes.

WHY. Everything we measure — time, memory — will be measured against how big this row is, so we must pin down "big" precisely before doing anything else. We call the number of boxes the input length and write it .

PICTURE. Below, the same idea (the number "thirteen") is written two ways. On top it is one lonely symbol; underneath it is the row of bits a machine actually stores. Count the boxes — that is .

Figure — P — polynomial time

Notation earned so far: = the input string, = how many boxes it fills.


Step 2 — What is a "step", and what is "time"?

WHAT. A Turing Machine does exactly one tiny thing per tick: read the box under its head, maybe write a symbol, move one box left or right. Each tick is one step. The running time is just how many ticks pass before the machine stops and answers.

Throughout this page the machine is deterministic: from each configuration there is exactly one next move (no guessing, no branching). This matters because the class P is defined precisely as deterministic polynomial time — the guessing version lives in NP — nondeterministic polynomial time, a different club.

WHY. We want a count that does not depend on your particular laptop's clock speed — a machine-independent tally. Counting steps (not seconds) does that. Two boxes moved = two steps, whether your CPU is fast or slow.

PICTURE. Watch the head crawl across the tape. Each red hop is one step; the counter on the right ticks up.

Figure — P — polynomial time

Step 3 — Two families of growth: polynomial vs exponential

WHAT. We compare two shapes a step-count can take as grows:

  • polynomial: — like , . Symbol is a fixed whole number, the exponent, decided once and never changing.
  • exponential: — here is up in the exponent, so it drives the growth.

WHY this comparison and not another? Because the whole point of complexity theory is separating "the work grows steadily" from "the work explodes". Polynomials grow steadily; putting in the exponent makes the count double for every extra box. That doubling is the wall we want to detect.

PICTURE. The lavender curve and the coral curve start close, then the coral one shoots off the top of the chart. Notice where they cross — after that, exponential is hopeless forever.

Figure — P — polynomial time

Term by term: is a fixed multiplier (hardware slack), is the polynomial ceiling, says "never worse than this".


Step 3½ — A word we're about to lean on: Big-O

WHAT. Before Step 4 we need one shorthand. When we write — read "big-O of of " — we mean: "grows no faster than , once you allow a constant multiplier and ignore small inputs."

WHY this tool and not exact counts? Because the exact step-count depends on fussy details (which tape model, how you break ties) that we deliberately don't care about — remember from Step 2 we only want a machine-robust shape of growth. Big-O throws away the constant and the low-order clutter and keeps only the shape.

So " work" just means "at most (some constant) steps"; the constant is swept under the rug on purpose. See Time complexity & Big-O for more.


Step 4 — Worked case that works: is there an path? (in P)

WHAT. Given a graph, ask: can I walk from vertex to vertex ? We run Breadth-First Search — flood outward from one ring at a time and see if the flood reaches .

First, two names we will count with:

  • = the number of dots in the graph;
  • = the number of lines connecting dots.

WHY BFS and why count this way? Because we don't guess membership in P — we count steps and bound them (now using the Big-O shorthand from Step 3½). BFS touches each vertex once and each edge a constant number of times, so its count is easy to bound.

PICTURE. The flood spreads in coloured rings. Every vertex lights up once (mint), every edge is crossed at most twice (coral). Tally them.

Figure — P — polynomial time

Why — spelling out the encoding. We must pin down how the graph is written down before we can compare to . Writing a graph on vertices means naming vertices, and each distinct name needs bits to distinguish it from the others.

  • Adjacency-matrix encoding: you write a grid of entries (entry if an edge exists), so the string is exactly symbols → .
  • Adjacency-list encoding: you list, for each vertex, its neighbours' labels; each of the vertices contributes at least its own -bit label, so .

Under either reasonable encoding, . And since a graph on vertices has at most edges, we get . (Even the extra -bit label handling per step only multiplies the count by a further factor, which is still polynomial.) So BFS runs in steps (poly even with bit-level bookkeeping) — a polynomial in . ✅ Reachability P.


Step 5 — The trap case: is prime by trial division? (looks fast, isn't)

WHAT. Here the input string is the ==binary encoding of an integer == — so is a row of bits (exactly the "value vs length" split from Step 1, with the value and the length). To test if is prime, try dividing by every candidate up to . That's about divisions. Small number of operations... right?

WHY it's a trap — reason one (the value/length gap). Remember Step 1: time is measured against length , not the value . Since , we have: and for near the top of its bit-range this is . The number of divisions is already exponential in ! It only looked small because we compared it to the giant value instead of the tiny length .

WHY it's a trap — reason two (each division isn't free). On a deterministic Turing Machine, dividing two -bit numbers is not one step — it costs bit-operations (schoolbook long division is bit-steps). So the honest total is which is even worse — still dominated by the exponential . Adding the true bit-cost only makes trial division more clearly non-polynomial.

PICTURE. The horror in one frame: the input box is short (few bits), but the work bar next to it towers, because it scales with , not with .

Figure — P — polynomial time

Step 6 — The real proof: PRIMES ∈ P via a genuinely poly-in- method

WHAT. Being in P never depends on your first algorithm — only on whether some deterministic algorithm has a polynomial step-count in . For primality (input the -bit encoding of ), the AKS algorithm (2002) runs in time polynomial in , counting real bit-operations.

How poly, concretely? AKS is not just "poly" hand-waved — it has an explicit exponent. The original bound is (up to logarithmic factors) bit-operations; later refinements push it to about . Either way the exponent is a fixed constant — that is exactly the " with fixed" shape from Step 3, so it is genuinely in P.

WHY this fixes Step 5. Step 5's honest count was (off the chart because of the exponential factor). AKS's count is a tame with (or ) — big exponent, but fixed. Same problem, different algorithm — and one polynomial algorithm is all P ever requires.

PICTURE. Both attempts on one axis measured correctly against : trial division's coral exponential wall vs AKS's lavender polynomial curve hugging the floor.

Figure — P — polynomial time

Step 7 — Why "polynomial" is the right fence (closure)

WHAT. Suppose subroutine runs in steps and you call it inside algorithm that itself does rounds. Total work multiplies:

WHY this seals the deal. is still a polynomial — a fixed exponent. Poly-inside-poly stays poly. This closure is why P is stable: combine efficient pieces, stay efficient. Exponential time has no such clean rule, which is the real reason the fence is drawn at "polynomial" (this is the spirit of the Cobham–Edmonds thesis, and it's what makes P robust across every deterministic model — see TIME complexity classes).

PICTURE. Poly boxes nesting inside poly boxes — and the outermost box is still just a polynomial box.

Figure — P — polynomial time

The one-picture summary

One decision axis: convert every algorithm's step-count into a function of the length (counting real bit-operations), then read off which side of the polynomial/exponential fence it lands on. Reachability and AKS land in P; trial division, measured honestly, does not.

Figure — P — polynomial time
Recall Feynman: the whole walk in plain words

First we agreed a puzzle is really just the row of letters you typed to describe it, and its "size" is how many letters that is (Step 1). A "step" is one tick of a tiny deterministic machine — one that never guesses — and "time" is how many ticks (Step 2). Then we drew two growth shapes: steady and explosive — the only difference is whether sits in the base or up in the exponent (Step 3). We introduced Big-O as a way to say "no faster than this shape, ignoring the constant" (Step 3½). We proved graph-walking is steady by counting: each dot () once, each line () twice (Step 4). Then the sneaky bit: the input is the binary encoding of a number , written in only boxes, so trying divisors up to is really divisions — and each division itself costs poly-many bit-steps — an explosion in disguise (Step 5). The honest fix is a cleverer method (AKS, about bit-operations) that really is steady in (Step 6). And the reason "steady = polynomial" is the right rule: steady-inside-steady is still steady, so you can build big efficient programs out of small ones (Step 7). Motto: bits, not value.

Convert into a function of bit-length
, exponential in (and each division adds a poly- bit-cost on top).
What does mean formally?
There are constants with for all — "no faster than , ignoring the constant and small inputs".
Why is P closed under composing poly algorithms?
inside gives , still a fixed-exponent polynomial.
What is the membership rule for P?
Exhibit one deterministic machine whose step-count, expressed in (counting real bit-operations), is bounded by some .

Connections

  • Parent: P — polynomial time
  • NP — nondeterministic polynomial time
  • P vs NP problem
  • Polynomial-time reductions
  • NP-complete problems
  • Time complexity & Big-O
  • Turing Machine
  • Cobham–Edmonds thesis
  • TIME complexity classes