Minimax, also called the minimax algorithm, is an algorithm that minimizes potential loss in the worst-case (that is, maximum-loss) situation. This page briefly introduces the Minimax algorithm and Alpha–Beta pruning.
Minimax Algorithm
Minimax, also called the minimax algorithm, is an algorithm that minimizes potential loss in the worst-case (that is, maximum-loss) situation.
Process
In a two-player zero-sum game with a determined state, adversarial search is often needed to construct a search tree in which every node is a definite state. Odd levels correspond to the first player, and even levels correspond to the opponent. Each leaf node in the search tree is assigned a score; a larger score means a greater chance of our side winning. Our side seeks a larger chance of winning, while the opponent tries to reduce our side's chance of winning. On the search tree, this means that nodes at odd levels (our nodes) always choose the child state with the greatest chance of winning, while nodes at even levels (the opponent's nodes) always choose the child state with the smallest chance of winning for our side.
The Minimax algorithm traverses the search tree from top to bottom and updates the answer with subtree information while backtracking, finally obtaining its value of the root node—the maximum score our side can obtain when both sides adopt optimal strategies.
Example
Consider a simple example.
Call our side MAX and the opponent MIN, as shown below:
For the following position, suppose the search proceeds from left to right, and its value of the root node represents our chance of winning:
We should choose the middle route. If the left route is chosen, its worst-case chance of winning is ; if the middle route is chosen, its worst-case chance is ; if the right route is chosen, its worst-case chance is . Although the right route may have a chance of winning of , a sufficiently rational opponent will leave our side with only a chance of . Thus, after weighing the options, the middle route is clearly better.
In fact, when examining the right route, once a possible chance of winning of is found, there is no need to examine the branches with chances of winning of , , and . Compared with the chances of winning on the two routes to the left, it is already certain that the right route is not the best.
The naive Minimax algorithm often needs to construct a huge search tree, making both its time and space complexity unacceptable. Alpha–Beta pruning is a method that uses the upper and lower bounds of the scores of both sides at each node in the search tree to prune and optimize Minimax.
Note that the meaning of its value at each node of the search tree differs between problems: it may be a heuristic value, a score, a probability of winning, and so on. For convenience, the following text uniformly calls it a score.
Alpha–Beta Pruning
Alpha–Beta pruning is search pruning for the Minimax algorithm.
Process
In the Minimax algorithm, if the scores of all children of a node are known, the score of that node can be calculated: a MAX node takes the maximum score, while a MIN node takes the minimum score.
When the search has reached a node but is not yet complete, its score cannot be calculated, but the range of scores that both sides can obtain among the nodes searched so far can be calculated. During the search, maintain two variables, and , representing, among all nodes already searched when the game reaches this node, the lower and upper bounds of the scores that the Alpha player (the side seeking the maximum score) and Beta player (the side seeking the minimum score) can guarantee, respectively.
The pruning strategy of Alpha–Beta pruning depends on the values of and when searching the current node. If the current node is a MAX node, Alpha can continue searching its children to raise the lower bound . However, if some search results in , this node cannot occur in an actual game: once a node is reached, the Alpha player can guarantee a score of at least ; but the Beta player already knows a strategy (deviating from the current path) that guarantees a score no greater than , so Beta naturally will not allow the game to develop to the current node. Similarly, if the current node is a MIN node and, after searching one of its children, holds at that node, there is no need to continue searching its other children, because the Alpha player will not allow the game to enter the current node. In summary, when , the remaining branches of a node need not be searched (that is, pruning can be performed). Note that pruning is also required when , because no better result is possible, although a worse result may be possible.
During the search, it is unnecessary to maintain node scores; maintaining only and is sufficient. Initially, set . When searching downward, pass the information of and along with the search to record the alternatives of the two players.
When a child has been searched, the information at the current node must be updated. Suppose the current node is a MAX node and its child has just been searched. The value at node does not change; only needs to be updated with the maximum of its current value and the score of child . If child is a leaf node, directly use child 's score to update at ; otherwise, only the value of needs to be used to update at . There are three possibilities:
- The value of child lies strictly between the and values of node . Since inherited the value of and does not update it, having after the search of is complete means that no pruning occurred while searching . The final value of equals the smaller of the value inherited from and the scores of all children of . Since this minimum is strictly less than the value of , it must be the minimum score among all children of . Therefore, as a MIN node, the score of is this value. It is valid to use it to update the value of .
- The value of child equals the value of node . As described above, this means that all children of have scores no less than the value of . This further means that the Beta player will not allow the game to enter node : if the Alpha player chooses child , Beta cannot obtain a score lower than . Thus, using the value of to update the value of makes at , triggering the pruning condition. Its effect is the same as using the actual score at —a number greater than or equal to the value at —to update the value of .
- The value of child is less than or equal to the value of . In this case, triggered the pruning condition, so child 's actual score is no greater than its value and certainly no greater than the value of . Using the actual score of to update at would not change . This has the same effect as using the value of to update at .
This analysis shows that after a child has been searched, (or ) accurately records the actual score of that child as a MAX node (or MIN node) only in the first case. In the other cases, although it may not be the exact score, it provides enough information to ensure that pruning is performed correctly and therefore does not affect the score recorded at the root.
Example
This section analyzes an example to show how the and values at each node are updated during the search. The scores at the involved nodes are also calculated along the way. Thus, the relationship between the actual score at each node and its recorded and values can be observed. However, note that an implementation of this algorithm does not calculate the actual scores of these nodes.
For the following position, suppose the search proceeds from left to right:
Initially, set , and pass this information down along the search path.
When node A is reached, because the score of its left child is and A is a MIN node seeking a small score, its value is changed to , since is less than the current value (). The score of A's right child is then , but A's value is not changed because is greater than the current value (). At this point all children of A have been searched, so A's score can be calculated as , consistent with the value recorded at a node (case 1 above).
Node A is a child of node B. After calculating A's score, B's and values can be updated. Since B is a MAX node seeking a large score, its value is changed to , because the value at A () is greater than the current value (). Next, search B's right child C and pass B's and values to C.
For node C, the score of its left child is and C is a MIN node, so its value is changed to . Now , so C's remaining children need not be searched, because it can be determined that the Alpha player will not allow the game to develop to C. C is a MIN node, so its score is , no greater than the recorded value (case 3 above). Since all children of B have been searched, B's score can be calculated as , equal to its recorded value (case 1 above).
After B's score is calculated, B is a child of D, so D's and values can be updated. Since D is a MIN node, its value is changed to . D then passes and to E, which passes them on to F. F has only one child with score . Since is greater than the current value and F is a MIN node, its value is not updated. F's score can then be calculated as , greater than the recorded value (case 2 above).
After F's score is calculated, F is a child of E, so E's and values can be updated. E is a MAX node, so its value is updated; now , so E's remaining branches (that is, node G) can be pruned. E is a MAX node, so set its score to , strictly greater than its recorded value (case 3 above). Use E's value to update D's value, which remains . At this point all children of D have been searched, so D's score can be calculated as , equal to its recorded value (case 1 above).
After D's score is calculated, D is a child of H, so H's and values can be updated. H is a MAX node, so update . Then, in search order, pass H's and values to I, J, and K in turn. For K, the score of its left child is , and K is a MIN node, so update . Now , and K's remaining branches can be pruned. Then set K's score to , less than or equal to its recorded value (case 3 above).
After K's score is calculated, K is a child of J, so J's and values can be updated. J is a MAX node, so update . However, because K's score is less than , J's value remains . Then pass J's and values to L. Since L is a MIN node, update . Now , so L's remaining branches can be pruned. Since L has no remaining branches, no actual pruning occurs here. Then set L's score to , less than or equal to its recorded value (case 3 above).
After L's score is calculated, L is a child of J, so J's and values can be updated. J is a MAX node, so update . However, because L's score is less than or equal to , J's value remains . At this point all children of J have been searched, so J's score can be calculated as , equal to its recorded value (case 2 above).
After J's score is calculated, J is a child of I, so I's and values can be updated. I is a MIN node, so update . Now , and I's remaining branches can be pruned. It is worth noting that because the right child exists, I's actual score is , less than the recorded value (case 3 above).
After I's score is calculated, I is a child of H, so H's and values can be updated. H is a MAX node, so update . However, because I's score is less than or equal to , H's value remains . At this point all children of H have been searched, so H's score can be calculated as , equal to its recorded value (case 1 above).
This is the final result.
Implementation
Reference Code
int alpha_beta(int u, int alph, int beta, bool is_max) {
if (!son_num[u]) return val[u];
if (is_max) {
for (int i = 0; i < son_num[u]; ++i) {
int d = son[u][i];
alph = max(alph, alpha_beta(d, alph, beta, !is_max));
if (alph >= beta) break;
}
return alph;
} else {
for (int i = 0; i < son_num[u]; ++i) {
int d = son[u][i];
beta = min(beta, alpha_beta(d, alph, beta, !is_max));
if (alph >= beta) break;
}
return beta;
}
}
References and notes
This article partially quotes the blog post An In-Depth Explanation of the Minimax Algorithm and Alpha–Beta Pruning _Wenjianmuran, under the CC 4.0 BY-SA license. The content has been modified.