Skip to main content

Engine

Struct Engine 

Source
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>

Source

pub fn new() -> Self

Creates a new, empty MCTS engine.

§Examples
let mut engine = Engine::<7>::new();
Source

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);
Source

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);
Source

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 - The SelectionResult obtained from a previous call to select.
§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();
Source

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 - The MctsNodeId from 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();
Source

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 prior select call.
  • 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();
Source

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]);
Source

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.

Auto Trait Implementations§

§

impl<const N: usize> Freeze for Engine<N>

§

impl<const N: usize> RefUnwindSafe for Engine<N>

§

impl<const N: usize> Send for Engine<N>

§

impl<const N: usize> Sync for Engine<N>

§

impl<const N: usize> Unpin for Engine<N>

§

impl<const N: usize> UnsafeUnpin for Engine<N>

§

impl<const N: usize> UnwindSafe for Engine<N>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.