Planning and Monte-Carlo Tree Search

Consider the game of Go, where each position offers roughly 250 legal moves. Games last around 150 moves. The full game tree has more nodes than atoms in the observable universe. So no computer can enumerate it. Yet a program must still choose a move in seconds. It can use only a model of the rules and, perhaps, a rough evaluation of how good a position is. This is the planning problem in its starkest form. Given a simulator or transition model, decide what to do right now. Never build the whole tree. Monte-Carlo Tree Search (MCTS) solves this by growing a small, asymmetric tree. It does this through repeated simulated trials. It focuses computation on the moves that look most promising. It still occasionally checks on the rest. It builds directly on Model-Based Reinforcement Learning. It assumes access to a generative model of the environment's dynamics. It uses that model purely for lookahead at decision time. This is rather than for training a global policy offline. The tree grows deeper along strong lines of play. It stays shallow elsewhere. This is exactly the asymmetry that lets it scale to enormous branching factors. The centerpiece of MCTS is the UCT rule (Upper Confidence bounds applied to Trees). It treats each visited tree position as a small multi-armed bandit problem. It balances exploring untested moves against exploiting moves already known to be good. This turns a seemingly intractable search into a statistically principled, anytime algorithm. The longer you run it, the better the estimated values become. You can stop and act at any point. This article develops MCTS from first principles. It covers the four-phase algorithm (selection, expansion, simulation, backpropagation). It covers the UCT formula and its regret guarantees. It covers complexity and correctness arguments. It includes a fully worked trace on a small tree. It traces the historical path from bandit theory to the systems that eventually became AlphaGo and its successors.

Key takeaways
  • MCTS is a simulation-based planning algorithm for large or infinite discrete decision trees, using a model for lookahead.
  • It has four phases per iteration: selection, expansion, simulation (rollout), and backpropagation.
  • UCT balances exploration and exploitation using an upper-confidence bound derived from bandit theory.
  • The tree grows asymmetrically, concentrating search on promising lines rather than exploring uniformly.
  • MCTS is anytime: value estimates improve monotonically with more simulations, and it can act after any budget.
  • It underlies modern game-playing systems, later replaced rollouts with learned value networks in AlphaGo/AlphaZero.
The core insight

MCTS turns planning into repeated random sampling of full-depth trajectories, using a bandit-style confidence rule to grow a search tree asymmetrically toward the most promising actions.

The idea

A planning problem, in the sense used here, assumes an agent has a model of the environment — a function or simulator that, given a state and an action, returns a next state (and reward), possibly stochastically. This is the model-based setting: instead of learning a policy from real experience, the agent can query the model as many times as it likes to think ahead before acting, exactly as in Model-Based Reinforcement Learning. The difficulty is that for problems with large branching factor bb and depth dd, the full tree has O(bd)O(b^d) nodes, which is infeasible to enumerate exhaustively even for modest bb and dd.

Monte-Carlo Tree Search addresses this by building a partial search tree incrementally, using repeated simulated episodes ("rollouts") from the current state. Each simulation is a complete trajectory to a terminal state (or a fixed horizon) sampled using the model. The key design choice is that the tree is asymmetric: it is expanded most in the parts of the state space that appear most rewarding, and expanded conservatively — but never entirely ignored — elsewhere. This is achieved by treating every internal node of the tree as a multi-armed bandit problem, where the "arms" are the legal actions from that state, and the reward of pulling an arm is the outcome of a simulated trajectory that starts by taking that action. The bandit view motivates the UCT algorithm (Upper Confidence bounds applied to Trees), which selects, at each tree node, the action maximizing

UCT(s,a)=Q(s,a)+cln⁡N(s)N(s,a)\text{UCT}(s,a) = Q(s,a) + c \sqrt{\frac{\ln N(s)}{N(s,a)}}

where Q(s,a)Q(s,a) is the average simulated return after taking action aa from state ss, N(s)N(s) is the number of times ss has been visited, N(s,a)N(s,a) is the number of times aa was chosen at ss, and cc is an exploration constant. The first term favors actions with high estimated value (exploitation); the second term favors actions tried rarely relative to their parent (exploration), and shrinks as N(s,a)N(s,a) grows. This formula is derived directly from the UCB1 bandit algorithm, applied recursively at every node encountered along a simulated trajectory — hence "Trees."

How it works

MCTS proceeds by running many iterations, each consisting of four phases, until a computational budget (time or number of simulations) is exhausted. It then commits to an action at the root, typically the one with the highest visit count (more robust than raw average value, since visit count reflects sustained confidence).

1. Selection. Starting at the root, repeatedly apply the UCT rule to descend into the tree, choosing the child with highest UCT score, until reaching a node that is not fully expanded (has an untried action) or is a terminal state.

2. Expansion. If the reached node is non-terminal and has untried actions, add one new child node to the tree corresponding to one such action.

3. Simulation (rollout). From the newly added node, simulate the rest of the episode using a fast default policy — often uniformly random action choices, or a lightweight heuristic — without adding further nodes to the tree, until a terminal state or horizon is reached, yielding a return.

4. Backpropagation. Propagate the simulation's return back up through every node visited during selection and expansion, incrementing each visit count and updating each node's average value estimate. ```pseudocode function MCTS(root_state, num_iterations, c): root ← new Node(state = root_state, parent = null) for i in 1 .. num_iterations: node ← root

# 1. SELECTION: descend using UCT until a node with

# untried actions or a terminal state is reached while node.is_fully_expanded() and not node.is_terminal(): node ← select_child_UCT(node, c)

# 2. EXPANSION: add one untried child, if possible if not node.is_terminal() and not node.is_fully_expanded(): action ← node.pick_untried_action() next_state ← model.step(node.state, action) child ← new Node(state = next_state, parent = node, action = action) node.children.append(child) node ← child

# 3. SIMULATION: rollout to a terminal state / horizon return_value ← rollout(node.state, default_policy, model)

# 4. BACKPROPAGATION: update statistics along the path while node is not null: node.N ← node.N + 1 node.W ← node.W + return_value node.Q ← node.W / node.N return_value ← discount(return_value) # if using a discount factor node ← node.parent

# After the budget is exhausted, choose the root's best action return argmax_a root.children[a].N # robust child: most-visited action

function select_child_UCT(node, c): best_score ← -infinity best_child ← null for child in node.children: exploit ← child.Q explore ← c * sqrt( ln(node.N) / child.N ) score ← exploit + explore if score > best_score: best_score ← score best_child ← child return best_child

function rollout(state, policy, model): total_return ← 0 while not model.is_terminal(state): action ← policy(state) # e.g. uniform random state, reward ← model.step(state, action) total_return ← total_return + reward return total_return ``` Two implementation notes matter in practice. First, `N(s,a)` starting at zero makes the UCT formula undefined; the usual fix is to force every untried action to be tried once before the UCT rule is applied (this is exactly what the expansion phase guarantees, since selection only descends past fully expanded nodes). Second, for two-player zero-sum games the backpropagated value must flip sign at every other level (the opponent's gain is your loss), which is the basis for the minimax flavor of MCTS used in game-playing systems.

Figure
One MCTS iteration: selection descends via UCT, expansion adds a leaf, rollout estimates its value, backpropagation updates every ancestor
R N=12, Q=0.58 A N=7, Q=0.71 B N=4, Q=0.40 C N=1, Q=0.00 D N=4, Q=0.80 E N=2, Q=0.50 F new: N=0 rollout → return = 1 green = backpropagation amber = selection/expansion path

Complexity & correctness

Per-iteration time. Selection descends the tree along a single path of length at most the current tree depth dtreed_{\text{tree}}, at each step scanning up to bb children to compute UCT scores — cost O(b⋅dtree)O(b \cdot d_{\text{tree}}). Expansion is O(1)O(1) or O(b)O(b) depending on how untried actions are tracked. The simulation phase depends on the rollout horizon HH (up to the episode length), costing O(H)O(H) model calls. Backpropagation revisits the same path, O(dtree)O(d_{\text{tree}}). So one iteration costs

O(b⋅dtree+H).O(b \cdot d_{\text{tree}} + H).

Total time for nn iterations. Because the tree grows by at most one node per iteration, after nn iterations the tree has at most nn nodes, and dtree=O(min⁡(n,dmax⁡))d_{\text{tree}} = O(\min(n, d_{\max})) where dmax⁡d_{\max} is the maximum possible search depth. In the regime where rollouts dominate (common in practice), total cost is roughly O(n⋅H)O(n \cdot H), i.e. linear in the simulation budget — this is exactly what makes MCTS an anytime algorithm: doubling the time budget roughly doubles the number of simulations and further sharpens the value estimates, with no restructuring needed.

Space. The tree stores at most O(n)O(n) nodes after nn iterations (one node added per iteration in the worst case), each storing O(b)O(b) statistics for its children, giving O(nb)O(nb) space in the worst case — far smaller than the O(bdmax⁡)O(b^{d_{\max}}) required to store the full game tree.

Why UCT is a sound selection rule. At a single node, choosing among its children is a stochastic multi-armed bandit problem: each child aa has an unknown mean return μ(s,a)\mu(s,a), and pulling arm aa (running a simulation through it) yields a noisy sample. The UCB1 policy of choosing arg⁡max⁡a[Q(s,a)+cln⁡N(s)/N(s,a)]\arg\max_a \left[Q(s,a) + c\sqrt{\ln N(s)/N(s,a)}\right] is known to have regret (cumulative loss versus always playing the best arm) bounded by O(ln⁡n)O(\ln n) after nn pulls, meaning the fraction of pulls spent on suboptimal arms shrinks to zero — the algorithm eventually concentrates almost all trials on the best arm at each node while still probing others logarithmically often, which guarantees it will not get permanently stuck on a suboptimal move due to unlucky early samples. Chaining this bandit guarantee recursively down every level of the tree is the content of the UCT consistency theorem (Kocsis & Szepesvári, 2006): under the (mild) assumption that leaf rollout returns are bounded and the tree is finite-depth, the probability that UCT selects a suboptimal action at the root converges to zero as the number of simulations n→∞n \to \infty, and the bias of the value estimates decreases at rate O(log⁡n/n)O(\log n / n) at each node. Intuitively: correctness at the leaves (accurate rollout estimates) combined with the regret-minimizing property of UCB1 at every internal node implies that value estimates propagate upward with vanishing error, so the estimated best root action converges to the true optimal action given enough simulations.

Honest tradeoffs. MCTS gives no finite-sample optimality guarantee — with a small simulation budget it can and does pick suboptimal moves, especially in domains with "trap" states that look good on average but are catastrophic (the classic pathology is when a losing move has a slightly higher mean rollout return but a very low probability of leading to disaster, which random rollouts may under-sample). Random rollouts also make the estimated value depend heavily on the quality of the default policy: a poor rollout policy in a domain requiring precise tactics (many chess middlegames) yields noisy, misleading estimates, which is a central motivation for replacing rollouts with learned evaluation functions, foreshadowing the architecture used in AlphaGo and AlphaZero.

Worked example

Consider a small two-player decision tree at the root state RR, with two available actions, `Left` and `Right`, and c=1.0c = 1.0. We trace four MCTS iterations by hand (rollout returns are given as fixed illustrative numbers, since the "random" rollout policy is stochastic in general).

IterSelection pathExpansionRollout returnBackprop updates
1R (untried: Left, Right)expand `Left` → node A1 (win)A: N=1,Q=1.00; R: N=1,Q=1.00
2R (untried: Right)expand `Right` → node B0 (loss)B: N=1,Q=0.00; R: N=2,Q=0.50
3R → UCT picks A or B (tie, both N=1); say A chosen; A fully expanded (leaf, terminal for this toy tree) so we instead expand A's child `Left-Left`expand → node C1 (win)C: N=1,Q=1.00; A: N=2,Q=1.00; R: N=3,Q=0.67
4UCT at R: Left = 1.00 + 1·√(ln3/2) ≈ 1.74; Right = 0.00 + 1·√(ln3/1) ≈ 1.05 → select `Left`; descend into A → UCT picks between C and untried `Left-Right`; expand `Left-Right` → node Drollout0 (loss)D: N=1,Q=0.00; A: N=3,Q=0.67; R: N=4,Q=0.50

After 4 iterations the root's children have N(Left)=3N(\text{Left})=3, Q(Left)≈0.67Q(\text{Left})\approx 0.67, and N(Right)=1N(\text{Right})=1, Q(Right)=0.00Q(\text{Right})=0.00. Even though the raw averages might shift with more samples, `Left` has already attracted three times as many simulations as `Right`, illustrating the asymmetric growth: UCT's exploration term kept `Right` from being starved after its early loss (it was still worth ln⁡3/1≈1.05\sqrt{\ln 3 / 1} \approx 1.05 in exploration bonus at iteration 4), but the accumulating evidence for `Left` pulled the search decisively in that direction. With a much larger budget, this asymmetry becomes extreme — the tree under `Left` might contain thousands of nodes while `Right`'s subtree contains only a handful, exactly the behavior needed to make search feasible when bdb^d is astronomically large. The final action returned is the one with the highest visit count at the root — here, `Left`, with N=3N=3 versus N=1N=1 — rather than the one with the highest raw QQ, because visit count reflects sustained confidence and is empirically more robust to variance in individual rollout outcomes.

Common pitfalls & traps

PitfallWhy it happensFix
Choosing the highest-QQ child instead of highest-NN at the rootA single lucky rollout can inflate QQ for a rarely-visited nodeUse robust child (max visit count), or require a visit threshold before trusting QQ
Wrong sign flip in two-player backpropagationForgetting that returns alternate perspective by plyNegate (or apply 1−x1-x for win probabilities) the return at every other level during backpropagation
Division by zero in UCT when N(s,a)=0N(s,a)=0UCT formula undefined for untried actionsForce full expansion of untried actions before applying UCT (as pseudocode does)
Rollout policy too weak or too slowPurely random rollouts are fast but noisy; heavy rollouts are informative but expensiveTune rollout depth/policy, or replace with a learned value function (as in AlphaZero)
Ignoring the exploration constant ccWrong cc causes either premature convergence to a suboptimal move or excessive time wasted on clearly bad movesTune cc empirically (often via the range of possible returns) rather than using a default blindly
Confusing MCTS with exhaustive minimaxAssuming MCTS explores the whole tree given enough timeRecognize MCTS as a sampling method: correctness is asymptotic, not exact for any finite budget

Pioneers & history

The statistical backbone of MCTS — balancing exploration and exploitation via confidence bounds — traces to the theory of sequential decision-making and the multi-armed bandit problem, formalized decades before it was applied to trees.

Origins · 1 minHerbert Robbins and how this was discovered
HR
Herbert Robbins
1915–2001 · Formalized the multi-armed bandit problem and sequential design of experiments, laying the statistical groundwork later used in UCB and UCT

LK
Levente Kocsis
active 2000s–present · Co-developed UCT (Upper Confidence bounds applied to Trees) with Csaba Szepesvári, providing the theoretical bridge from bandit algorithms to tree search

RC
Rémi Coulom
active 2000s–present · Coined the term "Monte-Carlo Tree Search" and built early strong Go programs (Crazy Stone) demonstrating its practical power

History
1952
— Robbins formalizes the multi-armed bandit and sequential allocation problem.
2002
— Auer, Cesa-Bianchi, and Fischer publish the UCB1 algorithm with finite-time regret bounds.
2006
— Coulom introduces Monte-Carlo Tree Search for computer Go; Kocsis and Szepesvári publish UCT with convergence guarantees.
2008–2012
— MCTS-based Go programs (MoGo, Fuego, Crazy Stone) surpass prior handcrafted evaluation-function engines.
2016
— DeepMind's AlphaGo combines MCTS with deep neural network value and policy estimates, defeating a top human Go professional.

Where this matters

MCTS is the search engine behind essentially every strong modern game-playing system for domains with large branching factors: Go, Hex, general game playing competitions, and real-time strategy game AI. It is a natural fit whenever a simulator or generative model exists but a full policy is too costly to learn or compute in advance — general game playing agents, certain robotics motion-planning pipelines, and combinatorial optimization tools (scheduling, puzzle solving) all use MCTS variants when exact search is intractable. Its most influential legacy is architectural: AlphaGo replaced pure random rollouts with a learned value network (to estimate position quality) and a learned policy network (to bias the selection/expansion phase toward promising moves), while keeping the UCT-style tree search as the backbone. AlphaZero pushed this further, discarding rollouts entirely in favor of a single neural network trained by self-play whose outputs directly seed both the prior probabilities used during selection and the value estimates used at leaves — MCTS became the mechanism that generates high-quality training targets for the network, and the improved network in turn makes the tree search sharper, in a virtuous training loop. Related ideas underlie search-augmented reasoning in board games beyond Go (chess, shogi), and MCTS-style lookahead has been explored in non-game planning domains such as autonomous vehicle trajectory selection and industrial scheduling, wherever a model can be queried faster than the real world can be observed.

Ask the tutor: How does the PUCT variant used in AlphaZero modify the UCT formula to incorporate a learned policy prior?

How is MCTS different from standard depth-limited minimax with alpha-beta pruning?

Minimax with alpha-beta pruning explores the tree exhaustively up to a fixed depth, applying a hand-crafted static evaluation function at the cutoff, and its accuracy depends heavily on that evaluation function and search depth. MCTS instead samples complete trajectories to a terminal state (or a much greater depth) via rollouts, requiring no hand-crafted evaluation function, and grows an asymmetric tree rather than a uniform depth-limited one. Alpha-beta is deterministic and exact given its depth limit; MCTS is stochastic and only asymptotically correct, but tends to scale better to enormous branching factors like Go's, where alpha-beta's uniform expansion becomes infeasible.

Why does UCT use a logarithm in its exploration term?

The ln⁡N(s)/N(s,a)\sqrt{\ln N(s)/N(s,a)} term comes directly from the UCB1 bandit algorithm's regret analysis, which shows that scaling the exploration bonus by ln⁡n\sqrt{\ln n} (rather than, say, a constant or n\sqrt{n}) achieves the best known regret bound of O(log⁡n)O(\log n) for stochastic bandits with bounded rewards. The logarithm grows slowly, so the exploration bonus for a rarely-tried action shrinks only very slowly as the parent's total visits N(s)N(s) grow, ensuring every action keeps getting sampled occasionally, while the 1/N(s,a)1/N(s,a) term in the square root ensures actions already tried many times get progressively smaller bonuses, letting exploitation dominate over time.

Can MCTS be used in environments with continuous action spaces?

Not directly — the standard selection and expansion phases assume a finite, enumerable set of actions per node, since UCT compares alternatives by looping over children. Continuous domains require modifications such as progressive widening (gradually allowing more discretized action samples as visit counts grow), kernel-based generalization between similar actions, or hybrid approaches that discretize the action space coarsely for tree search while using a learned continuous policy to propose candidate actions. These extensions preserve the exploration-exploitation logic of UCT but relax the assumption of a small fixed branching factor.

Why is MCTS called an "anytime" algorithm, and why does that matter in practice?

An anytime algorithm can be interrupted after any amount of computation and still return a usable answer, with quality generally improving the longer it runs. MCTS satisfies this because every completed iteration only adds information (a new node, updated statistics) — there is no phase where the algorithm must run to completion before a decision is available. This matters enormously in real systems with hard time budgets, such as a game clock in competitive play or a real-time control loop in robotics, where the number of simulations affordable varies with available compute and remaining time, yet a reasonable move must always be returned.

How do AlphaGo and AlphaZero change the classic MCTS rollout and selection process?

Classic MCTS estimates a leaf's value using a fast rollout policy (often near-random) run to a terminal state, and gives every untried action equal initial priority during expansion. AlphaGo and AlphaZero replace the rollout with a neural network's value estimate at the leaf, avoiding the noise and slowness of full random playouts, and replace the uniform expansion prior with a policy network's output, biasing selection toward moves the network considers promising from the very first visit. The UCT-style formula is modified to a PUCT variant that incorporates this learned prior directly, but the core selection/expansion/backpropagation control loop of MCTS is preserved.

What is the role of the exploration constant c, and how sensitive is MCTS to it?

The constant cc in the UCT formula scales how strongly the algorithm favors under-explored actions versus known high-value ones; it must be matched to the typical range or variance of the return signal, since the theoretical UCB1 derivation assumes rewards are bounded (commonly rescaled to [0,1][0,1]). Too small a cc causes premature, possibly incorrect convergence onto an early-favored action; too large a cc wastes simulations exploring clearly inferior branches. In practice cc is tuned empirically per domain (or learned jointly with a value network, as in PUCT variants), and performance can degrade noticeably if it is mismatched to the reward scale.

Does more simulation time guarantee MCTS finds the truly optimal action?

Asymptotically yes, under the conditions of the UCT consistency result: as the number of simulations tends to infinity, the probability of selecting a suboptimal root action tends to zero, given a finite-depth tree and bounded rollout returns. In practice, however, budgets are always finite, and convergence can be slow in domains with deceptive local structure (trap states) or wide branching factors, so a bounded computation may still return a suboptimal move — a fact that motivated augmenting MCTS with learned priors and value functions in later systems rather than relying on raw simulation counts alone.

Before this

Where this leads