# Cour 6 -- Introduction a l'Intelligence Artificielle et à la Theorie des Jeux ###### tags `cour` `M1 S1` `IA` [Somaire](/8Sa-Z4QBS1ep0xPwtzigJA)\ [Precedent](/Lj3NskXUTea7kl21sp3EmQ) > [time= 16 oct 2020] et [time= 23 oct 2020] [TOC] ## Environnement non déterministe / adversarial - Une action n'a pas un effet unique - Dû à l'environnement qui peut agir de manère imprévisible - on peut voir ca comme un jeu entre l'agent et l'environnement - l'agent choisit une action, l'environnement choisit l'état successeur - l'agent veux atteindre le but quelque soit le comportement de l'environnement La solution n'est donc pas une séquence d'action.\ C'est un "plan", une "stratégie" ![](https://i.imgur.com/On8nmWV.png) - () : agent joue - noir: etat but (on a gagné) - blanc: etat ou on continue (on a pas gagné) - \[] : environnement joue ![](https://i.imgur.com/o94nWxm.png) ## recherche or and ![](https://i.imgur.com/RawM1xQ.png) - Similaire au parcours en profondeur, version récursive - On distingue les sommets AND (adversaire) et les sommets OR (l’agent) - On doit marquer les états traités, mais pour des raisons d’efficacité, on ne prend en compte que les états sur le chemin de l’état initial à l’état courant - Si on retombe sur un état déjà vu au dessus, on considère que c’est une feuille 0 (car si une possibilité de succès existe, on le trouvera sur une branche alternative à partir de l’occurrence précédente) - Le plan est construit récursivement à partir des plans pour les descendants ```python= def and_or_graph_search(problem): """ return: a conditional plan or failure """ return or_search(problem.initial_state, problem, []) def or_search(state, problem, path): """ state: etat a explorer problem: graph du probleme path: list des etat empreinté pour arrivé a cette état return: a conditional plan or failure """ if problem.goal_test(state): return EMPTY_PLAN elif state in path: return FAILURE for action in problem.actions(state): plan = and_search(results(state, action), problem, [state] + path ) if plan != FAILURE: return {action: plan} return FAILURE def and_search(states, problem, path): """ state: etat a explorer problem: graph du probleme path: list des etat empreinté pour arrivé a cette état return: a conditional plan or failure """ plan = {} for s in states: p = or_search(s, problem, path) if p != failure: return FAILURE plan[s] = p return plan ``` Ces probleme sont des **jeux a somme 0 et information parfaite** - 2 joueur - MIN - MAX - ce qu'un joueur gagne l'autre perd: - on a $u_{max} + u_{min} = 0$ si *o* le résultat de jeu et $u_{MAX}$ et $u_{MIN}$ les fonctions de paiement (les fonction d'utilité) de deux joueur alors: $$ u_{MIN}(o) + u_{MAX}(o) = 0 $$ pour chaque o. ![](https://i.imgur.com/4GBRWQr.png) ### Description d'un jeu - **s~0~** l'état initial - **PLAYER(s)** le joueur - **ACTIONS(s)** l'ensemble d'actions disponibles dans l'état *s* - **RESULTAT(s,a)** transition, l'état obtenu si on exécute l'action dans *s* - **TERMINAL(s)** test booléen pour déterminer si s est un état final - **UTILITE(s)** la fonction d'utilité définie pour chaque état final *s*. On suppose que *UTILITE* est la fonction d'utilité pour le joueur *MAX*, changeant le signe on obtient l'utilité pour le joueur *MIN*. ### Dificulté de jeux Grand nombre d'états : jeu d'échec : * facteur de branchement (en moyenne) *35* * nombre de coup par joueur *50* * l'arbre de jeu *35^100^* de noeuds ## MinMax ![](https://i.imgur.com/HJqwQUh.png) ```python= def MinMaxDecision(s: Etat): """ return: action a effectué """ if Player(s) == MAX: return max(MinMax(Resultat(s,a) for a in Actions(s)) else return min(MinMax(Resultat(s,a) for a in Actions(s)) def MinMax(s: Etat): """ return: valeur """ if Terminal(s): return Utilite(s) elif Player(s) == MAX: v = -INFINITY for a in Actions(s): v = max(v, MinMax(Resultat(s,a))) else: v = +INFINITY for a in Actions(s): v = min(v, MinMax(Resultat(s,a))) return v ``` ### Propriété - complet - oui (si arbre fini) - optimal - oui (si arbre fini et adversaire optimal) - compléxité en temps - $O(b^{m})$ - compléxité en espace - $O(b \times m)$ ## Elagage alpha beta ![](https://i.imgur.com/qjgSn5L.png) - Elagage n'affecte pas le résultat - L'**ordre de visite de enfants est important** et influence la complexité (qui dépend de la taille de parties élaguées). - Avec l'ordre de visite optimal la complexité en temps passe de $O(b^m)$ à O(b^{m / 2}), donc on peut doubler la hauteur de l'arbre visité. ### Le rôle de paramètres alpha-beta - $\alpha$ Max possède une stratégie qui lui garantie au moins $\alpha$ - $\beta$ Min possède une stratégie qui lui garantie de ne perdre au plus $\beta$ ![](https://i.imgur.com/dMGHuOo.png) ### Joueur Min ![](https://i.imgur.com/26A2NvM.png) ### Algorithme ```python= def alpha_beta_search(state): """ return action """ v = max_value(state, -INFINITY, +INFINITY) return action.with(v) def max_value(state, alpha, beta): """ return: utility value """ if terminal_test(state): return utility(state) v = -INFINITY for a in actions(state): v = max(v, min_value(result(s, a), alfa, beta)) if v >= beta: return v alpha = max(alpha, v) return v def min_value(state, alpha, beta): """ return: utility value """ if terminal_test(state): return utility(state) v = +INFINITY for a in actions(state): v = min(v, max_value(result(s, a), alfa, beta)) if v <= alpha: return v alpha = min(beta, v) return v ``` ![](https://i.imgur.com/kD4yH2q.png) ### fonction d'évaluation Si la profondeur de l'arbre trop grande on coupe à un niveau d et on applique une heuristique pour évaluer les positions à ce niveau (une estimation de valeur de sommets). La plupart de fonctions d'évaluation utilisent un certain nombre de propriétés (features) et ensuite on applique une somme pondérée pour évaluer la position: $$ Eval(s) = w_1 f_1(s) + \cdots + w_n f_n(s) $$ par exemple: - w1=9 - f1(s)=le nombre de reines blanches-le nombre de reines noires [suivant](/SsELiBJQSIuFPBUHO90pYw)