Aquesta pàgina es genera automàticament a partir de la presentació MARP
5-jocs_marp.md. No l’edites directament.
Búsqueda amb adversaris
Jocs
Models d’intel·ligència artificial

Jocs
- Fins ara en els nostres problemes de cerca, l’entorn era determinista i totalment observable.
- Solament calia planificar una seqüència d’accions per arribar a l’estat objectiu.
- En els jocs hi ha adversaris: Cada jugador té un objectiu diferent.
- Els jugadors modifiquen l’estat de l’entorn en benefici propi.
- La cooperació pot ocórrer, però solament si és beneficiosa per a tots els jugadors.
- Els jocs són un domini molt important en la intel·ligència artificial.
- Són un domini molt comú, complexe i útil per a la investigació.
Propietats
Tindrem en compte les següents propietats:
- Dos jugadors: Un pot ser la màquina i l’altre un humà.
- Finit: nombre finit d’estats. Si el nombre d’estats és molt gran es poden utilitzar aproximacions.
- Suma zero: el guany d’un jugador és la pèrdua de l’altre.
- Determinista: no hi ha aleatorietat.
- Informació perfecta: els jugadors coneixen l’estat del joc en tot moment. (Escacs, Go, etc.)
Dos jugadors i suma zero
- Dos jugadors: $MAX$ i $MIN$.
- Un conjunt de posicions $P$ (estats)
- Una posició inicial $p_0 \in P$
- Un conjunt de posicions terminals $T \subseteq P$
- Un conjunt d’eixos dirigits $E_{Max}$ i $E_{Min}$ entre les posicions.
- Representaran els moviments possibles de cada jugador.
- Una funció d’utilitat $u: T \rightarrow \mathbb{R}$ que
- el valor de cada posició terminal per a $MAX$.

Arbre de joc (I)
Característiques:
- Arbre de joc: capes d’estats alternant entre els jugadors.
- Arrel: Estat inicial.
- Estat del joc: posició i jugador a moure.
- Final del joc: Quan un jugador arriba a una posició terminal.
- Funció d’utilitat: Junt als terminals substitueix els objectius
- Cada node terminal $t$ s’etiqueta segons la seva utilitat $U(t)$.
- Per a $MAX$ serà $U(t)$, per a $MIN$ $-U(t)$.
- En la majoria de jocs que veurem, $U(t) \in {-1, 0, 1}$.
Arbre de joc (II) - Exemple

Estratègies
- $MAX$ vol maximitzar la seva utilitat.
- $MIN$ vol minimitzar la utilitat de $MAX$.
- $MAX$ no decideix sol a quin estat terminal arribarà.
- Quan $MAX$ mou, $MIN$ decideix a quin estat subseqüent es mourà.
- $MAX$ ha de tindre una estratègia:
- Ha de decidir que fer per a cada possible moviment de $MIN$.
- No hi ha prou en una seqüència d’accions predefinida, dependrà de les accions de $MIN$.
MiniMax

MiniMax
- Estratègia recursiva.
- Assumint que $MIN$ juga sempre el seu millor moviment,
- quin moviment s’ha de fer per minimitzar la utilitat de $MIN$?.
- Cada node tindrà una puntuació minimax.
- Serà la utilitat mínima que $\mathbf{MAX}$ pot obtenir si $\mathbf{MIN}$ juga òptimament.
Minimitzant el guany de $\mathbf{MIN}$ estem maximitzant el nostre guany.
Exemple
- En l’exemple de la dreta els nodes $\triangle$ són $MAX$ i els $\triangledown$ $MIN$.
- Els nodes terminals mostren la utilitat per a $MAX$.
- La resta de nodes mostren la seva puntuació minimax
- En l’arrel la millor opció per a $MAX$ és $a_1$, ja que porta al node en millor puntuació minimax
- En el segon nivell la millor opció per a $MIN$ és $b_1$ per dur al node en menos puntuació

Algorisme
- Entrada: Un arbre de joc $A$, un node $n$, un jugador $j$.
- Sortida: La puntuació minimax del node $n$.
- Algorisme: Algorisme recursiu.
- Si $n$ és un node terminal, retornar la seva utilitat.
- Si $j$ és $MAX$: Retornar el màxim de les puntuacions dels fills.
- Si $j$ és $MIN$: Retornar el mínim de les puntuacions dels fills.
Implementació (I)
def cerca_minimax(joc, estat):
jugador = estat.a_moure
return valor_maxim(joc, jugador, estat)
def valor_maxim(joc, jugador, estat):
if joc.es_terminal(estat):
return joc.utilitat(estat, jugador), None
v, moviment = float('-inf'), None
for a in joc.accions(estat):
v2, _ = valor_minim(joc, jugador, joc.resultat(estat, a))
if v2 > v:
v, moviment = v2, a
return v, moviment
Implementació (II)
def valor_minim(joc, jugador, estat):
if joc.es_terminal(estat):
return joc.utilitat(estat, jugador), None
v, moviment = float('inf'), None
for a in joc.accions(estat):
v2, _ = valor_maxim(joc, jugador, joc.resultat(estat, a))
if v2 < v:
v, moviment = v2, a
return v, moviment
Problemes
- Complexitat: $O(b^m)$
- sent $b$ el nombre de branques per node i $m$ la profunditat de l’arbre.
- La complexitat pot ser massiva.
- En el joc d’escacs, $b \approx 35$ i $m \approx 100$. $Nodes \approx 10^{54}$
- En el joc del Go, $b \approx 250$ i $m \approx 150$. $Nodes \approx 10^{360}$
- Això fa que sigui impossible explorar tot l’arbre de joc en jocs complexos.
- Veurem técniques que poden ajudar-nos.
Poda alfa-beta

Introducció
- Poda alfa-beta: técnica per reduir el nombre de nodes a explorar en l’arbre de joc.
- Poda: eliminar nodes de l’arbre de joc sense explorar-los.
- Alfa: valor mínim que $MAX$ està assegurat de poder obtenir.
- Beta: valor màxim que $MIN$ està assegurat de poder obtenir.
- Nodes a podar: Nodes que, indepentment del seu valor, no modificarán el nivell superior.
Exemple (I)
- La primera fulla baix $B$ té valor $3$. Per tant $B$ (node $MIN$) té un valor màxim de $3$.
- La segona fulla baix $B$ té valor $12$.
- $MIN$ evitaria aquest moviment, per lo que $B$ encara té un valor màxim de $3$.
- La tercera fulla baix $B$ té valor $8$. El valor de final de $B$ és $3$.
- Podem deduir llavors que el valor mínim d’$A$ és $3$, al tindre un node terminal amb valor $3$.
Exemple (II)
- La primera fulla baix $C$ té valor $2$. Per tant $C$, que es un node $MIN$, té un valor màxim de $2$.
- Sabem que $B$ té un valor de $3$, per lo que $MAX$ mai escollirà $C$
- Així sabem que no cal explorar els altres nodes fills de $C$,
- Aquesta és la poda alfa-beta.
- Sabem que $B$ té un valor de $3$, per lo que $MAX$ mai escollirà $C$
- Al acabar l’exploració sabem els valors de cada node necessari.
Regles
- La poda alfa-beta no afecta al resultat de l’algorisme.
- Es pot aplicar a qualsevol profunditat de l’arbre.
- Moltes vegades es poden, fins i tot, podar arbres sencers.
- Principi general, per un node $n$:
- Si hi ha una opció millor al mateix nivell $($m’$)$ o superior $($m$)$, $n$ no es visitarà.

Implementació (I)
def busqueda_alfa_beta(joc, estat):
jugador = estat.a_moure
return valor_maxim_ab(joc, jugador, estat, float('-inf'), float('inf'))
def valor_maxim_ab(joc, jugador, estat, alfa, beta):
if joc.es_terminal(estat):
return joc.utilitat(estat, jugador), None
v, moviment = float('-inf'), None
for a in joc.accions(estat):
v2, _ = valor_minim_ab(joc, jugador, joc.resultat(estat, a), alfa, beta)
if v2 > v:
v, moviment = v2, a
if v >= beta:
return v, moviment
alfa = max(alfa, v)
return v, moviment
Implementació (II)
def valor_minim_ab(joc, jugador, estat, alfa, beta):
if joc.es_terminal(estat):
return joc.utilitat(estat, jugador), None
v, moviment = float('inf'), None
for a in joc.accions(estat):
v2, _ = valor_maxim_ab(
joc, jugador, joc.resultat(estat, a), alfa, beta
)
if v2 < v:
v, moviment = v2, a
if v <= alfa:
return v, moviment
beta = min(beta, v)
return v, moviment
Millores
- Ordenació de nodes: Ordenar els nodes fills corréctament permet podar més.
- Una bona ordenació pot permetre passar d’examinar de $O(b^{3d/4})$ a $O(b^{d/2})$
- En un joc d’escacs, els moviments que mengen peces són més probables de ser bons.
- Una bona ordenació pot permetre passar d’examinar de $O(b^{3d/4})$ a $O(b^{d/2})$
- Per no explorar estates repetits, es pot utilitzar una taula de transposició semblant al conjunt de visitats, però amb els valors de cada node.
- Aplicar heurístiques per tallar l’avaluació: aplicar una funció d’avaluació a les posicions no terminals per fer-les terminals
Funcions d’avaluació
Introducció
- En jocs complexos, no es pot explorar tot l’arbre de joc.
- En lloc d’això, es pot utilitzar una funció d’avaluació per estimar la utilitat d’un estat.
- La funció d’avaluació no ha de ser perfecta.
- Ha de ser rápida de calcular.
- Ha de ser consistent amb la utilitat real.
Funcions d’avaluació
Exemple: Tic-Tac-Toe
- En el joc del tres en ratlla, podem utilitzar la següent funció d’avaluació:
- $u(s) = \sum_{i=1}^3 \sum_{j=1}^3 \begin{cases}
1 & \text{si } s_{i,j} = \text{MAX}
-1 & \text{si } s_{i,j} = \text{MIN}
0 & \text{altrament} \end{cases}$ - Explicació: Sumem 1 per cada fitxa de $MAX$ i restem 1 per cada fitxa de $MIN$.
- $u(s) = \sum_{i=1}^3 \sum_{j=1}^3 \begin{cases}
1 & \text{si } s_{i,j} = \text{MAX}
Funcions d’avaluació
Implementació
def avalua_tres_en_ratlla(joc, estat):
jugador = estat.a_moure
utilitat = 0
for i in range(3):
for j in range(3):
if estat.tauler[i][j] == jugador:
utilitat += 1
elif estat.tauler[i][j] == joc.jugador_contrari(jugador):
utilitat -= 1
return utilitat