Skip to content

Commit 491ddd0

Browse files
Update GA algorithm
1 parent 7816e03 commit 491ddd0

1 file changed

Lines changed: 121 additions & 23 deletions

File tree

public/automate-core.js

Lines changed: 121 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -436,19 +436,15 @@ function nouvelleGeneration(population, scores, tauxMutationSur1000, graine) {
436436
}
437437

438438
function evaluerFitness(univers, poidsObj) {
439-
// Computes metrics from univers and returns weighted fitness score
440-
const lignes = univers && univers.lignes ? univers.lignes : [];
441-
const totalCells = lignes.length > 0 ? lignes[0].length : 1;
442-
const liveCells = lignes.flat().filter((v) => v !== 0).length;
443-
444-
const densite = totalCells > 0 ? liveCells / totalCells : 0;
445-
const entropie = densite > 0 && densite < 1 ? -(densite * Math.log2(densite) + (1 - densite) * Math.log2(1 - densite)) : 0;
446-
const compacite = liveCells > 0 ? Math.sqrt(liveCells) / (liveCells + 1) : 0;
447-
448-
// Placeholder values for oscillation (would require historical data)
449-
const oscillation = 0;
450-
const complexite = Math.max(0, entropie * (1 - compacite));
451-
const croissance = 0; // Would need frame history
439+
const {
440+
entropie,
441+
densite,
442+
compacite,
443+
symetrie,
444+
oscillation,
445+
complexite,
446+
tauxCroissance,
447+
} = metriquesUnivers(univers);
452448

453449
const poids = [
454450
poidsObj.symetrie || 5,
@@ -459,12 +455,12 @@ function evaluerFitness(univers, poidsObj) {
459455
poidsObj.croissance || 5,
460456
];
461457

462-
const fSym = callPacked("fitness_symetrie_scalaire", [0.5], 0.5);
458+
const fSym = callPacked("fitness_symetrie_scalaire", [symetrie], symetrie);
463459
const fDen = callPacked("fitness_densite_scalaire", [densite, 0.45], Math.abs(densite - 0.45) < 0.2 ? 0.8 : 0.2);
464-
const fSta = callPacked("fitness_stabilite_scalaire", [0, compacite], compacite * 0.5);
460+
const fSta = callPacked("fitness_stabilite_scalaire", [Math.abs(tauxCroissance), compacite], ((1 - Math.abs(tauxCroissance)) * 0.5) + (compacite * 0.5));
465461
const fOsc = oscillation;
466462
const fCmp = callPacked("fitness_complexite_scalaire", [entropie, compacite], complexite);
467-
const fCro = croissance;
463+
const fCro = callPacked("fitness_croissance_scalaire", [Math.max(0, tauxCroissance)], Math.max(0, tauxCroissance));
468464

469465
const score = callPacked("fitness_ponderee_scalaire",
470466
[fSym, fDen, fSta, fOsc, fCmp, fCro, ...poids],
@@ -474,7 +470,16 @@ function evaluerFitness(univers, poidsObj) {
474470

475471
return {
476472
score: Math.max(0, Math.min(1, score)),
477-
metriques: { entropie, densite, compacite, oscillation, complexite, croissance },
473+
metriques: {
474+
entropie,
475+
densite,
476+
compacite,
477+
symetrie,
478+
oscillation,
479+
complexite,
480+
croissance: Math.max(0, tauxCroissance),
481+
tauxCroissance,
482+
},
478483
};
479484
}
480485

@@ -595,16 +600,109 @@ function calculerCentreDesMasse(ligne) {
595600
return vivants.reduce((a, b) => a + b, 0) / vivants.length;
596601
}
597602

603+
function clamp01(value) {
604+
return Math.max(0, Math.min(1, value));
605+
}
606+
607+
function celluleVivante(value, valeurVide) {
608+
return String(value) !== String(valeurVide);
609+
}
610+
611+
function calculerDensiteLigne(ligne, valeurVide) {
612+
if (!ligne || ligne.length === 0) return 0;
613+
const actives = ligne.filter((value) => celluleVivante(value, valeurVide)).length;
614+
return actives / ligne.length;
615+
}
616+
617+
function calculerSymetrieLigne(ligne) {
618+
if (!ligne || ligne.length <= 1) return 1;
619+
let accords = 0;
620+
const paires = Math.floor(ligne.length / 2);
621+
for (let i = 0; i < paires; i += 1) {
622+
if (String(ligne[i]) === String(ligne[ligne.length - 1 - i])) accords += 1;
623+
}
624+
return paires > 0 ? accords / paires : 1;
625+
}
626+
627+
function calculerCompaciteLigne(ligne, valeurVide) {
628+
if (!ligne || ligne.length === 0) return 0;
629+
const indicesVivants = ligne
630+
.map((value, index) => (celluleVivante(value, valeurVide) ? index : -1))
631+
.filter((index) => index >= 0);
632+
if (indicesVivants.length === 0) return 0;
633+
const debut = indicesVivants[0];
634+
const fin = indicesVivants[indicesVivants.length - 1];
635+
const etendue = Math.max(1, fin - debut + 1);
636+
return indicesVivants.length / etendue;
637+
}
638+
639+
function varianceDensite(historiqueDensites) {
640+
if (!historiqueDensites || historiqueDensites.length < 2) return 0;
641+
const moyenne = historiqueDensites.reduce((sum, value) => sum + value, 0) / historiqueDensites.length;
642+
const sommeCarres = historiqueDensites.reduce((sum, value) => sum + ((value - moyenne) ** 2), 0);
643+
return Math.sqrt(sommeCarres / historiqueDensites.length);
644+
}
645+
646+
function detecterPeriode(historiqueDensites, fenetre) {
647+
if (!historiqueDensites || historiqueDensites.length < fenetre || fenetre < 2) return 0;
648+
const derniers = historiqueDensites.slice(-fenetre);
649+
for (let periode = 1; periode <= Math.floor(fenetre / 2); periode += 1) {
650+
let correlation = 0;
651+
let compte = 0;
652+
for (let i = 0; i < derniers.length - periode; i += 1) {
653+
correlation += Math.abs(derniers[i] - derniers[i + periode]);
654+
compte += 1;
655+
}
656+
const correlationMoyenne = compte > 0 ? correlation / compte : 0;
657+
if (correlationMoyenne < 0.1) return periode;
658+
}
659+
return 0;
660+
}
661+
598662
function metriquesUnivers(univers) {
599663
const lignes = univers && univers.lignes ? univers.lignes : [];
600-
const totalCells = lignes.length > 0 ? lignes[0].length : 1;
601-
const liveCells = lignes.flat().filter((v) => v !== 0).length;
664+
const configuration = univers && univers.configuration ? univers.configuration : {};
665+
const valeurVide = configuration.alphabet_entree ? configuration.alphabet_entree[0] : 0;
666+
const totalCells = lignes.reduce((sum, ligne) => sum + ligne.length, 0);
667+
const liveCells = lignes.flat().filter((value) => celluleVivante(value, valeurVide)).length;
602668
const densite = totalCells > 0 ? liveCells / totalCells : 0;
603669
const entropie = densite > 0 && densite < 1 ? -(densite * Math.log2(densite) + (1 - densite) * Math.log2(1 - densite)) : 0;
604-
const compacite = liveCells > 0 ? Math.sqrt(liveCells) / (liveCells + 1) : 0;
605-
const symetrie = 0.5; // Placeholder
606-
const tauxCroissance = 0; // Placeholder
607-
return { entropie, compacite, symetrie, tauxCroissance, densite };
670+
671+
const densitesParGeneration = lignes.map((ligne) => calculerDensiteLigne(ligne, valeurVide));
672+
const compacites = lignes.map((ligne) => calculerCompaciteLigne(ligne, valeurVide));
673+
const symetries = lignes.map((ligne) => calculerSymetrieLigne(ligne));
674+
675+
const compacite = compacites.length > 0
676+
? compacites.reduce((sum, value) => sum + value, 0) / compacites.length
677+
: 0;
678+
const symetrie = symetries.length > 0
679+
? symetries.reduce((sum, value) => sum + value, 0) / symetries.length
680+
: 0.5;
681+
682+
const tranche = Math.max(1, Math.floor(densitesParGeneration.length / 5));
683+
const densiteDebut = densitesParGeneration.slice(0, tranche).reduce((sum, value) => sum + value, 0) / tranche;
684+
const densiteFin = densitesParGeneration.slice(-tranche).reduce((sum, value) => sum + value, 0) / tranche;
685+
const tauxCroissance = Math.max(-1, Math.min(1, densiteFin - densiteDebut));
686+
687+
const variance = clamp01(varianceDensite(densitesParGeneration) * 4);
688+
const fenetre = Math.min(24, densitesParGeneration.length);
689+
const periodeDetectee = detecterPeriode(densitesParGeneration, fenetre);
690+
const scoreVariance = 1 - Math.min(1, Math.abs(variance - 0.5) * 2);
691+
const scorePeriode = periodeDetectee > 0 ? 1 : 0;
692+
const oscillation = clamp01((scoreVariance * 0.7) + (scorePeriode * 0.3));
693+
const complexite = clamp01(entropie * (1 - compacite));
694+
695+
return {
696+
entropie,
697+
compacite,
698+
symetrie,
699+
tauxCroissance,
700+
densite,
701+
oscillation,
702+
complexite,
703+
varianceDensite: variance,
704+
periodeDetectee,
705+
};
608706
}
609707

610708
window.AutomaginariumCore = {

0 commit comments

Comments
 (0)