Algoritmo Minimax en Teoría de Juegos | Juego 4 (Poda Alfa-Beta)

Prerrequisitos: algoritmo Minimax en teoría de juegos , función de evaluación en teoría de juegos
La poda alfa-beta no es en realidad un algoritmo nuevo, sino una técnica de optimización para el algoritmo minimax. Reduce el tiempo de cálculo en un factor enorme. Esto nos permite buscar mucho más rápido e incluso adentrarnos en niveles más profundos en el árbol del juego. Corta ramas en el árbol del juego que no necesitan ser buscadas porque ya existe un mejor movimiento disponible. Se llama poda alfa-beta porque pasa 2 parámetros adicionales en la función minimax, a saber, alfa y beta.
Definamos los parámetros alfa y beta. 
Alfa es el mejor valor que el maximizador actualmente puede garantizar en ese nivel o superior. 
Betaes el mejor valor que el minimizador puede garantizar actualmente en ese nivel o superior.
 

Pseudocódigo:

function minimax(node, depth, isMaximizingPlayer, alpha, beta):

    if node is a leaf node :
        return value of the node
    
    if isMaximizingPlayer :
        bestVal = -INFINITY 
        for each child node :
            value = minimax(node, depth+1, false, alpha, beta)
            bestVal = max( bestVal, value) 
            alpha = max( alpha, bestVal)
            if beta <= alpha:
                break
        return bestVal

    else :
        bestVal = +INFINITY 
        for each child node :
            value = minimax(node, depth+1, true, alpha, beta)
            bestVal = min( bestVal, value) 
            beta = min( beta, bestVal)
            if beta <= alpha:
                break
        return bestVal
// Calling the function for the first time.
minimax(0, 0, true, -INFINITY, +INFINITY)

Aclaremos el algoritmo anterior con un ejemplo. 
 

Alpha Beta Pruning

  • La llamada inicial comienza desde A . El valor de alfa aquí es -INFINITY y el valor de beta es +INFINITY . Estos valores se transmiten a los Nodes posteriores del árbol. En A , el maximizador debe elegir el máximo de B y C , por lo que A llama a B primero
  • En B , el minimizador debe elegir min de D y E y, por lo tanto, llama a D primero.
  • En D , mira a su hijo izquierdo, que es un Node de hoja. Este Node devuelve un valor de 3. Ahora el valor de alfa en D es max(-INF, 3) que es 3.
  • Para decidir si vale la pena mirar su Node derecho o no, comprueba la condición beta<=alfa. Esto es falso ya que beta = +INF y alpha = 3. Entonces continúa la búsqueda.
  • D ahora mira a su hijo derecho que devuelve un valor de 5. En D , alpha = max(3, 5) que es 5. Ahora el valor del Node D es 5
  • D devuelve un valor de 5 a B . En B , beta = min( +INF, 5) que es 5. El minimizador ahora tiene garantizado un valor de 5 o menos. B ahora llama a E para ver si puede obtener un valor inferior a 5.
  • En E , los valores de alfa y beta no son -INF y +INF, sino -INF y 5 respectivamente, porque el valor de beta se cambió en B y eso es lo que B pasó a E
  • Ahora E mira a su hijo izquierdo que es 6. En E , alpha = max(-INF, 6) que es 6. Aquí la condición se vuelve verdadera. beta es 5 y alfa es 6. Así que beta<=alfa es verdadero. Por lo tanto se rompe y E devuelve 6 a B
  • Nótese cómo no importa cuál sea el valor del hijo derecho de E. Podría haber sido +INF o -INF, igual no importaría. Ni siquiera tuvimos que mirarlo porque el minimizador tenía garantizado un valor de 5 o menos. Entonces, tan pronto como el maximizador vio el 6, supo que el minimizador nunca llegaría de esta manera porque puede obtener un 5 en el lado izquierdo de B . De esta manera, no tenemos que mirar ese 9 y, por lo tanto, ahorramos tiempo de cálculo.
  • E devuelve un valor de 6 a B . En B , beta = min(5, 6) que es 5. El valor del Node B también es 5

Hasta ahora, así es como se ve nuestro árbol de juegos. El 9 está tachado porque nunca se calculó. 
 

Alpha Beta Pruning 2

  • B devuelve 5 a A. En A , alpha = max( -INF, 5) que es 5. Ahora el maximizador tiene garantizado un valor de 5 o mayor. A ahora llama a C para ver si puede obtener un valor superior a 5.
  • En C , alfa = 5 y beta = +INF. C llama a F
  • En F , alfa = 5 y beta = +INF. F mira a su hijo izquierdo, que es un 1. alfa = max (5, 1), que sigue siendo 5.
  • F mira a su hijo derecho, que es un 2. Por lo tanto, el mejor valor de este Node es 2. Alfa sigue siendo 5
  • F devuelve un valor de 2 a C . En C , beta = min( +INF, 2). La condición beta <= alfa se vuelve verdadera cuando beta = 2 y alfa = 5. Entonces se rompe y ni siquiera tiene que calcular todo el subárbol de G .
  • La intuición detrás de esta ruptura es que, en C , al minimizador se le garantizó un valor de 2 o menos. Pero el maximizador ya tenía garantizado un valor de 5 si elegía B . Entonces, ¿por qué el maximizador elegiría C y obtendría un valor menor que 2? Una vez más, puede ver que no importaba cuáles fueran esos últimos 2 valores. También ahorramos muchos cálculos al omitir un subárbol completo.
  • C ahora devuelve un valor de 2 a A . Por lo tanto, el mejor valor en A es max( 5, 2) que es 5.
  • Por lo tanto, el valor óptimo que puede obtener el maximizador es 5

Así es como se ve nuestro árbol de juego final. Como puede ver, G se ha tachado porque nunca se calculó. 
 

Alpha Beta Pruning 3

CPP

// C++ program to demonstrate
// working of Alpha-Beta Pruning
#include<bits/stdc++.h>
using namespace std;
 
// Initial values of
// Alpha and Beta
const int MAX = 1000;
const int MIN = -1000;
 
// Returns optimal value for
// current player(Initially called
// for root and maximizer)
int minimax(int depth, int nodeIndex,
            bool maximizingPlayer,
            int values[], int alpha,
            int beta)
{
     
    // Terminating condition. i.e
    // leaf node is reached
    if (depth == 3)
        return values[nodeIndex];
 
    if (maximizingPlayer)
    {
        int best = MIN;
 
        // Recur for left and
        // right children
        for (int i = 0; i < 2; i++)
        {
             
            int val = minimax(depth + 1, nodeIndex * 2 + i,
                              false, values, alpha, beta);
            best = max(best, val);
            alpha = max(alpha, best);
 
            // Alpha Beta Pruning
            if (beta <= alpha)
                break;
        }
        return best;
    }
    else
    {
        int best = MAX;
 
        // Recur for left and
        // right children
        for (int i = 0; i < 2; i++)
        {
            int val = minimax(depth + 1, nodeIndex * 2 + i,
                              true, values, alpha, beta);
            best = min(best, val);
            beta = min(beta, best);
 
            // Alpha Beta Pruning
            if (beta <= alpha)
                break;
        }
        return best;
    }
}
 
// Driver Code
int main()
{
    int values[8] = { 3, 5, 6, 9, 1, 2, 0, -1 };
    cout <<"The optimal value is : "<< minimax(0, 0, true, values, MIN, MAX);;
    return 0;
}

Java

// Java program to demonstrate
// working of Alpha-Beta Pruning
import java.io.*;
 
class GFG {
 
// Initial values of
// Alpha and Beta
static int MAX = 1000;
static int MIN = -1000;
 
// Returns optimal value for
// current player (Initially called
// for root and maximizer)
static int minimax(int depth, int nodeIndex,
                   Boolean maximizingPlayer,
                   int values[], int alpha,
                   int beta)
{
    // Terminating condition. i.e
    // leaf node is reached
    if (depth == 3)
        return values[nodeIndex];
 
    if (maximizingPlayer)
    {
        int best = MIN;
 
        // Recur for left and
        // right children
        for (int i = 0; i < 2; i++)
        {
            int val = minimax(depth + 1, nodeIndex * 2 + i,
                              false, values, alpha, beta);
            best = Math.max(best, val);
            alpha = Math.max(alpha, best);
 
            // Alpha Beta Pruning
            if (beta <= alpha)
                break;
        }
        return best;
    }
    else
    {
        int best = MAX;
 
        // Recur for left and
        // right children
        for (int i = 0; i < 2; i++)
        {
             
            int val = minimax(depth + 1, nodeIndex * 2 + i,
                              true, values, alpha, beta);
            best = Math.min(best, val);
            beta = Math.min(beta, best);
 
            // Alpha Beta Pruning
            if (beta <= alpha)
                break;
        }
        return best;
    }
}
 
    // Driver Code
    public static void main (String[] args)
    {
         
        int values[] = {3, 5, 6, 9, 1, 2, 0, -1};
        System.out.println("The optimal value is : " +
                            minimax(0, 0, true, values, MIN, MAX));
     
    }
}
 
// This code is contributed by vt_m.

Python3

# Python3 program to demonstrate
# working of Alpha-Beta Pruning
 
# Initial values of Alpha and Beta
MAX, MIN = 1000, -1000
 
# Returns optimal value for current player
#(Initially called for root and maximizer)
def minimax(depth, nodeIndex, maximizingPlayer,
            values, alpha, beta):
  
    # Terminating condition. i.e
    # leaf node is reached
    if depth == 3:
        return values[nodeIndex]
 
    if maximizingPlayer:
      
        best = MIN
 
        # Recur for left and right children
        for i in range(0, 2):
             
            val = minimax(depth + 1, nodeIndex * 2 + i,
                          False, values, alpha, beta)
            best = max(best, val)
            alpha = max(alpha, best)
 
            # Alpha Beta Pruning
            if beta <= alpha:
                break
          
        return best
      
    else:
        best = MAX
 
        # Recur for left and
        # right children
        for i in range(0, 2):
          
            val = minimax(depth + 1, nodeIndex * 2 + i,
                            True, values, alpha, beta)
            best = min(best, val)
            beta = min(beta, best)
 
            # Alpha Beta Pruning
            if beta <= alpha:
                break
          
        return best
      
# Driver Code
if __name__ == "__main__":
  
    values = [3, 5, 6, 9, 1, 2, 0, -1] 
    print("The optimal value is :", minimax(0, 0, True, values, MIN, MAX))
     
# This code is contributed by Rituraj Jain

C#

// C# program to demonstrate
// working of Alpha-Beta Pruning
using System;
     
class GFG
{
 
// Initial values of
// Alpha and Beta
static int MAX = 1000;
static int MIN = -1000;
 
// Returns optimal value for
// current player (Initially called
// for root and maximizer)
static int minimax(int depth, int nodeIndex,
                Boolean maximizingPlayer,
                int []values, int alpha,
                int beta)
{
    // Terminating condition. i.e
    // leaf node is reached
    if (depth == 3)
        return values[nodeIndex];
 
    if (maximizingPlayer)
    {
        int best = MIN;
 
        // Recur for left and
        // right children
        for (int i = 0; i < 2; i++)
        {
            int val = minimax(depth + 1, nodeIndex * 2 + i,
                            false, values, alpha, beta);
            best = Math.Max(best, val);
            alpha = Math.Max(alpha, best);
 
            // Alpha Beta Pruning
            if (beta <= alpha)
                break;
        }
        return best;
    }
    else
    {
        int best = MAX;
 
        // Recur for left and
        // right children
        for (int i = 0; i < 2; i++)
        {
             
            int val = minimax(depth + 1, nodeIndex * 2 + i,
                            true, values, alpha, beta);
            best = Math.Min(best, val);
            beta = Math.Min(beta, best);
 
            // Alpha Beta Pruning
            if (beta <= alpha)
                break;
        }
        return best;
    }
}
 
// Driver Code
public static void Main (String[] args)
{
     
    int []values = {3, 5, 6, 9, 1, 2, 0, -1};
    Console.WriteLine("The optimal value is : " +
                        minimax(0, 0, true, values, MIN, MAX));
 
}
}
 
// This code is contributed by 29AjayKumar

Javascript

<script>
// Javascript program to demonstrate
// working of Alpha-Beta Pruning
 
// Initial values of
// Alpha and Beta
let MAX = 1000;
let MIN = -1000;
 
// Returns optimal value for
// current player (Initially called
// for root and maximizer)
function minimax(depth,nodeIndex,maximizingPlayer,values,alpha,beta)
{
    // Terminating condition. i.e
    // leaf node is reached
    if (depth == 3)
        return values[nodeIndex];
   
    if (maximizingPlayer)
    {
        let best = MIN;
   
        // Recur for left and
        // right children
        for (let i = 0; i < 2; i++)
        {
            let val = minimax(depth + 1, nodeIndex * 2 + i,
                              false, values, alpha, beta);
            best = Math.max(best, val);
            alpha = Math.max(alpha, best);
   
            // Alpha Beta Pruning
            if (beta <= alpha)
                break;
        }
        return best;
    }
    else
    {
        let best = MAX;
   
        // Recur for left and
        // right children
        for (let i = 0; i < 2; i++)
        {
               
            let val = minimax(depth + 1, nodeIndex * 2 + i,
                              true, values, alpha, beta);
            best = Math.min(best, val);
            beta = Math.min(beta, best);
   
            // Alpha Beta Pruning
            if (beta <= alpha)
                break;
        }
        return best;
    }
}
 
// Driver Code
let values=[3, 5, 6, 9, 1, 2, 0, -1];
document.write("The optimal value is : " +
                            minimax(0, 0, true, values, MIN, MAX));
 
// This code is contributed by rag2127
</script>

Producción :

The optimal value is : 5

Este artículo es una contribución de Akshay L Aradhya . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.
Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *