@@ -45,6 +45,103 @@ def normaliser_configuration(configuration):
4545 }
4646
4747
48+ def parser_symbole(brut):
49+ soit texte = str(brut).strip()
50+ si texte == " " :
51+ retour None
52+ essayer:
53+ soit numerique = float (texte)
54+ si numerique.is_integer() :
55+ soit entier = int (numerique)
56+ si str(entier) == texte:
57+ retour entier
58+ sauf:
59+ rien
60+ retour texte
61+
62+
63+ def parser_liste_virgules(valeur, repli):
64+ soit elements = [parser_symbole(fragment) pour fragment dans str(valeur).split(" ," )]
65+ soit filtres = [element pour element dans elements si element is not None ]
66+ retour filtres si len(filtres) > 0 sinon repli
67+
68+
69+ def encoder_liste(valeurs):
70+ retour " ," .join([str(valeur) pour valeur dans (valeurs ou [] )])
71+
72+
73+ def etat_formulaire_vers_configuration(etat_formulaire, configuration_courante= None ):
74+ si configuration_courante is None :
75+ configuration_courante = {}
76+ soit alphabet_entree = parser_liste_virgules(etat_formulaire.get(" alphabetInput" , " " ), [0 , 1 ])
77+ soit alphabet_sortie = parser_liste_virgules(etat_formulaire.get(" alphabetOutput" , " " ), alphabet_entree)
78+ soit voisinage = int (etat_formulaire.get(" neighborhood" , 3 ))
79+ si voisinage % 2 == 0 :
80+ voisinage = voisinage + 1
81+ soit mode_initial = etat_formulaire.get(" initialMode" , " centre" )
82+ soit configuration = dict(configuration_courante)
83+ configuration[" nom" ] = str(etat_formulaire.get(" name" , " " )).strip() or " Univers sans nom"
84+ configuration[" alphabet_entree" ] = alphabet_entree
85+ configuration[" alphabet_sortie" ] = alphabet_sortie
86+ configuration[" taille_voisinage" ] = max(1 , voisinage)
87+ configuration[" nombre_canaux_sortie" ] = max(1 , int (etat_formulaire.get(" channels" , 1 )))
88+ configuration[" largeur" ] = max(1 , int (etat_formulaire.get(" width" , 161 )))
89+ configuration[" hauteur" ] = max(1 , int (etat_formulaire.get(" height" , 100 )))
90+ configuration[" frontiere" ] = etat_formulaire.get(" boundary" , " fixe" )
91+ configuration[" mode_regle" ] = etat_formulaire.get(" ruleMode" , " table" )
92+ configuration[" numero_regle" ] = etat_formulaire.get(" ruleNumber" , " 0" )
93+ configuration[" etat_initial" ] = {" mode" : mode_initial}
94+ soit rendu = dict(configuration_courante.get(" rendu" , {}))
95+ rendu[" taille_cellule" ] = max(1 , int (etat_formulaire.get(" cellSize" , 5 )))
96+ configuration[" rendu" ] = rendu
97+
98+ si mode_initial == " motif" :
99+ configuration[" etat_initial" ][" valeurs" ] = parser_liste_virgules(
100+ etat_formulaire.get(" initialValues" , " " ),
101+ [alphabet_sortie[1 ] si len(alphabet_sortie) > 1 sinon alphabet_sortie[0 ]],
102+ )
103+ si mode_initial == " aleatoire" :
104+ configuration[" etat_initial" ][" graine" ] = configuration_courante.get(" etat_initial" , {}).get(" graine" , 42 )
105+ configuration[" etat_initial" ][" probabilite" ] = max(
106+ 0.0 ,
107+ min(1.0 , float (etat_formulaire.get(" initialProbability" , 0.28 ))),
108+ )
109+
110+ soit alphabet_change = False
111+ si " alphabet_entree" dans configuration_courante:
112+ si len(configuration_courante[" alphabet_entree" ]) != len(alphabet_entree):
113+ alphabet_change = True
114+ si configuration_courante.get(" taille_voisinage" ) != voisinage:
115+ alphabet_change = True
116+ si configuration_courante.get(" nombre_canaux_sortie" ) != configuration[" nombre_canaux_sortie" ]:
117+ alphabet_change = True
118+ si alphabet_change:
119+ configuration[" table_transition" ] = {}
120+ si " table_transition" non dans configuration:
121+ configuration[" table_transition" ] = {}
122+ retour configuration
123+
124+
125+ def configuration_vers_etat_formulaire(configuration):
126+ soit config = normaliser_configuration(configuration)
127+ retour {
128+ " name" : config[" nom" ],
129+ " alphabetInput" : encoder_liste(config[" alphabet_entree" ]),
130+ " alphabetOutput" : encoder_liste(config[" alphabet_sortie" ]),
131+ " neighborhood" : str(config[" taille_voisinage" ]),
132+ " channels" : str(config[" nombre_canaux_sortie" ]),
133+ " width" : str(config[" largeur" ]),
134+ " height" : str(config[" hauteur" ]),
135+ " boundary" : config[" frontiere" ],
136+ " initialMode" : config.get(" etat_initial" , {}).get(" mode" , " centre" ),
137+ " initialValues" : encoder_liste(config.get(" etat_initial" , {}).get(" valeurs" , [] )),
138+ " initialProbability" : str(config.get(" etat_initial" , {}).get(" probabilite" , 0.28 )),
139+ " cellSize" : str(config.get(" rendu" , {}).get(" taille_cellule" , 5 )),
140+ " ruleMode" : config[" mode_regle" ],
141+ " ruleNumber" : str(config.get(" numero_regle" , 0 )),
142+ }
143+
144+
48145def cle_voisinage(voisinage):
49146 retour json.dumps(voisinage).replace(" , " , " ," )
50147
@@ -189,6 +286,57 @@ def table_symetrique(configuration, graine=42):
189286 retour table
190287
191288
289+ def assurer_configuration_rendable(configuration):
290+ soit config = normaliser_configuration(configuration)
291+ si len(config.get(" table_transition" , {})) == 0 :
292+ soit cles = toutes_cles_voisinage(config[" alphabet_entree" ], config[" taille_voisinage" ])
293+ config[" table_transition" ] = {}
294+ pour cle dans cles[: min(5 , len(cles))]:
295+ config[" table_transition" ][cle] = [config[" alphabet_sortie" ][0 ]]
296+ retour config
297+
298+
299+ def construire_configuration_regle_generee(configuration, generateur, regle_wolfram):
300+ soit config = normaliser_configuration(configuration)
301+ soit generateur_effectif = generateur
302+ soit binaire = False
303+ si len(config[" alphabet_entree" ]) == 2 :
304+ si str(config[" alphabet_entree" ][0 ]) == " 0" :
305+ si str(config[" alphabet_entree" ][1 ]) == " 1" :
306+ binaire = True
307+ soit wolfram_invalide = False
308+ si config[" taille_voisinage" ] != 3 :
309+ wolfram_invalide = True
310+ si non binaire:
311+ wolfram_invalide = True
312+ si config[" nombre_canaux_sortie" ] != 1 :
313+ wolfram_invalide = True
314+ si generateur_effectif == " wolfram" et wolfram_invalide:
315+ generateur_effectif = " random"
316+
317+ si generateur_effectif == " wolfram" :
318+ config[" alphabet_entree" ] = [0 , 1 ]
319+ config[" alphabet_sortie" ] = [0 , 1 ]
320+ config[" taille_voisinage" ] = 3
321+ config[" nombre_canaux_sortie" ] = 1
322+ config[" mode_regle" ] = " table"
323+ config[" table_transition" ] = table_wolfram(int (regle_wolfram))
324+ si generateur_effectif == " random" :
325+ config[" mode_regle" ] = " table"
326+ config[" table_transition" ] = table_aleatoire(config)
327+ si generateur_effectif == " symmetric" :
328+ config[" mode_regle" ] = " table"
329+ config[" table_transition" ] = table_symetrique(config)
330+ si generateur_effectif == " totalistic" :
331+ config[" mode_regle" ] = " totalistique"
332+ config[" table_transition" ] = table_totalistique(config)
333+
334+ retour {
335+ " config" : config,
336+ " effectiveGenerator" : generateur_effectif,
337+ }
338+
339+
192340def valider_configuration(configuration):
193341 soit config = normaliser_configuration(configuration)
194342 soit erreurs = []
@@ -337,6 +485,12 @@ def configuration_regle(configuration):
337485 }
338486
339487
488+ def etiquette_espace_regles(configuration):
489+ soit spec = configuration_regle(normaliser_configuration(configuration))
490+ soit max_regle = spec[" base" ] ** spec[" chiffres" ]
491+ retour str(spec[" t" ]) + " ^(" + str(spec[" m" ]) + " ·" + str(spec[" s" ]) + " ^" + str(spec[" k" ]) + " ) = " + str(max_regle) + " regles possibles"
492+
493+
340494def voisinage_vers_index(voisinage, alphabet):
341495 soit s = len(alphabet)
342496 soit index = 0
@@ -582,6 +736,80 @@ def preset_fitness_oscillant():
582736 retour [4 , 5 , 3 , 9 , 5 , 1 ]
583737
584738
739+ def etiquette_regle_hud(etat_regle):
740+ soit voisinage = int (etat_regle.get(" neighborhood" , 3 ))
741+ soit canaux = int (etat_regle.get(" channels" , 1 ))
742+ soit mode_regle = etat_regle.get(" ruleMode" , " table" )
743+ soit regle_wolfram = etat_regle.get(" wolframRule" , " 90" )
744+ si mode_regle == " totalistique" :
745+ retour " Tot(" + str(voisinage) + " )"
746+ si mode_regle == " aleatoire" :
747+ retour " Alea(" + str(voisinage) + " )"
748+ si mode_regle == " numerique" :
749+ retour " R" + str(voisinage) + " x" + str(canaux)
750+ si mode_regle == " table" :
751+ retour " T" + str(voisinage) + " x" + str(canaux)
752+ retour str(regle_wolfram)
753+
754+
755+ def resumer_configuration(configuration):
756+ soit config = normaliser_configuration(configuration)
757+ soit resume = str(config[" largeur" ]) + " x " + str(config[" hauteur" ]) + " cellules, "
758+ resume = resume + str(len(config[" alphabet_sortie" ])) + " etat(s) visibles, voisinage "
759+ resume = resume + str(config[" taille_voisinage" ]) + " , depart "
760+ resume = resume + str(config.get(" etat_initial" , {}).get(" mode" , " centre" ))
761+ retour resume
762+
763+
764+ def resumer_transition(configuration):
765+ soit config = normaliser_configuration(configuration)
766+ soit entrees = list (config.get(" table_transition" , {}).items() )
767+ si config[" mode_regle" ] == " totalistique" :
768+ retour " Mode totalistique avec " + str(len(config[" alphabet_sortie" ])) + " etat(s) de sortie."
769+ si len(entrees) == 0 :
770+ retour " Mode " + str(config[" mode_regle" ]) + " pilote par le noyau sans table explicite."
771+ retour str(len(entrees)) + " transition(s) actives dans la table en cours."
772+
773+
774+ def decrire_configuration(configuration):
775+ soit config = normaliser_configuration(configuration)
776+ soit entrees = list (config.get(" table_transition" , {}).items() )[:24 ]
777+ soit html = " <span><b>" + str(config[" mode_regle" ]) + " </b> -> genere par le noyau</span>"
778+ si len(entrees) > 0 :
779+ html = " " .join([" <span><b>" + cle + " </b> -> " + json.dumps(valeur) + " </span>" pour cle, valeur dans entrees])
780+ soit meta = str(len(config[" alphabet_entree" ])) + " symbole(s) entree | "
781+ meta = meta + str(len(config[" alphabet_sortie" ])) + " sortie | voisinage "
782+ meta = meta + str(config[" taille_voisinage" ]) + " | "
783+ meta = meta + str(config[" nombre_canaux_sortie" ]) + " canal(aux) | "
784+ meta = meta + str(config[" mode_regle" ])
785+ retour {
786+ " title" : config[" nom" ],
787+ " metaText" : meta,
788+ " ruleTableHtml" : html,
789+ }
790+
791+
792+ def signaux_transition(configuration, limite= 6 ):
793+ soit config = normaliser_configuration(configuration)
794+ soit entrees = list (config.get(" table_transition" , {}).items() )[:limite]
795+ si len(entrees) == 0 :
796+ retour [{
797+ " label" : config[" mode_regle" ],
798+ " title" : " Noyau dynamique" ,
799+ " body" : " Les sorties sont derivees sans table visible." ,
800+ }]
801+ soit signaux = []
802+ pour indice in range(len(entrees)):
803+ soit cle = entrees[indice][0 ]
804+ soit valeur = entrees[indice][1 ]
805+ signaux.append({
806+ " label" : " Transition " + str(indice + 1 ),
807+ " title" : cle,
808+ " body" : json.dumps(valeur),
809+ })
810+ retour signaux
811+
812+
585813# ============================================================================
586814# PERTURBATION : Interactive event injection into cellular automata
587815# ============================================================================
0 commit comments