Skip to content

t5lab.planner_vs_greedy

planner_vs_greedy

The planner's reason to exist: mvprop routes AROUND walls; greedy gets trapped by them.

Single-agent navigation on rooms / corridors / maze / random-obstacle maps (the frozen distilled planner, no policy, no GPU). For each (map, start, goal) we descend two controllers to the goal:

  • greedy — step to the free 4-neighbour that most reduces Chebyshev distance to the goal; STAY if none strictly improves (exactly ctde_v0's greedy_move, single-agent). This is the reactive baseline: it CANNOT climb "away" to get around a wall, so a wall on the straight line traps it.
  • mvprop — step to the free 4-neighbour of maximum learned value V; STAY at a local max. The value field floods around walls, so descending it follows a true geodesic.

Reports reach-rate + path/optimal length for each, per map type, and renders a composite PNG of cases where greedy is trapped but mvprop routes through.

Run: PYTHONPATH=. PLANNER=/tmp/mvprop_distilled.eqx JAX_PLATFORMS=cpu $PY -m t5lab.planner_vs_greedy

descend

descend(start, goal, wall, score, budget, greedy)

score(cell)->higher-is-better for mvprop; for greedy we use -Chebyshev(cell,goal). Returns (path, reached).

Source code in experiments/t5lab/planner_vs_greedy.py
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
def descend(start, goal, wall, score, budget, greedy):
    """score(cell)->higher-is-better for mvprop; for greedy we use -Chebyshev(cell,goal).
    Returns (path, reached)."""
    cur = np.asarray(start); path = [tuple(cur)]; seen = {tuple(cur)}
    for _ in range(budget):
        if tuple(cur) == tuple(goal):
            return path, True
        nb = free_nbrs(cur, wall)
        if len(nb) == 0:
            return path, False
        if greedy:
            here = -cheby(cur, goal); vals = np.array([-cheby(c, goal) for c in nb])
        else:
            here = score[cur[0], cur[1]]; vals = score[nb[:, 0], nb[:, 1]]
        j = int(np.argmax(vals))
        if vals[j] <= here + 1e-9:                 # no strict improvement -> trapped / local max
            return path, False
        cur = nb[j]
        if tuple(cur) in seen:                     # cycle -> trapped
            return path, False
        seen.add(tuple(cur)); path.append(tuple(cur))
    return path, tuple(cur) == tuple(goal)