11"""Test Cmhmey Jr.'s Uncle Poole"""
2- from os import path
2+ from os import cpu_count , path
33from time import perf_counter
4+ from typing import List , Optional , Tuple
45from unittest import TestCase
56from unittest .mock import patch
67
@@ -52,7 +53,6 @@ def test_initialization_default(self):
5253 self .assertIsInstance (self .executor .engine .board , Board )
5354 self .assertEqual (self .executor .engine .board .fen (), self .starting_board .fen ())
5455 self .assertEqual (self .executor .engine .depth , 1 )
55- self .assertIsNone (self .executor .max_workers )
5656 self .assertIsInstance (self .executor .engine , CMHMEngine2 )
5757
5858 def test_initialization_custom (self ):
@@ -61,10 +61,9 @@ def test_initialization_custom(self):
6161 with self .assertRaises (ValueError ):
6262 _ = CMHMEngine2PoolExecutor (board = custom_board , depth = 3 , max_workers = 4 )
6363 custom_board = Board (MATE_IN_ONE_4 )
64- executor = CMHMEngine2PoolExecutor (board = custom_board , depth = 0 , max_workers = 0 )
64+ executor = CMHMEngine2PoolExecutor (board = custom_board , depth = 0 , max_workers = 1 )
6565 self .assertEqual (executor .engine .board , custom_board )
6666 self .assertEqual (executor .engine .depth , 0 )
67- self .assertEqual (executor .max_workers , 0 )
6867
6968 @patch ("chmengine.engines.cmhmey2_pool_executor.CMHMEngine2.pick_move" )
7069 def test_pick_move_valid (self , mock_pick_move ):
@@ -95,40 +94,26 @@ def test_debug_output(self):
9594
9695 def test_pick_move (self ) -> None :
9796 """Tests pick_move method."""
98- start = perf_counter ()
99- pick = self .executor .pick_move ()
100- duration_first = (perf_counter () - start ) / self .executor .engine .board .legal_moves .count ()
101- print (
102- f"{ self .executor .engine .fen ()} pick_move call: ({ pick [0 ].uci ()} ,"
103- f" { pick [1 ]:.2f} ) { duration_first :.3f} s/branch"
104- )
105- init_w_moves = list (self .executor .engine .board .legal_moves )
97+ pick : Pick
98+ duration_per_branch : float
99+ duration : float
100+ branch_count : int
101+ pick , duration_per_branch , duration , branch_count = self .measure_pick (message = 1 )
102+ init_w_moves : List [Move ] = list (self .executor .engine .board .legal_moves )
106103 move : Move
107- first_time_pick_times = [duration_first ]
108- init_board_pick_times = [duration_first ]
109- revisit_pick_times = []
104+ first_time_pick_times = [duration_per_branch ] # list of all times a position was seen for the first time.
105+ init_board_pick_times = [duration_per_branch ] # list of all times the first board position was seen.
106+ revisit_pick_times = [] # lists all the times the init board position was revisited.
110107 new_duration = 999999.99
111- for i , move in enumerate (init_w_moves [:len (init_w_moves ) // 2 ], 2 ):
112- self .executor .engine .board .push (move )
113- start = perf_counter ()
114- response_pick = self .executor .pick_move ()
115- duration_rep_pick = (perf_counter () - start ) / self .executor .engine .board .legal_moves .count ()
108+ for i , move in enumerate (init_w_moves [:len (init_w_moves ) // 2 ], 1 ):
109+ self .executor .push (move )
110+ response_pick , duration_rep_pick , duration , branch_count = self .measure_pick (move = move , message = 2 )
116111 first_time_pick_times .append (duration_rep_pick )
117- print (
118- f"'{ move .uci ()} ' -> '{ self .executor .engine .fen ()} ' pick_move call: "
119- f"({ response_pick [0 ].uci ()} , { response_pick [1 ]:.2f} ) { duration_rep_pick :.3f} s/branch"
120- )
121112 self .executor .engine .board .pop ()
122- start = perf_counter ()
123- new_pick = self .executor .pick_move ()
124- new_duration = (perf_counter () - start ) / self .executor .engine .board .legal_moves .count ()
113+ new_pick , new_duration , duration , branch_count = self .measure_pick (i = i , message = 3 )
125114 init_board_pick_times .append (new_duration )
126115 revisit_pick_times .append (new_duration )
127- print (
128- f"{ self .executor .engine .fen ()} pick_move call { i } : ({ new_pick [0 ].uci ()} ,"
129- f" { new_pick [1 ]:.2f} ) { new_duration :.3f} s/branch"
130- )
131- self .assertLess (new_duration , duration_first )
116+ self .assertLess (new_duration , duration_per_branch )
132117 avg_duration = mean (init_board_pick_times )
133118 avg_response = mean (first_time_pick_times )
134119 avg_revisit = mean (revisit_pick_times )
@@ -143,3 +128,49 @@ def test_pick_move(self) -> None:
143128 print (
144129 f"mean revisit time: { avg_revisit :.3f} s\n percentiles (0, 1, 10, 25, 50, 75, 90, 99, 100):\n { pre_revisit } "
145130 )
131+
132+ def measure_pick (
133+ self ,
134+ i : Optional [int ] = None ,
135+ move : Optional [Move ] = None ,
136+ message : int = 0
137+ ) -> Tuple [Pick , float , float , int ]:
138+ """
139+
140+ Parameters
141+ ----------
142+ i : Optional[int]
143+ move : Optional[Move]
144+ message : int
145+
146+ Returns
147+ -------
148+ Tuple[Pick, float]
149+ """
150+ branch_count : int = self .executor .engine .board .legal_moves .count ()
151+ start : float = perf_counter ()
152+ pick : Pick = self .executor .pick_move ()
153+ end : float = perf_counter ()
154+ duration : float = (end - start )
155+ duration_per_branch : float = duration / branch_count
156+ if message == 1 :
157+ print (
158+ f"{ self .executor .engine .fen ()} initial pick_move call: "
159+ f"({ pick :+.2f} ) { duration_per_branch :.3f} s/branch"
160+ f" (branch_count={ branch_count } , duration={ duration :.3f} s)"
161+ )
162+ elif message == 2 :
163+ if move is not None :
164+ print (
165+ f"{ move } -> { self .executor .engine .fen ()} initial pick_move call: "
166+ f"({ pick :+.2f} ) { duration_per_branch :.3f} s/branch"
167+ f" (branch_count={ branch_count } , duration={ duration :.3f} s)"
168+ )
169+ elif message == 3 :
170+ if i is not None :
171+ print (
172+ f"{ self .executor .engine .fen ()} revisit { i } pick_move call: "
173+ f"({ pick :+.2f} ) { duration_per_branch :.3f} s/branch"
174+ f" (branch_count={ branch_count } , duration={ duration :.3f} s)"
175+ )
176+ return pick , duration_per_branch , duration , branch_count
0 commit comments