/// <summary> /// Selects the child with the highest relative reward. /// </summary> /// <param name="node">A node.</param> /// <exception cref="ArgumentNullException">Is thrown, if the given node is null.</exception> /// <exception cref="InvalidOperationException">Is thrown, if no child nodes are available.</exception> public IGameTreeNode finalChildSelection(IGameTreeNode node) { if (node == null) { throw new ArgumentNullException("CLASS: FinalChildSelectionServiceMAX, METHOD: finalChildSelection - the given node is null!"); } if (!node.areChildNodesExpanded) { throw new InvalidOperationException("CLASS: FinalChildSelectionServiceMAX, METHOD: finalChildSelection - no child nodes are available!"); } double maxScore = 0; List <IGameTreeNode> bestChilds = new List <IGameTreeNode>(); foreach (IGameTreeNode child in node.getChildNodes()) { if (child.value / child.playouts >= maxScore) { if (child.value / child.playouts > maxScore) { maxScore = child.value / child.playouts; bestChilds.Clear(); } bestChilds.Add(child); } } Random rng = new Random(); return(bestChilds[rng.Next(bestChilds.Count)]); }
public static IMctsableGameState calculateGameStateFromNode(MctsNode node) { List <IGameTreeNode> pathInTheGameTree = new List <IGameTreeNode>(); IGameTreeNode currentNode = node; pathInTheGameTree.Add(node); while (currentNode.previousNode != null) { pathInTheGameTree.Insert(0, currentNode.previousNode); currentNode = currentNode.previousNode; } MctsRootNode rootNode = currentNode as MctsRootNode; if (rootNode == null) { throw new InvalidOperationException("CLASS: MctsNode, METHOD: calculateGameStateFromNode - no root node available in game tree!"); } IMctsableGameState gameState = rootNode.initialGameState.duplicate(); pathInTheGameTree.RemoveAt(0); foreach (MctsNode pathNode in pathInTheGameTree) { gameState.makeMove(pathNode.move); } return(gameState); }
/// <summary> /// Selects the best child of the given node via the RAVE algorithm. /// </summary> /// <param name="node">A node in the game tree.</param> /// <param name="explorationConstant">A tunable exploration constant.</param> /// <exception cref="ArgumentNullException">Is thrown, if the given node is null.</exception> /// <exception cref="InvalidOperationException">Is thrown, if no child nodes are available.</exception> public IGameTreeNode childSelection(IGameTreeNode node, double explorationConstant) { if (node == null) { throw new ArgumentNullException("CLASS: ChildSelectionServiceRAVE, METHOD: childSelection - given node is null!"); } if (!node.areChildNodesExpanded) { throw new InvalidOperationException("CLASS: ChildSelectionServiceRAVE, METHOD: childSelection - no child nodes are available!"); } double score, maxScore = 0, alpha; List <IGameTreeNode> bestChildren = new List <IGameTreeNode>(); foreach (IGameTreeNode child in node.getChildNodes()) { if (child.playouts == 0) { return(child); } alpha = Math.Max(0, (double)(_playoutsBound - child.playouts) / _playoutsBound); score = alpha * child.valueAMAF + (1 - alpha) * child.value + explorationConstant * Math.Sqrt(Math.Log(node.playouts) / child.playouts); if (score >= maxScore) { if (score > maxScore) { maxScore = score; bestChildren.Clear(); } bestChildren.Add(child); } } Random rng = new Random(); return(bestChildren[rng.Next(bestChildren.Count)]); }