Skip to content
AI360Xpert
Beta

Policy Improvement

Policy improvement transforms an existing policy into a superior one by choosing actions that maximize expected return under current value estimates.

Policy improvement transforms evaluated state values into a strictly superior policy by greedily maximizing expected future returns.
Policy improvement transforms evaluated state values into a strictly superior policy by greedily maximizing expected future returns.

Why Does This Exist?

In reinforcement learning, evaluating an agent's current strategy through policy evaluation computes how much cumulative return each state yields under that fixed behavior. However, evaluation alone does not change behavior. To discover an optimal strategy, an agent requires a systematic, mathematically principled mechanism to upgrade its choices.

Without a formal improvement rule, attempting to modify an agent's actions risks catastrophic instability. In a sequential decision problem, changing an action in one state alters the state distribution and downstream trajectories throughout the entire environment. Naively tweaking actions can inadvertently degrade long-term performance, trap the agent in suboptimal cycles, or cause performance collapse.

The Policy Improvement Theorem provides the theoretical guarantee that prevents this failure. It proves that by taking an action that looks locally greedy with respect to the current state-value function vπv_\pi, the resulting policy π′\pi' is guaranteed to achieve equal or greater expected return from every single state in the environment (vπ′(s)≥vπ(s)v_{\pi'}(s) \ge v_\pi(s) for all ss). This monotonic improvement property turns policy search into an orderly ascent toward optimality.

Think of It Like This

Upgrading Chess Openings Against an Opponent's Repertoire

Imagine you are a tournament chess player with an established opening repertoire (π\pi). After analyzing hundreds of recorded games against a rival, your chess engine calculates your expected win rate from every board position that typically arises (vπ(s)v_\pi(s)).

On move 6, your traditional opening book dictates playing a modest pawn move a1a_1. Your engine evaluation shows that a1a_1 maintains your baseline win expectation of +0.20+0.20 (vπ(s)=0.20v_\pi(s) = 0.20). However, deep engine calculations reveal an alternative knight move a2a_2: taking this move yields an immediate tactical threat and leads to board configurations that evaluate to +0.80+0.80 (qπ(s,a2)=0.80q_\pi(s, a_2) = 0.80), even assuming you revert to your standard opening repertoire for all subsequent moves.

Policy improvement is the decision to update your opening notebook: whenever you reach this specific board state, you permanently replace a1a_1 with a2a_2 (π′(s)=a2\pi'(s) = a_2).

Because the expected return of taking a2a_2 once and following π\pi thereafter exceeds the baseline value of π\pi, committing to a2a_2 every time you encounter that position can never hurt your long-term score. Even better, because this superior position is reached repeatedly, the advantage compounds across all subsequent games.

Where the analogy stops: In tournament chess, a human opponent actively studies your games and prepares counter-strategies in response, creating a non-stationary two-player game. In a standard Markov Decision Process, the environment's transition dynamics and reward functions remain stationary, meaning that improvements against the environment never trigger an adversarial counter-adjustment.

How It Actually Works

Action-Value Greedification and the Policy Improvement Theorem

Let an environment be defined as a Markov Decision Process (S,A,p,γ)(\mathcal{S}, \mathcal{A}, p, \gamma), where S\mathcal{S} is the state space, A\mathcal{A} is the action space, p(s′,r∣s,a)p(s', r \mid s, a) represents the transition dynamics, and γ∈[0,1)\gamma \in [0, 1) is the discount factor.

Suppose the agent follows an initial deterministic policy π:S→A\pi: \mathcal{S} \to \mathcal{A}, yielding evaluated state-values vπ(s)=Eπ[Gt∣St=s]v_\pi(s) = \mathbb{E}_\pi [G_t \mid S_t = s].

1. Computing Action-Values

To determine whether selecting an alternative action a≠π(s)a \neq \pi(s) in state ss improves return, we evaluate the action-value function qπ(s,a)q_\pi(s, a). This represents the expected return of taking action aa right now, and subsequently following policy π\pi forever after:

qπ(s,a)≐Eπ[Rt+1+γvπ(St+1)∣St=s,At=a]=∑s′∈S∑r∈Rp(s′,r∣s,a)[r+γvπ(s′)]q_\pi(s, a) \doteq \mathbb{E}_\pi [R_{t+1} + \gamma v_\pi(S_{t+1}) \mid S_t = s, A_t = a] = \sum_{s' \in \mathcal{S}} \sum_{r \in \mathcal{R}} p(s', r \mid s, a) \left[ r + \gamma v_\pi(s') \right]

2. Greedification (Policy Update)

We construct a new deterministic policy π′\pi' by selecting the action that maximizes qπ(s,a)q_\pi(s, a) at each state:

π′(s)≐arg⁡max⁡a∈Aqπ(s,a)=arg⁡max⁡a∈A∑s′,rp(s′,r∣s,a)[r+γvπ(s′)]\pi'(s) \doteq \arg\max_{a \in \mathcal{A}} q_\pi(s, a) = \arg\max_{a \in \mathcal{A}} \sum_{s', r} p(s', r \mid s, a) \left[ r + \gamma v_\pi(s') \right]

By definition of the arg⁡max⁡\arg\max operator, the new action satisfies:

qπ(s,π′(s))=max⁡a∈Aqπ(s,a)≥qπ(s,π(s))=vπ(s)q_\pi(s, \pi'(s)) = \max_{a \in \mathcal{A}} q_\pi(s, a) \ge q_\pi(s, \pi(s)) = v_\pi(s)

3. Mathematical Proof of the Policy Improvement Theorem

The Policy Improvement Theorem (Bellman, 1957; Howard, 1960; Sutton & Barto, 2018) asserts:

If qπ(s,π′(s))≥vπ(s)q_\pi(s, \pi'(s)) \ge v_\pi(s) for all s∈Ss \in \mathcal{S}, then the overall policy π′\pi' is globally as good as, or better than, π\pi: vπ′(s)≥vπ(s)∀s∈Sv_{\pi'}(s) \ge v_\pi(s) \quad \forall s \in \mathcal{S}

The proof proceeds by repeatedly unrolling the Bellman inequality:

vπ(s)≤qπ(s,π′(s))=E[Rt+1+γvπ(St+1)∣St=s,At=π′(s)]=Eπ′[Rt+1+γvπ(St+1)∣St=s]\begin{aligned} v_\pi(s) &\le q_\pi(s, \pi'(s)) \\ &= \mathbb{E}[R_{t+1} + \gamma v_\pi(S_{t+1}) \mid S_t = s, A_t = \pi'(s)] \\ &= \mathbb{E}_{\pi'}[R_{t+1} + \gamma v_\pi(S_{t+1}) \mid S_t = s] \end{aligned}

Because the inequality vπ(s′)≤qπ(s′,π′(s′))v_\pi(s') \le q_\pi(s', \pi'(s')) holds for every successor state s′s', we substitute vπ(St+1)≤Eπ′[Rt+2+γvπ(St+2)∣St+1]v_\pi(S_{t+1}) \le \mathbb{E}_{\pi'}[R_{t+2} + \gamma v_\pi(S_{t+2}) \mid S_{t+1}] into the expression:

vπ(s)≤Eπ′[Rt+1+γEπ′[Rt+2+γvπ(St+2)∣St+1]∣St=s]=Eπ′[Rt+1+γRt+2+γ2vπ(St+2)∣St=s]\begin{aligned} v_\pi(s) &\le \mathbb{E}_{\pi'}[R_{t+1} + \gamma \mathbb{E}_{\pi'}[R_{t+2} + \gamma v_\pi(S_{t+2}) \mid S_{t+1}] \mid S_t = s] \\ &= \mathbb{E}_{\pi'}[R_{t+1} + \gamma R_{t+2} + \gamma^2 v_\pi(S_{t+2}) \mid S_t = s] \end{aligned}

Expanding this relationship recursively across kk consecutive time steps:

vπ(s)≤Eπ′[Rt+1+γRt+2+γ2Rt+3+⋯+γk−1Rt+k+γkvπ(St+k) | St=s]v_\pi(s) \le \mathbb{E}_{\pi'}\left[ R_{t+1} + \gamma R_{t+2} + \gamma^2 R_{t+3} + \dots + \gamma^{k-1} R_{t+k} + \gamma^k v_\pi(S_{t+k}) \,\middle|\, S_t = s \right]

Taking the infinite-horizon limit as k→∞k \to \infty, with discount factor γ<1\gamma < 1 and bounded immediate rewards, the terminal discounted term vanishes: lim⁡k→∞γkEπ′[vπ(St+k)]=0\lim_{k \to \infty} \gamma^k \mathbb{E}_{\pi'}[v_\pi(S_{t+k})] = 0. Therefore:

vπ(s)≤Eπ′[∑k=0∞γkRt+k+1 | St=s]=vπ′(s)v_\pi(s) \le \mathbb{E}_{\pi'}\left[ \sum_{k=0}^{\infty} \gamma^k R_{t+k+1} \,\middle|\, S_t = s \right] = v_{\pi'}(s)

This completes the proof: vπ′(s)≥vπ(s)v_{\pi'}(s) \ge v_\pi(s) for all s∈Ss \in \mathcal{S}.

4. Convergence to Optimality

If the improved policy π′\pi' achieves strictly identical values to π\pi (vπ′(s)=vπ(s)v_{\pi'}(s) = v_\pi(s) for all ss), then:

vπ′(s)=max⁡a∈A∑s′,rp(s′,r∣s,a)[r+γvπ′(s′)]v_{\pi'}(s) = \max_{a \in \mathcal{A}} \sum_{s', r} p(s', r \mid s, a) \left[ r + \gamma v_{\pi'}(s') \right]

This matches the Bellman Optimality Equation. Consequently, both π\pi and π′\pi' must be optimal policies π∗\pi^*. In any finite MDP with ∣S∣|\mathcal{S}| states and ∣A∣|\mathcal{A}| actions, there are exactly ∣A∣∣S∣|\mathcal{A}|^{|\mathcal{S}|} distinct deterministic policies; because each improvement step strictly increases value until reaching optimality, policy improvement cannot cycle and must terminate at the optimal policy in a finite number of steps.

Worked numerical example

Consider a 2-state environment with discount factor γ=0.90\gamma = 0.90:

  • State s1s_1 (Staging Area) offers two actions:
    • a1a_1 (Conservative): Transitions to s1s_1 with probability 0.800.80 (r=+1.0r = +1.0), and to s2s_2 with probability 0.200.20 (r=+1.0r = +1.0).
    • a2a_2 (Venturesome): Transitions to s2s_2 with probability 0.900.90 (r=0.0r = 0.0), and slips back to s1s_1 with probability 0.100.10 (r=−1.0r = -1.0).
  • State s2s_2 (High-Yield Vault) has a single fixed action:
    • stay\text{stay}: Transitions to s2s_2 with probability 0.700.70 (r=+5.0r = +5.0), and drops back to s1s_1 with probability 0.300.30 (r=0.0r = 0.0).

Step 1: Evaluate Baseline Policy π\pi

Our baseline policy π\pi selects action a1a_1 in s1s_1 (π(s1)=a1\pi(s_1) = a_1). We solve the linear Bellman expectation system:

vπ(s1)=0.80[1.0+0.90vπ(s1)]+0.20[1.0+0.90vπ(s2)]=1.00+0.72vπ(s1)+0.18vπ(s2)vπ(s2)=0.70[5.0+0.90vπ(s2)]+0.30[0.0+0.90vπ(s1)]=3.50+0.63vπ(s2)+0.27vπ(s1)\begin{aligned} v_\pi(s_1) &= 0.80 [1.0 + 0.90 v_\pi(s_1)] + 0.20 [1.0 + 0.90 v_\pi(s_2)] = 1.00 + 0.72 v_\pi(s_1) + 0.18 v_\pi(s_2) \\ v_\pi(s_2) &= 0.70 [5.0 + 0.90 v_\pi(s_2)] + 0.30 [0.0 + 0.90 v_\pi(s_1)] = 3.50 + 0.63 v_\pi(s_2) + 0.27 v_\pi(s_1) \end{aligned}

Rearranging into standard matrix form:

[0.28−0.18−0.270.37][vπ(s1)vπ(s2)]=[1.003.50]\begin{bmatrix} 0.28 & -0.18 \\ -0.27 & 0.37 \end{bmatrix} \begin{bmatrix} v_\pi(s_1) \\ v_\pi(s_2) \end{bmatrix} = \begin{bmatrix} 1.00 \\ 3.50 \end{bmatrix}

Solving this system yields:

vπ(s1)≈18.18,vπ(s2)≈22.73v_\pi(s_1) \approx 18.18, \qquad v_\pi(s_2) \approx 22.73

Step 2: Compute Action-Values qπ(s1,a)q_\pi(s_1, a)

Now we evaluate both candidate actions available in state s1s_1:

  • Action a1a_1: qπ(s1,a1)=1.00+0.72(18.18)+0.18(22.73)=18.18=vπ(s1)q_\pi(s_1, a_1) = 1.00 + 0.72(18.18) + 0.18(22.73) = 18.18 = v_\pi(s_1)
  • Action a2a_2: qπ(s1,a2)=0.90[0.0+0.90×vπ(s2)]+0.10[−1.0+0.90×vπ(s1)]=0.90[0.90×22.73]+0.10[−1.0+0.90×18.18]=0.90[20.457]+0.10[15.362]=18.411+1.536=19.95\begin{aligned} q_\pi(s_1, a_2) &= 0.90 [0.0 + 0.90 \times v_\pi(s_2)] + 0.10 [-1.0 + 0.90 \times v_\pi(s_1)] \\ &= 0.90 [0.90 \times 22.73] + 0.10 [-1.0 + 0.90 \times 18.18] \\ &= 0.90 [20.457] + 0.10 [15.362] \\ &= 18.411 + 1.536 = 19.95 \end{aligned}

Comparing the two action-values:

qπ(s1,a2)=19.95>vπ(s1)=18.18q_\pi(s_1, a_2) = 19.95 > v_\pi(s_1) = 18.18

Step 3: Greedification

The policy improvement step selects:

π′(s1)=arg⁡max⁡a∈{a1,a2}qπ(s1,a)=a2\pi'(s_1) = \arg\max_{a \in \{a_1, a_2\}} q_\pi(s_1, a) = a_2

Step 4: True Value of the Improved Policy π′\pi'

Now we compute the actual state values vπ′v_{\pi'} under the updated policy:

vπ′(s1)=0.10[−1.0+0.90vπ′(s1)]+0.90[0.0+0.90vπ′(s2)]=−0.10+0.09vπ′(s1)+0.81vπ′(s2)vπ′(s2)=3.50+0.63vπ′(s2)+0.27vπ′(s1)\begin{aligned} v_{\pi'}(s_1) &= 0.10 [-1.0 + 0.90 v_{\pi'}(s_1)] + 0.90 [0.0 + 0.90 v_{\pi'}(s_2)] = -0.10 + 0.09 v_{\pi'}(s_1) + 0.81 v_{\pi'}(s_2) \\ v_{\pi'}(s_2) &= 3.50 + 0.63 v_{\pi'}(s_2) + 0.27 v_{\pi'}(s_1) \end{aligned}

In matrix form:

[0.91−0.81−0.270.37][vπ′(s1)vπ′(s2)]=[−0.103.50]\begin{bmatrix} 0.91 & -0.81 \\ -0.27 & 0.37 \end{bmatrix} \begin{bmatrix} v_{\pi'}(s_1) \\ v_{\pi'}(s_2) \end{bmatrix} = \begin{bmatrix} -0.10 \\ 3.50 \end{bmatrix}

Solving this linear system gives:

vπ′(s1)≈23.71,vπ′(s2)≈26.76v_{\pi'}(s_1) \approx 23.71, \qquad v_{\pi'}(s_2) \approx 26.76

Notice the global ripple effect:

  • vπ′(s1)−vπ(s1)=23.71−18.18=+5.53v_{\pi'}(s_1) - v_\pi(s_1) = 23.71 - 18.18 = +5.53 (+30.4% gain)
  • vπ′(s2)−vπ(s2)=26.76−22.73=+4.03v_{\pi'}(s_2) - v_\pi(s_2) = 26.76 - 22.73 = +4.03 (+17.7% gain)

Even though the agent took the exact same action in state s2s_2, its value rose by +4.03+4.03 because when transitions occasionally drop the agent back into s1s_1, the improved policy makes the superior choice a2a_2, boosting cumulative returns across the entire trajectory.

Code

from typing import Dict, List, Tuple
# Transition model: (state, action) -> list of (probability, next_state, reward)TransitionModel = Dict[Tuple[str, str], List[Tuple[float, str, float]]]Policy = Dict[str, str]ValueFunction = Dict[str, float]

def evaluate_policy(    policy: Policy,    transitions: TransitionModel,    states: List[str],    gamma: float = 0.9,    theta: float = 1e-9,) -> ValueFunction:    """Iteratively computes state values v_pi(s) via the Bellman expectation equation."""    v: ValueFunction = {s: 0.0 for s in states}    while True:        delta = 0.0        for s in states:            a = policy[s]            # Bellman expectation backup: v(s) = sum_{s', r} p(s', r | s, a) * [r + gamma * v(s')]            v_new = sum(                prob * (r + gamma * v[s_next])                for prob, s_next, r in transitions[(s, a)]            )            delta = max(delta, abs(v[s] - v_new))            v[s] = v_new        if delta < theta:            break    return v

def compute_action_value(    state: str,    action: str,    v: ValueFunction,    transitions: TransitionModel,    gamma: float = 0.9,) -> float:    """Computes q_pi(s, a) = sum_{s', r} p(s', r | s, a) * [r + gamma * v(s')]."""    return sum(        prob * (r + gamma * v[s_next])        for prob, s_next, r in transitions[(state, action)]    )

def policy_improvement(    v: ValueFunction,    transitions: TransitionModel,    states: List[str],    actions: Dict[str, List[str]],    gamma: float = 0.9,) -> Policy:    """    Greedifies policy: pi'(s) = argmax_a q_pi(s, a).    Applies deterministic tie-breaking by candidate order.    """    improved_policy: Policy = {}
    for s in states:        available_actions = actions[s]        # Evaluate q_pi(s, a) for all candidate actions        action_values = {            a: compute_action_value(s, a, v, transitions, gamma)            for a in available_actions        }        # Deterministic greedification: break numerical ties by fixed index        best_action = max(            available_actions,            key=lambda a: (round(action_values[a], 7), -available_actions.index(a)),        )        improved_policy[s] = best_action
    return improved_policy

if __name__ == "__main__":    states = ["s1", "s2"]    actions = {        "s1": ["a1", "a2"],        "s2": ["stay"],    }    transitions: TransitionModel = {        ("s1", "a1"): [(0.8, "s1", 1.0), (0.2, "s2", 1.0)],        ("s1", "a2"): [(0.9, "s2", 0.0), (0.1, "s1", -1.0)],        ("s2", "stay"): [(0.7, "s2", 5.0), (0.3, "s1", 0.0)],    }    gamma = 0.9
    # 1. Evaluate baseline policy pi where pi(s1) = a1    baseline_policy: Policy = {"s1": "a1", "s2": "stay"}    v_pi = evaluate_policy(baseline_policy, transitions, states, gamma=gamma)
    print("--- 1. Baseline Policy Evaluation v_pi ---")    for s in states:        print(f"v_pi({s}) = {v_pi[s]:.2f}")
    # 2. Compute action-values q_pi(s1, a)    print("\n--- 2. Action-Value Greedification in s1 ---")    q_s1_a1 = compute_action_value("s1", "a1", v_pi, transitions, gamma=gamma)    q_s1_a2 = compute_action_value("s1", "a2", v_pi, transitions, gamma=gamma)    print(f"q_pi(s1, a1) = {q_s1_a1:.2f} (current baseline)")    print(f"q_pi(s1, a2) = {q_s1_a2:.2f} (candidate improvement)")
    # 3. Policy improvement step    improved_policy = policy_improvement(v_pi, transitions, states, actions, gamma=gamma)    print(f"\nImproved Policy pi': {improved_policy}")
    # 4. Evaluate new policy pi'    v_prime = evaluate_policy(improved_policy, transitions, states, gamma=gamma)    print("\n--- 3. Improved Policy Evaluation v_pi' ---")    for s in states:        print(f"v_pi'({s}) = {v_prime[s]:.2f} (Delta: +{v_prime[s] - v_pi[s]:.2f})")
    # Assertions validating Policy Improvement Theorem    assert q_s1_a2 > v_pi["s1"], "Candidate action must yield strictly higher q-value"    assert improved_policy["s1"] == "a2", "Greedy update must select action a2"    assert v_prime["s1"] >= v_pi["s1"], "Monotonic improvement guarantee violated for s1"    assert v_prime["s2"] >= v_pi["s2"], "Monotonic improvement guarantee violated for s2"    print("\nPolicy Improvement Theorem assertions passed successfully.")
--- 1. Baseline Policy Evaluation v_pi ---v_pi(s1) = 18.18v_pi(s2) = 22.73
--- 2. Action-Value Greedification in s1 ---q_pi(s1, a1) = 18.18 (current baseline)q_pi(s1, a2) = 19.95 (candidate improvement)
Improved Policy pi': {'s1': 'a2', 's2': 'stay'}
--- 3. Improved Policy Evaluation v_pi' ---v_pi'(s1) = 23.71 (Delta: +5.53)v_pi'(s2) = 26.76 (Delta: +4.04)
Policy Improvement Theorem assertions passed successfully.

Watch Out For

Non-deterministic tie-breaking causing policy oscillation

When two or more actions yield identical action-values (qπ(s,a1)=qπ(s,a2)q_\pi(s, a_1) = q_\pi(s, a_2)), arbitrary or random tie-breaking breaks convergence. If Python's dictionary iteration or non-deterministic sorting flips the winner on consecutive iterations, policy iteration will oscillate endlessly between a1a_1 and a2a_2 despite having already reached optimal value.

Symptom: The policy never stabilizes, reporting changes on every iteration even though state values have completely converged (Δv=0\Delta v = 0).

Fix: Implement a strict, deterministic tie-breaking rule. Always prefer retaining the existing action π(s)\pi(s) whenever an alternative action's value is within numerical tolerance ∣q(s,a)−q(s,π(s))∣≤10−7|q(s, a) - q(s, \pi(s))| \le 10^{-7}. If multiple novel actions tie, break ties using a fixed alphabetical or indexed action hierarchy.

Greedifying on imprecise or noisy value estimates

The Policy Improvement Theorem strictly guarantees vπ′(s)≥vπ(s)v_{\pi'}(s) \ge v_\pi(s) only when action-values are computed from the exact true state values vπv_\pi. In approximate reinforcement learning or early-stopped policy evaluation, value estimates contain estimation errors v^π=vπ+ϵ\hat{v}_\pi = v_\pi + \epsilon.

Symptom: Greedification on noisy value estimates selects an action that appears superficially better but actually degrades policy return (vπ′(s)<vπ(s)v_{\pi'}(s) < v_\pi(s)), causing policy degradation or divergence.

Fix: In dynamic programming, ensure iterative policy evaluation converges beneath a stringent threshold (θ≤10−8\theta \le 10^{-8}) before greedifying. In sample-based or deep reinforcement learning, avoid hard 1-step greedification; instead, employ conservative policy updates, trust-region constraints (such as TRPO or PPO), or entropy-regularized policy gradients that bound policy divergence per step.

The Quick Version

  • Policy improvement generates a new policy π′\pi' by acting greedily with respect to current value estimates: π′(s)=arg⁡max⁡aqπ(s,a)\pi'(s) = \arg\max_a q_\pi(s, a).
  • The Policy Improvement Theorem mathematically guarantees monotonic non-decreasing expected return from every state: vπ′(s)≥vπ(s)v_{\pi'}(s) \ge v_\pi(s) for all s∈Ss \in \mathcal{S}.
  • Greedifying an action in one state causes a positive ripple effect throughout the entire Markov chain, increasing values even in states where the policy did not change.
  • When greedification produces no change in policy return (vπ′(s)=vπ(s)v_{\pi'}(s) = v_\pi(s) for all ss), the policy has satisfied the Bellman Optimality Equation and is guaranteed optimal (π=π∗\pi = \pi^*).