MGS-7d : Michalewicz (steep ridges) + Dixon-Price (narrow valley non-scalable) en projection N-D

← MGS-7c RosenbrockGriewank · MGS-8 LandscapeExplorer →

Pourquoi Michalewicz et Dixon-Price ?

MGS-7b/7c ont couvert les six fonctions classiques du banc CEC : Sphère (c.732), Rastrigin (c.732), Schwefel (c.732), Ackley (c.785), Rosenbrock (c.787), Griewank (c.787).

Restent deux fonctions avec des structures très différentes :

  1. Michalewicz \(f(\vec x) = -\sum_{i=1}^{n} \sin(x_i) \sin^{2m}\left(\frac{i x_i^2}{\pi}\right)\) — les crêtes raides paramétrées (m=10). Chaque dimension a une fréquence propre \(i/\pi\) et une amplitude contrôlée par \(\sin^{20}\), ce qui crée des vallées extrêmement étroites et diagonales dans l’espace 2-D. L’optimum en \(n=2\) est \(\approx -1.8013\), et l’optimum dépend de \(n\) (propriété rare dans le banc CEC). Recommandé \([0, \pi]\).

  2. Dixon-Price \(f(\vec x) = (x_1-1)^2 + \sum_{i=2}^{n} i \cdot (2 x_i^2 - x_{i-1})^2\) — la vallée étroite NON-scalable. Contrairement à Rosenbrock (vallée-courbe-étroite où la courbure est régulière), Dixon-Price a une vallée asymétrique : la coordonnée \(x_i\) est couplée à \(x_{i-1}\) via un terme \(i \cdot (2 x_i^2 - x_{i-1})^2\), et l’optimum \(x_i = 2^{-(2^i-2)/2^i}\) décroît exponentiellement avec \(i\). Recommandé \([-10, 10]\).

Ce que ce notebook teste

Question pédagogique : la projection MAX préserve-t-elle la structure fine des crêtes raides de Michalewicz (paramètre \(m=10\) = quasi-binaire) ? Et comment Dixon-Price se distingue-t-il de Rosenbrock en 2-D alors que les deux ont une vallée étroite ?

Hypothèses à vérifier : - Michalewicz 2-D = crêtes diagonales nettes (param \(m=10\) = amplitude \(\sin^{20}\) quasi-binaire), distinctes des bassines d’Ackley et des bandes de Griewank. - Dixon-Price 2-D = vallée étroite asymétrique (couplage \(x_2\) à \(x_1\)), contrairement à Rosenbrock 2-D qui a une vallée-courbe-étroite mais scalable (\(x_2 \approx x_1^2\)). - En 30-D, les deux fonctions s’effondrent sous MAX-projection mais pour des raisons différentes : Michalewicz car \(\sin^{20}\) sature rapidement, Dixon-Price car le couplage cross-dim rend les coordonnées cachées presque indépendantes.

Anti-pattern INTRINSIC documenté : si Michalewicz-n=30 ou Dixon-Price-n=30 devient quasi-uniforme, c’est la signature de la projection MAX + la structure intrinsèque de la fonction, pas un bug. Cf L785-L2 ★ et L787-L1 ★.

Reproductibilité

Les graines sont explicites dans les cellules (Random(42 + dim) pour Michalewicz, Random(7 + dim) pour Dixon-Price — une graine par dimension). Les heatmaps sont générées via le moteur KnownFunctionLandscape.RenderHeatmap du submodule MetaGeneticSharp.Extensions (port PR #7583 + #7776), rendu déterministe par pixel depuis la PR MetaGeneticSharp #49 (graine RNG dérivée de (x, y, base)) : l’ordre du Parallel.For n’influence plus le rendu, la double exécution est byte-identique.

#r "..\MetaGeneticSharp\src\MetaGeneticSharp.Extensions\bin\Debug\net9.0\MetaGeneticSharp.Extensions.dll"

using MetaGeneticSharp;
using GeneticSharp;

// Verifier l'API du submodule -- check BLOQUANT. Le porteur des bornes est
// KnownFunctionsBounds.For (KnownFunctions.cs), unique point d'acces canonique.
var boundsFor = typeof(KnownFunctionsBounds).GetMethod("For",
    System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
if (boundsFor is null)
    throw new InvalidOperationException(
        "KnownFunctionsBounds.For absent du submodule -- recompiler MetaGeneticSharp.Extensions");
var michalewiczType = System.Type.GetType("MetaGeneticSharp.MichalewiczFitness, MetaGeneticSharp.Extensions");
var dixonPriceType = System.Type.GetType("MetaGeneticSharp.DixonPriceFitness, MetaGeneticSharp.Extensions");
if (michalewiczType is null || dixonPriceType is null)
    throw new InvalidOperationException(
        "Classes de fitness introuvables dans MetaGeneticSharp.Extensions");
Console.WriteLine($"KnownFunctionsBounds.For present: {boundsFor is not null}");
Console.WriteLine($"MichalewiczFitness charge: {michalewiczType.FullName}");
Console.WriteLine($"DixonPriceFitness charge: {dixonPriceType.FullName}");

// Affichage des bornes en culture invariante (separateur decimal point,
// independant des reglages de la machine hote).
var fmt = "0.###";
var fmt4 = "0.####";
var invCulture = System.Globalization.CultureInfo.InvariantCulture;
// Echelles recommandees : mesurees par l'appel REEL au submodule (KnownFunctions.cs:236),
// pas recopiees en litteral.
var (michalewiczMin, michalewiczMax) = KnownFunctionsBounds.For(michalewiczType);
var (dixonPriceMin, dixonPriceMax) = KnownFunctionsBounds.For(dixonPriceType);
Console.WriteLine($"Michalewicz: range [{michalewiczMin.ToString(fmt, invCulture)}, {michalewiczMax.ToString(fmt4, invCulture)}] (KnownFunctionsBounds.For, m=10)");
Console.WriteLine($"DixonPrice:  range [{dixonPriceMin.ToString(fmt, invCulture)}, {dixonPriceMax.ToString(fmt, invCulture)}] (KnownFunctionsBounds.For, narrow valley non-scalable)");
KnownFunctionsBounds.For present: True
MichalewiczFitness charge: MetaGeneticSharp.MichalewiczFitness
DixonPriceFitness charge: MetaGeneticSharp.DixonPriceFitness
Michalewicz: range [0, 3.1416] (KnownFunctionsBounds.For, m=10)
DixonPrice:  range [-10, 10] (KnownFunctionsBounds.For, narrow valley non-scalable)

Michalewicz en \(n = 2, 5, 30\) : crêtes raides paramétrées

En 2-D, Michalewicz dessine une crête diagonale étroite au voisinage de l’optimum \(\vec x^* \approx (2.20, 1.57)\) pour \(n=2\) (optimum dépend de \(n\), propriété rare). La heatmap exhibe des bandes obliques très contrastées : le paramètre \(m=10\) dans \(\sin^{2m}(\cdot)\) sature l’amplitude entre 0 et 1, créant des transitions abruptes. Visuellement, cela donne un motif quasi-binaire alternant bandes sombres (fitness faible) et bandes claires (fitness haute).

En 30-D, chaque pixel \((x_1, x_2)\) doit explorer 28 dimensions cachées via MAX-projection. Le paramètre \(m=10\) rend chaque dimension très discontinue (presque digitale), ce qui amplifie la sensibilité au MAX : une coordonnée cachée en dehors de sa crête tire la fitness vers 0 ou \(-1\) brutalement. Question à trancher par la mesure (§ Tell visuel) : la MAX-projection effondre-t-elle la structure (« quasi-uniforme sombre ») ou densifie-t-elle les transitions ?

Substance distincte de Griewank (c.787) : - Griewank 2-D = produit-cosinus ondulé (anneaux concentriques ou bandes ondulantes) - Michalewicz 2-D = crêtes obliques abruptes (\(\sin^{20}\) quasi-binaire) La différence visuelle est radicale : Griewank est doux, Michalewicz est tranchant.

using System.IO;
using System.Security.Cryptography;

// Piege corrige : un unique Random etatique partage a travers plusieurs RenderHeatmap
// faisait degenerer la pipeline de rendu (d=2 et d=30 sortaient byte-identiques).
// Ici chaque dimension recoit un RNG independant et reproductible (42 + dim) : chaque
// heatmap est une MAX-projection N-D distincte, et le rendu ne peut plus collapser.
var written = new List<(int dim, string path, string hash)>();
foreach (int dim in new[] { 2, 5, 30 })
{
    using var h = KnownFunctionLandscape.RenderHeatmap(
        new MichalewiczFitness(), dimension: dim, nbSamples: 50, rng: new Random(42 + dim),
        width: 120, height: 120);

    var path = "assets/landscape_multidim_michalewicz_d" + dim + ".png";
    var bytes = h.ToPngGdi();
    File.WriteAllBytes(path, bytes);

    var hash = Convert.ToHexString(SHA256.HashData(bytes));
    written.Add((dim, path, hash));

    var (px, py) = h.ToPixel(0.0, 0.0);
    Console.WriteLine("Michalewicz dim=" + dim.ToString().PadLeft(2) + " - pixel(0,0) = " + h.Bitmap.GetPixel(px, py) + " (PNG: " + path + ", sha256=" + hash.Substring(0, 12) + ").");
}

// Controle durable : la classe entiere de defaut (deux dimensions qui rendent le meme
// fichier) doit echouer ici, pas seulement etre observee a posteriori.
if (written.Select(x => x.hash).Distinct().Count() != written.Count)
{
    foreach (var w in written) Console.Error.WriteLine("  d" + w.dim + "  " + w.hash);
    throw new InvalidOperationException("Collision de rendu Michalewicz : deux dimensions ont produit le meme PNG (hash identiques).");
}
Console.WriteLine("Michalewicz d2/d5/d30 distincts : "
    + string.Join(", ", written.Select(w => "d" + w.dim + "=" + w.hash.Substring(0, 12))));
Michalewicz dim= 2 - pixel(0,0) = Color [A=255, R=255, G=255, B=255] (PNG: assets/landscape_multidim_michalewicz_d2.png, sha256=AAAFF21B944B).
Michalewicz dim= 5 - pixel(0,0) = Color [A=255, R=0, G=255, B=178] (PNG: assets/landscape_multidim_michalewicz_d5.png, sha256=5524DBDAF08E).
Michalewicz dim=30 - pixel(0,0) = Color [A=255, R=0, G=255, B=16] (PNG: assets/landscape_multidim_michalewicz_d30.png, sha256=1C2CC62DA9DE).
Michalewicz d2/d5/d30 distincts : d2=AAAFF21B944B, d5=5524DBDAF08E, d30=1C2CC62DA9DE

Exercice 1 : quantifier la discontinuité de Michalewicz

Mesurer le gradient spatial moyen du canal rouge de Michalewicz-d2 et de Michalewicz-d30, et le comparer à celui d’une fonction plus lisse (Griewank, Ackley) rendue par le même moteur. La prédiction intuitive — la discontinuité \(\sin^{20}\) donne un gradient d=2 plus élevé — est-elle confirmée par la mesure ? Interpréter le résultat : que mesure réellement un gradient moyen, et qu’apprend-il sur la discontinuité des transitions versus leur densité dans le plan ?

La cellule ci-dessous fournit le squelette : elle rend les six heatmaps (Michalewicz / Ackley / Griewank en dimensions 2 et 30) et tient la structure d’accueil — la mesure du gradient reste à compléter. La section « Tell visuel (contrôlé par mesure) », plus bas, publie les mêmes mesures produites par une cellule sur les rendus des sections précédentes (graines 42 + dim) ; les rendus de cet exercice utilisent une graine unique (42), donc ses valeurs diffèrent — cette section documente la méthode, elle ne donne pas la réponse.

// Exercice 1 : quantifier la discontinuite de Michalewicz (gradient spatial
// moyen du canal rouge). Squelette d'accompagnement -- la mesure reste a completer.
// TODO etudiant : pour chaque heatmap ci-dessous, calculer la moyenne de
// |R(i+1,j) - R(i,j)| + |R(i,j+1) - R(i,j)| sur tous les pixels internes
// (colonnes 1..Width-2, lignes 1..Height-2), puis remplacer les NaN.
// Indice : h.Bitmap.GetPixel(colonne, ligne).R expose le canal rouge ; chaque
// pixel interne porte deux differences (voisin horizontal + voisin vertical).
// Etape 1 : accumuler la somme des differences sur les pixels internes.
// Etape 2 : diviser par (Width-2) * (Height-2) * 2.
// Etape 3 : afficher le tableau et confronter Michalewicz-d2 / Griewank-d2 /
// Michalewicz-d30 a la prediction intuitive de la consigne.
var ex1Stats = new List<(string fn, int dim, double gradientRouge)>();
foreach (var (fnName, fit) in new[] {
    ("Michalewicz", (IFitness)new MichalewiczFitness()),
    ("Ackley", new AckleyFitness()),
    ("Griewank", new GriewankFitness()),
}) {
    foreach (int dim in new[] { 2, 30 }) {
        using var h = KnownFunctionLandscape.RenderHeatmap(
            fit, dimension: dim, nbSamples: 50, rng: new Random(42),
            width: 120, height: 120);
        // TODO etudiant : boucle sur les pixels internes de h.Bitmap, accumuler
        // les differences du canal rouge, puis remplacer le NaN ci-dessous.
        ex1Stats.Add((fnName, dim, double.NaN)); // a remplacer par la mesure
    }
}
display(ex1Stats);
display("Exercice 1 a completer : les NaN ci-dessus attendent le gradient moyen du canal rouge de chaque heatmap.");
index value
0
(Michalewicz, 2, NaN)
Item1
Michalewicz
Item2
2
Item3
NaN
1
(Michalewicz, 30, NaN)
Item1
Michalewicz
Item2
30
Item3
NaN
2
(Ackley, 2, NaN)
Item1
Ackley
Item2
2
Item3
NaN
3
(Ackley, 30, NaN)
Item1
Ackley
Item2
30
Item3
NaN
4
(Griewank, 2, NaN)
Item1
Griewank
Item2
2
Item3
NaN
5
(Griewank, 30, NaN)
Item1
Griewank
Item2
30
Item3
NaN
Exercice 1 a completer : les NaN ci-dessus attendent le gradient moyen du canal rouge de chaque heatmap.

Dixon-Price en \(n = 2, 5, 30\) : vallée étroite non-scalable

En 2-D, Dixon-Price dessine une vallée étroite asymétrique. La formule se réduit à : \[f(x_1, x_2) = (x_1 - 1)^2 + 2 (2 x_2^2 - x_1)^2\]

L’optimum est en \(x_1 = 1\) et \(x_2 = \pm 1/\sqrt{2}\) (deux points symétriques). La vallée n’est pas diagonale comme Rosenbrock mais parabolique-croisée : le terme \(2(2 x_2^2 - x_1)^2\) impose que \(x_2\) suive \(x_1\) mais avec un exposant quadratique (et non linéaire \(x_1^2\) comme Rosenbrock). La heatmap 2-D exhibe une vallée non-rectiligne : étroite en haut (où \(x_2^2\) varie peu) et qui s’évase en bas (où le couplage domine).

En 30-D, le couplage cross-dim rend chaque coordonnée cachée quasi-indépendante : l’optimum \(x_i = 2^{-(2^i-2)/2^i}\) décroît exponentiellement (\(i=2 \to 0.707\), \(i=3 \to 0.594\), \(i=10 \to 0.501\), \(i=30 \to 0.5\)), donc la majorité des dimensions sont proches de \(0.5\). La MAX-projection sur 28 dimensions cachées retient quasi-systématiquement le fitness proche de l’optimum (région dense de fitness haute), produisant un fond quasi-uniforme (canal G saturé) — mais le couplage cross-dim laisse émerger des grains rouges très tranchés (grad(R)=96.2 en d=30, cf. § Tell visuel) : le fond est uniforme, pas la texture, ce qui la distingue de l’uniformité-même de l’ancien rendu.

Substance distincte de Rosenbrock (c.787) :

Fonction Forme vallée 2-D Couplage Asymétrie
Rosenbrock banane-diagonale \(x_2 \approx x_1^2\) léger (courbe monotone)
Dixon-Price parabolique-croisée \(x_2^2 \approx x_1/2\) fort (deux branches symétriques \(x_2 = \pm\sqrt{x_1/2}\))

La différence 2-D est radicale : Rosenbrock a une vallée continue et monotone, Dixon-Price a une vallée bifurquée en haut et un fond plus large en bas.

using System.IO;
using System.Security.Cryptography;

// Meme correction que Michalewicz : RNG independant par dimension + controle de
// distinction des sorties, pour que la classe entiere de defaut ne revienne pas.
var written = new List<(int dim, string path, string hash)>();
foreach (int dim in new[] { 2, 5, 30 })
{
    using var h = KnownFunctionLandscape.RenderHeatmap(
        new DixonPriceFitness(), dimension: dim, nbSamples: 50, rng: new Random(7 + dim),
        width: 120, height: 120);

    var path = "assets/landscape_multidim_dixon_price_d" + dim + ".png";
    var bytes = h.ToPngGdi();
    File.WriteAllBytes(path, bytes);

    var hash = Convert.ToHexString(SHA256.HashData(bytes));
    written.Add((dim, path, hash));

    var (px, py) = h.ToPixel(0.0, 0.0);
    Console.WriteLine("Dixon-Price dim=" + dim.ToString().PadLeft(2) + " - pixel(0,0) = " + h.Bitmap.GetPixel(px, py) + " (PNG: " + path + ", sha256=" + hash.Substring(0, 12) + ").");
}

if (written.Select(x => x.hash).Distinct().Count() != written.Count)
{
    foreach (var w in written) Console.Error.WriteLine("  d" + w.dim + "  " + w.hash);
    throw new InvalidOperationException("Collision de rendu Dixon-Price : deux dimensions ont produit le meme PNG (hash identiques).");
}
Console.WriteLine("Dixon-Price d2/d5/d30 distincts : "
    + string.Join(", ", written.Select(w => "d" + w.dim + "=" + w.hash.Substring(0, 12))));
Dixon-Price dim= 2 - pixel(0,0) = Color [A=255, R=255, G=0, B=0] (PNG: assets/landscape_multidim_dixon_price_d2.png, sha256=65FF2A763B82).
Dixon-Price dim= 5 - pixel(0,0) = Color [A=255, R=255, G=2, B=0] (PNG: assets/landscape_multidim_dixon_price_d5.png, sha256=9BD15A51ABC4).
Dixon-Price dim=30 - pixel(0,0) = Color [A=255, R=255, G=244, B=0] (PNG: assets/landscape_multidim_dixon_price_d30.png, sha256=F45122818961).
Dixon-Price d2/d5/d30 distincts : d2=65FF2A763B82, d5=9BD15A51ABC4, d30=F45122818961

Exercice 2 : bifurcation de la vallée Dixon-Price

Charger Dixon-Price-d2, tracer les isovaleurs de \(f\) au voisinage de l’optimum \(\vec x^* \approx (1, \pm 1/\sqrt{2})\). Vérifier que la vallée se bifurque pour \(x_1 > 1.5\) (deux branches symétriques) alors qu’elle est unique pour \(x_1 < 0.5\).

La cellule ci-dessous fournit la forme fermée 2-D de \(f\) comme évaluateur direct (PointChromosome est internal au sous-module : DixonPriceFitness.Evaluate n’est pas appelable sur un point libre depuis le notebook). Le quadrillage 200×200 et la localisation des isovaleurs restent à compléter.

// Exercice 2 : bifurcation de la vallee Dixon-Price -- isovaleurs au voisinage
// de l'optimum. Ex2F est la forme fermee 2-D de la section ci-dessus (evaluateur
// direct : PointChromosome est internal au sous-module).
// TODO etudiant : quadriller [-1, 2] x [-1, 2] en 200 x 200 noeuds, evaluer f,
// puis localiser les isovaleurs v = 0.01, 0.1, 1.0, 10.0.
// Indice : pour chaque colonne x1, le minimum sur x2 de |f(x1, x2) - v| dit si
// le niveau v est traverse ; suivre x1 de -1 a 2 pour voir la vallee unique se
// dedoubler en deux branches symetriques.
// Etape 1 : construire la grille 200 x 200 et evaluer f sur chaque noeud.
// Etape 2 : pour chaque isovaleur v, determiner les x2 traversant le niveau.
// Etape 3 : verifier 1 branche pour x1 < 0.5 et 2 branches pour x1 > 1.5.
double Ex2F(double x1, double x2) =>
    (x1 - 1.0) * (x1 - 1.0) + 2.0 * (2.0 * x2 * x2 - x1) * (2.0 * x2 * x2 - x1);
var ex2Isovaleurs = new[] { 0.01, 0.1, 1.0, 10.0 };
// TODO etudiant : boucle 200 x 200 sur [-1, 2] x [-1, 2] avec Ex2F, puis
// localiser chaque isovaleur de ex2Isovaleurs.
display($"Exercice 2 a completer : localiser les isovaleurs {string.Join(", ", ex2Isovaleurs)} de Dixon-Price-d2 sur [-1, 2] x [-1, 2].");
display($"Temoin d'optimum : f(1, 1/sqrt(2)) = {Ex2F(1.0, 1.0 / Math.Sqrt(2.0)):0.######} (la valeur attendue en x* est 0).");
Exercice 2 a completer : localiser les isovaleurs 0,01, 0,1, 1, 10 de Dixon-Price-d2 sur [-1, 2] x [-1, 2].
Temoin d'optimum : f(1, 1/sqrt(2)) = 0 (la valeur attendue en x* est 0).
// Mesure de la structure par canal des six rendus ecrits ci-dessus.
// Les quantites citees par la section « Tell visuel » ci-dessous (variance,
// moyenne et gradient horizontal moyen du canal rouge) sont PRODUITES ici au
// lieu d'etre recopiees dans la prose. Elles sont lues sur les PNG committes --
// donc exactement sur les heatmaps des sections precedentes (graines 42 + dim
// pour Michalewicz, 7 + dim pour Dixon-Price), aucun re-rendu.
using System.Drawing;

var fichiers = new[] {
    ("Michalewicz", "michalewicz",  2), ("Michalewicz", "michalewicz",  5),
    ("Michalewicz", "michalewicz", 30),
    ("Dixon-Price", "dixon_price",  2), ("Dixon-Price", "dixon_price",  5),
    ("Dixon-Price", "dixon_price", 30),
};
var mesures = new List<(string fonction, int dim, double varR, double varG, double varB,
                       double moyR, double moyG, double moyB, double gradR)>();
foreach (var (fonction, slug, dim) in fichiers)
{
    using var img = new Bitmap("assets/landscape_multidim_" + slug + "_d" + dim + ".png");
    double sr = 0, sg = 0, sb = 0, qr = 0, qg = 0, qb = 0, grad = 0;
    long n = 0, paires = 0;
    for (int ligne = 0; ligne < img.Height; ligne++)
    {
        for (int colonne = 0; colonne < img.Width; colonne++)
        {
            var c = img.GetPixel(colonne, ligne);
            sr += c.R; sg += c.G; sb += c.B;
            qr += (double)c.R * c.R; qg += (double)c.G * c.G; qb += (double)c.B * c.B;
            n++;
            // Gradient horizontal : |R(i+1,j) - R(i,j)| sur toutes les paires
            // de colonnes voisines, moyenne sur les lignes.
            if (colonne + 1 < img.Width)
            {
                grad += Math.Abs(img.GetPixel(colonne + 1, ligne).R - c.R);
                paires++;
            }
        }
    }
    double mR = sr / n, mG = sg / n, mB = sb / n;
    mesures.Add((fonction, dim, qr / n - mR * mR, qg / n - mG * mG, qb / n - mB * mB,
                 mR, mG, mB, grad / paires));
}

Console.WriteLine("Structure par canal des six rendus (variance, moyenne, gradient horizontal de R) :");
foreach (var m in mesures)
{
    Console.WriteLine(m.fonction.PadRight(12) + " d" + m.dim.ToString().PadLeft(2)
        + "  var(R)=" + m.varR.ToString("0.0").PadLeft(8)
        + " var(G)=" + m.varG.ToString("0.0").PadLeft(8)
        + " var(B)=" + m.varB.ToString("0.0").PadLeft(8)
        + "  | moy(R)=" + m.moyR.ToString("0.0").PadLeft(6)
        + " moy(G)=" + m.moyG.ToString("0.0").PadLeft(6)
        + " moy(B)=" + m.moyB.ToString("0.0").PadLeft(6)
        + "  | grad(R)=" + m.gradR.ToString("0.00").PadLeft(6));
}
Structure par canal des six rendus (variance, moyenne, gradient horizontal de R) :
Michalewicz  d 2  var(R)=  2101,8 var(G)=   192,4 var(B)=  9603,5  | moy(R)=  15,7 moy(G)= 253,8 moy(B)= 182,9  | grad(R)=  1,89
Michalewicz  d 5  var(R)=  3186,3 var(G)=    71,8 var(B)=  3812,3  | moy(R)=  27,7 moy(G)= 254,3 moy(B)=  60,4  | grad(R)= 26,06
Michalewicz  d30  var(R)=  2742,6 var(G)=    35,7 var(B)=  2148,2  | moy(R)=  30,0 moy(G)= 254,6 moy(B)=  38,5  | grad(R)= 41,52
Dixon-Price  d 2  var(R)=  6671,4 var(G)= 10878,2 var(B)=  1127,1  | moy(R)= 217,0 moy(G)=  97,5 moy(B)=   8,3  | grad(R)=  0,18
Dixon-Price  d 5  var(R)=  6050,4 var(G)=  9961,0 var(B)=   606,0  | moy(R)= 220,0 moy(G)= 102,7 moy(B)=   5,5  | grad(R)=  1,96
Dixon-Price  d30  var(R)=  7212,5 var(G)=   365,5 var(B)=   725,5  | moy(R)= 104,4 moy(G)= 250,8 moy(B)=   9,4  | grad(R)= 96,18

Tell visuel (contrôlé par mesure)

Les 6 heatmaps sont issues du moteur déterministe par pixel (MetaGeneticSharp #49 : graine RNG dérivée de (x, y, base) — l’ordre du Parallel.For n’influence plus le rendu). Chaque dimension garde sa graine propre (Random(42 + dim) pour Michalewicz, Random(7 + dim) pour Dixon-Price), et le contrôle de distinction inséré dans la cellule de rendu (hash des octets écrits, échec si deux dimensions coïncident) empêche la classe d’artefact antérieure (d=2 et d=30 tombés sur le même fichier) de revenir :

fonction dim sha256 (12 hexa)
Michalewicz 2 AAAFF21B944B
Michalewicz 5 5524DBDAF08E
Michalewicz 30 1C2CC62DA9DE
Dixon-Price 2 65FF2A763B82
Dixon-Price 5 9BD15A51ABC4
Dixon-Price 30 F45122818961

Six hexa, six fichiers distincts — plus aucune lecture ne peut « confirmer la stationnarité » en relisant la même image.

Mesure de la structure par canal (variance + gradient horizontal moyen du canal qui porte la structure de chaque fonction) :

fonction dim var(R) var(G) var(B) grad(R)
Michalewicz 2 2101.8 192.4 9603.5 1.9
Michalewicz 5 3186.3 71.8 3812.3 26.1
Michalewicz 30 2742.6 35.7 2148.2 41.5
Dixon-Price 2 6671.4 10878.2 1127.1 0.2
Dixon-Price 5 6050.4 9961.0 606.0 2.0
Dixon-Price 30 7212.5 365.5 725.5 96.2

Lecture corrigée (remplace la conclusion « la structure résiste ») :

  • Michalewicz — la MAX-projection ne lisse pas, elle granule. La 2-D expose des transitions \(m=10\) tranchantes mais rares (var(B)=9603.5 porte les bandes, grad(R)=1.9 faible : les crêtes sont fines). En 30-D, la structure ne s’estompe pas : var(R) monte de d=2 à d=5 (2101.8 → 3186.3) puis redescend en d=30 (2742.6) — non monotone, +30 % au global d=2 → d=30 — grad(R) s’élève d’un ordre de grandeur (1.9 → 26.1 → 41.5), var(B) décroît fortement (-78 % au global d=2 → d=30, 9603.5 → 2148.2) tout comme var(G) (-81 %, 192.4 → 35.7), plus fortement encore. La lecture committée (« la structure s’estompe, d=30 nettement plus uniforme que d=2 ») décrivait les rendus plats de l’état RNG partagé (fichiers committés 3,0-4,5 Ko contre 18-24 Ko pour les rendus déterministes), pas la texture réelle. L’hypothèse du § « Michalewicz en n = 2, 5, 30 » (« quasi-uniforme sombre » en 30-D) est réfutée : le MAX sur 28 dimensions cachées densifie les transitions (grad(R) ×22), il ne les effondre pas.
  • Dixon-Price — la structure 2-D persiste en d=5, puis se décompose en d=30. La 2-D exhibe une structure forte (var(R)=6671, var(G)=10879 : vallée asymétrique). Elle ne chute pas en d=5 : var(R)=6050, var(G)=9961, le profil R+G est quasi inchangé. La décomposition arrive en d=30 : var(G) s’effondre (10878 → 366, canal quasi-uniforme, mean(G)=250.8), tandis que var(R) passe de 6671.4 (d=2) à 6050.4 (d=5) puis remonte à 7212.5 (d=30) — non monotone, +8.1 % au global d=2 → d=30 — avec grad(R) qui explose (0.2 → 96.2) — le couplage cross-dim ne produit pas une heatmap uniforme mais un fond jaune-vert quasi constant (G saturé) parcouru de grains orange-rouge au gradient très élevé (reproductible : double exécution byte-identique). La « légère remontée d5 → d30 » de l’ancienne lecture (644 → 1040) était le bruit d’une image quasi-plate, pas un signal.

Note de méthode : la lecture est ici quantifiée (variance + gradient par canal, le contrôle objectif qui a servi à établir le constat d’artefact). Le récit visuel précédent (« structure quasi-stationnaire », croix verte, contraste avec Rosenbrock/Griewank) était fondé sur une lecture d’images dont deux étaient identiques — il est remplacé par la mesure ci-dessus. Reproductibilité : les valeurs ci-dessus proviennent du moteur déterministe par pixel (MetaGeneticSharp #49) — vérifiées par double exécution A→B (notebook byte-identique, 6/6 PNG md5-stables entre passes). Une re-exécution future doit les retrouver à l’identique.

Exercice 3 : anisotropie du paysage, gradient horizontal vs vertical

Dixon-Price possède une vallée incurvée puis bifurquée (cf. Exercice 2). Une vallée orientée produit un paysage anisotrope : le long de l’axe de la vallée le canal rouge varie peu, perpendiculairement il varie beaucoup. Calculer séparément la moyenne des gradients horizontaux \(|R_{i+1,j}-R_{i,j}|\) et verticaux \(|R_{i,j+1}-R_{i,j}|\) sur la heatmap Dixon-Price-d2, puis former le rapport V/H. Le comparer à Sphere-d2 (fonction isotrope, rapport \(\approx 1\)). Un ratio loin de 1 quantifie l’orientation du paysage, l’information qu’une métaheuristique à covariance adaptative (CMA-ES) exploite pour apprendre la géométrie locale.

La cellule ci-dessous rend les deux heatmaps avec le même moteur déterministe que les sections précédentes (graine 42) — les sommes H et V restent à compléter.

// Exercice 3 : anisotropie du paysage -- gradient horizontal vs vertical.
// TODO etudiant : sur chaque heatmap, sommer separement |R(i+1,j) - R(i,j)|
// (gradient horizontal) et |R(i,j+1) - R(i,j)| (gradient vertical) sur les
// pixels internes, puis former le rapport V/H et remplacer les NaN.
// Indice : les deux heatmaps utilisent le meme moteur deterministe par pixel
// que les rendus des sections precedentes (graine 42, dimensions 2).
// Etape 1 : accumuler les sommes H et V sur les pixels internes de hDP et hSP.
// Etape 2 : former V/H pour Dixon-Price-d2 puis Sphere-d2.
// Etape 3 : interpreter l'ecart a 1 comme l'orientation de la vallee (CMA-ES).
var ex3Stats = new List<(string fn, double gradientH, double gradientV, double ratioVH)>();
{
    // Bloc explicite : en tete de submission .NET Interactive, 'using var' nu serait
    // parse comme using-directive (CS1002) -- cf. cellules 3 et 7 ou le meme
    // 'using var' est legale a l'interieur d'un foreach.
    using var hDP = KnownFunctionLandscape.RenderHeatmap(
        new DixonPriceFitness(), dimension: 2, nbSamples: 50,
        rng: new Random(42), width: 120, height: 120);
    using var hSP = KnownFunctionLandscape.RenderHeatmap(
        new SphereFitness(), dimension: 2, nbSamples: 50,
        rng: new Random(42), width: 120, height: 120);
    // TODO etudiant : parcourir hDP.Bitmap et hSP.Bitmap, remplir ex3Stats.
    ex3Stats.Add(("Dixon-Price", double.NaN, double.NaN, double.NaN)); // a remplacer
    ex3Stats.Add(("Sphere", double.NaN, double.NaN, double.NaN)); // a remplacer
}
display(ex3Stats);
display("Exercice 3 a completer : les NaN attendent les gradients H/V et le rapport V/H de chaque heatmap.");
index value
0
(Dixon-Price, NaN, NaN, NaN)
Item1
Dixon-Price
Item2
NaN
Item3
NaN
Item4
NaN
1
(Sphere, NaN, NaN, NaN)
Item1
Sphere
Item2
NaN
Item3
NaN
Item4
NaN
Exercice 3 a completer : les NaN attendent les gradients H/V et le rapport V/H de chaque heatmap.

Liens

  • MGS-7c RosenbrockGriewank — Rosenbrock + Griewank dim ∈ {2, 5, 30} (c.787 PR #7999).
  • MGS-7b LandscapeMultidim — Ackley dim ∈ {2, 30} (c.785 PR #7993), Rastrigin/Schwefel/Sphere dim ∈ {2, 5, 10, 30} (c.732 PR #7583).
  • MGS-6 Benchmarks — les 10 fonctions canoniques et leur banc CEC d’origine.
  • MGS-8 LandscapeExplorer — exploration interactive GTK#.
  • Issue #7483 — port de la projection N-D (parent).
  • Issue #7997 — [search,#7483-suite] MGS-7c/7d (parent saturé c.732/c.785/c.787/c.788).
  • PR #7583 — port initial MGS-7b N-D.
  • PR #7993 — c.785 MGS-7b Ackley.
  • PR #7999 — c.787 MGS-7c Rosenbrock+Griewank.
  • L785-L2 ★ — inversion chromatique chiffrable d2 → d30 = signature projection MAX.
  • L787-L1 ★ — inversion chromatique chiffrable d2 → d30 PAR FONCTION (Rosenbrock/Griewank vs Ackley).
  • L787-L2 ★ — Griewank d=5 = damier oblique sweet-spot (interférence 5 coords à fréquences \(1/\sqrt{3..5}\)).
Retour au sommet