Dynamic Programming in RL
You know the rules of the game, so you work backward from the end instead of playing thousands of practice rounds. Each state's value comes from its successors.
Why Does This Exist?
Planning steps ahead with actions means possible futures. With 4 actions and 20 steps that is over a trillion paths. You cannot enumerate them.
Dynamic programming breaks the giant problem into one-step pieces. If you already know the value of every successor state, the value of the current state is just the best probability-weighted mix of reward plus discounted successor value. Sweep that backup across all states and the values settle to the optimum.
This page covers planning with a perfect model. Markov decision processes define the model, value functions store the cached answers, and temporal-difference learning learns the same answers without a model. If you can write down transition probabilities, start here. If you can only sample experience, start with model-free methods instead.
The one idea you need first
A model means two tables. says how likely each successor is after action in state , and says the immediate reward on that branch. The discount in says future reward counts a bit less than present reward. The full setup lives in Markov decision processes.
Think of It Like This
A subway map with travel times already filled in
You stand at one station and want the fastest route downtown. Taped to the wall is a map where every station already has a number: minutes to downtown from there.
You do not ride every line to find out. For each line out of your station you add the ride time plus the posted number at the station where you get off, weighting by how often that line stalls or reroutes. Pick the smallest total. Then you write your station's new number on the map. Repeat for every station and the whole map sharpens.
Where it stops: real subway delays are not listed in a clean table. Dynamic programming needs that table to be complete and correct.
How It Actually Works
For a fixed policy , where is the chance of picking action in state , the Bellman expectation backup averages over actions and successors:
For the optimal policy the average over actions becomes a max. That is the Bellman optimality backup:
In plain words: each action gets a Q value equal to its expected one-step reward plus discounted future value, and the state takes the best Q. Both backups are contractions, so repeated sweeps converge to one fixed point from any start. That is why the method does not depend on the initial guess.
Policy iteration alternates full evaluation with greedy improvement. Value iteration skips the inner loop and applies the max backup every sweep. Same operator, different schedule.
Worked example
Take at state with two actions. Action branches to with probability 0.8 (reward 2.0, cached ) and to with probability 0.2 (reward 5.0, cached ). Action goes to with probability 1.0 (reward 1.0, cached ).
Branch targets add reward to discounted successor value:
Weight by probability for :
For there is one branch:
The optimality backup takes the max:
No sampling happened. Every number came from the model table plus cached successor values.
Code
A Bellman backup is a probability-weighted sum, not a loop over episodes. This snippet computes the two Q values above.
def bellman_q(probs: list, rewards: list, values: list, gamma: float) -> float: total: float = 0.0 # expected return for one action for p, r, v in zip(probs, rewards, values): total += p * (r + gamma * v) return total
q1 = bellman_q([0.8, 0.2], [2.0, 5.0], [10.0, 4.0], 0.9)q2 = bellman_q([1.0], [1.0], [9.0], 0.9)print(f"{q1:.2f} {q2:.2f} {max(q1, q2):.2f}")# -> 10.52 9.10 10.52The printed triple is , , and the backed-up . It matches the hand computation.
Watch Out For
Running DP without a true model
The backup sums over for every successor. If you do not have those probabilities, the sum has nothing to iterate over. Plugging in guessed tables gives exact answers to the wrong environment, and the policy looks confident while failing in the real one.
If you only have sampled transitions , use temporal-difference learning or Monte Carlo methods. They learn from samples and never need the full table.
Sweeping every state in a huge space
One sweep touches every state, every action, and every successor. When the state count grows with each new sensor or attribute, the table outgrows memory long before the values converge. The math still contracts, but you cannot store the vector.
Fix it by backing up only visited states, as in real-time methods, or by replacing the table with a parameterized approximator. Do not run full tabular sweeps past a few thousand states.
The Quick Version
- Dynamic programming plans with a known model by turning Bellman equations into update rules.
- Each backup mixes immediate reward with discounted cached successor values across every branch.
- The update is a gamma contraction, so repeated sweeps converge from any start.
- Policy iteration separates evaluation and improvement while value iteration merges them into one max backup.
- It needs exact transition probabilities and it scans the full state space, so it fits small tabular problems and grounds every sample-based method.