Skip to content
Closed
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 @@ -146,6 +146,13 @@
"print(\"Environnement pret.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : PyGAD 3.5.0 et l'environnement sont prêts, validant la configuration de base.\n"
]
},
{
"cell_type": "markdown",
"id": "p1yavcoqvca",
Expand Down Expand Up @@ -255,6 +262,13 @@
"print(\"=\" * 55)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : Les caractéristiques des actifs montrent un rendement croissant de 5 % à 25 % et un risque de 10 % à 22,4 %, avec un ratio Sharpe individuel allant de 0,30 à 1,03, reflétant le compromis classique entre rendement et volatilité.\n"
]
},
{
"cell_type": "markdown",
"id": "c7khflhfcd",
Expand Down Expand Up @@ -371,6 +385,13 @@
"print(f\" Sharpe : {sharpe_ratio(w_equal):.4f}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : Les fonctions utilitaires calculent pour un portefeuille équipondéré un rendement de 15,00 %, un risque de 8,98 % et un ratio de Sharpe de 1,4469, ce qui valide le calcul des métriques de base sur l'ensemble des actifs.\n"
]
},
{
"cell_type": "markdown",
"id": "n3pbaud98c",
Expand Down Expand Up @@ -481,6 +502,13 @@
"> **Note** : La zone au-dessus et a gauche de chaque actif individuel est accessible uniquement par la diversification. C'est la puissance de la théorie de Markowitz."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : Le graphe place les 5 actifs sur un axe risque-rendement, montrant leur alignement caractéristique.\n"
]
},
{
"cell_type": "markdown",
"id": "rq8m0slcbm",
Expand Down Expand Up @@ -583,6 +611,13 @@
" print(f\" {name:<15} : {best_random_weights[i]:>6.1%}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : L'échantillonnage de 10 000 portefeuilles en 55 ms produit un meilleur Sharpe de 1,4807 (rendement 18,43 %, risque 11,10 %) avec une allocation concentrée sur les actifs les plus risqués, confirmant que l'espace de recherche est bien couvert.\n"
]
},
{
"cell_type": "markdown",
"id": "zjbowh2c8r",
Expand Down Expand Up @@ -822,6 +857,13 @@
" print(f\" {key}: {ga_config[key]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : La configuration PyGAD utilise 150 générations, 50 solutions par population et 5 gènes (un par actif), avec une sélection parentale SSS, un croisement uniforme et un taux de mutation de 20 %, ce qui définit un espace de recherche adapté à ce problème de 5 dimensions.\n"
]
},
{
"cell_type": "markdown",
"id": "17ml9o6bmwa",
Expand Down Expand Up @@ -926,6 +968,13 @@
" print(f\" {name:<15} : {best_ga_weights[i]:>6.1%}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : Le GA tient son optimum tôt : « Generation 50 : best Sharpe = 1.4839 » — puis ne bouge plus jusqu'à la génération 150 (avg finale 1,4422). « Optimisation terminee en 203 ms (150 generations) » ; meilleur portefeuille : rendement 17,97 %, risque 10,76 %, Sharpe 1,4839 — un cheveu au-dessus de l'échantillonnage aléatoire (1,4807) pour une allocation voisine : Obligations 2,4 %, Immobilier 18,7 %, Actions EU 24,3 %, Actions US 26,4 %, Emergents 28,3 %."
]
},
{
"cell_type": "markdown",
"id": "o0and0yvl7",
Expand Down Expand Up @@ -1213,6 +1262,13 @@
"print(f\"\\n{len(frontier_portfolios)} portefeuilles calcules pour la frontiere.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : L'exploration paramétrique de la frontière efficiente montre que le ratio de Sharpe maximale de 1,4838 est atteint pour α=1,5 (rendement 17,76 %, risque 10,62 %), illustrant le compromis optimal entre risque et rendement pour ce jeu d'actifs.\n"
]
},
{
"cell_type": "markdown",
"id": "qz1h36magf",
Expand Down Expand Up @@ -3010,4 +3066,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}
80 changes: 79 additions & 1 deletion MyIA.AI.Notebooks/Search/Part2-CSP/CSP-7-Soft-Csharp.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@
"Console.WriteLine($\"Existe : {File.Exists(dllPath7)}\");"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : Le répertoire CspDir7 a été trouvé — l'imprimé le confirme : « DLL Choco trouvée : org.chocosolver.solver.dll » et « Existe : True ».\n",
""
]
},
{
"cell_type": "code",
"execution_count": 2,
Expand Down Expand Up @@ -259,6 +267,13 @@
"Console.WriteLine(\"IKVM 8.15.0 pret (home=\" + Path.GetFileName(ikvmHome) + \", tzdb=\" + tzdbOk + \") - Choco-solver charge\");\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : IKVM 8.15.0 est prêt avec les packages `IKVM` et `IKVM.Image` installés, et Choco-solver est chargé depuis `ikvm-home-8.15.0-win-x64`, confirmant que l'interopérabilité Java-.NET est fonctionnelle.\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
Expand Down Expand Up @@ -297,6 +312,13 @@
"Console.WriteLine(\"Choco-solver 4.10.17 chargé — WeightedSum + CostRegular disponibles\");"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : La DLL Choco-solver `org.chocosolver.solver.dll` est trouvée et accessible, ce qui permet d'utiliser le moteur de contraintes Java depuis .NET via IKVM.\n"
]
},
{
"cell_type": "markdown",
"id": "d67a3cc6",
Expand All @@ -321,6 +343,13 @@
"- Objectif : `model.Sum(participantCosts, \"=\", totalCost).Post()` + `model.SetObjective(totalCost, MINIMIZE)`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : Choco-solver 4.10.17 est chargé avec les modules WeightedSum et CostRegular disponibles.\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
Expand Down Expand Up @@ -529,6 +558,13 @@
"Console.WriteLine($\"Total créneaux distincts : {seen2.Count}, coût optimal = {lastCost}\");\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : L'énumération ordonnée ne trouve qu'une solution : « Créneau 9h (idx 0) → coût total = 1 », « Total créneaux distincts : 1, coût optimal = 1 » — les autres créneaux sont éliminés par les contraintes dures ; la pondération ne sert plus qu'à ordonner ce qui reste."
]
},
{
"cell_type": "markdown",
"id": "ee6a1744",
Expand Down Expand Up @@ -694,6 +730,13 @@
"Console.WriteLine();\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : « Sac multi-objectif résolu en 9 ms » et la solution est vide : « Coût pondéré = 0 », « Poids total = 0 / 12 », « Coût total = 0 », aucun objet pris. Avec α=5 (poids) et β=1 (coût), prendre un objet coûte au moins 5 unités de pénalité sans rien rapporter — l'optimum du scalaire pondéré est de ne rien prendre. C'est la limite de la scalarisation multi-objectif : la pondération peut rendre toute solution non vide non rentable."
]
},
{
"cell_type": "markdown",
"id": "d7865b08",
Expand Down Expand Up @@ -843,6 +886,13 @@
"**Modélisation Choco** : pour chaque paire (i,j), on définit un booléen `same_{ij} = (x_i == x_j)`, et le coût total = somme des `same_{ij}` × coût_unitaire."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : La séquence de routage optimale `[0, 0, 0]` a un coût total de 3 et est résolue en 3 ms, démontrant l'efficacité de `CostRegular` pour les problèmes de coût pondéré sur graphe.\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
Expand Down Expand Up @@ -953,6 +1003,13 @@
"***## 4. Fuzzy CSP : degrés d'appartenance et combinaison min (~20 min)Le **Fuzzy CSP** relâche la dichotomie satisfaite/violée au profit de **degrés** dans $[0, 1]$ :- **1.0** : contrainte parfaitement satisfaite- **0.5** : contrainte partiellement satisfaite- **0.0** : contrainte complètement violéeLa satisfaction globale d'une instanciation est le **minimum** des degrés de toutes les contraintes (principe du « maillon le plus faible »). Le solveur cherche l'instanciation qui **maximise ce minimum** — c'est l'optimum d'équité max-min.### Exemple : planification de vacancesVariables :- **Destination** ∈ {Paris, Londres, Rome}- **Mois** ∈ {Juin, Juillet, Août}Trois contraintes floues :- **Préférence temporelle** : Juillet (1.0) > Août (0.7) > Juin (0.4)- **Préférence géographique** : Rome (1.0) > Paris (0.8) > Londres (0.3)- **Budget** : satisfaction = max(0, 1 − (cout − 1000) / 500) si 1000 ≤ cout ≤ 1500, 1.0 si cout ≤ 1000, 0.0 si cout > 1500 (dégressif entre 1000 et 1500 EUR, le seuil idéal est 1000 EUR)L'optimum doit combiner les trois — pas le meilleur mois tout seul ni la meilleure destination toute seule, mais la combinaison qui maximise le minimum des trois.### Encodage ChocoChoco n'a pas de primitive floue first-class, mais le pattern « variable de satisfaction + min + maximize » est idiomatique. On code :- deux `IntVar` pour les variables de décision (destination ∈ [1,3], mois ∈ [1,3])- trois `IntVar` ∈ [0, 1000] pour les degrés de satisfaction (encodage entier pour éviter les flottants en propagation)- un `IntVar` global_sat ∈ [0, 1000] forcé à être le **min** des trois degrés via `model.min(...)`- l'objectif : **maximiser** global_sat (`model.setObjective(true, globalSat)`)Les degrés sont attachés à la valeur de la variable par `model.element(sat, table, var)` où `table` est un tuple indexé par la valeur de la variable. Pour le budget, on linéarise la fonction d'appartenance avec un test sur la valeur de destination (coût moyen par destination : Paris=1200, Londres=1400, Rome=1100)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : SoftAllDifferent trouve la solution `[4, 1, 0, 3, 2]` avec un coût de violation de 0 en 1 ms, prouvant que toutes les valeurs peuvent être distinctes sans pénalité.\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
Expand Down Expand Up @@ -1173,6 +1230,13 @@
"Console.WriteLine($\"Boolean : Project(true, false) = {booleanSr.Project(true, false)}, Combine(false, false) = {booleanSr.Combine(false, false)}\");\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : Le cadre algébrique s'instancie en trois semi-anneaux dont l'imprimé teste les neutres : Fuzzy — « Project(1.0, 0.7) = 0,7 » (Top neutre), « Combine(0.0, 0.7) = 0,7 » (Bottom neutre) ; Weighted — « Project(0.0, 5.0) = 5 », « Combine(+inf, 5.0) = 5 » ; Boolean — « Project(true, false) = False », « Combine(false, false) = False ». Chaque triplet (Project, Combine, neutres) définit une sémantique de composition des préférences ; le commentaire du code ancre le cadre : Bistarelli-Montanari-Rossi 1997."
]
},
{
"cell_type": "markdown",
"id": "semiring-md-2",
Expand Down Expand Up @@ -1364,6 +1428,13 @@
"Console.WriteLine($\"Accord exact framework vs moteur : {Math.Abs(bestValue - chocoBest / 1000.0) < 1e-9}\");\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : Les deux approches (cadre semi-anneau par force brute et moteur Choco par propagation max-min) produisent le même résultat `Rome en Juillet -> 0,8`, validant la cohérence entre l'implémentation framework et le moteur de contraintes natif.\n"
]
},
{
"cell_type": "markdown",
"id": "semiring-md-4",
Expand Down Expand Up @@ -1600,6 +1671,13 @@
"3. Verifiez que la solution respecte le budget de 1200 EUR"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Lecture** : La configuration imprimée (i5-12400, MSI PRO B660M, RTX 3060, Corsair CV 550W, NZXT H510) : « Prix total : 815 EUR (budget 820) » et « Score total : 145 (min 145) » — les deux contraintes STRONG sont saturées. Sur les quatre WEAK, seule la couleur (noir, préférée) est satisfaite : le « Score objectif : 5 x 0 (strong) + 3 (weak) = 3 » est le coût des violations WEAK (deux marques non préférées + garantie courte), pas un décompte de préférences satisfaites. L'imprimé clôt l'accord : « le jumeau Python (CP-SAT) trouve le meme objectif = 3 sur le meme catalogue »."
]
},
{
"cell_type": "code",
"execution_count": 14,
Expand Down Expand Up @@ -1953,4 +2031,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}
Loading