Skip to content
AI360Xpert
Beta

Generalized Policy Iteration (GPI)

GPI is the shared loop behind most RL: estimate how good the current policy is, then make the policy greedier, and repeat until neither can improve.

Evaluation pulls values toward the policy while greedy improvement pulls the policy toward values, meeting at values 5.0 and 4.0
Evaluation pulls values toward the policy while greedy improvement pulls the policy toward values, meeting at values 5.0 and 4.0

Why Does This Exist?

You need values to improve a policy, and you need a policy to define values. That circle is the whole difficulty. Policy evaluation fixes behavior and measures return. Greedy improvement fixes values and picks better actions. Doing either one perfectly before touching the other wastes work, because each step invalidates the other.

Sutton and Barto named the general pattern GPI. It says the two processes can interleave at any grain, from full sweeps to single samples, and still head to the same optimum. That one idea turns policy iteration, value iteration, SARSA, Q-learning and actor critic into settings on one dial rather than separate tricks.

The one idea you need first

The Bellman expectation for fixed π\pi says vπ(s)v_{\pi}(s) equals mean reward plus γ\gamma times next values. The greedy policy picks the action with the largest one step lookahead under current VV. GPI is those two updates chasing each other.

Think of It Like This

Two legs walking uphill

Your left leg plants and feels the slope where you stand. That is evaluation. Your right leg swings toward higher ground based on that feel. That is improvement. Neither leg walks alone.

If the left leg kept measuring without stepping, you would stand still polishing a number for a path you never take. If the right leg kept lunging without planting, you would trip. Alternating small steps climbs fastest.

Where it stops: hikers take even steps. GPI steps can be lopsided, like ten tiny critic moves per actor move.

How It Actually Works

Hold π\pi, move VV toward vπv_{\pi} with Bellman backups. Hold VV, move π\pi toward greedy VV by picking arg⁡max⁡a\arg\max_a one step returns. The improvement theorem says a policy that looks better under old values is no worse in truth, so return does not go down.

Picture two lines crossing. One line is V=vπV = v_{\pi}, where values match the policy. The other is π=greedy(V)\pi = \text{greedy}(V), where the policy matches values. Each update moves toward one line and off the other, making a zigzag. The only joint rest point satisfies the Bellman optimum, hence (π∗,v∗)(\pi_*, v_*).

Where common methods sit

  • Full sweeps to convergence then greedy replacement behaves like policy iteration.
  • One sweep then greedy replacement behaves like value iteration.
  • One state at a time in any order behaves like asynchronous dynamic programming.
  • One sampled transition with epsilon greedy behavior behaves like SARSA or Q-learning.
  • Small critic and actor gradient steps together behave like actor critic.

No table needed: smaller evaluation grain means faster policy turns at noisier values.

Worked example

Two states {s1,s2}\{s_1, s_2\}, actions {a1,a2}\{a_1, a_2\}, γ=0.5\gamma = 0.5. Rewards are fixed: in s1s_1, a1a_1 stays in s1s_1 for 1.01.0, a2a_2 goes to s2s_2 for 3.03.0; in s2s_2, a1a_1 goes to s1s_1 for 0.00.0, a2a_2 stays in s2s_2 for 2.02.0. Start π0=[a1,a1]\pi_0 = [a_1, a_1], V0=[0.0,0.0]V_0 = [0.0, 0.0].

First evaluation sweep under π0\pi_0: V1(s1)=1.0+0.5×0.0=1.0V_1(s_1) = 1.0 + 0.5 \times 0.0 = 1.0, V1(s2)=0.0+0.5×0.0=0.0V_1(s_2) = 0.0 + 0.5 \times 0.0 = 0.0, so V1=[1.0,0.0]V_1 = [1.0, 0.0].

Greedy step on V1V_1: in s1s_1, Q(a1)=1.0+0.5×1.0=1.5Q(a_1) = 1.0 + 0.5 \times 1.0 = 1.5 and Q(a2)=3.0+0.5×0.0=3.0Q(a_2) = 3.0 + 0.5 \times 0.0 = 3.0, pick a2a_2; in s2s_2, Q(a1)=0.0+0.5×1.0=0.5Q(a_1) = 0.0 + 0.5 \times 1.0 = 0.5 and Q(a2)=2.0+0.5×0.0=2.0Q(a_2) = 2.0 + 0.5 \times 0.0 = 2.0, pick a2a_2. So π1=[a2,a2]\pi_1 = [a_2, a_2], already optimal.

Next evaluation under π1\pi_1: V2(s1)=3.0+0.5×0.0=3.0V_2(s_1) = 3.0 + 0.5 \times 0.0 = 3.0, V2(s2)=2.0+0.5×0.0=2.0V_2(s_2) = 2.0 + 0.5 \times 0.0 = 2.0. The policy stays put. True fixed point solves v∗(s2)=2.0+0.5v∗(s2)=4.0v_*(s_2) = 2.0 + 0.5 v_*(s_2) = 4.0 and v∗(s1)=3.0+0.5×4.0=5.0v_*(s_1) = 3.0 + 0.5 \times 4.0 = 5.0. Later sweeps give [4.0,3.0][4.0, 3.0], [4.5,3.5][4.5, 3.5], [4.75,3.75][4.75, 3.75], closing on [5.0,4.0][5.0, 4.0].

Code

One sweep plus greedy choice, matching the hand trace:

def eval_sweep(V: list[float], policy: list[int], gamma: float) -> list[float]:    """One Bellman expectation sweep for the 2 state MDP."""    # next state and reward tables: [state][action] -> (next_state, reward)    nxt = [[0, 1], [0, 1]]    rew = [[1.0, 3.0], [0.0, 2.0]]    out = [0.0, 0.0]    for s in (0, 1):        a = policy[s]        out[s] = rew[s][a] + gamma * V[nxt[s][a]]    return [round(x, 2) for x in out]

def greedy(V: list[float], gamma: float) -> list[int]:    """Greedy policy over one step lookahead."""    nxt = [[0, 1], [0, 1]]    rew = [[1.0, 3.0], [0.0, 2.0]]    pol = [0, 0]    for s in (0, 1):        qs = [rew[s][a] + gamma * V[nxt[s][a]] for a in (0, 1)]        pol[s] = max((0, 1), key=lambda a: qs[a])    return pol

V1 = eval_sweep([0.0, 0.0], [0, 0], 0.5)print(V1)  # -> [1.0, 0.0]print(greedy(V1, 0.5))  # -> [1, 1]print(eval_sweep(V1, [1, 1], 0.5))  # -> [3.0, 2.0]

Here 00 means a1a_1 and 11 means a2a_2, so [1,1][1, 1] is [a2,a2][a_2, a_2]. Numbers match V1V_1 and V2V_2 above.

Watch Out For

Evaluating a bad policy to high precision

Teams run evaluation to tiny tolerance before one improvement, polishing values for behavior about to be discarded. The symptom is slow progress with shrinking Bellman error but a frozen policy.

Use truncated sweeps. One to a few backups per improvement is enough early, as in value iteration. Save deep evaluation for after the policy stabilizes.

Going fully greedy too early on noisy values

Strict greedy choice on fresh estimates kills search. Unvisited actions stay underestimated forever, so evaluation never corrects them. The symptom is fast lock in to a weak policy.

Keep search alive during improvement with epsilon greedy moves, optimistic starts, or entropy terms, then anneal toward greedy as values settle.

The Quick Version

  • GPI alternates VV toward vπv_{\pi} and π\pi toward greedy VV at any grain.
  • Each move helps one side and disturbs the other, tracing a zigzag to one rest point.
  • That rest point satisfies Bellman optimality, hence (π∗,v∗)(\pi_*, v_*).
  • On the two state MDP with gamma 0.5, one sweep finds the optimal policy and values close on 5.0 and 4.0.
  • Policy iteration, value iteration, SARSA, Q-learning and actor critic are grain choices on this loop.