tnfr 1.0__py3-none-any.whl → 2.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tnfr might be problematic. Click here for more details.

tnfr/matrix/operators.py DELETED
@@ -1,500 +0,0 @@
1
- import random
2
-
3
- def aplicar_glifo(G, nodo, nodo_id, nombre_glifo, historial_glifos_por_nodo, paso):
4
- nodo["glifo"] = nombre_glifo
5
- nodo["estado"] = "silencio" if nombre_glifo == "SHA" else "activo"
6
-
7
- # Preservar valor anterior de θ para detección de mutaciones
8
- if "θ_prev" not in nodo:
9
- nodo["θ_prev"] = nodo.get("θ", 0)
10
- else:
11
- nodo["θ_prev"] = nodo.get("θ", nodo["θ_prev"])
12
-
13
- # Registro en historial global
14
- if historial_glifos_por_nodo is not None and paso is not None:
15
- historial_glifos_por_nodo.setdefault(nodo_id, []).append((paso, nombre_glifo))
16
-
17
- # Registro en historial local (para EPIs compuestas)
18
- if paso is not None:
19
- if "historial_glifos" not in nodo:
20
- nodo["historial_glifos"] = []
21
- nodo["historial_glifos"].append((paso, nombre_glifo))
22
-
23
- # === Transformaciones estructurales por glifo TNFR ===
24
-
25
- if nombre_glifo == "AL": # Emisión
26
- nodo["EPI"] += 0.2
27
- nodo["Si"] += 0.05
28
- nodo["νf"] *= 1.05
29
- nodo["ΔNFR"] *= 0.97
30
-
31
- elif nombre_glifo == "EN": # Recepción
32
- nodo["Si"] += 0.08
33
- nodo["νf"] *= 0.95
34
- nodo["θ"] = max(0.0, nodo["θ"] - random.uniform(0.05, 0.15))
35
-
36
- elif nombre_glifo == "IL": # Coherencia
37
- nodo["Si"] += 0.1
38
- nodo["EPI"] *= 1.05
39
- nodo["ΔNFR"] *= 0.95
40
-
41
- elif nombre_glifo == "OZ": # Disonancia
42
- nodo["EPI"] *= 0.85
43
- nodo["ΔNFR"] *= 1.4
44
- nodo["νf"] *= 1.05
45
- nodo["Si"] *= 0.9
46
-
47
- elif nombre_glifo == "UM": # Acoplamiento
48
- vecinos = list(G.neighbors(nodo_id))
49
- if vecinos:
50
- media_vf = sum(G.nodes[v]["νf"] for v in vecinos) / len(vecinos)
51
- nodo["νf"] = (nodo["νf"] + media_vf) * 0.5
52
- nodo["ΔNFR"] *= 0.9
53
-
54
- elif nombre_glifo == "RA": # Resonancia
55
- nodo["Si"] += 0.15
56
- nodo["EPI"] *= 1.05
57
- nodo["νf"] *= 1.02
58
-
59
- elif nombre_glifo == "SHA": # Silencio
60
- nodo["estado"] = "silencio"
61
- nodo["νf"] *= 0.3
62
- nodo["ΔNFR"] *= 0.1
63
- nodo["Si"] *= 0.5
64
- nodo["EPI"] *= 0.9
65
-
66
- elif nombre_glifo == "VAL": # Expansión
67
- nodo["EPI"] *= 1.15
68
- nodo["Si"] *= 1.08
69
- nodo["νf"] *= 1.05
70
- nodo["EPI"] = min(nodo["EPI"], 3.0) # Límite fijo mientras umbrales no esté disponible
71
-
72
- elif nombre_glifo == "NUL": # Contracción
73
- nodo["EPI"] *= 0.82
74
- nodo["Si"] *= 0.92
75
- nodo["νf"] *= 0.92
76
-
77
- elif nombre_glifo == "THOL": # Autoorganización
78
- nodo["νf"] *= 1.25
79
- nodo["Si"] *= 1.15
80
- nodo["θ"] = min(1.0, nodo["θ"] + random.uniform(0.1, 0.2))
81
-
82
- elif nombre_glifo == "ZHIR": # Mutación
83
- nodo["EPI"] += 0.5
84
- nodo["νf"] *= 1.2
85
- nodo["θ"] = min(1.0, nodo["θ"] + random.uniform(0.15, 0.3))
86
- nodo["Si"] *= 1.1
87
-
88
- elif nombre_glifo == "NAV": # Nacimiento
89
- nodo["νf"] *= 1.08
90
- nodo["ΔNFR"] *= 0.9
91
- nodo["Si"] += 0.1
92
- if nodo["estado"] == "silencio":
93
- nodo["estado"] = "activo"
94
-
95
- elif nombre_glifo == "REMESH": # Recursividad
96
- nodo["EPI"] = (nodo.get("EPI_prev", nodo["EPI"]) + nodo.get("EPI_prev2", nodo["EPI"])) / 2
97
- nodo["Si"] *= 0.98
98
- nodo["νf"] *= 0.98
99
-
100
- def evaluar_patron_glifico(glifos):
101
- patron = " → ".join(glifos)
102
-
103
- analisis = {
104
- "ciclos_REMESH": glifos.count("REMESH"),
105
- "uso_THOL": glifos.count("THOL"),
106
- "uso_ZHIR": glifos.count("ZHIR"),
107
- "latencia_prolongada": any(
108
- glifos[i] == "SHA" and glifos[i+1] == "SHA"
109
- for i in range(len(glifos) - 1)
110
- ),
111
- "inicio_creativo": glifos[0] == "AL" if glifos else False,
112
- "coherencia_expansiva": "IL" in glifos and "VAL" in glifos,
113
- "disonancia_sostenida": any(
114
- glifos[i] == "OZ" and glifos[i+1] == "OZ"
115
- for i in range(len(glifos) - 1)
116
- ),
117
- "patron_glifico": patron,
118
- "tipo_nodal": (
119
- "creador" if glifos and glifos[0] == "AL" else
120
- "mutante" if "ZHIR" in glifos else
121
- "colapsante" if glifos.count("REMESH") > 2 else
122
- "expansivo" if "VAL" in glifos else
123
- "latente"
124
- )
125
- }
126
-
127
- return analisis
128
-
129
- def glifo_por_estructura(nodo, G):
130
- n_id = nodo.get("nodo", None)
131
- vecinos = list(G.neighbors(n_id)) if n_id else []
132
-
133
- # 1. SHA – Silencio ante alta disonancia
134
- if nodo["EPI"] < 0.5 and abs(nodo["ΔNFR"]) > 0.8:
135
- return "SHA"
136
-
137
- # 2. NAV – Activación desde silencio
138
- if nodo["estado"] == "silencio" and abs(nodo["ΔNFR"] - nodo["νf"]) < 0.05:
139
- return "NAV"
140
-
141
- # 3. AL – Emisión si es latente y sensible
142
- if nodo["estado"] == "latente" and nodo["Si"] < 0.2 and nodo["νf"] > 1.0:
143
- return "AL"
144
-
145
- # 4. EN – Recepción ante apertura sensible
146
- if nodo["ΔNFR"] > 0.6 and nodo["EPI"] > 1.0 and nodo["Si"] < 0.3:
147
- return "EN"
148
-
149
- # 5. OZ – Disonancia fuerte
150
- if abs(nodo["ΔNFR"]) > 1.0 and nodo["EPI"] > 1.0:
151
- return "OZ"
152
-
153
- # 6. ZHIR – Mutación por cambio abrupto
154
- if abs(nodo["EPI"] - nodo.get("EPI_prev", nodo["EPI"])) > 0.5 and nodo["Si"] > 0.5:
155
- return "ZHIR"
156
-
157
- # 7. VAL – Expansión estructural
158
- if nodo["Si"] > 0.6 and nodo["EPI"] > 1.2:
159
- return "VAL"
160
-
161
- # 8. NUL – Contracción por exces
162
- if nodo["EPI"] > 1.3 and nodo["Si"] < 0.4:
163
- return "NUL"
164
-
165
- # 9. THOL – Autoorganización
166
- if abs(nodo["EPI"] - nodo["EPI_prev2"]) > 0.2 and abs(nodo["ΔNFR"]) < 0.1:
167
- return "THOL"
168
-
169
- # 10. IL – Coherencia estable
170
- if abs(nodo["ΔNFR"]) < 0.05 and abs(nodo["EPI"] - nodo["EPI_prev"]) < 0.05:
171
- return "IL"
172
-
173
- # 11. RA – Resonancia coherente
174
- if nodo["glifo"] == "IL" and nodo["Si"] > 0.5 and nodo["νf"] > 1.2:
175
- return "RA"
176
-
177
- # 12. UM – Acoplamiento con vecinos
178
- for v in vecinos:
179
- if abs(nodo["νf"] - G.nodes[v]["νf"]) < 0.05:
180
- return "UM"
181
-
182
- # 13. REMESH – Recursividad (si ya hay historial)
183
- hist = nodo.get("historial_glifos", [])
184
- if (
185
- len(hist) >= 3
186
- and hist[-1][1] == hist[-2][1] == hist[-3][1]
187
- and abs(nodo["EPI"] - nodo["EPI_prev"]) < 0.05
188
- ):
189
- return "REMESH"
190
-
191
- return None # si no se detecta un glifo resonante
192
-
193
- def transicion_glifica_canonica(nodo):
194
- glifo = nodo["glifo"]
195
-
196
- if glifo == "ZHIR":
197
- if nodo["νf"] > 1.5 and nodo["EPI"] > 2.5:
198
- return "VAL"
199
- elif nodo["ΔNFR"] < 0:
200
- return "RA"
201
- else:
202
- return "NAV"
203
-
204
- elif glifo == "IL":
205
- if nodo["νf"] > 1.2 and nodo["Si"] > 0.4:
206
- return "RA"
207
-
208
- elif glifo == "OZ":
209
- if nodo["EPI"] > 2.2 and nodo["Si"] > 0.3:
210
- return "THOL"
211
-
212
- elif glifo == "NAV":
213
- if abs(nodo["ΔNFR"]) < 0.1:
214
- return "IL"
215
-
216
- elif glifo == "RA":
217
- if nodo["Si"] > 0.6 and nodo["EPI"] > 2.0:
218
- return "REMESH"
219
-
220
- elif glifo == "VAL":
221
- if nodo["EPI"] > 3.0 and nodo["Si"] > 0.4:
222
- return "NUL"
223
-
224
- elif glifo == "AL":
225
- if nodo["Si"] > 0.3 and nodo["ΔNFR"] < 0.2:
226
- return "UM"
227
-
228
- return None
229
-
230
- def acoplar_nodos(G):
231
- for n in G.nodes:
232
- vecinos = list(G.neighbors(n))
233
- if not vecinos:
234
- vecinos = list(G.nodes)
235
- Si_vecinos = [G.nodes[v]["Si"] for v in vecinos if v != n]
236
- if Si_vecinos:
237
- G.nodes[n]["Si"] = (sum(Si_vecinos) / len(Si_vecinos)) * 0.9 + G.nodes[n]["Si"] * 0.1
238
- for v in vecinos:
239
- if v != n:
240
- if abs(G.nodes[n]["θ"] - G.nodes[v]["θ"]) < 0.1:
241
- G.nodes[n]["ΔNFR"] *= 0.95
242
-
243
- def detectar_EPIs_compuestas(G, umbrales=None):
244
- # Si no se pasan umbrales, usar valores por defecto
245
- if umbrales is None:
246
- umbral_theta = 0.12
247
- umbral_si = 0.2
248
- else:
249
- umbral_theta = umbrales.get('θ_conexion', 0.12)
250
- umbral_si = umbrales.get('Si_conexion', 0.2)
251
-
252
- compuestas = []
253
- nodos_por_glifo_y_paso = {}
254
-
255
- for n in G.nodes:
256
- historial = G.nodes[n].get("historial_glifos", [])
257
- for paso, glifo in historial:
258
- clave = (paso, glifo)
259
- nodos_por_glifo_y_paso.setdefault(clave, []).append(n)
260
-
261
- for (paso, glifo), nodos_en_glifo in nodos_por_glifo_y_paso.items():
262
- if len(nodos_en_glifo) < 3:
263
- continue
264
-
265
- grupo_coherente = []
266
- for i, ni in enumerate(nodos_en_glifo):
267
- for nj in nodos_en_glifo[i+1:]:
268
- θi, θj = G.nodes[ni]["θ"], G.nodes[nj]["θ"]
269
- Sii, Sij = G.nodes[ni].get("Si", 0), G.nodes[nj].get("Si", 0)
270
- if abs(θi - θj) < umbral_theta and abs(Sii - Sij) < umbral_si:
271
- grupo_coherente.extend([ni, nj])
272
-
273
- grupo_final = list(set(grupo_coherente))
274
- if len(grupo_final) >= 3:
275
- compuestas.append({
276
- "paso": paso,
277
- "glifo": glifo,
278
- "nodos": grupo_final,
279
- "tipo": clasificar_epi(glifo)
280
- })
281
-
282
- return compuestas
283
-
284
- def clasificar_epi(glifo):
285
- if glifo in ["IL", "RA", "REMESH"]:
286
- return "coherente"
287
- elif glifo in ["ZHIR", "VAL", "NUL"]:
288
- return "mutante"
289
- elif glifo in ["SHA", "OZ"]:
290
- return "disonante"
291
- else:
292
- return "otro"
293
-
294
- def interpretar_sintaxis_glífica(historial):
295
- sintaxis = {}
296
- for nodo, secuencia in historial.items():
297
- trayecto = [glifo for _, glifo in secuencia]
298
- transiciones = list(zip(trayecto, trayecto[1:]))
299
- ciclos_val_nul = sum(
300
- 1 for i in range(len(trayecto)-2)
301
- if trayecto[i] == "VAL" and trayecto[i+1] == "NUL" and trayecto[i+2] == "VAL"
302
- )
303
-
304
- tipo = "desconocido"
305
- if "ZHIR" in trayecto:
306
- tipo = "mutante"
307
- elif "REMESH" in trayecto:
308
- tipo = "recursivo"
309
- elif ciclos_val_nul >= 2:
310
- tipo = "pulsante"
311
- elif trayecto.count("IL") > 2:
312
- tipo = "estabilizador"
313
-
314
- sintaxis[nodo] = {
315
- "trayectoria": trayecto,
316
- "transiciones": transiciones,
317
- "mutaciones": trayecto.count("ZHIR"),
318
- "colapsos": trayecto.count("SHA"),
319
- "ciclos_val_nul": ciclos_val_nul,
320
- "diversidad_glifica": len(set(trayecto)),
321
- "tipo_nodal": tipo
322
- }
323
-
324
- return sintaxis
325
-
326
- def aplicar_remesh_red(G, historial_glifos_por_nodo, paso):
327
- for n in G.nodes:
328
- nodo = G.nodes[n]
329
- aplicar_glifo(G, nodo, n, "REMESH", historial_glifos_por_nodo, paso)
330
-
331
- def aplicar_remesh_si_estabilizacion_global(G, historial_glifos_por_nodo, historia_glifos, paso):
332
- if len(G) == 0:
333
- return
334
-
335
- nodos_estables = 0
336
-
337
- for n in G.nodes:
338
- nodo = G.nodes[n]
339
- estabilidad_epi = abs(nodo.get("EPI", 0) - nodo.get("EPI_prev", 0)) < 0.01
340
- estabilidad_nfr = abs(nodo.get("ΔNFR", 0)) < 0.05
341
- estabilidad_dEPI = abs(nodo.get("dEPI_dt", 0)) < 0.01
342
- estabilidad_acel = abs(nodo.get("d2EPI_dt2", 0)) < 0.01
343
-
344
- if all([estabilidad_epi, estabilidad_nfr, estabilidad_dEPI, estabilidad_acel]):
345
- nodos_estables += 1
346
-
347
- fraccion_estables = nodos_estables / len(G)
348
-
349
- if fraccion_estables > 0.8:
350
- aplicar_remesh_red(G, historial_glifos_por_nodo, paso)
351
- for n in G.nodes:
352
- historial_glifos_por_nodo.setdefault(n, []).append((paso, "REMESH"))
353
- historia_glifos.append(f"{paso},{n},REMESH")
354
-
355
- def limpiar_glifo(glifo_raw):
356
- """
357
- Limpia glifos que pueden tener comillas adicionales o formato incorrecto
358
- """
359
- if not isinstance(glifo_raw, str):
360
- return str(glifo_raw)
361
-
362
- # Remover comillas simples y dobles del inicio y final
363
- glifo_limpio = glifo_raw.strip().strip("'").strip('"')
364
-
365
- # Casos específicos problemáticos
366
- correcciones = {
367
- "RE'MESH": "REMESH",
368
- "T'HOL": "THOL",
369
- "Z'HIR": "ZHIR",
370
- "A'L": "AL",
371
- "E'N": "EN",
372
- "I'L": "IL",
373
- "O'Z": "OZ",
374
- "U'M": "UM",
375
- "R'A": "RA",
376
- "SH'A": "SHA",
377
- "VA'L": "VAL",
378
- "NU'L": "NUL",
379
- "NA'V": "NAV"
380
- }
381
-
382
- # Buscar coincidencia exacta o parcial
383
- for glifo_correcto in correcciones.values():
384
- if glifo_correcto in glifo_limpio or glifo_limpio in glifo_correcto:
385
- return glifo_correcto
386
-
387
- return glifo_limpio
388
-
389
- def normalizar_historial_glifos(historial_glifos_por_nodo, analizar_dinamica=False, expandido=False):
390
- glifo_codigo = {
391
- "AL": 1, "EN": 2, "IL": 3, "OZ": 4, "UM": 5,
392
- "RA": 6, "SHA": 7, "VAL": 8, "NUL": 9, "THOL": 10,
393
- "ZHIR": 11, "NAV": 12, "REMESH": 13
394
- }
395
-
396
- codigo_glifo = {v: k for k, v in glifo_codigo.items()}
397
- resumen_dinamico = {}
398
- historial_expandido = {}
399
-
400
- for nodo_id, historial in historial_glifos_por_nodo.items():
401
- nuevo_historial = []
402
- historial_completo = []
403
- glifos_validos = []
404
-
405
- for entrada in historial:
406
- # Validación de entrada básica
407
- if not isinstance(entrada, (list, tuple)) or len(entrada) != 2:
408
- continue
409
-
410
- elemento_a, elemento_b = entrada
411
-
412
- # CORRECCIÓN: Lógica simplificada y robusta
413
- glifo = None
414
- paso = None
415
-
416
- # Caso 1: (paso_int, "glifo_string")
417
- if isinstance(elemento_a, (int, float)) and isinstance(elemento_b, str):
418
- glifo_limpio = limpiar_glifo(elemento_b)
419
- if glifo_limpio in glifo_codigo:
420
- paso = elemento_a
421
- glifo = glifo_limpio
422
-
423
- # Caso 2: ("glifo_string", paso_int)
424
- elif isinstance(elemento_a, str) and isinstance(elemento_b, (int, float)):
425
- glifo_limpio = limpiar_glifo(elemento_a)
426
- if glifo_limpio in glifo_codigo:
427
- glifo = glifo_limpio
428
- paso = elemento_b
429
-
430
- # Caso 3: (paso_int, codigo_int)
431
- elif isinstance(elemento_a, (int, float)) and isinstance(elemento_b, (int, float)):
432
- if elemento_b in codigo_glifo:
433
- paso = elemento_a
434
- glifo = codigo_glifo[elemento_b]
435
- elif elemento_a in codigo_glifo:
436
- paso = elemento_b
437
- glifo = codigo_glifo[elemento_a]
438
-
439
- # Validación final
440
- if glifo is None or paso is None:
441
- continue
442
-
443
- # Conversión segura de paso a entero
444
- try:
445
- paso_int = int(float(paso)) # Doble conversión para manejar floats
446
- if paso_int < 0:
447
- continue
448
- except (ValueError, TypeError) as e:
449
- continue
450
-
451
- # Validación del glifo
452
- glifo_final = limpiar_glifo(glifo)
453
- if glifo_final not in glifo_codigo:
454
- continue
455
- glifo = glifo_final
456
-
457
- # Agregar entrada válida
458
- codigo = glifo_codigo[glifo]
459
- nuevo_historial.append((paso_int, codigo))
460
- historial_completo.append({
461
- "paso": paso_int,
462
- "glifo": glifo,
463
- "codigo": codigo
464
- })
465
- glifos_validos.append(glifo)
466
-
467
- # Actualizar historial procesado
468
- historial_glifos_por_nodo[nodo_id] = nuevo_historial
469
- historial_expandido[nodo_id] = historial_completo
470
-
471
- # Análisis dinámico si se solicita
472
- if analizar_dinamica and glifos_validos:
473
- resumen_dinamico[nodo_id] = evaluar_patron_glifico(glifos_validos)
474
-
475
- # Retornar según parámetros
476
- if analizar_dinamica and expandido:
477
- return resumen_dinamico, historial_expandido
478
- elif expandido:
479
- return historial_expandido
480
- elif analizar_dinamica:
481
- return resumen_dinamico
482
-
483
- return historial
484
-
485
- __all__ = [
486
- 'aplicar_glifo',
487
- 'evaluar_patron_glifico',
488
- 'glifo_por_estructura',
489
- 'transicion_glifica_canonica',
490
- 'acoplar_nodos',
491
- 'detectar_EPIs_compuestas',
492
- 'clasificar_epi',
493
- 'normalizar_historial_glifos',
494
- 'interpretar_sintaxis_glífica',
495
- 'aplicar_remesh_red',
496
- 'aplicar_remesh_si_estabilizacion_global',
497
- 'limpiar_glifo',
498
- ]
499
-
500
-