|
1 | 1 | importer json |
| 2 | +importer math |
2 | 3 | importer random |
3 | 4 | importer dégradés_couleur |
4 | 5 |
|
@@ -676,6 +677,151 @@ def nouvelle_generation(population, scores, taux_mutation_sur_1000, graine): |
676 | 677 | retour nouvelle |
677 | 678 |
|
678 | 679 |
|
| 680 | +def cellule_vivante(valeur, valeur_vide): |
| 681 | + retour str(valeur) != str(valeur_vide) |
| 682 | + |
| 683 | + |
| 684 | +def calculer_densite_ligne(ligne, valeur_vide): |
| 685 | + si len(ligne) == 0: |
| 686 | + retour 0.0 |
| 687 | + soit vivantes = [valeur pour valeur dans ligne si cellule_vivante(valeur, valeur_vide)] |
| 688 | + retour len(vivantes) / len(ligne) |
| 689 | + |
| 690 | + |
| 691 | +def calculer_symetrie_ligne(ligne): |
| 692 | + si len(ligne) <= 1: |
| 693 | + retour 1.0 |
| 694 | + soit accords = 0 |
| 695 | + soit paires = len(ligne) // 2 |
| 696 | + pour indice dans range(paires): |
| 697 | + si str(ligne[indice]) == str(ligne[len(ligne) - 1 - indice]): |
| 698 | + accords = accords + 1 |
| 699 | + retour accords / paires si paires > 0 sinon 1.0 |
| 700 | + |
| 701 | + |
| 702 | +def calculer_compacite_ligne(ligne, valeur_vide): |
| 703 | + soit indices_vivants = [indice pour indice dans range(len(ligne)) si cellule_vivante(ligne[indice], valeur_vide)] |
| 704 | + si len(indices_vivants) == 0: |
| 705 | + retour 0.0 |
| 706 | + soit debut = indices_vivants[0] |
| 707 | + soit fin = indices_vivants[len(indices_vivants) - 1] |
| 708 | + retour len(indices_vivants) / max(1, fin - debut + 1) |
| 709 | + |
| 710 | + |
| 711 | +def metriques_univers(univers): |
| 712 | + soit lignes = univers.get("lignes", []) |
| 713 | + soit configuration = univers.get("configuration", {}) |
| 714 | + soit valeur_vide = configuration.get("alphabet_entree", [0])[0] |
| 715 | + si len(lignes) == 0: |
| 716 | + retour { |
| 717 | + "entropie": 0.0, |
| 718 | + "compacite": 0.0, |
| 719 | + "symetrie": 0.5, |
| 720 | + "tauxCroissance": 0.0, |
| 721 | + "densite": 0.0, |
| 722 | + "oscillation": 0.0, |
| 723 | + "complexite": 0.0, |
| 724 | + "varianceDensite": 0.0, |
| 725 | + "periodeDetectee": 0, |
| 726 | + } |
| 727 | + |
| 728 | + soit densites = [calculer_densite_ligne(ligne, valeur_vide) pour ligne dans lignes] |
| 729 | + soit compacites = [calculer_compacite_ligne(ligne, valeur_vide) pour ligne dans lignes] |
| 730 | + soit symetries = [calculer_symetrie_ligne(ligne) pour ligne dans lignes] |
| 731 | + soit toutes_valeurs = [] |
| 732 | + pour ligne dans lignes: |
| 733 | + pour valeur dans ligne: |
| 734 | + toutes_valeurs.append(str(valeur)) |
| 735 | + |
| 736 | + soit comptes = {} |
| 737 | + pour cle_valeur dans toutes_valeurs: |
| 738 | + comptes[cle_valeur] = comptes.get(cle_valeur, 0) + 1 |
| 739 | + |
| 740 | + soit total = max(1, len(toutes_valeurs)) |
| 741 | + soit entropie = 0.0 |
| 742 | + pour cle_compte dans comptes: |
| 743 | + soit probabilite = comptes[cle_compte] / total |
| 744 | + si probabilite > 0: |
| 745 | + entropie = entropie - (probabilite * math.log2(probabilite)) |
| 746 | + |
| 747 | + soit densite = sum(densites) / len(densites) |
| 748 | + soit compacite = sum(compacites) / len(compacites) |
| 749 | + soit symetrie = sum(symetries) / len(symetries) |
| 750 | + soit tranche = max(1, len(densites) // 5) |
| 751 | + soit densite_debut = sum(densites[:tranche]) / tranche |
| 752 | + soit densite_fin = sum(densites[-tranche:]) / tranche |
| 753 | + soit taux_croissance = max(-1.0, min(1.0, densite_fin - densite_debut)) |
| 754 | + soit variance = max(0.0, min(1.0, variance_densite(densites) * 4.0)) |
| 755 | + soit periode = detecter_periode(densites, min(24, len(densites))) |
| 756 | + soit score_variance = 1.0 - min(1.0, abs(variance - 0.5) * 2.0) |
| 757 | + soit score_periode = 1.0 si periode > 0 sinon 0.0 |
| 758 | + soit oscillation = max(0.0, min(1.0, (score_variance * 0.7) + (score_periode * 0.3))) |
| 759 | + soit complexite = max(0.0, min(1.0, entropie * (1.0 - compacite))) |
| 760 | + |
| 761 | + retour { |
| 762 | + "entropie": entropie, |
| 763 | + "compacite": compacite, |
| 764 | + "symetrie": symetrie, |
| 765 | + "tauxCroissance": taux_croissance, |
| 766 | + "densite": densite, |
| 767 | + "oscillation": oscillation, |
| 768 | + "complexite": complexite, |
| 769 | + "varianceDensite": variance, |
| 770 | + "periodeDetectee": periode, |
| 771 | + } |
| 772 | + |
| 773 | + |
| 774 | +def evaluer_fitness(univers, poids_obj={}): |
| 775 | + soit metriques = metriques_univers(univers) |
| 776 | + soit poids = [ |
| 777 | + poids_obj.get("symetrie", 5), |
| 778 | + poids_obj.get("densite", 5), |
| 779 | + poids_obj.get("stabilite", 5), |
| 780 | + poids_obj.get("oscillation", 5), |
| 781 | + poids_obj.get("complexite", 5), |
| 782 | + poids_obj.get("croissance", 5), |
| 783 | + ] |
| 784 | + soit f_sym = metriques["symetrie"] |
| 785 | + soit f_den = 0.8 si abs(metriques["densite"] - 0.45) < 0.2 sinon 0.2 |
| 786 | + soit f_sta = ((1.0 - abs(metriques["tauxCroissance"])) * 0.5) + (metriques["compacite"] * 0.5) |
| 787 | + soit f_cmp = metriques["complexite"] |
| 788 | + soit f_cro = max(0.0, metriques["tauxCroissance"]) |
| 789 | + soit total_poids = max(1, sum(poids)) |
| 790 | + soit score = ((f_sym * poids[0]) + (f_den * poids[1]) + (f_sta * poids[2]) + (metriques["oscillation"] * poids[3]) + (f_cmp * poids[4]) + (f_cro * poids[5])) / total_poids |
| 791 | + soit score_borne = max(0.0, min(1.0, score)) |
| 792 | + soit configuration = univers.get("configuration", {}) |
| 793 | + soit canaux = max(1, int(configuration.get("nombre_canaux_sortie", 1))) |
| 794 | + soit scores_par_canal = [score_borne pour _ dans range(canaux)] |
| 795 | + retour { |
| 796 | + "score": score_borne, |
| 797 | + "metriques": { |
| 798 | + "entropie": metriques["entropie"], |
| 799 | + "densite": metriques["densite"], |
| 800 | + "compacite": metriques["compacite"], |
| 801 | + "symetrie": metriques["symetrie"], |
| 802 | + "oscillation": metriques["oscillation"], |
| 803 | + "complexite": metriques["complexite"], |
| 804 | + "croissance": max(0.0, metriques["tauxCroissance"]), |
| 805 | + "tauxCroissance": metriques["tauxCroissance"], |
| 806 | + "scores_par_canal": scores_par_canal, |
| 807 | + }, |
| 808 | + } |
| 809 | + |
| 810 | + |
| 811 | +def evaluer_population(population, poids_obj={}): |
| 812 | + soit evaluations = [] |
| 813 | + pour config dans population: |
| 814 | + soit univers = generer_univers_detaille(config) |
| 815 | + soit evaluation = evaluer_fitness(univers, poids_obj) |
| 816 | + evaluations.append({ |
| 817 | + "config": config, |
| 818 | + "univers": univers, |
| 819 | + "score": evaluation["score"], |
| 820 | + "metriques": evaluation["metriques"], |
| 821 | + }) |
| 822 | + retour evaluations |
| 823 | + |
| 824 | + |
679 | 825 | # ============================================================================ |
680 | 826 | # FONCTIONS DE FITNESS: Scoring criteria for genetic evolution |
681 | 827 | # ============================================================================ |
|
0 commit comments