Real-Time Dynamic Programming
Sweeping every state is wasteful when most states never matter. RTDP only updates the states its simulated trials actually walk through, and still converges on those.
Why Does This Exist?
Classic dynamic programming sweeps every state on every pass. In a warehouse robot with a million states, that means recomputing values for locked closets the robot will never enter, over and over. The cost grows with the size of the whole map, not with the size of the actual job.
The observation behind RTDP is that goal directed tasks only need a slice of the map: the states a good policy can actually reach from the start. Barto, Bradtke, and Singh showed in 1995 that running value iteration style backups only along simulated start to goal trials converges to the optimal policy on exactly those relevant states. This page covers that trajectory sampling mechanism. For the sampling idea on its own, read trajectory sampling.
The one idea you need first
A Bellman backup refreshes one state's value from its successors: . Here is the model giving transition probabilities, is the immediate reward, and is the discount factor weighting future value. Full sweeps apply this everywhere. RTDP applies it only where its trials walk.
Think of It Like This
The spelunker who maps only the way out
A surveyor insists on mapping every side cave in the mountain before moving, including flooded pits nowhere near the exit. A spelunker with a compass heading just starts walking. At each fork she scores the options, scribbles the result in her notebook for that junction only, and takes the best looking tunnel. Dead ends get downgraded the moment they disappoint, so later trips avoid them.
After a few trips from entrance to daylight, her notebook holds an optimal route. Thousands of side caves stay blank, and that blankness cost nothing. The compass heading matters: it must be optimistic, treating unknown tunnels as promising, or she settles into the first mediocre corridor and never checks the better one.
Where the analogy stops: the spelunker walks once per trip, while RTDP interleaves its notebook updates with greedy steps inside a known probabilistic model, sampling next states from it rather than physically traveling.
How It Actually Works
RTDP runs repeated trials from a start state to the goal, using a known model . At each visited state it does two things. First, the local backup:
Second, it acts greedily with respect to those fresh values and samples the next state from the model. Unvisited states keep their initial heuristic values until a trial reaches them.
Convergence rests on three conditions for stochastic shortest path tasks: the goal stays reachable, lingering costs something (negative step costs or ), and initial values are optimistic, meaning everywhere. Optimism makes unexplored states look inviting, so trials keep spreading until the values settle. Pessimistic starts trap the agent in the first corridor it tries.
Worked example
Four states with goal value . Every move costs with no discounting. From , action risky reaches with probability 0.8 and with 0.2, while action safe reaches for sure. Both and lead straight to . Start optimistic with all values at .
Trial 1 at : and . Update . Tie goes to risky, the sample lands on , which backs up to and reaches the goal. stays untouched at .
Trial 2 at : now while . Greedy picks safe, lands on , which backs up to .
Trial 3 at : and . Update , the true optimum, after three short walks. The diagram draws these three trials and the untouched states around them.
Code
This snippet replays the three trials with plain arithmetic. Check the printed Q values against the hand computation above.
if __name__ == "__main__": V = {"S0": 0.0, "S1": 0.0, "S2": 0.0, "G": 0.0}
# Trial 1 at S0, everything still 0.0 q_risky = -1.0 + 0.8 * V["S1"] + 0.2 * V["S2"] q_safe = -1.0 + V["S2"] V["S0"] = max(q_risky, q_safe) print(f"trial 1: risky={q_risky:.1f} safe={q_safe:.1f} V(S0)={V['S0']:.1f}") V["S1"] = -1.0 + V["G"] print(f"trial 1: V(S1)={V['S1']:.1f} V(S2) untouched={V['S2']:.1f}")
# Trial 2 at S0, S1 now -1.0 q_risky = -1.0 + 0.8 * V["S1"] + 0.2 * V["S2"] q_safe = -1.0 + V["S2"] V["S0"] = max(q_risky, q_safe) print(f"trial 2: risky={q_risky:.1f} safe={q_safe:.1f} V(S0)={V['S0']:.1f}") V["S2"] = -1.0 + V["G"] print(f"trial 2: V(S2)={V['S2']:.1f}")
# Trial 3 at S0, both successors known q_risky = -1.0 + 0.8 * V["S1"] + 0.2 * V["S2"] q_safe = -1.0 + V["S2"] V["S0"] = max(q_risky, q_safe) print(f"trial 3: risky={q_risky:.1f} safe={q_safe:.1f} V(S0)={V['S0']:.1f}")# -> expected output:trial 1: risky=-1.0 safe=-1.0 V(S0)=-1.0trial 1: V(S1)=-1.0 V(S2) untouched=0.0trial 2: risky=-1.8 safe=-1.0 V(S0)=-1.0trial 2: V(S2)=-1.0trial 3: risky=-2.0 safe=-2.0 V(S0)=-2.0Watch Out For
Pessimistic starts trap the agent in the first corridor
The symptom: RTDP converges fast to a mediocre route and never improves, no matter how many trials run. The cause is initialization below the true values. Tried states look better than untouched ones simply because untouched ones started gloomy, so greed never wanders.
The fix: start optimistic. For step cost tasks, zero works since true values are negative. For anything else, use a relaxed domain heuristic such as straight line distance that overestimates rather than underestimates. Confirm the goal holds value zero so it keeps pulling trials forward.
Loops with free steps spin forever
The symptom: trials run to the step cap without reaching the goal, values barely move. The cause is zero or positive rewards on non goal transitions with no discounting, which makes wandering costless. The backup then sees no reason to prefer the exit.
The fix: keep step costs strictly negative or set so every extra loop lowers the estimate until the greedy policy breaks out. Cap trial length as a backstop, but treat frequent cap hits as a modeling flag, not a tuning knob.
The Quick Version
- RTDP replaces full sweeps with start to goal trials, backing up only visited states with .
- With an optimistic start, reachability, and costly lingering, it converges to optimal values on relevant states only.
- The worked MDP settles at minus 2.0 across three trials while untouched states cost zero compute.
- Pessimistic initialization traps the policy in the first corridor it tries.
- Free loops need negative step costs or discounting, or trials wander without learning.