Exemple #1
0
 /// <summary>
 /// Dumps the PV (principal variation) to the output stream.
 /// </summary>
 /// <param name="withDetail"></param>
 private void DumpPV(bool withDetail)
 {
     if (curManager != null)
     {
         using (new SearchContextExecutionBlock(curContext))
         {
             SearchPrincipalVariation pv2 = new SearchPrincipalVariation(curContext.Root);
             MCTSPosTreeNodeDumper.DumpPV(curContext.StartPosAndPriorMoves, curContext.Root, withDetail, null);
         }
     }
     else
     {
         Console.WriteLine("info string No search manager created");
     }
 }
Exemple #2
0
 /// <summary>
 /// Dumps the PV (principal variation) to the output stream.
 /// </summary>
 /// <param name="withDetail"></param>
 private void DumpPV(bool withDetail)
 {
     if (CeresEngine?.Search != null)
     {
         using (new SearchContextExecutionBlock(CeresEngine?.Search.Manager.Context))
         {
             SearchPrincipalVariation pv2 = new SearchPrincipalVariation(CeresEngine.Search.Manager.Root);
             MCTSPosTreeNodeDumper.DumpPV(CeresEngine.Search.Manager.Context.Root, withDetail);
         }
     }
     else
     {
         UCIWriteLine("info string No search manager created");
     }
 }
Exemple #3
0
        public static void Analyze(string fenAndMoves, SearchLimit searchLimit,
                                   NNEvaluatorDef evaluatorDef,
                                   bool forceDisablePruning,
                                   LC0Engine lc0Engine         = null,
                                   GameEngine comparisonEngine = null,
                                   bool verbose = false)
        {
            Console.WriteLine("=============================================================================");
            Console.WriteLine("Analyzing FEN   : " + fenAndMoves);
            Console.WriteLine("Search limit    : " + searchLimit.ToString());
            Console.WriteLine("Ceres evaluator : " + evaluatorDef.ToString());
            if (comparisonEngine != null)
            {
                Console.WriteLine("Opponent      : " + comparisonEngine.ToString());
            }
            Console.WriteLine();
            Console.WriteLine();

            NNEvaluatorSet nnEvaluators = new NNEvaluatorSet(evaluatorDef);

            // Warmup (in parallel)
            lc0Engine?.DoSearchPrepare();
            Parallel.Invoke(
                () => nnEvaluators.Warmup(true),
                () => comparisonEngine?.Warmup());

            bool ceresDone = false;

            lastInfoUpdate = DateTime.Now;

            UCISearchInfo lastCeresInfo = null;

            // Launch Ceres
            MCTSearch ceresResults = null;
            Task      searchCeres  = Task.Run(() =>
            {
                ParamsSearch searchParams = new ParamsSearch();
                searchParams.FutilityPruningStopSearchEnabled = !forceDisablePruning;
                PositionWithHistory positionWithHistory       = PositionWithHistory.FromFENAndMovesUCI(fenAndMoves);
                ceresResults = new MCTSearch();
                ceresResults.Search(nnEvaluators, new ParamsSelect(), searchParams, null, null,
                                    null, positionWithHistory, searchLimit, verbose, DateTime.Now, null,
                                    manager => lastCeresInfo = new UCISearchInfo(UCIInfo.UCIInfoString(manager), null, null), false, true);
            });

            // Possibly launch search for other engine
            Task searchComparison = null;

            if (lc0Engine != null || comparisonEngine != null)
            {
                searchComparison = Task.Run(() =>
                {
                    if (lc0Engine != null)
                    {
                        lc0Engine.DoSearchPrepare();
                        lc0Engine.AnalyzePositionFromFENAndMoves(fenAndMoves, searchLimit);
                    }
                    else
                    {
                        comparisonEngine.Search(PositionWithHistory.FromFENAndMovesUCI(fenAndMoves), searchLimit, verbose: true);
                    }
                });
            }
            ;

            while (!searchCeres.IsCompleted || (searchComparison != null && !searchComparison.IsCompleted))
            {
                Thread.Sleep(1000);
//Console.WriteLine(DateTime.Now + " --> " + lastCeresInfo?.PVString + " OTHER " + comparisonEngine?.UCIInfo?.RawString);

                int numCharactersSame = int.MaxValue;
                if (lastCeresInfo?.PVString != null || comparisonEngine?.UCIInfo?.RawString != null)
                {
                    if (lastCeresInfo != null && comparisonEngine?.UCIInfo != null)
                    {
                        numCharactersSame = 0;
                        string        pv1 = lastCeresInfo.PVString;
                        UCISearchInfo lastComparisonInfo = comparisonEngine.UCIInfo;
                        string        pv2 = lastComparisonInfo.PVString;
                        while (pv1.Length > numCharactersSame &&
                               pv2.Length > numCharactersSame &&
                               pv1[numCharactersSame] == pv2[numCharactersSame])
                        {
                            numCharactersSame++;
                        }
                    }
                }

                if (lastCeresInfo != null)
                {
                    WriteUCI("Ceres", lastCeresInfo, numCharactersSame);
                }

                if (comparisonEngine != null)
                {
                    WriteUCI(comparisonEngine.ID, comparisonEngine.UCIInfo, numCharactersSame);
                }
                Console.WriteLine();
            }

            searchCeres.Wait();
            searchComparison?.Wait();

            string infoUpdate = UCIInfo.UCIInfoString(ceresResults.Manager);

            double q2 = ceresResults.SearchRootNode.Q;

            //SearchPrincipalVariation pv2 = new SearchPrincipalVariation(worker2.Root);
            MCTSPosTreeNodeDumper.DumpPV(ceresResults.SearchRootNode, true);
        }
Exemple #4
0
        /// <summary>
        /// Writes extensive descriptive information to a specified TextWriter,
        /// including verbose move statistics, principal variation, and move timing information.
        /// </summary>
        /// <param name="searchRootNode"></param>
        /// <param name="writer"></param>
        /// <param name="description"></param>
        public void DumpFullInfo(MGMove bestMove, MCTSNode searchRootNode = null, TextWriter writer = null, string description = null)
        {
            searchRootNode = searchRootNode ?? Root;
            writer         = writer ?? Console.Out;

            int moveIndex = searchRootNode.Tree.Store.Nodes.PriorMoves.Moves.Count;

            writer.WriteLine();
            writer.WriteLine("=================================================================================");
            writer.Write(DateTime.Now + " SEARCH RESULT INFORMATION,  Move = " + ((1 + moveIndex / 2)));
            writer.WriteLine($" Thread = {Thread.CurrentThread.ManagedThreadId}");
            if (description != null)
            {
                writer.WriteLine(description);
            }
            writer.WriteLine();

            writer.WriteLine("Tree root           : " + Context.Root);
            if (searchRootNode != Root)
            {
                writer.WriteLine("Search root         : " + searchRootNode);
            }
            writer.WriteLine();

            MCTSNode[] nodesSortedN = null;
            MCTSNode[] nodesSortedQ = null;

            string bestMoveInfo = "";

            if (searchRootNode.NumChildrenExpanded > 0 &&
                StopStatus != SearchStopStatus.TablebaseImmediateMove &&
                StopStatus != SearchStopStatus.OnlyOneLegalMove)
            {
                MCTSNode[] childrenSortedN = searchRootNode.ChildrenSorted(node => - node.N);
                MCTSNode[] childrenSortedQ = searchRootNode.ChildrenSorted(node => (float)node.Q);
                bool       isTopN          = childrenSortedN[0].Annotation.PriorMoveMG == bestMove;
                bool       isTopQ          = childrenSortedQ[0].Annotation.PriorMoveMG == bestMove;
                if (isTopN && isTopQ)
                {
                    bestMoveInfo = "(TopN and TopQ)";
                }
                else if (isTopN)
                {
                    bestMoveInfo = "(TopN)";
                }
                else if (isTopQ)
                {
                    bestMoveInfo = "(TopQ)";
                }
            }

            // Output position (with history) information.
            writer.WriteLine("Position            : " + searchRootNode.Annotation.Pos.FEN);
            writer.WriteLine("Tree root position  : " + Context.Tree.Store.Nodes.PriorMoves);
            writer.WriteLine("Search stop status  : " + StopStatus);
            writer.WriteLine("Best move selected  : " + bestMove.MoveStr(MGMoveNotationStyle.LC0Coordinate) + " " + bestMoveInfo);
            writer.WriteLine();

            using (new SearchContextExecutionBlock(Context))
            {
                string infoUpdate = UCIInfo.UCIInfoString(this, searchRootNode);
                writer.WriteLine(infoUpdate);

                writer.WriteLine();
                DumpTimeInfo(writer);

                writer.WriteLine();
                searchRootNode.Dump(1, 1, writer: writer);

                writer.WriteLine();
                MCTSPosTreeNodeDumper.DumpPV(searchRootNode, true, writer);
            }
        }