Es un motor de redistribución de renta que simula un sistema fiscal donde cada hogar tiene un umbral de dignidad personalizado (k_hogar) basado en su composición familiar y el coste de vida de su municipio.
El sistema clasifica a cada hogar en dos categorías:
- Contribuyente: su renta supera
k_hogar. Paga una cuota progresiva y asintótica sobre el excedente. Nunca pierde más delL × 100%de su renta (por defecto 80%). - Receptor: su renta no alcanza
k_hogar. El Estado le complementa hasta ese umbral mediante un subsidio.
Una de las ventajas que proporciona es que, a diferencia del IRPF tradicional, no existen tramos fijos. Una única fórmula continua cubre a toda la población, garantizando que la transición entre receptor y contribuyente sea suave y sin saltos bruscos. Esto garantiza que nunca se gane menos trabajando más y que la progresividad sea infinita.
[Fuentes externas]
Catastro · Padrón · IRPF/AEAT · Seg. Social · Servicios Sociales · INE
│
▼
conexion/transformador.py ← pobla la BD principal (externo al proyecto)
│
▼
Base_Datos_MACRO.db
└── tabla: Base_Datos_MACRO ← una fila por persona censada
│
▼
main.py
├── EFRD_Protocol_v4_1() ← calcula k_base, verifica solvencia
├── procesar_simulacion_efrd() ← calcula cuota de cada hogar → resultados_ciudadanos
└── generar_liquidaciones() ← agrega por ref_catastral → Liquidaciones_EFRD.db
│
├──▶ Base_Datos_MACRO.db
└── tabla: resultados_ciudadanos
|
|
└──▶ Liquidaciones_EFRD.db
└── tabla: liquidaciones_hogares
│
▼
diagnostico.py ← análisis macroeconómico independiente
├── graficar_diagnostico_comparativo() ← ANTES vs DESPUÉS
├── calcular_analizar_y_graficar_pareto_semilog()
└── graficar_distribucion_saldos()
│
▼
ejemplos/salida/*.png + *.txt ← gráficas e informes conexion/outputs/efrd_config.json ← parámetros del motor para diagnostico.py
Para visualizar este apartado de una manera gráfica, visitar: link
k_base = α · (Y / N) · (1 − G) · π
| Variable | Significado | Fuente |
|---|---|---|
| Fracción del PIB per cápita destinada al suelo | Parámetro de política (0.05 por refecto) | |
| Y | PIB nominal en euros | INE / Banco de España |
| N | Población total censada en la Base de Datos | Conteo de 'dni_nie_nif' |
| G | Coeficientes de Gini | Parámetro de política (0.33 por defecto) |
|
|
Factor IPC = 1+tasa de inflación | INE |
El factor (1 − G) hace que a mayor desigualdad, menor sea el suelo base que el sistema puede garantizar de forma sostenible, reflejando que una economía más desigual tiene menos renta distribuible de forma eficiente.
k_hogar = k_base × φ × γ
- φ (phi): multiplicador de composición familiar.
- Persona sola: φ = 1.0
- +0.5 por cada adulto adicional en el hogar
- +0.3 por cada hijo menor de edad
- Ejemplo: dos adultos y un hijo → φ = 1.0 + 0.5 + 0.3 = 1.8
- γ (gamma): índice de coste de vida del municipio, derivado del valor catastral. Municipios caros tienen γ > 1; municipios rurales, γ < 1.
Para un hogar con renta > k_hogar:
x = (renta − k_hogar) / k_hogar ← exceso relativo de renta
tasa = L · (1 − e^(−σ · x)) ← tasa efectiva (asintótica)
cuota = (renta − k_hogar) · tasa
neto = renta − cuota
Propiedades de la función:
- Cuando
x → 0(renta apenas supera el umbral):tasa → 0. No se paga casi nada.
- Cuando
x → ∞(renta muy superior al umbral):tasa → L. Nunca se supera el límite máximo.
- La función es estrictamente creciente y continua: no hay saltos de tipo marginal.
Para un hogar con renta ≤ k_hogar:
subsidio = k_hogar − renta (siempre positivo)
neto = k_hogar (el Estado completa hasta el umbral)
El Estado no da más que el umbral: garantiza la dignidad, no la igualdad.
Si por algún motivo k_hogar = 0 (datos corruptos o gamma = 0), _calcular_x satura x = 10, lo que produce tasa ≈ L (máxima contribución posible). Esto evita una división por cero y documenta el caso explícitamente.
k_arope = 0.6 × renta_mediana_nacional
Estándar europeo de riesgo de pobreza. Si k_base < k_arope, el sistema no cumple el mínimo de dignidad reconocido por la UE. El motor ofrece el Protocolo PSD para corregirlo si el presupuesto lo permite.
C:.
│ README(Guia).md <- Esta guia
│ requirements.txt <- Dependencias del código
│ main.py <- programa principal (punto de entrada)
│ EFRD.py <- motor distributivo + visualizadores
│ diagnostico.py <- análisis macroeconómico (independiente del resto del código) ┐
│ simulacion.py <- calculo de cuotas individuales |
│ traductores.py <- adaptadores de datos externos (INE, BdE…) |
│ LICENSE <- La licencia bajo la que opera el proyecto (GPL-3.0) |
│ |
├───.obsidian <- Carpeta de formatos para visualizar la documentación |
│ app.json |
│ appearance.json |
│ core-plugins.json |
│ workspace.json |
│ |
├───ejemplos |
│ └───salida <- Carpeta de resultados de diagnostico.py ─────────────────────┘
│ distribucion_saldos_histograma.png
│ grafica_diagnostico_macro_semilog.png
│ ingresos_informe_pareto.txt
|
├───Análisis <- Estudios sobre el sistema
│ └───Cadenas-Markov
│ ANÉXO TÉCNICO.md
│ Markov.ipynb
│
├───conexión
│ │ crear_db_ejemplo.py <- Crea las bases inputs/ de ejemplo
│ │ emulador.py <- Ofrece la posibilidad de ejecutar código monolineares de sql
│ │ generador_aleatorio.py <- Genera Base_Datos_Macro.db con datos aleatorios (sin basarte en inputs/)
│ │ transformador.py <- (externo y realista) genera Base_Datos_MACRO.db basado en inputs/
│ │ |
│ ├───Croquis |
│ │ Croquis_Base_datos.dbml |
│ │ Croquis_base_datos.pdf |
│ │ |
│ ├───inputs <───────────┘
│ │ asistencia.db
│ │ cnp.db
│ │ hacienda.db
│ │ ine.db
│ │ padron.db
│ │ vivienda.db
│ │
│ └───outputs
│ Base_Datos_MACRO.db <- BD principal (personas + resultados)
| Liquidaciones_EFRD.db <- BD de salida (liquidaciones por hogar)
│ efrd_config.json <- parámetros del motor para diagnostico.py
│
│
├───Documentacion
│ Propuesta técnica.md
│
│
│
└───Screenshots <- Capturas de pantalla de los gráficos que ofrece main.py
Impacto_alpha_1.png
Impacto_alpha_2.png
Impacto_limite_maximo_1.png
Impacto_limite_maximo_2.png
Impacto_sigma_progresividad.png
Mapa_Calor_sist_redistributivo.png
Núcleo del sistema. Se instancia una vez por ejecución y encapsula todos los parámetros macroeconómicos y la lógica de solvencia. Constructor:
EFRD_Protocol_v4_1(
PIB_Y, # PIB nominal en EUR
Gini, # Coeficiente de Gini (0–1)
Alpha, # Fracción del PIB per cápita para k_base
Sigma, # Velocidad de progresividad de la cuota
Limite_L, # Techo asintótico de la tasa efectiva (0–1)
G_op, # Gastos operativos del Estado en EUR/mes
IPC_Pi, # Factor IPC (1 + tasa de inflación)
db_path, # Ruta a Base_Datos_MACRO.db
tabla_central, # Nombre de la tabla principal
modo # 'interactivo' | 'deuda' | 'ajuste' | 'test'
) Secuencia de inicialización:
_cargar_datos_desde_db()— lee y agrupa hogares desde SQLitecalcular_k_base()— calcula el suelo vitalicio base_ejecutar_logica_central()— verifica solvencia y dignidad_finalizar_auditoria()— imprime liquidación y guardaefrd_config.json
Métodos públicos principales:
| Método | Descripción |
|---|---|
| calcular_k_base( |
Estático. Fórmula canónica del sueldo vitalicio |
_calcular_x(diferencial, k_hogar) |
Estático. Exceso relativo de renta (con saturación en k=0) |
| simular_balance(k_prueba) | Simula la recaudación y subsidios para un k dado. Usado en búsqueda binaria. |
| calcular_cuota_hogar(renta, adultos, hijos, gamma) | Calcula una cuota para un hogar hipotético. Usado por los visualizadores. |
Cuando simular_balance(k_base) < 0, el motor ejecuta 100 iteraciones de búsqueda binaria entre [0, k_base] para encontrar el k_equilibrio máximo que mantiene el sistema solvente. La precisión tras 100 iteraciones es k_base / 2^100, prácticamente irrelevante en la práctica.
Si k_base < k_arope, el motor comprueba si subir hasta k_arope seguiría siendo solvente. Si sí, ofrece activarlo (solo en modo interactivo). Si el Protocolo de Solvencia ya ajustó k_base a la baja, el PSD queda bloqueado para evitar contradicción lógica.
Verifica que al menos el 40% de los hogares sean contribuyentes netos. Si no se cumple, emite una alerta estructural: el sistema tiene demasiados receptores para ser autosostenible a largo plazo sin deuda.
RATIO_MASA_CRITICA_MIN = 0.40 Herramienta de análisis de sensibilidad paramétrica. Usa deepcopy del motor para simular variaciones de σ, L y α sin modificar el estado del motor original.
| Método | Qué muestra |
|---|---|
| comparar_sigmas() | Cuota vs ingreso para distintos valores de |
| comparar_limite_L() | Tipo efectivo vs ingreso para distintos techos L |
| comparar_alpha() | Ingreso neto vs ingreso bruto para distintos |
| mapa_calor() | Ingreso neto como función de (bruto, |
Es un visualizador analítico sobre datos reales de la BD. Lee directamente de SQLite.
| Método | Qué muestra |
|---|---|
| graficar_curva_sostenibilidad() | Recaudación, subsidios y saldo neto en función de k_base |
| graficar_ingreso_bruto_vs_neto() | Curvas de redistribución para distintas composiciones de hogar |
| graficar_tipo_impositivo_efectivo() | Progresividad asintótica con línea de techo L |
| graficar_mapa_calor_bienestar() | Ingreso neto en el espacio (bruto |
| graficar_distribucion_ingresos() | Histograma de rentas brutas anuales con k_base superpuesto |
Todos los métodos aceptan guardar: bool y ruta: str. Si guardar=False llaman a plt.show(); si guardar=True guardan el PNG en la ruta indicada (modo headless/servidor). |
Lee motor.unidades_convivencia (ya cargado en memoria) y escribe los resultados individuales en la tabla resultados_ciudadanos de Base_Datos_MACRO.db.
Lógica por hogar:
k_hogar = motor.k_base × phi_total × gamma
diferencial = renta_total − k_hogar
si diferencial > 0:
x = diferencial / k_hogar
tasa = L × (1 − e^(−σ × x))
cuota = diferencial × tasa → CONTRIBUYENTE
sino:
cuota = diferencial → negativo, es subsidio
estado = RECEPTOR o AUDITORÍA
Parámetro ciclo_id: permite ejecuciones históricas múltiples. Si se proporciona, solo se borran las filas del ciclo actual; el histórico de otros ciclos se conserva.
Si es None, se trunca la tabla (ejecución simple).
Migración de esquema: al arrancar comprueba el número de columnas de resultados_ciudadanos con PRAGMA table_info. Si detecta el esquema antiguo (≠ 10 columnas), lo elimina y lo recrea. Evita errores sqlite3.OperationalError en BDs heredadas.
UMBRAL_GAMMA_SOSPECHOSO = 1.3 # zona de alto coste de vida
UMBRAL_RENTA_CERO = 100 # EUR/mes
PREFIJOS_REF_VIRTUAL = ("VIRTUAL_", "SIN_REF", "TEST_", "MOCK_") Un hogar se marca como AUDITORÍA si cumple las tres condiciones:
- La ref. catastral es real (no empieza por ninguno de los prefijos virtuales).
renta < 100 €/mes(declaración prácticamente cero).gamma > 1.3(vive en zona de coste de vida alto). El estadoAUDITORÍAno bloquea el subsidio: el hogar sigue recibiéndolo. Solo lo señala para revisión manual posterior. Las referencias virtuales quedan excluidas explícitamente porque no corresponden a contribuyentes reales.
1. Parseo de argumentos CLI (--gop, --modo)
2. Carga de PIB e IPC desde traductores.py
3. Instanciación de EFRD_Protocol_v4_1 (calcula k_base, ejecuta protocolos) 4. procesar_simulacion_efrd() -> tabla resultados_ciudadanos
4. generar_liquidaciones() -> Liquidaciones_EFRD.db
5. EFRD_AnalyticVisualizer -> 5 gráficas
Agregaresultados_ciudadanosporref_catastraly produce la tabla finalliquidaciones_hogares`.
Tratamiento semántico de hogares sin renta:
| Situación | renta_neta_hogar | subsidio_estatal | tipo_efectivo_pct | |
|---|---|---|---|---|
| Contribuyente (renta > k_hogar) | 0 | |||
| Receptor con renta > 0 | 0 |
|
||
| Receptor con renta = 0 | 0 | NULL |
El NULL en tipo_efectivo_pct cuando renta = 0 es semánticamente correcto: no existe base imponible sobre la que calcular un porcentaje. Un valor 0% sería engañoso (implicaría que tienen renta y no pagan nada).
EFRD_HEADLESS=1 python main.py Activa guardar=True en todos los métodos gráficos, guardando PNGs en ejemplos/salida/ en lugar de abrir ventanas. Necesario en servidores sin entorno gráfico o en pipelines automatizados.
Módulo independiente del motor. Lee la BD directamente y usa los parámetros del efrd_config.json generado en la última ejecución.
Figura de 4 paneles que compara la distribución antes (salarios brutos) y después (salarios netos EFRD) del sistema:
![[Diagnostico_distrib.png]]
Análisis de la cola superior de la distribución de saldos netos:
- Alpha de Pareto (α): estimado por MLE sobre el top
(100 − percentil_cola)%. Mide la concentración de la riqueza en la cúspide. - Palma Ratio: masa económica del top
(100 − percentil_cola)%dividida entre el bottom 40%. > 3.0 indica oligarquía; ≤ 1.2 indica equilibrio. - S80/S20: ratio entre la masa del quintil superior y la del quintil inferior. Interpretación de α:
| Rango | Diagnóstico macroeconómico |
|---|---|
| Clase media hipertrofiada. |
|
| Distribución saludable |
|
| Cola pesada. |
|
| Dominio extremo de mega-ricos. |
|
Genera también un informe .txt en ejemplos/salida/ingresos_informe_pareto.txt. |
Histograma de frecuencias + boxplot horizontal de los saldos netos reales (filtrando saldos ≤ 0). ![[Diagnostico_saldos.png]]
_cargar_parametros_sistema(ruta_db) busca efrd_config.json en el mismo directorio que la BD. Si no existe, usa valores por defecto {k_base: 900, sigma: 1.5, L: 0.60} con aviso. Esto permite ejecutar diagnostico.py de forma autónoma sin necesidad de reinstanciar el motor completo.
Capa de abstracción entre el motor y las fuentes macroeconómicas externas. Cada función intenta primero la API real (pendiente de implementar) y cae en respaldo auditado si falla.
| Función | Devuelve | Fuente respaldo |
|---|---|---|
| get_pib_nominal_precios_corrientes() | (año, EUR) | macro_fallback.json |
| get_IPC_mas_reciente() | (año, factor) | macro_fallback.json |
| get_renta_mediana() | EUR/año | macro_fallback.json |
Los valores de respaldo se pueden actualizar anualmente editando datos_referencia/macro_fallback.json sin tocar el código. |
Para información más detallada: ![[conexion/Croquis_base_datos.pdf]]
Tabla de entrada. Una fila por persona censada. Generada porconexion/transformador.py`
| Columna | Tipo | Descripción |
|---|---|---|
| dni_nie_nif | str (TEXT) | Identificador único de la persona |
| ref_catastral | str (TEXT) | Referencia de la vivienda (puede ser virtual) |
| renta_mensual | float (REAL) | Renta mensual declarada en EUR |
| phi | float (REAL) | Aportación de esta persona al |
| gamma | float (REAL) | Índice de coste de vida del municipio |
Tabla de resultados individuales. Generada por simulacion.py. Una fila por hogar (agrupación de ref_catastral).
| Columna | Tipo | Descripción |
|---|---|---|
| ciclo_id | str (TEXT) | Identificador del ciclo de ejecución (NULL en ejecución simple) |
| ref_catastral | str (TEXT) | Referencia catastral del hogar |
| renta_total | float (REAL) | Suma de rentas de todos los miembros |
| phi_total | float (REAL) |
|
| gamma | float (REAL) |
|
| k_hogar | float (REAL) | Umbral de dignidad calculado |
| cuota | float (REAL) | Importe fiscal (>0 si contribuyente, <0 si receptor) |
| neto | float (REAL) | Renta neta disponible |
| tipo_efectivo | float (REAL) | Porcentaje efectivo sobre renta |
| estado | str (TEXT) | CONTRIBUYENTE, RECEPTOR o AUDITORÍA |
Tabla de salida final. Una fila por hogar. Generada por main.py.
| Columna | Tipo | Descripción |
|---|---|---|
| ref_catastral | str (TEXT | Referencia catastral |
| renta_bruta_hogar | float (REAL) | Renta propia del hogar ( |
| cuota_hogar | float (REAL) | A ingresar ( |
| renta_neta_hogar | float (REAL) | Renta disponible tras cuota (0 si |
| subsidio_estatal | float (REAL) | Aportación del estado cuando |
| tipo_efectivo_pct | float (REAL) |
|
| estado_hogar | str (TEXT) | CONTRIBUYENTE o RECEPTOR o AUDITORÍA o NEUTRO |
| phi_total | float (REAL) | Factor de composición familiar del hogar |
| gamma | float (REAL) | Índice de coste de vida del municipio |
| Parámetro | Valor por defecto | Impacto |
|---|---|---|
| Alpha | 0.05 | Fracción del PIB per cápita para k_base. Subir |
| Gini | 0.33 | Desigualdad estructural. Solo modifica k_base en el arranque |
| Sigma | 1.5 | Velocidad de progresividad. |
| Limite_L | 0.6 | Techo de la tasa efectiva. Nadie paga más del 80$ aunque tenga renta infinita |
| IPC_Pi | 1.034 | Factor de inflación. Sube k_base para mantener poder adquisitivo |
| Constante | Valor | Descripción |
|---|---|---|
| UMBRAL_GAMMA_SOSPECHOSO | 1.3 |
|
| UMBRAL_RENTA_CERO | 100 €/mes | Renta por debajo de la cual se considera declaración cero |
| PREFIJOS_REF_VIRTUAL | VIRTUAL_, SIN_REF, TEST_, MOCK_ | Prefijos de refs. catastrales sintéticas, excluidas del detector de fraude |
| Constante | Valor | Descripción |
|---|---|---|
| RATIO_MASA_CRITICA_MIN | 0.40 | Mínimo de hogares contribuyentes para sostenibilidad estructural |
El motor ejecuta dos protocolos en secuencia al arrancar.
Condición de disparo: recaudación − subsidios − G_op < 0
Opciones:
- Deuda pública — mantiene k_base, asume el déficit vía endeudamiento soberano.
- Ajuste fiscal — reduce k_base al mínimo solvente mediante búsqueda binaria (100 iteraciones).
Modos de resolución automática (argumento
--modo):
interactivo→ pregunta al operador por consola .deuda→ elige opción 1 automáticamente .ajuste→ elige opción 2 automáticamente .test→ elige opción 2 sin imprimir (para pipelines de test) .
Condición de disparo: k_base < k_arope (suelo por debajo del umbral europeo de pobreza)
Condición de bloqueo: no se puede activar si el Protocolo de Solvencia ya redujo k_base.
Comportamiento: solo se activa en modo interactivo. En modos automáticos, la política es conservadora (no se aumenta el gasto sin intervención humana explícita).
El estado AUDITORÍA es una señal, no un bloqueo. El hogar sigue recibiendo su subsidio. Lo que se marca es la necesidad de revisión manual posterior.
Criterios de marcado (AND lógico):
- Referencia catastral real (no virtual/sintética)
renta_mensual < 100 €/mes3.gamma > 1.3(zona de coste de vida alto) Razonamiento: una persona que declara ingresos prácticamente nulos pero vive en una zona cara (Madrid, Barcelona, etc.) presenta una inconsistencia estadística. Puede tener renta no declarada, patrimonio no computado, o simplemente ser una situación límite legítima (desempleo reciente, herencia de vivienda). El sistema no puede saberlo, por lo que delega la decisión a revisión humana.
En la tabla liquidaciones_hogares: si algún miembro del hogar tiene estado AUDITORÍA, el estado del hogar completo se eleva a AUDITORÍA (prioridad máxima en el CASE).
python main.py [--gop VALOR_EUR] [--modo {interactivo,deuda,ajuste,test}]
# Ejemplos:
python main.py # ejecución interactiva, G_op = 0
python main.py --gop 5000000000 # con gastos operativos del Estado
python main.py --modo ajuste # resolución automática de insolvencia
python main.py --modo test # para pipelines automatizados
# Modo headless (sin GUI):
EFRD_HEADLESS=1 python main.py --modo test python diagnostico.py [--db RUTA] [--tabla NOMBRE] [--percentil-cola N] [--headless]
# Ejemplos:
python diagnostico.py # usa rutas por defecto
python diagnostico.py --headless # guarda PNGs, no muestra ventanas
python diagnostico.py --percentil-cola 95 # analiza el top 5% en lugar del top 10%
python diagnostico.py --db /ruta/custom.db --tabla MiTabla No. Hacerlo sería un error de duplicidad muy apreciable que quebraría el sistema en la primera iteración. La relación es de jerarquía y transformación, no de suma:
-
$k_{base}$ es la constante teórica (la "base" de dignidad). Es lo que le correspondería a un adulto solo en una zona de coste de vida neutro ($\gamma=1.0$ ). -
$k_{hogar}$ es el$k_{base}$ ya procesado por las circunstancias del ciudadano. Es el umbral final que el motor usa para calcular la cuota$C$
La fórmula que transforma
Entonces, ejemplificando la respuesta: Un sin hogar que gane 0€ se le donará un
| Término | Definición |
|---|---|
| k_base | Sueldo vitalicio base individual. Importe mensual mínimo garantizado. |
| k_hogar | Umbral de dignidad específico del hogar: |
|
|
Multiplicador de composición familiar. Escala k_base según el número de miembros y características. |
|
|
Índice de coste de vida municipal derivado del catastro. |
|
|
Velocidad de progresividad de la cuota. Controla cuán rápido sube la tasa hacia el techo L. |
| L | Límite asintótico de la tasa efectiva. Garantiza que nadie pierde más del |
|
|
Fracción del PIB per cápita destinada a financiar el suelo vitalicio. |
| AROPE | At Risk Of Poverty or Exclusion. Umbral europeo de pobreza: 60% de la renta mediana nacional. |
| Palma Ratio | Cociente entre la masa económica del top X% y el bottom 40%. Indicador de desigualdad estructural |
| Alpha Pareto | Exponente de la ley de potencias en la cola de distribución. |
| S80/S20 | Ratio entre la renta del quintil superior y el inferior. |
| Masa crítica | Porcentaje mínimo de de contribuyentes necesarios para que el sistema sea autosostenible sin deuda permanente. |
| Protocolo PSD | Protocolo de Suelo de Dignidad. Mecanismo para elevar k_base hasta el umbral AROPE cuando el presupuesto lo permite. |
| Modo headless | Ejecución sin interfaz gráfica. Las figuras se guardan como PNG en lugar de mostrarse en pantalla |
| ciclo_id | Identificador de ejecución para soporte multicíclo. Permite conservar histórico de varias simulaciones en la misma BD. |
| Ref. catastral virtual | Referencia sintética (prefijos VIRTUAL_, TEST_, etc. ) usada para hogares sin domicilio catastrable. Excluida del detector de fraude. |
Los datos de entrada han de actualizarse anualmente, tales como el índice Gini y el IPC. Además, es importante que el PIB sea lo más reciente posible.
Para visualizar más detalles, entre en 'Documentacion/propuesta técnica.md'
Este -ambicioso- proyecto está bajo la licencia GNU General Public License v3.0 (GPL-3.0). Esto garantiza que el algoritmo permanezca abierto, auditable y que cualquier cambio o mejora sea compartida y de libre acceso con la comunidad. Esto garantiza esa "Caja de Cristal", es decir, garantiza que la transparencia se mantenga aún habiendo realizado cambios.