home

Reinforcement Learning Greedy Policy

Creator: Petar Veličković (original)

A grid-world policy that greedily selects the locally best action under estimated state values, steering toward the goal while avoiding a penalty state.


Reinforcement Learning Greedy Policy

Download

PNG PDF SVG

Code

reinforcement-learning-greedy-policy.typ (153 lines)

#import "@preview/cetz:0.5.2": canvas, decorations, draw
#import draw: bezier, content, line, rect

#set page(width: auto, height: auto, margin: 8pt, fill: none)
#set text(size: 12pt)

#canvas({
  let arrow = (mark: (end: "stealth", fill: black, scale: .55), stroke: .9pt)
  let heavy = (mark: (end: "stealth", fill: black, scale: .65), stroke: 1.3pt)
  let panel-w = 1.65
  let marker-w = .65
  let y-box = -3.9
  let state-gap = 4.8
  let x0 = 0
  let x1 = state-gap
  let x2 = 2 * state-gap
  let west-rim(x) = (x - .03, y-box + panel-w / 2)

  let wave-arrow(start, end, segments: 8, straight-end: .18) = {
    let direction = (end.at(0) - start.at(0), end.at(1) - start.at(1))
    let distance = calc.sqrt(
      direction.at(0) * direction.at(0) + direction.at(1) * direction.at(1),
    )
    let straight-start = (
      end.at(0) - straight-end * direction.at(0) / distance,
      end.at(1) - straight-end * direction.at(1) / distance,
    )
    decorations.wave(
      line(start, straight-start),
      amplitude: .035,
      segments: segments,
      stroke: .9pt,
    )
    line(straight-start, end, ..arrow)
  }
  let transition(start, end, ctrl-1, ctrl-2, label-pos, label) = {
    bezier(start, end, ctrl-1, ctrl-2, ..heavy)
    content(label-pos, label, anchor: "east", fill: rgb("#cdd3da"), padding: 2pt)
  }
  let state(x, idx, q, action, reward, reward-label, mark-pos, wiggle-x, dollar-pos) = {
    let id = "s" + str(idx)
    let mid = x + panel-w / 2
    let panel = ((x, y-box), (x + panel-w, y-box + panel-w))
    let panel-name = id + "-panel"
    let panel-sw = panel-name + ".south-west"
    let policy = id + "-policy"
    let reward-arrow = id + "-reward"
    rect(
      panel.at(0),
      panel.at(1),
      stroke: none,
      fill: rgb("#cdd3da"),
      name: panel-name,
    )
    rect(
      (rel: mark-pos, to: panel-sw),
      (
        rel: (mark-pos.at(0) + marker-w, mark-pos.at(1) + marker-w),
        to: panel-sw,
      ),
      fill: rgb("#aaaaff"),
      stroke: none,
    )
    rect(panel.at(0), panel.at(1), stroke: 1.2pt, fill: none)
    content(
      (rel: dollar-pos, to: panel-sw),
      text(fill: green)[\$ \$],
      anchor: "center",
    )
    content(
      (rel: (0, -.28), to: panel-name + ".south"),
      $s_#idx$,
      anchor: "north",
    )

    line(
      panel-name + ".north",
      (rel: (0, 1.6), to: panel-name + ".north"),
      ..heavy,
      name: policy,
    )
    content(
      (rel: (-.55, -.8), to: policy + ".end"),
      $pi_(theta)(s_#idx)$,
      anchor: "east",
    )
    content((rel: (0, .2), to: policy + ".end"), q, anchor: "south")

    wave-arrow((mid + wiggle-x, y-box + 3.85), (mid, y-box + 4.95))
    content((rel: (0, 1.8), to: policy + ".end"), action, anchor: "south")
    line(
      (rel: (0, 2.2), to: policy + ".end"),
      (rel: (0, 3.1), to: policy + ".end"),
      ..heavy,
      name: reward-arrow,
    )
    content(
      (rel: (-.5, .05), to: reward-arrow + ".mid"),
      reward-label,
      anchor: "east",
    )
    content((rel: (0, .25), to: reward-arrow + ".end"), reward, anchor: "south")
  }

  state(
    x0,
    0,
    $[0.12, bold(0.64), 0.07, 0.17]$,
    [up],
    $r_0 = 0$,
    $cal(R)(s_0, "↑")$,
    (0, 0),
    -.35,
    (1.18, 1.24),
  )
  state(
    x1,
    1,
    $[0.03, 0.24, bold(0.47), 0.26]$,
    [right],
    $r_1 = 0$,
    $cal(R)(s_1, "→")$,
    (0, panel-w - marker-w),
    .35,
    (1.18, 1.24),
  )
  state(
    x2,
    2,
    $[bold(0.82), 0.04, 0.08, 0.06]$,
    [pick up],
    $r_2 = 2$,
    $cal(R)(s_2, "⋆")$,
    (panel-w - marker-w, panel-w - marker-w),
    -.65,
    (panel-w - marker-w / 2, panel-w - marker-w / 2),
  )

  for (x, next-x, label) in (
    (x0, x1, $cal(T)(s_0, "↑")$),
    (x1, x2, $cal(T)(s_1, "→")$),
  ) {
    transition(
      (x + 1.35, 1.10),
      west-rim(next-x),
      (x + 3.65, 1.10),
      (x + 3.55, -3.0),
      (next-x - .25, -3.18),
      label,
    )
  }
})