Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@
"source": [
"### Classe Board\n",
"\n",
"La classe `Board` encapsule l'etat du jeu et fournit les opérations fondamentales : coups legaux, placement de jeton, détection de victoire et affichage."
"La classe `Board` encapsule l'état du jeu et fournit les opérations fondamentales : coups legaux, placement de jeton, détection de victoire et affichage."
]
},
{
Expand Down Expand Up @@ -338,9 +338,9 @@
"| représentation | Matrice numpy 6x7, 0/1/2 |\n",
"| Gravite | Les jetons s'empilent du bas vers le haut |\n",
"| détection victoire | 4 directions : horizontale, verticale, 2 diagonales |\n",
"| Backtracking | `undo_move` permet de defaire un coup (utile pour Minimax) |\n",
"| Backtracking | `undo_move` permet de défaire un coup (utile pour Minimax) |\n",
"\n",
"**Points cles** :\n",
"**Points clés** :\n",
"1. La méthode `legal_moves()` vérifie la ligne supérieure (indice 0) : si elle est occupee, la colonne est pleine\n",
"2. `check_win` parcourt les 4 directions avec des fenêtrès de taille 4 -- complexité O(ROWS x COLS)\n",
"3. L'utilisation de `undo_move` évite de copier le plateau a chaque noeud de l'arbre de recherche"
Expand Down Expand Up @@ -476,7 +476,7 @@
"\n",
"**Sortie obtenue** : Le plateau apparaît avec les cercles rouge (joueur 1) et jaune (joueur 2) sur fond bleu, fidélément au jeu réel.\n",
"\n",
"**Points cles** :\n",
"**Points clés** :\n",
"1. L'axe Y est inverse pour que la gravite soit naturelle (les jetons tombent vers le bas)\n",
"2. Les cases vides sont affichees en bleu clair pour simuler les trous du plateau\n",
"3. Cette visualisation sera réutilisée pour afficher les parties entre IA"
Expand Down Expand Up @@ -704,9 +704,9 @@
"\n",
"| Aspect | observation |\n",
"|--------|-------------|\n",
"| Qualite de jeu | très faible : coups absurdes fréquents |\n",
"| Qualité de jeu | très faible : coups absurdes fréquents |\n",
"| Temps par coup | Negligeable (cf. sortie cell. 13) |\n",
"| utilité | Baseline pour mesurer la qualite des autrès IA |\n",
"| utilité | Baseline pour mesurer la qualité des autrès IA |\n",
"\n",
"**Point cle** : Le joueur aléatoire ne détecte même pas les victoires immédiates. Il peut \"oublier\" de gagner ou de bloquer l'adversaire. C'est la pire IA possible -- tout algorithme raisonnable devrait le battre systématiquement."
]
Expand All @@ -733,14 +733,14 @@
"- **Max** : le joueur courant maximise son score\n",
"- **Min** : l'adversaire minimise le score du joueur courant\n",
"\n",
"L'**elagage alpha-beta** permet de couper des branches de l'arbre sans perdre en qualite de décision :\n",
"L'**elagage alpha-beta** permet de couper des branches de l'arbre sans perdre en qualité de décision :\n",
"- $\\alpha$ = meilleur score garanti pour Max sur le chemin courant\n",
"- $\\beta$ = meilleur score garanti pour Min sur le chemin courant\n",
"- Si $\\alpha \\geq \\beta$, on coupe (la branche ne sera jamais choisie)\n",
"\n",
"### Fonction d'évaluation\n",
"\n",
"Pour limiter la profondeur de recherche, il faut une **fonction d'évaluation** qui estime la qualite d'une position non terminale. Notre évaluation analyse les fenêtrès de 4 cases :\n",
"Pour limiter la profondeur de recherche, il faut une **fonction d'évaluation** qui estime la qualité d'une position non terminale. Notre évaluation analyse les fenêtrès de 4 cases :\n",
"\n",
"| Configuration dans une fenêtre de 4 | Score |\n",
"|--------------------------------------|-------|\n",
Expand Down Expand Up @@ -1012,7 +1012,7 @@
"source": [
"### Test : Minimax vs Random\n",
"\n",
"vérifions que Minimax domine clairement le joueur aléatoire. Nous utilisons une profondeur de 4 pour un bon compromis qualite/vitesse."
"vérifions que Minimax domine clairement le joueur aléatoire. Nous utilisons une profondeur de 4 pour un bon compromis qualité/vitesse."
]
},
{
Expand Down Expand Up @@ -1123,11 +1123,11 @@
"\n",
"| Aspect | Minimax (d=4) | Random |\n",
"|--------|---------------|--------|\n",
"| Qualite de jeu | Bonne (détecte menaces a 4 coups) | Nulle |\n",
"| Qualité de jeu | Bonne (détecte menaces a 4 coups) | Nulle |\n",
"| Temps par coup | fraction de seconde (cell. 20) | negligeable (cell. 20) |\n",
"| stratégie | Offensive et defensive | Aucune |\n",
"\n",
"**Points cles** :\n",
"**Points clés** :\n",
"1. Minimax gagne rapidement car il exploite les erreurs du joueur aléatoire\n",
"2. L'elagage alpha-beta réduit considérablement le nombre de noeuds explores\n",
"3. L'ordonnancement des coups (centre en premier) améliore l'efficacité de l'elagage"
Expand All @@ -1149,7 +1149,7 @@
"source": [
"### Experiment : Effet de la profondeur\n",
"\n",
"Comparons trois profondeurs de Minimax pour observer le compromis qualite/temps. Chaque profondeur joue 10 parties contre le joueur aléatoire."
"Comparons trois profondeurs de Minimax pour observer le compromis qualité/temps. Chaque profondeur joue 10 parties contre le joueur aléatoire."
]
},
{
Expand Down Expand Up @@ -1278,7 +1278,7 @@
"\n",
"**Temps de calcul** : mesure live par la cellule 23 (croissance d’environ un ordre de grandeur par niveau de profondeur ; voir la sortie « ms/coup »).\n",
"\n",
"**Points cles** :\n",
"**Points clés** :\n",
"1. même d=2 suffit contre un joueur aléatoire (10/10 victoires)\n",
"2. Le temps croit **exponentiellement** avec la profondeur : $O(b^d)$ ou $b \\approx 4$ en moyenne\n",
"3. L'elagage alpha-beta réduit la complexité de $O(b^d)$ a $O(b^{d/2})$ dans le meilleur cas\n",
Expand Down Expand Up @@ -1496,7 +1496,7 @@
"source": [
"### Test : MCTS vs Minimax\n",
"\n",
"Faisons s'affronter MCTS (1000 itérations) contre Minimax (profondeur 4) pour observer la qualite de jeu des deux approches."
"Faisons s'affronter MCTS (1000 itérations) contre Minimax (profondeur 4) pour observer la qualité de jeu des deux approches."
]
},
{
Expand Down Expand Up @@ -1730,7 +1730,7 @@
"| Profondeur | variable (adaptative) | Fixe (4 niveaux) |\n",
"| Temps par coup | plus lent (cell. 28) | plus rapide (cell. 28) |\n",
"\n",
"**Points cles** :\n",
"**Points clés** :\n",
"1. Sur cette partie, MCTS(1000) l'emporte mais il est ~7x plus lent par coup que Minimax(d=4)\n",
"2. MCTS n'a **pas besoin de fonction d'évaluation artisanale**\n",
"3. MCTS explore automatiquement plus profondement les lignes prometteuses\n",
Expand Down Expand Up @@ -1877,7 +1877,7 @@
"| Force | détecte les victoires et menaces immédiates |\n",
"| Faiblesse | Pas de vision stratégique a long terme |\n",
"\n",
"**Points cles** :\n",
"**Points clés** :\n",
"1. Le glouton est **extrêmêment rapide** car il ne construit pas d'arbre\n",
"2. Il détecte les coups gagnants et les menaces immédiates (profondeur 1)\n",
"3. Il sera surpasse par Minimax qui voit plus loin dans l'arbre de jeu\n",
Expand All @@ -1902,7 +1902,7 @@
"\n",
"Organisons un tournoi complet entre toutes les IA. Chaque paire joue **6 parties** (3 en tant que joueur 1, 3 en tant que joueur 2) pour eliminer l'avantage du premier joueur.\n",
"\n",
"> **Note** : Le nombre de parties a ete réduit a 6 pour ce notebook pedagogique. Pour des résultats statistiquement significatifs, utilisez 20+ parties par paire.\n",
"> **Note** : Le nombre de parties a ete réduit a 6 pour ce notebook pédagogique. Pour des résultats statistiquement significatifs, utilisez 20+ parties par paire.\n",
"\n",
"### Participants\n",
"\n",
Expand Down Expand Up @@ -2245,7 +2245,7 @@
"tags": []
},
"source": [
"Visualisons ces résultats sous forme de graphiques pour mieux comparer les performances relatives et les couts en temps de calcul."
"Visualisons ces résultats sous forme de graphiques pour mieux comparer les performances relatives et les coûts en temps de calcul."
]
},
{
Expand Down Expand Up @@ -2362,11 +2362,11 @@
"| 4 | Greedy | Moyenne | Negligeable | Bloque les menaces immédiates |\n",
"| 5 | Random | Nulle | Negligeable | Perd contre tout (0W-0D-6L partout) |\n",
"\n",
"**Points cles** :\n",
"**Points clés** :\n",
"1. **La profondeur compte** : Minimax(d=6) domine Minimax(d=4) car il voit plus loin\n",
"2. **MCTS(500) est competitif** sans fonction d'évaluation artisanale -- il prend même 2 parties a Minimax(d=6)\n",
"3. **Greedy est un bon rapport qualite/prix** : presque instantané, il bat Random a chaque fois\n",
"4. **Le compromis temps/qualite** est clairement visible dans le graphique de droite\n",
"3. **Greedy est un bon rapport qualité/prix** : presque instantané, il bat Random a chaque fois\n",
"4. **Le compromis temps/qualité** est clairement visible dans le graphique de droite\n",
"5. **L'avantage du premier joueur** est partiellement neutralise par les 3+3 parties alternees\n",
"\n",
"> **observation** : Augmenter les itérations de MCTS (5000+) ou la profondeur de Minimax (d=8) améliorérait les performances, mais au prix d'un temps de calcul significativement plus élevé.\n"
Expand All @@ -2390,7 +2390,7 @@
"\n",
"### 8.1 Le framework Game de Russell & Norvig\n",
"\n",
"Le livre **\"Artificial Intelligence: A Modern Approach\"** (AIMA) de Russell et Norvig propose un framework elegant pour les jeux a deux joueurs. Ce framework est disponible dans le module `games4e.py` du depot [aima-python](https://github.com/aimacode/aima-python), avec une implementation Java plus sophistiquee dans [aima-java](https://github.com/aimacode/aima-java).\n",
"Le livre **\"Artificial Intelligence: A Modern Approach\"** (AIMA) de Russell et Norvig propose un framework elegant pour les jeux a deux joueurs. Ce framework est disponible dans le module `games4e.py` du dépôt [aima-python](https://github.com/aimacode/aima-python), avec une implementation Java plus sophistiquee dans [aima-java](https://github.com/aimacode/aima-java).\n",
"\n",
"**Principe cle** : séparer la **logique du jeu** (classe Game) des **algorithmes de recherche** (fonctions joueurs).\n",
"\n",
Expand Down Expand Up @@ -3530,7 +3530,7 @@
"\n",
"### Lecons retenues\n",
"\n",
"1. **Profondeur vs Qualite** : Minimax gagne ~200 ELO par niveau de profondeur supplémentaire, au prix d'un facteur ~10x en temps de calcul.\n",
"1. **Profondeur vs Qualité** : Minimax gagne ~200 ELO par niveau de profondeur supplémentaire, au prix d'un facteur ~10x en temps de calcul.\n",
"\n",
"2. **Alpha-Beta essentiel** : L'elagage réduit le facteur de branchement effectif de ~7 a ~3-4, rendant les profondeurs 5-6 accessibles.\n",
"\n",
Expand All @@ -3543,7 +3543,7 @@
"### Pour aller plus loin\n",
"\n",
"- **résolution complète** : utiliser une base de données d'ouvertures (solution parfaite connue depuis 1988)\n",
"- **deep reinforcement learning (DQN, etc.)** : hors scope de ce carnet — voir l'EPIC DQN-RL dedie (a venir). Les methodes implementees ici (Minimax α-β, MCTS, AIMA) sont toutes des methodes de recherche classique, sans composante apprentissage.\n",
"- **deep reinforcement learning (DQN, etc.)** : hors scope de ce carnet — voir l'EPIC DQN-RL dedie (a venir). Les méthodes implementees ici (Minimax α-β, MCTS, AIMA) sont toutes des méthodes de recherche classique, sans composante apprentissage.\n",
"- **Parallelisation** : Paralleliser MCTS ou Alpha-Beta pour explorer plus de noeuds\n",
"- **recherche de Monte Carlo améliorée** : Ajouter une heuristique de simulation (RAVE, etc.)\n"
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
"\n",
"**Serie** : Search / Part3-Cas-pratiques (Bonus) — jumeau .NET du notebook Python [App-12b-ConnectFour](App-12b-ConnectFour.ipynb).\n",
"\n",
"**Duree estimee** : ~1h30\n",
"**Durée estimee** : ~1h30\n",
"\n",
"**Prerequis** : [Search-06-AdversarialSearch](../Part1-Foundations/Search-06-AdversarialSearch.ipynb) (Minimax, Alpha-Beta), [Search-07-MCTS](../Part1-Foundations/Search-07-MCTS-And-Beyond.ipynb), notions de C# / .NET.\n",
"**Prérequis** : [Search-06-AdversarialSearch](../Part1-Foundations/Search-06-AdversarialSearch.ipynb) (Minimax, Alpha-Beta), [Search-07-MCTS](../Part1-Foundations/Search-07-MCTS-And-Beyond.ipynb), notions de C# / .NET.\n",
"\n",
"**Pourquoi un jumeau C# ?** Le notebook Python compare 5 intelligences artificielles (aleatoire, Minimax avec elagage alpha-beta, MCTS, glouton, iterative deepening) sur le jeu de Puissance 4, en s'appuyant sur `numpy` et `matplotlib`. Ce jumeau reimplemente les mêmes algorithmes en **C# .NET 9 (BCL seule, 0 NuGet)** : moteur de jeu, heuristique de fenêtre, Minimax alpha-beta, MCTS (UCB1), tournoi round-robin et iterative deepening. Les graphiques `matplotlib` sont remplacés par un rendu **ASCII autonome**. Les deux notebooks derivent les mêmes résultats (echelle de profondeur, tournoi).\n"
"**Pourquoi un jumeau C# ?** Le notebook Python compare 5 intelligences artificielles (aléatoire, Minimax avec elagage alpha-beta, MCTS, glouton, iterative deepening) sur le jeu de Puissance 4, en s'appuyant sur `numpy` et `matplotlib`. Ce jumeau reimplemente les mêmes algorithmes en **C# .NET 9 (BCL seule, 0 NuGet)** : moteur de jeu, heuristique de fenêtre, Minimax alpha-beta, MCTS (UCB1), tournoi round-robin et iterative deepening. Les graphiques `matplotlib` sont remplacés par un rendu **ASCII autonome**. Les deux notebooks derivent les mêmes résultats (echelle de profondeur, tournoi).\n"
]
},
{
Expand All @@ -25,10 +25,10 @@
"source": [
"## 1. Introduction\n",
"\n",
"Le Puissance 4 est un jeu de stratégie combinatoire abstrait a information complete : deux joueurs (Rouge = joueur 1, Jaune = joueur 2) s'affrontent sur un plateau 6x7 en cherchant a aligner 4 jetons. Sa profondeur de jeu limitee (42 coups maximum) et son espace d'etats reduit (~4.5 trillions mais très echantillonnable) en font un banc d'essai ideal pour comparer des algorithmes de decision.\n",
"Le Puissance 4 est un jeu de stratégie combinatoire abstrait a information complete : deux joueurs (Rouge = joueur 1, Jaune = joueur 2) s'affrontent sur un plateau 6x7 en cherchant a aligner 4 jetons. Sa profondeur de jeu limitee (42 coups maximum) et son espace d'états réduit (~4.5 trillions mais très echantillonnable) en font un banc d'essai ideal pour comparer des algorithmes de decision.\n",
"\n",
"Ce notebook met en compétition **5 approches** :\n",
"1. **Joueur aleatoire** (baseline)\n",
"1. **Joueur aléatoire** (baseline)\n",
"2. **Minimax avec elagage alpha-beta** (recherche exhaustive avec heuristique)\n",
"3. **Monte Carlo Tree Search (MCTS)** (recherche statistique par simulations)\n",
"4. **Joueur glouton** (heuristique immediate, 1-ply)\n",
Expand Down Expand Up @@ -534,7 +534,7 @@
"source": [
"## 3. Heuristique de position (fenêtres de 4)\n",
"\n",
"L'evaluation du plateau pour Minimax repose sur le decompte des **fenêtres de 4 cases** contigues (horizontales, verticales, diagonales). Pour chaque fenêtre :\n",
"L'évaluation du plateau pour Minimax repose sur le decompte des **fenêtres de 4 cases** contigues (horizontales, verticales, diagonales). Pour chaque fenêtre :\n",
"- 4 jetons du joueur : **+1000** (gagnant)\n",
"- 3 jetons + 1 vide : **+10** (pres de gagner)\n",
"- 2 jetons + 2 vides : **+2** (potential)\n",
Expand Down Expand Up @@ -850,7 +850,7 @@
"source": [
"### Expérience : effet de la profondeur\n",
"\n",
"Plus la profondeur de recherche augmente, plus Minimax anticipe loin — au prix du temps de calcul (croissance exponentielle). On mesure le **taux de victoire** et le **temps par coup** pour les profondeurs 2, 4 et 6 contre le joueur aleatoire.\n"
"Plus la profondeur de recherche augmente, plus Minimax anticipe loin — au prix du temps de calcul (croissance exponentielle). On mesure le **taux de victoire** et le **temps par coup** pour les profondeurs 2, 4 et 6 contre le joueur aléatoire.\n"
]
},
{
Expand Down Expand Up @@ -922,7 +922,7 @@
"source": [
"## 5. IA 3 : Monte Carlo Tree Search (MCTS)\n",
"\n",
"MCTS construit progressivement un arbre de jeu par **simulations aleatoires** (rollouts). Chaque noeud choisit ses enfants via **UCB1** (Upper Confidence Bound) qui equilibre exploitation (moyenne des recompenses) et exploration (visites rares). Après un budget d'itérations, on joue le coup le plus visite.\n"
"MCTS construit progressivement un arbre de jeu par **simulations aléatoires** (rollouts). Chaque noeud choisit ses enfants via **UCB1** (Upper Confidence Bound) qui equilibre exploitation (moyenne des récompenses) et exploration (visites rares). Après un budget d'itérations, on joue le coup le plus visite.\n"
]
},
{
Expand Down Expand Up @@ -1964,7 +1964,7 @@
"Ce jumeau C# a reimplemente, sans aucune librairie externe, le banc d'essai comparatif du notebook Python :\n",
"\n",
"- **Moteur de jeu** complet (plateau 6x7, legalite, victoire, undo pour backtracking)\n",
"- **5 algorithmes** : joueur aleatoire, glouton (1-ply), Minimax alpha-beta, MCTS (UCB1), iterative deepening\n",
"- **5 algorithmes** : joueur aléatoire, glouton (1-ply), Minimax alpha-beta, MCTS (UCB1), iterative deepening\n",
"- **Heuristique de fenêtres** (4 alignes +1000, 3+vide +10, etc., bonus centre)\n",
"- **Tournoi round-robin** revelant la hiérarchie des algorithmes\n",
"\n",
Expand All @@ -1982,7 +1982,7 @@
"\n",
"### Pathologie de l'arbre de jeu (note honnete, G.1)\n",
"\n",
"Le tournoi revele un résultat contre-intuitif mais **reel et documente** : **Minimax(d=2) bat Minimax(d=4)** dans cette configuration (match aller-retour 4-0 dans les deux sens). Ce n'est pas un bug — le moteur et l'heuristique sont verifies (scores de position re-derives a la main, P1=9/P2=5 sur le plateau de demo). C'est la **pathologie de la recherche dans les arbres de jeu** (Nau, 1982) : avec une heuristique *imparfaite*, une recherche plus profonde peut systematiquement perdre contre une recherche moins profonde, parce que l'effet d'horizon fait sur-evaluer des menaces qui ne se realisent jamais. Les matchs Minimax-vs-Minimax etant **déterministes** (aucun aleatoire dans la recherche), le même coup est joue a chaque partie — d'ou des scores 4-0 nets. L'avantage du **premier joueur** (P1 = Rouge) est également massif au Puissance 4 (victoire forcee en jeu parfait). Ce phenomene est une lecon pedagogique centrale : « plus profond » n'implique pas « meilleur » des qu'on s'ecarte du jeu parfait. Les **valeurs numériques exactes** (temps, compteurs) différent C# vs Python (JIT .NET plus rapide que CPython) — c'est un effet runtime attendu, pas une différence algorithmique.\n",
"Le tournoi revele un résultat contre-intuitif mais **réel et documente** : **Minimax(d=2) bat Minimax(d=4)** dans cette configuration (match aller-retour 4-0 dans les deux sens). Ce n'est pas un bug — le moteur et l'heuristique sont verifies (scores de position re-derives a la main, P1=9/P2=5 sur le plateau de demo). C'est la **pathologie de la recherche dans les arbres de jeu** (Nau, 1982) : avec une heuristique *imparfaite*, une recherche plus profonde peut systematiquement perdre contre une recherche moins profonde, parce que l'effet d'horizon fait sur-evaluer des menaces qui ne se realisent jamais. Les matchs Minimax-vs-Minimax etant **déterministes** (aucun aléatoire dans la recherche), le même coup est joue a chaque partie — d'ou des scores 4-0 nets. L'avantage du **premier joueur** (P1 = Rouge) est également massif au Puissance 4 (victoire forcee en jeu parfait). Ce phenomene est une lecon pédagogique centrale : « plus profond » n'implique pas « meilleur » des qu'on s'ecarte du jeu parfait. Les **valeurs numériques exactes** (temps, compteurs) différent C# vs Python (JIT .NET plus rapide que CPython) — c'est un effet runtime attendu, pas une différence algorithmique.\n",
"\n",
"### Prochaines étapes\n",
"\n",
Expand Down
Loading
Loading