Skip to content
Merged
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
109 changes: 94 additions & 15 deletions MyIA.AI.Notebooks/Search/Part2-CSP/CSP-7-Soft.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -643,20 +643,17 @@
"source": [
"### Interpretation : Visualisation des préférences floues\n",
"\n",
"**Sortie obtenue** : les trois graphiques montrent les fonctions d'appartenance floues et la meilleure solution.\n",
"**Sortie obtenue** : les trois graphiques tracent les degrés d'appartenance du problème de vacances — préférence par mois, préférence par destination, et fonction d'appartenance budgétaire décroissante.\n",
"\n",
"| Aspect | Valeur | Signification |\n",
"|--------|--------|---------------|\n",
"| Destination optimale | Paris (0.8) | Préférence la plus elevee |\n",
"| Mois optimal | Juillet (0.8) | Meilleur compromis meteo/budget |\n",
"| Satisfaction globale | 0.80 | Le min aggrave la pire composante |\n",
"| Londres | 0.30 partout | Destination la moins preferree |\n",
"| Graphique | Valeurs tracées | Signification |\n",
"|-----------|-----------------|---------------|\n",
"| Préférence par mois | Juin 0.4, Juillet 1.0, Août 0.7 | Juillet est le mois le plus désiré |\n",
"| Préférence par destination | Londres 0.3, Paris 0.8, Rome 1.0 | Londres est la destination la moins préférée |\n",
"| Fonction budgétaire | 1.0 jusqu'à 1000 EUR, 0 à 1500 EUR | Au-delà de 1500 EUR, le budget n'est plus acceptable |\n",
"\n",
"**Points cles** :\n",
"1. L'opérateur **min** (semi-anneau flou) garantit que la solution est jugee par sa **pire composante** -- philosophie \"un chainon faible\"\n",
"2. La solution Paris+Juillet a 0.80 car c'est le minimum des satisfactions destination=0.80, mois=0.80 et budget\n",
"3. Rome+Juillet (0.20) est la pire car la satisfaction budget est très faible en Juillet\n",
"4. Un Fuzzy CSP avec opérateur **produit** aurait donne des scores plus differencies (0.64 vs 0.04 au lieu de 0.80 vs 0.20)"
"**Points clés** :\n",
"1. Ces trois courbes sont les **entrées** du Fuzzy CSP : ce sont leurs degrés que l'opérateur **min** (semi-anneau flou) combinera pour noter une solution complète — philosophie \"un chaînon faible\" : la satisfaction globale est la **pire composante**.\n",
"2. Aucune solution n'est calculée ici : la figure ne montre que les préférences. La démonstration chiffrée du mécanisme arrive en section 7, avec le menu de la semaine."
]
},
{
Expand Down Expand Up @@ -820,6 +817,16 @@
"print(f\"Meilleur creneau: {best_slot}\")"
]
},
{
"cell_type": "markdown",
"id": "lec-csp7-1",
"metadata": {},
"source": [
"### Interpretation : Coûts de violation\n",
"\n",
"**Sortie obtenue** : la cellule somme, pour chaque créneau, les indisponibilités des trois participants et le coût de la salle (nulle le matin, 5 EUR l'après-midi) ; le total minimal est de **1**, atteint à **9h** (seul Bob y est indisponible, à 1) — 10h atteint le même total, la sortie retenant le premier minimum rencontré. L'après-midi, la salle à 5 EUR et les indisponibilités cumulées font grimper la facture."
]
},
{
"cell_type": "markdown",
"id": "08e5d684",
Expand Down Expand Up @@ -923,12 +930,12 @@
"source": [
"### Interpretation : Visualisation du Weighted CSP\n",
"\n",
"**Sortie obtenue** : le diagramme en barres empilees montre les couts de violation par creneau et par participant. Le solveur retourne `9h` comme creneau optimal (cout total = 1).\n",
"**Sortie obtenue** : le diagramme en barres groupées montre les couts de violation par creneau et par participant. Le solveur retourne `9h` comme creneau optimal (cout total = 1).\n",
"\n",
"| Aspect | Valeur | Signification |\n",
"|--------|--------|---------------|\n",
"| Creneau optimal | 9h (cout=1) | Somme minimale des couts de violation |\n",
"| Creneau le pire | 14h/15h (cout=8) | Salle non disponible + plusieurs conflits |\n",
"| Creneau le pire | 15h (cout=10) | Salle à 5 EUR + indisponibilités des trois participants |\n",
"| Cout salle | 0 (matin), 5 (après-midi) | La salle est plus chere l'après-midi |\n",
"\n",
"**Points cles** :\n",
Expand Down Expand Up @@ -1084,6 +1091,16 @@
"print(\"Fonction solve_nurse_scheduling_soft definie.\")"
]
},
{
"cell_type": "markdown",
"id": "lec-csp7-2",
"metadata": {},
"source": [
"### Interpretation : Solveur CP-SAT à contraintes souples\n",
"\n",
"**Sortie obtenue** : la fonction `solve_nurse_scheduling_soft` est définie. Elle durcit la couverture minimale par poste, la limite d'un poste par infirmier et par jour, et le plafond de postes par infirmier ; les préférences (0 = préféré, 5 = neutre, 10 = détesté) forment l'objectif que CP-SAT minimise."
]
},
{
"cell_type": "markdown",
"id": "51b5bd30",
Expand Down Expand Up @@ -1390,6 +1407,16 @@
"print(f\"\\nRepartition : {counts}\")\n"
]
},
{
"cell_type": "markdown",
"id": "lec-csp7-3",
"metadata": {},
"source": [
"### Interpretation : Menu Planning Fuzzy\n",
"\n",
"**Sortie obtenue** : le Fuzzy CSP énumère les 3^7 combinaisons et retourne un score de satisfaction global de **0.800** : poisson le lundi, le mercredi, le vendredi et le dimanche, végétarien le mardi, le jeudi et le samedi — la viande n'apparaît jamais (`{'viande': 0, 'poisson': 4, 'vegetarien': 3}`)."
]
},
{
"cell_type": "markdown",
"id": "140cf741",
Expand Down Expand Up @@ -1624,6 +1651,16 @@
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "lec-csp7-4",
"metadata": {},
"source": [
"### Interpretation : Planification de voyage\n",
"\n",
"**Sortie obtenue** : le Weighted CSP énumère les combinaisons destination/transport/hébergement et retient **Paris | train | airbnb** pour un total de **492 EUR** — temps 2h × 15 = 30 EUR, transport 100 EUR, hébergement 63 EUR par nuit sur 5 nuits (315 EUR), plus 7 EUR d'inconfort transport et 40 EUR d'inconfort logement. Les prix de nuit générés (86, 116 et 63 EUR) écartent l'hôtel 4 étoiles."
]
},
{
"cell_type": "markdown",
"id": "72ee6639",
Expand Down Expand Up @@ -1854,6 +1891,16 @@
"print(\"Fonction solve_nurse_scheduling_fair definie.\")"
]
},
{
"cell_type": "markdown",
"id": "lec-csp7-5",
"metadata": {},
"source": [
"### Interpretation : Variante équitable (min-max)\n",
"\n",
"**Sortie obtenue** : la fonction `solve_nurse_scheduling_fair` est définie. Elle réifie la pénalité de chaque infirmier dans une variable entière `penalty_per_nurse[n]` et borne le pire cas par `max_penalty` ; l'objectif devient `total + fairness_weight × max_penalty`, le poids nul redonnant exactement le solveur baseline."
]
},
{
"cell_type": "markdown",
"id": "5018a72b",
Expand All @@ -1870,7 +1917,9 @@
"source": [
"### Application : comparaison baseline vs equite\n",
"\n",
"Nous comparons le solveur baseline (minimisation pure du total) avec trois niveaux de `fairness_weight` sur un scénario de conflit de préférences : trois infirmiers se disputent les postes du matin."
"Nous comparons le solveur baseline (minimisation pure du total) avec trois niveaux de `fairness_weight` sur un scénario de conflit de préférences : trois infirmiers se disputent les postes du matin.\n",
"\n",
"Le tableau récapitule, pour chaque poids, le total, le max, le min et le spread des pénalités, ainsi que le profil par infirmier."
]
},
{
Expand Down Expand Up @@ -1962,6 +2011,16 @@
" f\"{res['min_penalty']:>4} | {res['spread']:>6} | {res['penalties_by_nurse']}\")"
]
},
{
"cell_type": "markdown",
"id": "lec-csp7-6",
"metadata": {},
"source": [
"### Interpretation : Baseline vs équité\n",
"\n",
"**Sortie obtenue** : le tableau compare trois poids d'équité sur le scénario de conflit. À `fw=0` (baseline), le total vaut 70 mais l'infirmier 3 concentre **40** pénalités (spread 40, profil `[30, 0, 0, 40, 0, 0]`) ; dès `fw=5`, la charge se redistribue (`[30, 0, 20, 20, 0, 0]`, max 30, spread 30) pour un total identique de 70 — l'équité ne change pas le coût global, seulement sa répartition. `fw=20` confirme ce plateau."
]
},
{
"cell_type": "markdown",
"id": "858bc8fe",
Expand Down Expand Up @@ -2042,6 +2101,16 @@
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "lec-csp7-7",
"metadata": {},
"source": [
"### Interpretation : Impact du poids d'équité\n",
"\n",
"**Sortie obtenue** : le diagramme en barres groupées matérialise le tableau précédent, infirmier par infirmier : en gris (`fw=0`), l'infirmier 3 culmine à 40 pénalités, seul au-dessus de 30 (profil `[30, 0, 0, 40, 0, 0]`) ; en `fw=5` et `fw=20`, le perdant redescend à 20, à égalité avec l'infirmier 2 (`[30, 0, 20, 20, 0, 0]`). Les lignes pointillées matérialisent le `max_penalty` de chaque configuration (40, puis 30)."
]
},
{
"cell_type": "markdown",
"id": "5ec979f0",
Expand Down Expand Up @@ -2354,6 +2423,16 @@
" print(f\"\\n Score objectif : {M} x {n_strong} (strong) + {n_weak} (weak) = {M * n_strong + n_weak}\")\n"
]
},
{
"cell_type": "markdown",
"id": "lec-csp7-8",
"metadata": {},
"source": [
"### Interpretation : Configuration PC (Hierarchical CSP)\n",
"\n",
"**Sortie obtenue** : le solveur retient une configuration à **815 EUR** pour un budget de 820 EUR, avec un score total de **145** (minimum requis 145) : Core i5-12400 (200 EUR), carte mère MSI PRO B660M (130 EUR), RTX 3060 (320 EUR), alimentation Corsair CV 550W (75 EUR) et boîtier NZXT H510 (90 EUR). Les contraintes STRONG (budget, performance minimale) sont satisfaites ; les WEAK cèdent partiellement (marques non préférées, garantie courte), pour un score objectif de 3."
]
},
{
"cell_type": "markdown",
"id": "01f13ad9",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@
"Show(\"Tournée [0,1,2,3,4,5] longueur = \" + FI(small.TourLength(t)));\n"
]
},
{
"cell_type": "markdown",
"id": "app13b-lec-1",
"metadata": {},
"source": [
"**Lecture.** L'instance est constituée de 6 villes : la sortie affiche la matrice des distances — symétrique, diagonale nulle, paire la plus proche à 6.64 (villes 2 et 5) — et la tournée identité `[0,1,2,3,4,5]`, longue de 309.75. C'est le point de départ naïf, avant toute optimisation."
]
},
{
"cell_type": "markdown",
"id": "d6a170c7-dcd5-402d-961a-f54f4524caa3",
Expand Down Expand Up @@ -257,6 +265,14 @@
"Show(\"Croissance : (N-1)! -> N=10 = 362880, N=12 = 4e7, N=15 = 8.7e10 (inatteignable).\");\n"
]
},
{
"cell_type": "markdown",
"id": "app13b-lec-2",
"metadata": {},
"source": [
"**Lecture.** Sur l'instance à 8 villes, la force brute énumère 5 040 permutations (7!) et prouve l'optimum **293.19**, atteint par la tournée `[0,5,4,7,1,6,2,3]`. La sortie rappelle aussi la croissance factorielle — 362 880 permutations à N=10, 8,7×10¹⁰ à N=15 — qui la rend inatteignable au-delà d'une dizaine de villes."
]
},
{
"cell_type": "markdown",
"id": "56e04982-f0d6-4f1f-869e-b8edd28c22ce",
Expand Down Expand Up @@ -310,6 +326,14 @@
"Show(\"Tournée NN : \" + TourStr(nnTour));\n"
]
},
{
"cell_type": "markdown",
"id": "app13b-lec-3",
"metadata": {},
"source": [
"**Lecture.** Le plus proche voisin construit la tournée `[0,5,2,3,4,7,1,6]`, longue de **344.77** : un gap de **17.6%** au-dessus de l'optimum 293.19. Le glouton paie sa myopie — aucune vision au-delà du prochain pas."
]
},
{
"cell_type": "markdown",
"id": "fb07ce8a-bfbd-4795-9bc8-f676801decc4",
Expand Down Expand Up @@ -375,6 +399,14 @@
"Show(\"2-opt rapproche fortement de l'optimum en O(N^2) par passage.\");\n"
]
},
{
"cell_type": "markdown",
"id": "app13b-lec-4",
"metadata": {},
"source": [
"**Lecture.** Parti de la tournée du glouton, le 2-opt réalise **4 inversions** de segments et rejoint exactement l'optimum **293.19** (gap 0.00%) : sur cette instance de 8 villes, la recherche locale suffit à effacer tout l'écart laissé par la construction."
]
},
{
"cell_type": "markdown",
"id": "1e409b28-9f9b-432c-a1a1-8ff9db1dc39a",
Expand Down Expand Up @@ -431,6 +463,14 @@
"Show(\"Recuit simulé N=8 (depuis NN, 20000 iters) : longueur = \" + FI(saLen) + \" (\" + saAcc + \" moves acceptes). Gap vs optimum = \" + FI(100*(saLen-bl)/bl, \"F2\") + \"%.\");\n"
]
},
{
"cell_type": "markdown",
"id": "app13b-lec-5",
"metadata": {},
"source": [
"**Lecture.** Le recuit simulé, lancé depuis la tournée gloutonne avec 20 000 itérations, accepte **2 056 mouvements** et retrouve l'optimum **293.19** : sur 8 villes, la métaheuristique ne fait pas mieux que le 2-opt — le benchmark dira à partir de quelle taille elle prend l'avantage."
]
},
{
"cell_type": "markdown",
"id": "833095d7-ec99-43b5-b3e3-67282e2ddd2b",
Expand Down Expand Up @@ -580,6 +620,14 @@
"Show(\"la force brute est infaisable (OR-Tools dans le twin Python donne la reference industrielle).\");"
]
},
{
"cell_type": "markdown",
"id": "app13b-lec-6",
"metadata": {},
"source": [
"**Lecture.** Le tableau quantifie la hiérarchie : à N=6, 8 et 10, le 2-opt et le recuit simulé égalent la force brute (278.24, 293.19, 314.41 — gap 0.0%) tandis que le plus proche voisin reste à +17.9%, +17.6% et +16.4% ; à N=30, 60 et 100, la brute est infaisable (N/A) et le recuit simulé creuse un écart de 2.8%, 1.2% et 1.4% sur le 2-opt."
]
},
{
"cell_type": "markdown",
"id": "ccfdb229-0fe2-4894-9b20-74350424a5f4",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
date: '2026-10-29'
by: myia-po-2025:CoursIA
python_sha: 68f1b07aa399b1883c7aded25d99bf3818389745
csharp_sha: 597b1dc8b9102ed035eb80d1e7fcf572481fed5f
content_python_sha: cc1f8546c2f05e2013b6afbd555a20facecd7ea0368a1cc134edb6861e6a5981
content_csharp_sha: 39d5db95d6aff48afba84cc06f3c5dea845b6ab55b3a807d6f782a67699dbb41
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
date: '2026-11-01'
by: myia-po-2025:CoursIA
python_sha: 68f1b07aa399b1883c7aded25d99bf3818389745
csharp_sha: 38fa5934713c9bdd73c75e9f99e07c286eebfc6c
content_python_sha: cc1f8546c2f05e2013b6afbd555a20facecd7ea0368a1cc134edb6861e6a5981
content_csharp_sha: 2afac5d897ccac7b5cb985ec76e64d7c67bfff88c298a00b97283f449ae50808
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
date: '2026-10-29'
by: myia-po-2025:CoursIA
python_sha: b8fc5c7c3217587404a763b809259d85c2f3af6b
csharp_sha: 71bd83f6b6ef0df928e90b23f9ebcbb3334630e9
content_python_sha: 3ad0ec785e9269a6366fd4adb212ac40f753777d35019471c8246dee25821a95
content_csharp_sha: e4740471c9f61985edfd807088d448f8d8174f5e4917eedc38f111559ae825a4
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
date: '2026-11-01'
by: myia-po-2025:CoursIA
python_sha: b8fc5c7c3217587404a763b809259d85c2f3af6b
csharp_sha: 54796686f976e5994c420bd4504404fdb5478582
content_python_sha: 3ad0ec785e9269a6366fd4adb212ac40f753777d35019471c8246dee25821a95
content_csharp_sha: c20eaffa881365c2f09962fe5a0e7d4eaae6b4c1c2bfaca868859b0e45e27d1a
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
date: '2026-11-01'
by: myia-po-2025:CoursIA
python_sha: 801c3b5af4da450554886a244fb065abf2bdafac
csharp_sha: 54796686f976e5994c420bd4504404fdb5478582
content_python_sha: 25893f1e06db2fff00806796e9b442bedc07328b8c6030ab7b34f967a73907ec
content_csharp_sha: c20eaffa881365c2f09962fe5a0e7d4eaae6b4c1c2bfaca868859b0e45e27d1a
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
date: '2026-11-02'
by: myia-po-2025:CoursIA
python_sha: dd29150fb31dcaba81e1ed018c228bff1db9de11
csharp_sha: 46cdb6e25cabe6608daf93ab81abac3e29f07631
content_python_sha: d698a6bce596f76ced2458e05565f8d5d6a29f0bf1cfb4948dab470243b2c3d5
content_csharp_sha: 27208188cd8beec032fbddc4bc2b99e18ac96b9140a9c82274d2a8f1e9dc96cf
Loading