update comments

This commit is contained in:
2026-06-30 15:59:00 +07:00
parent c5ad5c882c
commit 6a18591a0b
3 changed files with 149 additions and 48 deletions
+43 -10
View File
@@ -75,33 +75,50 @@ function runMCTS(
)::NamedTuple{(:root, :bestNextState, :bestTerminalState, :highValueStateList),
Tuple{MCTSNode,T,T,Vector{Dict{String,Any}}}} where {T<:Any}
# Initialize the MCTS tree with a root node representing the initial state
# root.visits=0: no visits yet
# root.statevalue=0: no simulation results yet
root = MCTSNode("root", initialstate, 0, 0, 0, 0, false, nothing, Dict{String,MCTSNode}(),
Dict{String,Any}())
# storage for holding all high reward terminal nodes
# Channel to collect high-value terminal states (reward >= 8)
# These are "good solutions" that can be returned to the user
highValueState = Channel{Any}(100)
# Main MCTS loop: perform iterations to build the search tree
# Each iteration: SELECTION → EXPANSION → SIMULATION → BACKPROPAGATION
for nth in 1:maxiterations
# Start from root and traverse down using UCT selection
node = root
node.visits += 1
node.visits += 1 # Count this iteration's visit to root
# Phase 1: SELECTION - Traverse tree using UCT until reaching a leaf node
# UCT balances exploration (new branches) vs exploitation (promising branches)
while !isleaf(node)
node = UCTselect(node, explorationweight)
end
# Phase 2: TERMINAL CHECK - If leaf is terminal, just backpropagate
if node.isterminal
# If this terminal state has high reward (>= 8), store it for later
if node.state[:reward] >= 8
put!(highrewardNode, deepcopy(node.state))
put!(highValueState, deepcopy(node.state))
end
# MCTS arrive at the leaf node that is also a terminal state,
# do nothing then go directly to backpropagation. It means the end of this iteration
# Backpropagate the terminal node's own reward up to root
# This updates all ancestors with this path's outcome
backpropagate(node, node.reward)
else
# Phase 3: EXPANSION - Generate children for this non-terminal leaf
# Horizontal sampling: create multiple child nodes via LLM transition
_ = expand(node, transition, transitionargs;
horizontalSample=horizontalSampleExpansionPhase,
multithread=multithread)
# Phase 4: SIMULATION + BACKPROPAGATION
# For each newly expanded child, run simulation and update statistics
if multithread
# Parallel simulation: spawn threads for each child node
@sync for (leafNodeKey, leafNode) in node.children
@spawn simulateThenBackpropagate(leafNode, transition, transitionargs;
maxSimulationDepth=maxSimulationDepth,
@@ -112,6 +129,7 @@ function runMCTS(
)
end
else
# Sequential simulation: process each child one at a time
for (leafNodeKey, leafNode) in node.children
simulateThenBackpropagate(leafNode, transition, transitionargs;
maxSimulationDepth=maxSimulationDepth,
@@ -123,22 +141,27 @@ function runMCTS(
end
end
# stop if the early stop condition is met
# Phase 5: EARLY STOP CHECK
# Optional: stop search early if a condition is met
if typeof(earlystop) <: Function && earlystop(node.state)
break
end
end
# select the best next state and the best terminal state along the best trajectory
# After all iterations, extract results from the search tree
# Select best immediate next state (best child of root)
bestNextState = selectBestNextNode(root)
# Select best terminal state along the optimal trajectory
bestTerminalState = selectBestTrajectoryNode(root)
# take all high value state from highValueState channel and put it in a list
# Collect all high-value states from the channel into a list
highValueStateList = Vector{Dict{String, Any}}()
while !isempty(highValueState)
push!(highValueStateList, take!(highValueState))
end
# Return complete search results
result = (
root=root,
bestNextState=bestNextState.state,
@@ -186,12 +209,17 @@ function simulateThenBackpropagate(node::MCTSNode, transition::Function, transit
saveSimulatedNode::Bool=false,
multithread=false,
highValueState=Union{Nothing,Any}=nothing)
# Phase 1: RUN SIMULATION (rollout)
# Perform a rollout from this node, accumulating rewards along the way
simTrajectoryReward, terminalstate =
simulate(node, transition, transitionargs;
maxSimulationDepth=maxSimulationDepth,
horizontalSample=horizontalSampleSimulationPhase,
multithread=multithread)
# if a node has state value >= 8, store it in highValueState
# Phase 2: HIGH-VALUE STATE TRACKING
# If we reached a terminal state with high reward (>= 8), store it
# This allows users to access multiple good solutions, not just the best one
if highValueState !== nothing &&
terminalstate !== nothing &&
terminalstate[:reward] >= 8
@@ -199,9 +227,14 @@ function simulateThenBackpropagate(node::MCTSNode, transition::Function, transit
put!(highValueState, deepcopy(terminalstate))
end
# Phase 3: BACKPROPAGATE
# Update statistics (visits, statevalue) for all ancestors up to root
# The simulation result is now incorporated into the tree
backpropagate(node, simTrajectoryReward)
# check if the user wants to keep the simulated node
# Phase 4: MEMORY MANAGEMENT
# Clear children unless user wants to keep them for analysis
# This frees memory for the next iteration while preserving tree structure
if saveSimulatedNode == false
node.children = Dict{String, MCTSNode}()
end