Machine Learning

Markov Decision Processes: The Math of Making Good Choices

A warehouse robot at a fork in the aisle. A poker bot deciding whether to fold. A datacenter scheduler choosing which VM to migrate. Strip away the domain and each faces the identical problem: pick an action now to maximize reward accumulated over an uncertain future. The Markov Decision Process (MDP) — formalized by Richard Bellman in 1957 — is the mathematical object that makes this precise, and its central equation is so foundational that it underpins everything from Q-learning to AlphaGo to the RLHF loop that fine-tuned this model.

The surprise is how cheaply it can be solved. Given the transition and reward tables, the optimal policy for a problem with |S| states and |A| actions falls out of a fixed-point iteration that converges geometrically — each sweep costs O(|S|²·|A|) and shrinks the error by a factor of γ. Value iteration and policy iteration turn "making good choices under uncertainty" into linear algebra.

  • InventedBellman, 1957 (dynamic programming)
  • Defined by⟨S, A, P, R, γ⟩
  • Value iter / sweepO(|S|²·|A|) time
  • Policy iter / stepO(|S|³ + |S|²·|A|)
  • Convergencegeometric, rate γ
  • Key invariantBellman optimality fixed point

Interactive visualization

Press play, or step through manually. The visualization is yours to drive — try it before reading on.

Open visualization fullscreen ↗

Watch the 60-second explainer

A condensed visual walkthrough — narrated, captioned, under a minute.

The core idea: memoryless state plus the Bellman fixed point

An MDP is a 5-tuple ⟨S, A, P, R, γ⟩: a set of states S, a set of actions A, a transition kernel P(s′ | s, a), a reward function R(s, a), and a discount factor γ ∈ [0, 1). The name comes from the Markov property: the distribution over the next state depends only on the current state and action, not on the entire history. That single assumption — memorylessness — is what makes the whole problem tractable, because it lets the future be summarized by one number per state.

That number is the value function V(s): the expected discounted return if you start in s and act optimally forever. The invariant every solver maintains is the Bellman optimality equation, a self-consistency condition the optimal V* must satisfy:

V*(s) = max over a ∈ A of [ R(s,a) + γ · Σ over s′ of P(s′|s,a) · V*(s′) ]

Read it as: the best you can do from s is the best immediate reward plus the discounted best-you-can-do from wherever you land. Because γ < 1, the operator that maps V to the right-hand side is a γ-contraction in the sup-norm — apply it repeatedly and successive value functions get closer by a factor of γ each time, so a unique fixed point exists (Banach). Solving the MDP means finding that fixed point, then reading off the greedy action per state as the optimal policy π*.

Value iteration, step by step

Value iteration just applies the Bellman operator as an assignment until it stops changing. Start from any V₀ (zeros work), then repeatedly compute a full Bellman backup for every state:

function ValueIteration(S, A, P, R, γ, ε):
    V = array of 0.0, size |S|
    repeat:
        Δ = 0
        for s in S:
            v_old = V[s]
            V[s] = max over a of ( R[s,a] + γ · Σ_s′ P[s′|s,a] · V[s′] )
            Δ = max(Δ, |v_old − V[s]|)
    until Δ < ε·(1−γ)/γ          # stopping rule bounds ‖V − V*‖_∞
    π[s] = argmax over a of ( R[s,a] + γ · Σ_s′ P[s′|s,a] · V[s′] )
    return π, V
  • Backup: the inner max/argmax over actions is a one-step lookahead; each action's value is a dot product of the transition row P(·|s,a) with the current V.
  • Sweep: one pass over all states is one iteration; you may do it in-place (Gauss–Seidel, often faster) or with a fresh copy (Jacobi).
  • Stopping rule: when the max change Δ per sweep is small, the Bellman residual bound guarantees ‖V − V*‖∞ ≤ γΔ/(1−γ). This is the precise handle on "close enough."

The output policy is greedy with respect to the converged value. Crucially, you extract π only once at the end — the algorithm never stores a policy while iterating, which is what distinguishes it from policy iteration.

Policy iteration: evaluate, then improve

Policy iteration (Howard, 1960) alternates two phases and typically converges in far fewer outer iterations than value iteration:

  • Policy evaluation: fix the current policy π and solve for its exact value Vπ. Since π picks one action per state, the Bellman equation becomes linear: Vπ = Rπ + γPπVπ, i.e. (I − γPπ)Vπ = Rπ. Solve this |S|×|S| system directly in O(|S|³), or iterate it cheaply.
  • Policy improvement: for each state, set π(s) to the greedy action under Vπ. The policy improvement theorem guarantees the new policy is at least as good in every state, and strictly better somewhere unless it's already optimal.

The loop is: evaluate → improve → repeat until the policy stops changing. The key invariant is monotonic improvement — the value never decreases across iterations, and because there are only finitely many deterministic policies (|A|^|S| of them), the process must terminate at π*. The classic bound was exponential in the worst case, but Ye (2011) proved policy iteration (and the simplex method it generalizes) is strongly polynomial for fixed γ, needing O(|S|²·|A|/(1−γ) · log(|S|/(1−γ))) iterations.

Modified policy iteration splits the difference: instead of solving evaluation exactly, run k sweeps of the linear Bellman backup, giving a knob between value iteration (k=1) and full policy iteration (k=∞).

Complexity: why it converges geometrically

Per-sweep time. A single value-iteration sweep evaluates, for every state–action pair, a sum over successor states: |S| states × |A| actions × |S| successors = O(|S|²·|A|) time, O(|S|) space for V (plus the transition table you already hold). If P is sparse with at most b successors per (s,a) — common in gridworlds and games — a sweep drops to O(|S|·|A|·b), a huge constant-factor win.

Iteration count. Because the Bellman operator contracts by γ, the error after n sweeps is ≤ γⁿ·‖V₀ − V*‖∞. To reach accuracy ε you need roughly n = O( log(1/(ε(1−γ))) / (1−γ) ) sweeps. The (1−γ) in the denominator is the villain: as γ → 1 (you care about the far future), the effective horizon 1/(1−γ) blows up and convergence crawls. Total value-iteration cost is therefore about O( |S|²·|A| · log(1/ε) / (1−γ) ).

Policy iteration trades many cheap sweeps for few expensive ones: each outer step pays O(|S|³) for the linear solve (or O(|S|²·|A|) for the improvement), but the outer-iteration count is tiny and, per Ye, polynomial regardless of γ. The curse of dimensionality looms over all of it: |S| is usually the product of state-variable ranges, so a problem with d variables each taking m values has |S| = m^d states — the tables themselves become infeasible long before the per-sweep math does. That's exactly the wall that function approximation (neural nets, tile coding) exists to break.

Where MDPs actually run

The MDP is the substrate under nearly all of modern reinforcement learning, and its exact solvers ship in real systems:

  • Reinforcement learning: when P and R are unknown, you can't do Bellman backups directly — so Q-learning and SARSA estimate Q(s,a) from sampled transitions, and Deep Q-Networks replace the table with a CNN. Every one of these is solving an MDP; they just learn the model implicitly. RLHF, which aligns large language models, frames token generation as an MDP and optimizes it with PPO.
  • Operations research: inventory control, equipment maintenance/replacement, and queue admission are textbook MDPs solved by policy iteration in tools like Python's pymdptoolbox.
  • Robotics and control: motion planning under uncertainty, often as the partially observable extension (POMDP), where the agent maintains a belief distribution over states because it can't see s directly.
  • Systems: adaptive bitrate streaming, congestion control, cache admission, and cluster schedulers have all been cast as MDPs; Google's datacenter cooling and several RL-based query optimizers are production examples.

The standard references are Bellman's Dynamic Programming (1957), Puterman's Markov Decision Processes (1994), and Sutton & Barto's Reinforcement Learning: An Introduction — the last being the canonical bridge from MDP theory to learning.

Pitfalls, edge cases, and variants

γ = 1 breaks the contraction. With no discount the Bellman operator is no longer a contraction and value iteration need not converge; returns can be infinite in cyclic MDPs. Undiscounted problems require the average-reward or total-reward (episodic, proper-policy) formulations, or a proof that all policies reach an absorbing terminal state.

  • Reward scaling & γ tuning: γ near 1 makes convergence glacial and amplifies estimation error; γ too small makes the agent myopic. The effective horizon is ≈ 1/(1−γ), so γ = 0.99 "looks ahead" about 100 steps.
  • Non-Markov state: the entire framework collapses if the true dynamics depend on history. The fix is state augmentation — fold enough history into the state (e.g. frame-stacking in Atari) to restore the Markov property.
  • Floating-point & ties: two actions with nearly equal value make argmax flap between sweeps; break ties deterministically to avoid spurious "non-convergence" of the policy while V is already converged.
  • Continuous / huge S: exact tables are impossible; you approximate V or Q with a parametric function, giving up the convergence guarantee (approximate value iteration can diverge — the "deadly triad" of bootstrapping + off-policy + approximation).
  • Partial observability (POMDP): when you can't observe the true state, solving the belief-state MDP is PSPACE-hard in the finite-horizon case — a categorical jump in difficulty from the polynomial fully-observed MDP.
Value iteration vs. policy iteration vs. linear programming for solving a finite MDP
MethodCost per iterationIterations to εBest when
Value iterationO(|S|²·|A|)O( log(1/(ε(1−γ))) / (1−γ) )large |S|, γ not near 1, want simple code
Policy iterationO(|S|³ + |S|²·|A|)few (strongly polynomial, Ye 2011)moderate |S|, γ near 1, few actions
Modified policy iterO(k·|S|²·|A|)between the twobalance eval cost vs. improvement
Linear programmingpoly(|S|,|A|) (LP solve)1 solveneed exactness / theoretical guarantees
Q-learning (model-free)O(1) per sampleno P/R needed; sample-hungryP and R unknown, learn from experience

Frequently asked questions

What exactly is the Markov property, and why does it matter?

It says the next state's distribution depends only on the current state and action, not on the full history: P(sₜ₊₁ | sₜ, aₜ) = P(sₜ₊₁ | s₀…sₜ, a₀…aₜ). This is what lets you summarize the future with a single value per state, making the Bellman equation a fixed-point over |S| numbers instead of over exponentially many histories. If your problem isn't Markov, you augment the state until it is.

Value iteration or policy iteration — which should I use?

Policy iteration usually needs far fewer outer iterations and is preferred when |S| is moderate and γ is close to 1, but each step pays O(|S|³) for the exact policy evaluation solve. Value iteration is simpler, has O(|S|²·|A|) sweeps, and wins when |S| is large or you only need approximate answers. Modified policy iteration interpolates between them with a tunable number of evaluation sweeps.

What is the complexity of solving an MDP?

A value-iteration sweep is O(|S|²·|A|) time (O(|S|·|A|·b) if each state has ≤ b successors), and you need O(log(1/(ε(1−γ)))/(1−γ)) sweeps for accuracy ε. Policy iteration is O(|S|³ + |S|²·|A|) per step but converges in a strongly-polynomial number of steps (Ye 2011). Finite MDPs are solvable in polynomial time; the practical wall is |S| itself growing exponentially in the number of state variables.

Why not just use Q-learning for everything?

Q-learning is for when you don't know the transition kernel P or reward R and must learn from sampled experience — it's model-free. If you already have P and R, value/policy iteration solve the MDP exactly and far more sample-efficiently, since Q-learning may need millions of samples to approximate what a Bellman backup computes in closed form. Use dynamic programming when the model is known; use RL when it isn't.

What does the discount factor γ actually do?

γ ∈ [0,1) weights future rewards: a reward t steps away is worth γᵗ times its face value, and the effective planning horizon is about 1/(1−γ) (so γ = 0.99 ≈ 100 steps). It also guarantees convergence by making the Bellman operator a γ-contraction, keeping infinite-horizon returns finite. Pushing γ toward 1 makes the agent far-sighted but slows convergence dramatically.

When does the MDP framework break down?

It breaks when the state isn't fully observable (you get a POMDP, whose finite-horizon solution is PSPACE-hard), when dynamics depend on history (non-Markov), or when γ = 1 removes the contraction. It also breaks in practice under the curse of dimensionality — |S| = m^d for d state variables — forcing function approximation, which can diverge under the deadly triad of bootstrapping, off-policy updates, and approximation.