pub struct Engine<const N: usize> { /* private fields */ }Expand description
The core Engine handling the Monte Carlo Tree Search algorithm.
It manages the internal tree structure and provides methods to traverse, expand, and backpropagate statistics.
Implementations§
Source§impl<const N: usize> Engine<N>
impl<const N: usize> Engine<N>
Sourcepub fn with_capacity(capacity: usize) -> Self
pub fn with_capacity(capacity: usize) -> Self
Creates a new MCTS engine with a pre-allocated capacity for the underlying tree.
This is recommended to avoid reallocations when running millions of simulations.
§Examples
let mut engine = Engine::<7>::with_capacity(1_000_000);Sourcepub fn select(
&self,
path_out: &mut impl ResettableBuffer,
score_f: &impl SelectionFunction,
c: f32,
) -> SelectionResult
pub fn select( &self, path_out: &mut impl ResettableBuffer, score_f: &impl SelectionFunction, c: f32, ) -> SelectionResult
Traverses the tree from the root to a leaf node according to the selection function.
The traversal path (sequence of actions) is recorded in path_out.
§Arguments
path_out- A mutable reference to a buffer that will be cleared and filled with the chosen actions.score_f- The selection heuristic (e.g., PUCT formula).c- The exploration hyperparameter.
§Returns
A SelectionResult indicating whether a new leaf was found, a terminal state was hit, or the tree is empty.
§Panics
Panics if the internal tree structure is corrupted (i.e., a parent node ID points to a non-existent element). Also panics if an active node has no legal moves (all policies are <= 0.0).
§Examples
let mut path = Vec::new();
let mut engine = Engine::<7>::new();
let result = engine.select(&mut path, &puct, 1.414);Sourcepub fn expand(
&mut self,
evaluation: StateEvaluation<N>,
selection: SelectionResult,
) -> Result<MctsNodeId, MctsEngineError>
pub fn expand( &mut self, evaluation: StateEvaluation<N>, selection: SelectionResult, ) -> Result<MctsNodeId, MctsEngineError>
Expands the tree by attaching a new child node to the result of a previous selection.
§Arguments
evaluation- The evaluated data of the new state (score and policies if active, or just the final score if terminal).selection- TheSelectionResultobtained from a previous call toselect.
§Returns
Returns the newly minted MctsNodeId on success, or an MctsEngineError.
§Panics
Panics if the SelectionResult contains an out-of-bounds action index (>= N).
Because valid selections are exclusively generated by the engine’s select method,
this panic indicates that the provided SelectionResult was either manually forged,
corrupted, or used entirely out of context.
§Examples
let mut path = Vec::new();
let mut engine = Engine::<2>::new();
let result = engine.select(&mut path, &puct, 1.414);
// Expand an ongoing game state
let evaluation = StateEvaluation::Active(-0.2, [0.3, 0.7]);
engine.expand(evaluation, result).unwrap();Sourcepub fn backpropagate(
&mut self,
node: MctsNodeId,
score: f32,
score_updater: impl ScoreTransformer,
) -> Result<(), MctsEngineError>
pub fn backpropagate( &mut self, node: MctsNodeId, score: f32, score_updater: impl ScoreTransformer, ) -> Result<(), MctsEngineError>
Backpropagates a simulation score up to the root of the tree.
Every node encountered on the way up will have its visits incremented and
its children statistics updated. The score is transformed at every step using score_updater.
§Arguments
node- TheMctsNodeIdfrom which to start the backpropagation (usually the newly expanded leaf).score- The initial score to propagate.score_updater- A function or closure applied to the score at each step (e.g., negating it).
§Returns
Returns Ok(()) on success, or an error if an invalid node ID is encountered.
§Examples
use crate::simple_mcts::Engine;
let mut path = Vec::new();
let mut engine = Engine::<2>::new();
let result = engine.select(&mut path, &puct, 1.414);
let evaluation = StateEvaluation::Active(-0.2, [0.3, 0.7]);
// Invert the score at each step for an alternating-turn game
let node = engine.expand(evaluation, result).unwrap();
engine.backpropagate(node, 1.0, |s| -s).unwrap();Sourcepub fn update(
&mut self,
evaluation: StateEvaluation<N>,
selection: SelectionResult,
score_updater: impl ScoreTransformer,
) -> Result<(), MctsEngineError>
pub fn update( &mut self, evaluation: StateEvaluation<N>, selection: SelectionResult, score_updater: impl ScoreTransformer, ) -> Result<(), MctsEngineError>
A convenience method that sequentially performs expand and backpropagate.
If the selection provided was already terminal, expansion is skipped and backpropagation starts immediately from the terminal node.
§Arguments
evaluation- The evaluated data of the leaf node (score and policies).selection- The result returned by a priorselectcall.score_updater- The transformation applied to the score during backpropagation (e.g., inverting it).
§Examples
let mut path = Vec::new();
let mut engine = Engine::<2>::new();
let result = engine.select(&mut path, &puct, 1.414);
// Expand and backpropagate in one step, inverting the score at each depth
let evaluation = StateEvaluation::Active(-0.2, [0.3, 0.7]);
engine.update(evaluation, result, |s| -s).unwrap();Sourcepub fn scores(&self) -> [i32; N]
pub fn scores(&self) -> [i32; N]
Retrieves the visit counts of all possible actions from the root node.
This array is typically used at the end of the MCTS cycle to decide the actual move to play in the game.
§Returns
An array of integers representing the number of visits for each child branch. Returns an array of zeros if the tree is currently empty.
§Panics
Panics if the internal tree has a root ID but the root node cannot be retrieved.
§Examples
let mut engine = Engine::<3>::new();
let scores = engine.scores();
assert_eq!(scores, [0, 0, 0]);Sourcepub fn commit_action(&mut self, action: Action)
pub fn commit_action(&mut self, action: Action)
Promotes the child node corresponding to the given action to the new root of the tree.
This method updates the MCTS tree to reflect a move played on the actual game board. It performs an amortized memory cleanup (compacting) if the number of unreachable nodes exceeds a heuristic threshold (twice the number of visits of the new root).
If the action leads to a path that has not been explored by the MCTS, the current tree is cleared, as it no longer contains valid information for the new state.
§Arguments
action- The action that was performed on the game board.
§Panics
Panics if:
- The action index is out of bounds (i.e.,
action.0 >= N). - The internal tree structure is corrupted (e.g., attempting to move the root to a non-existent node).
§Note
This is an amortized operation. self.tree.compact() is only called when
memory overhead becomes significant, ensuring high performance during game play.