Esempio n. 1
0
        /// <summary>
        /// Virtual worker method that attempts to resolve the evaluation of a specified node from the cache.
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        protected override LeafEvaluationResult DoTryEvaluate(MCTSNode node)
        {
            PositionEvalCacheEntry cacheEntry = default;
            bool inCache = cache.TryLookupFromHash(node.Annotation.PositionHashForCaching, ref cacheEntry);

            if (inCache)
            {
                if (CeresEnvironment.MONITORING_METRICS)
                {
                    NumCacheHits++;
                }

                Debug.Assert(!float.IsNaN(cacheEntry.WinP + cacheEntry.LossP));

                LeafEvaluationResult result = new LeafEvaluationResult(cacheEntry.TerminalStatus, cacheEntry.WinP, cacheEntry.LossP, cacheEntry.M);
                result.PolicySingle = cacheEntry.Policy;
                return(result);
            }
            else
            {
                if (CeresEnvironment.MONITORING_METRICS)
                {
                    NumCacheMisses++;
                }

                return(default);
Esempio n. 2
0
        /// <summary>
        ///
        /// TODO: this method similar to one below, try to unify them
        /// </summary>
        /// <param name="nodes"></param>
        /// <param name="results"></param>
        void RetrieveResults(Span <MCTSNode> nodes, IPositionEvaluationBatch results, EvalResultTarget resultTarget)
        {
            for (int i = 0; i < nodes.Length; i++)
            {
                MCTSNode node = nodes[i];

                FP16 winP;
                FP16 lossP;
                FP16 rawM = results.GetM(i);

                // Copy WinP
                FP16 rawWinP = results.GetWinP(i);
                Debug.Assert(!float.IsNaN(rawWinP));

                // Copy LossP
                FP16 rawLossP = results.GetLossP(i);
                Debug.Assert(!float.IsNaN(rawLossP));

                // Assign win and loss probabilities
                // If they look like non-WDL result, try to rewrite them
                // in equivalent way that avoids negative probabilities
                if (rawWinP < 0 && rawLossP == 0)
                {
                    winP  = 0;
                    lossP = -rawWinP;
                }
                else
                {
                    winP  = rawWinP;
                    lossP = rawLossP;
                }

                LeafEvaluationResult evalResult = new LeafEvaluationResult(GameResult.Unknown, winP, lossP, rawM);
                evalResult.PolicyInArray = results.GetPolicy(i);

                // Copy policy
                if (resultTarget == EvalResultTarget.PrimaryEvalResult)
                {
                    node.EvalResult = evalResult;
                }
                else if (resultTarget == EvalResultTarget.SecondaryEvalResult)
                {
                    node.EvalResultSecondary = evalResult;
                }
                else
                {
                    throw new Exception("Internal error: unexpected EvalResultTarget");
                }

                // Save back to cache
                if (SaveToCache)
                {
                    Cache.Store(node.Annotation.PositionHashForCaching,
                                GameResult.Unknown, rawWinP, rawLossP, rawM,
                                in node.EvalResult.PolicyRef);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Attempts to evaluate node immediately and returns if successful (else default).
        /// </summary>
        /// <param name="node"></param>
        public LeafEvaluationResult TryEvaluate(MCTSNode node)
        {
            LeafEvaluationResult result = DoTryEvaluate(node);

            if (!result.IsNull)
            {
                Interlocked.Increment(ref CountHits);
            }
            return(result);
        }
Esempio n. 4
0
        private static LeafEvaluationResult ExtractTranspositionNodesFromSubtree(MCTSNode node, ref MCTSNodeStruct transpositionRootNode,
                                                                                 ref int numAlreadyLinked, MCTSNodeTranspositionVisitor linkedVisitor)
        {
            LeafEvaluationResult result = default;

            // Determine how many evaluations we should extract (based on number requested and number available)
            int numAvailable = linkedVisitor.TranspositionRootNWhenVisitsStarted - numAlreadyLinked;
            int numDesired   = node.NInFlight + node.NInFlight2;

            if (numDesired > numAvailable && WARN_COUNT < 10)
            {
                Console.WriteLine(numDesired + " Warning: multiple nodes were requested from the transposition subtree, available " + numAvailable);
                WARN_COUNT++;
            }
            int numToFetch = Math.Min(numDesired, numAvailable);

            Debug.Assert(numToFetch > 0);

            // Extract each evaluation
            for (int i = 0; i < numToFetch; i++)
            {
                MCTSNodeStructIndex transpositionSubnodeIndex = linkedVisitor.Visitor.GetNext();
                Debug.Assert(!transpositionSubnodeIndex.IsNull);

                NumExtractedAndNeverCloned++;
                numAlreadyLinked++;

                // Prepare the result to return
                ref MCTSNodeStruct   transpositionSubnode = ref node.Context.Tree.Store.Nodes.nodes[transpositionSubnodeIndex.Index];
                LeafEvaluationResult thisResult           = new LeafEvaluationResult(transpositionSubnode.Terminal, transpositionRootNode.WinP,
                                                                                     transpositionRootNode.LossP, transpositionRootNode.MPosition);

                // Update our result node to include this node
                result = AddResultToResults(result, numToFetch, i, thisResult);

                if (VERBOSE)
                {
                    Console.WriteLine($"ProcessAlreadyLinked {node.Index} yields {result.WinP} {result.LossP} via linked subnode root {transpositionRootNode.Index.Index} {transpositionRootNode} chose {transpositionSubnode.Index.Index}");
                }

                node.Ref.NumNodesTranspositionExtracted++;
            }