A neural policy solving structured STRIPS planning tasks from first principles.
Combining Potential-Based Reward Shaping (PBRS), Environmental Action Masking, and Batched REINFORCE with entropy regularization to solve 5-block re-stacking problems, paired with an interactive Next.js trajectory inspector featuring an articulated overhead robotic gantry.
- 🎯 Aim of the Project
- 📈 Experimental Evolution & Findings (v1 vs. v2 vs. v3)
- 🧩 Problem Formulation & Environment Design
- ⚖️ Reward Engineering & Potential Shaping
- 🕹️ Interactive Web Visualizer
- 💻 Technical Tooling
- 🚀 Quickstart Guide
- 📂 Repository Architecture
- 📚 References
The Blocks World is a foundational benchmark in AI planning and symbolic reasoning. In this domain, an agent must manipulate a set of labelled blocks located either on a table or stacked upon one another, transitioning from an arbitrary disordered configuration to a designated goal stack (e.g.
While classical planners like
-
Extreme Reward Sparsity: If only the final completed goal stack receives positive feedback, the probability of randomly stumbling into the exact sequence of 10–15 coordinated actions is negligible (
$\sim 0%$ ). - Credit Assignment & Local Minima: Deconstructing an existing tower to reach an obscured block temporarily breaks partial subgoals, penalizing naive distance heuristics.
- Invalid Transitions & Action Explosions: Out of all possible permutations of actions, only a subset are physically admissible at any state.
The primary aim of this project is to:
- Formulate a clean, vector-based STRIPS-style environment in pure PyTorch/Python.
- Implement and compare Reward Modeling paradigms: from naive sparse metrics to Potential-Based Reward Shaping (PBRS) that preserves policy invariance while steering search.
- Overcome policy entropy collapse through Batched Policy Gradients (REINFORCE) with entropy loss and gradient norm clipping.
- Provide a responsive, dark-mode Next.js + SVG visualization platform to scrub, inspect, diff, and diagnose recorded trajectory rollouts.
The training dynamics across all three iterations are summarized below. (Click on any dashboard to view in full resolution):
Analyzing the three iterations reveals how algorithmic adjustments resolved distinct failure modes:
-
v1 Failure: In Phase 1, using naive step penalties with hardcoded predicate bonuses, the policy floundered between
$0% - 8%$ during training and peaked at only$10-15%$ in greedy evaluation. The agent repeatedly fell into local minima (e.g. resting a block on the table and picking it back up). -
v2 Recovery: Introducing bottom-up Potential-Based Reward Shaping (PBRS) that only rewarded stacking if the foundation block
onTable(E)was firmly grounded allowed the agent to discover multi-step subgoals, driving success up to$\sim 60%$ by Epoch 500. -
v3 Mastery: Combining PBRS with Batched Trajectory Rollouts eliminated high-variance gradient noise, driving success to an asymptotic
$80% - 95%$ solve rate across evaluation folds.
- In v1, the trajectory length stayed pegged at the ceiling of
$50.0$ steps (the timeout horizon), indicating the agent was timing out without ever satisfying the terminal goal condition. - In v2, as the agent learned to respect bottom-up tower assembly, the mean steps to solve dropped to
$25 - 35$ steps. - In v3, trajectory lengths plummeted rapidly to
$10 - 15$ steps, which matches the theoretical optimal plan length for randomly partitioned 5-block configurations.
-
Premature Collapse in v1: In Phase 1, policy entropy experienced a catastrophic collapse from
$1.3$ down to$<0.15$ within the first 500 epochs. Because the agent lacked structured credit assignment, it converged prematurely onto sub-optimal deterministic loops before ever seeing positive goal trajectories. -
Controlled Decay in v2: Phase 2 maintained entropy above
$0.2$ for longer, allowing sustained exploration of valid configurations. -
Entropy Regularization in v3: Adding an explicit entropy loss penalty ($\beta \mathcal{H}(\pi)$) and gradient norm clipping (
$|\mathbf{g}|_2 \le 1.0$ ) prevented policy overconfidence. The agent maintained sufficient stochastic exploration early on, only consolidating into deterministic choices once valid planning paths were reinforced.
| Diagnostic Metric | Iteration 1 (v1 Baseline) | Iteration 2 (v2 Subgoal PBRS) | Iteration 3 (v3 Batched + Entropy) |
|---|---|---|---|
| Peak Solve Rate | 10% – 15% |
~60% |
80% – 95% |
| Mean Horizon | 50.0 steps (Timeout) | 25 – 35 steps | 10 – 15 steps (Optimal) |
| Entropy Profile | Premature Collapse ( |
Moderate Decay | Controlled Regularization |
| Gradient Updates | Single-trajectory REINFORCE | Single-trajectory REINFORCE | Batched Rollouts ( |
| Gradient Clipping | None | None | |
| Reward Formulation | Naive step penalty + goal bonus | Bottom-up Potential Function |
PBRS + Step Cost + Goal Bonus |
| Core Resolution | ❌ Trapped in cyclic loops | ✅ Stable, near-optimal solver |
For a set of 5 distinct blocks
| Predicate | Arity / Permutations | Dimension | Semantic Meaning |
|---|---|---|---|
on(x, y) |
|
20 | Block x is stacked directly on top of block y
|
onTable(x) |
|
5 | Block x rests directly on the workspace surface |
clear(x) |
|
5 | Block x has no other block resting on top of it |
armempty |
Boolean state | 1 | The robotic manipulator is unoccupied |
holding(x) |
|
5 | The robotic manipulator is gripping block x
|
Each discrete action adheres to formal STRIPS preconditions, add-effects, and delete-effects:
1. unstack(x, y):
• Preconditions: armempty ∧ clear(x) ∧ on(x, y)
• Add-Effects: holding(x), clear(y)
• Del-Effects: armempty, on(x, y), clear(x)
2. stack(x, y):
• Preconditions: holding(x) ∧ clear(y)
• Add-Effects: on(x, y), armempty, clear(x)
• Del-Effects: holding(x), clear(y)
3. pickup(x):
• Preconditions: armempty ∧ clear(x) ∧ onTable(x)
• Add-Effects: holding(x)
• Del-Effects: armempty, onTable(x), clear(x)
4. putdown(x):
• Preconditions: holding(x)
• Add-Effects: onTable(x), armempty, clear(x)
• Del-Effects: holding(x)
The policy model is a multi-layer perceptron (MLP) taking a 72-dimensional vector (concatenation of current state
To prevent the agent from attempting physically invalid operations (e.g. unstacking a block buried beneath others or gripping while already holding), an eligibility mask
Early iterations demonstrated that unshaped step penalties with terminal bonuses fail completely due to the credit assignment bottleneck. The agent adopts cyclical behaviors (pickup putdown) that minimize immediate penalties without risking exploration.
To solve this, we formulated Potential-Based Reward Shaping (PBRS) based on grounded pile evaluation:
where
-
Manipulator Arm Condition:
$+2$ if the arm state aligns with goal arm configuration (armemptyorholding(x)). -
Bottom-Up Foundation Check:
- Check if the foundation base
onTable(E)exists. If missing, foundation is invalid (subsequent stacked blocks grant no points). - If base is valid, sequentially verify each ordered link:
on(D, E),on(C, D),on(B, C),on(A, B). Each consecutive intact link adds$+2$ . - If the stack is unbroken to the top, check if
clear(A)holds ($+2$ ).
- Check if the foundation base
-
Predicate Overlap Matching:
$+0.1$ for each matching active predicate with the target goal state. -
Step Penalty & Goal Bonus:
$c_{\text{step}} = 0.05$ per action taken;$R_{\text{goal}} = 50.0$ upon reaching terminal state.
The frontend is a bespoke web interface located in frontend/ built with Next.js 16, React 19, and Tailwind CSS v4 to analyze recorded trajectory rollouts.
- 🏗️ Overhead Robotic Gantry & Claw Gripper:
- A responsive overhead trolley rail dynamically travels horizontally to the targeted block column.
- Dual articulated mechanical claws spread open when
armemptyand firmly grip whenholding(X).
- 🏛️ Column Stability Engine:
- Resolves multi-block towers from dynamic
on(X, Y)andonTable(X)relationships. - Column stability algorithms ensure block stacks retain consistent horizontal coordinates across timesteps, eliminating visual hopping.
- Resolves multi-block towers from dynamic
- 🔍 Predicate Transition Diffing:
- Live inspector highlights newly added STRIPS predicates in green (
+) and deleted predicates in red (-) at each timestep. - Interactive block hover illuminates corresponding active predicates across the canvas.
- Live inspector highlights newly added STRIPS predicates in green (
- ⏱️ Timeline Scrubber & Playback Controls:
- Full-range interactive slider, playback rates (
$0.25\times$ to$4\times$ ), auto-loop toggle, and jumpable step markers.
- Full-range interactive slider, playback rates (
- 💾 In-Memory Streaming & Offline File Support:
- Parses diagnostics files with
$10,000+$ trajectories using browser IndexedDB and streaming disk cache.
- Parses diagnostics files with
| Shortcut | Description |
|---|---|
| ← | Step backward one timestep |
| → | Step forward one timestep |
| Space | Toggle auto-playback Play / Pause |
| Home | Jump to initial step ( |
| End | Jump to terminal step ( |
| L | Toggle continuous loop mode |
| ? | Open keyboard shortcuts reference modal |
| Esc | Dismiss active modal or overlay |
Clone the repository and open the self-contained training notebook:
git clone https://github.com/slyofzero/BlocksWorldSolver.git
cd BlocksWorldSolverOpen BlocksWorld.ipynb in Jupyter Lab, VS Code, or Google Colab:
- Run cells 1 through 10 to initialize the STRIPS environment, action pre-conditions, and
RewardModel. - Execute
train_policy()in cell 13 or runsave_diagnostics(5)in cell 16 to generate multi-run diagnostics. - Trajectories and metric histories are saved automatically to
training_runs/train_*/diagnostics.json.
To explore trajectories with the dark-mode Next.js visualizer:
cd frontend
# Install dependencies using Bun (or npm)
bun install
# Start development server
bun devVisit http://localhost:3000 in your browser. The visualizer will automatically detect and load the pre-recorded runs from training_runs/ and frontend/data/runs/demo_run.json.
BlocksWorldSolver/
├── assets/
│ ├── demo.gif # Interactive visualizer screen recording
│ ├── v1_dashboard.png # Iteration 1 training curves & failure diagnosis
│ ├── v2_dashboard.png # Iteration 2 subgoal reward shaping metrics
│ └── v3_dashboard.png # Iteration 3 batched REINFORCE + entropy metrics
│
├── frontend/ # Next.js 16 / React 19 Trajectory Visualizer
│ ├── app/
│ │ ├── components/
│ │ │ ├── BlocksWorldCanvas.tsx # SVG canvas with overhead gantry & claw
│ │ │ ├── InspectorPanel.tsx # Real-time STRIPS predicate diffs
│ │ │ ├── Controls.tsx # Playback speeds, loop & scrub buttons
│ │ │ └── EpisodeBrowserModal.tsx # Filter & select episodes by reward
│ │ ├── lib/
│ │ │ ├── layoutEngine.ts # Column stability and stack layout algorithm
│ │ │ ├── predicateParser.ts # STRIPS logic & syntax evaluator
│ │ │ └── runService.ts # Trajectory streaming and caching
│ │ └── page.tsx # Main dashboard layout
│ └── package.json
│
├── training_runs/
│ └── train_0/
│ ├── diagnostics.json # Full episodic metrics (returns, loss, entropy)
│ └── diagnostics.png # 8-metric matplotlib summary chart
│
├── BlocksWorld.ipynb # End-to-end environment, policy, and training code
├── trajectories.json # Sample evaluation trajectory rollouts
└── README.md # Project documentation
- Sutton & Barto — Reinforcement Learning: An Introduction (Policy Gradient Theorem & REINFORCE).
- Ng, Harada, & Russell (1999) — Policy Invariance Under Reward Transformations: Theory and Application to Reward Shaping (Potential-Based Reward Shaping).
- Fikes & Nilsson (1971) — STRIPS: A New Approach to the Application of Theorem Proving to Problem Solving.
- Mnih et al. (2016) — Asynchronous Methods for Deep Reinforcement Learning (Entropy Regularization).
"Curious about how machines learn structure, not just patterns."
