A hash is a number that replaces a phase. There is a hash in node_hash. It is used for the purpose of linking the situation and node information and processing various things.
A total of UCT_HASH_SIZE integers starting from 0. 4096 in the book. Convert the hash value to an index with hash_to_index () and use the hash value in association with the index. The reason why the hash value is not used as it is as an index and is once set to 4096 width is because the hash size is 64 bits, which is uselessly large.
node_hash node_hash is an array. Each element is an instance of the NodeHashEntry class, and each element has hash, turn, effort, and flag information. When creating, first create an instance of NodeHash class with self.xxx = NodeHash (). The node_hash array exists as a member in this instance called xxx.
In the book, xxx is named node_hash, which is the same name as the array inside. Be careful as it seems to be confusing.
If you extract only the outline, it will be like this.
UCT_HASH_SIZE = 4 #Must be 2 to the nth power. 4096 in the book. It was set to 4 for explanation.
class NodeHashEntry:
def __init__(self):
self.hash = 1 #Zobrist hash value. It's really 0. It was set to 1 for explanation.
self.color = 2 #Your turn. It's really 0. It was set to 2 for explanation.
# self.moves = 0 #Omitted for simplification of explanation.
# self.flag = False #Omitted for simplification of explanation.
class NodeHash:
def __init__(self):
self.node_hash = [NodeHashEntry() for _ in range(UCT_HASH_SIZE)]
I will try various things to understand the structure. First, create an instance a of class NodeHash and print it.
a = NodeHash()
print(a)
Reply
<__main__.NodeHash object at 0x0000015BDBB54948>
This class has an array of variable names called node_hash, and in this case UCT_HASH_SIZE = 4, so the number of elements in this array is four. node_hash = [NodeHashEntry object, NodeHashEntry object, NodeHashEntry object, NodeHashEntry object].
print a node_hash array of a
print(a.node_hash)
Reply
[<__main__.NodeHashEntry object at 0x0000015BE2B7FD88>,
<__main__.NodeHashEntry object at 0x0000015BE4E13E48>,
<__main__.NodeHashEntry object at 0x0000015BE67F0108>,
<__main__.NodeHashEntry object at 0x0000015BE65B5F08>]
These four objects have variables called hash and color, respectively.
Print hash and color of 4 objects
for i in range(4):
print(a.node_hash[i].hash, a.node_hash[i].color)
Reply
1 2
1 2
1 2
1 2
uct_node uct_node is an array. Each element is an instance of the UctNode class, and each element has the number of visits to the node, the total win rate, the number of child nodes, the move of the child node, the index of the child node, the number of visits to the child node, and the win rate of the child node. It has information on totals, predicted win rates for policy networks, predicted win rates for value networks, and evaluated flags. When generating, self.uct_node = [UctNode () for _ in range (UCT_HASH_SIZE)].
search_empty_index() A method that looks for unused indexes. The arguments are hash, turn, and effort.
What we're doing is creating an index from the hash and checking if the element at that index in the node_hash array is unused. If it is unused, the hash, turn, and effort of the argument are assigned to the element, and a flag indicating that the element is used is set. If it has been used, add 1 to the index and do the same until it goes around all the indexes. If there is no unused index after one lap, UCT_HASH_SIZE is returned.
For example, if UCT_HASH_SIZE = 4096 and there is an unused index, hash, turn, and number of moves are assigned to the first hit element in 4096 of node_hash [0] to node_hash [4095], and a flag is set to finish. If there is no unused index, the value of 4096 is returned and the process ends.
find_same_hash_index() A method to find the index corresponding to the situation. The arguments are hash, turn, and effort.
What we're doing is creating an index from the hash and checking if the element at that index in the node_hash array is unused. Returns UCT_HASH_SIZE if unused. If the hash, turn, and effort of the element match the argument during use, the index is returned. Do the same until you go around all the indexes while adding 1 to the index. If there is no index that matches the argument after one round, UCT_HASH_SIZE is returned.
For example, if UCT_HASH_SIZE = 4096 and there is an element that matches the hash, turn, and effort of the argument, the index of that element (which will be one of 4096 from 0 to 4095) is returned and the process ends. If there is no matching element, the value of 4096 is returned and the process ends.
Both search_empty_index () and find_same_hash_index () are in the same instance as the node_hash array. Therefore, when using it, use self.instance name.search_empty_index (). Note that the instance name is node_hash in the book, and it seems to be confusing with the same name as node_hash in the member array.
Recommended Posts