Resumen: Cinco bloques implementados sin modificar la firma pública de IAlgoritmo.
1. Resultado de ejecución y estadísticas sobre múltiples ejecuciones
- Nuevo:
algoritmogenetico/util/ResultadoEjecucion.java— Datos inmutables: mejorIndividuo, generacionFinal, objetivoAlcanzado; constructor y getters. - AlgoritmoGenetico: Campo
ultimoResultado; al final deejecutar(IDominio)se asigna unResultadoEjecucioncon el mejor de la última generación, generación en que se paró y si se paró por objetivo; gettergetUltimoResultado(). - AppGP: Spinner "N ejecuciones" (1–100, default 1). Si N > 1: bucle N veces con semilla
baseSeed + i, solo la última run con listener/logger; se acumulanResultadoEjecucion; al final se muestran en un Alert: media/std/min/max fitness, tasa de éxito, media de generaciones cuando éxito. - Tests:
AlgoritmoGeneticoIntegracionTest: getUltimoResultado coherente y varias ejecuciones con distintas semillas.
2. Evitar óptimo trivial en clasificación
- Nuevo:
algoritmogenetico/util/UtilExpresion.java— Método estáticoisConstant(INodo raiz): true si el árbol solo tiene constantes (TerminalConstante/funciones), false si hay al menos un TerminalAritmetico (variable). - AlgoritmoGenetico: En la condición de "objetivo alcanzado", si el dominio es
DominioClasificacionyUtilExpresion.isConstant(mejorIndiv.getExpresion()), no se hace break (no se considera objetivo alcanzado). - Tests:
UtilExpresionTest: isConstant con null, TerminalConstante, TerminalAritmetico.
3. Simplificación de expresiones
- Nuevo:
algoritmogenetico/util/SimplificadorExpresion.java— Método estáticosimplificar(INodo raiz)que devuelve un nuevo árbol. Reglas: x+0→x, 0+x→x, x1→x, 1x→x, 0x→0, x0→0, x-0→x, x/1→x. Soporte para +, -, *, / y funciones unarias (sin, cos, neg, abs, exp, log, sqrt, sqr) para reconstruir el árbol. - AppGP: Checkbox "Simplificar expresión" (por defecto desactivado). Tras obtener el mejor individuo, si está activo se usa la expresión simplificada para: texto en área, dibujo del árbol, exportar a fichero y curva datos vs curva.
- Tests:
SimplificadorExpresionTest: suma con 0, producto por 1, producto por 0, árbol original no mutado.
4. Exportar expresión a LaTeX y código
- Nuevo:
algoritmogenetico/util/ExportadorExpresion.java— Métodos estáticos:toPrefija(INodo)(equivalente a toString),toLatex(INodo)(infija con \frac, \sin, \cos, etc.),toPython(INodo)(expresión infija),toPythonDef(INodo)(def f(x): return ... con import math si aplica). - AppGP: ComboBox "Formato" junto a "Exportar expr." con opciones: Prefija (texto), LaTeX, Python. Al guardar se usa el formato elegido; si "Simplificar expresión" está activo se aplica antes de exportar.
- Tests:
ExportadorExpresionTest: toPrefija equivale a toString, toLatex y toPython formato razonable para ( * x x ), toPythonDef contiene def y return, null → cadena vacía.
5. Benchmarks estándar y documentación
- Nuevo:
benchmark_nguyen1.txt— Nguyen-1: y = x³ + x² + x, 21 puntos en [-1, 1] (TSV; líneas # omitidas). - Nuevo:
doc/BENCHMARKS.md— Descripción del problema Nguyen-1, columnas del fichero, parámetros recomendados (población, generaciones, funciones), resultado típico y uso de "N ejecuciones" para reportar estadísticas. - doc/DOCUMENTACION.md: Enlace a la sección de benchmarks (BENCHMARKS.md).
- README.md: Enlace a doc/BENCHMARKS.md en Documentación; fila en tabla de ficheros de ejemplo para benchmark_nguyen1.txt.
Archivos nuevos: ResultadoEjecucion.java, UtilExpresion.java, SimplificadorExpresion.java, ExportadorExpresion.java, benchmark_nguyen1.txt, doc/BENCHMARKS.md, UtilExpresionTest.java, SimplificadorExpresionTest.java, ExportadorExpresionTest.java.
Archivos modificados: AlgoritmoGenetico.java, AppGP.java, doc/DOCUMENTACION.md, README.md, AlgoritmoGeneticoIntegracionTest.java, changelog.md.
Resumen:
- Regresión (TSV):
valoresPolinomio4.txt(y = x⁴−2x², 17 puntos),valoresTrigComplejo.txt(y = sin(x)+0.5·cos(2x)),valoresExpGauss.txt(y = exp(−x²)),valoresX2Ruido.txt(y ≈ x² con ruido),valoresMultivariadoComplejo.txt(z = x+y+xy, 13 filas). - Clasificación (CSV):
clasificacionXOR.csv(XOR, no lineal),clasificacionCirculo.csv(25 puntos: dentro/fuera de círculo x²+y²<1). - Booleano (TSV):
tablaVerdad4vars.txt(parity de 4 bits, 16 filas),tablaVerdadMayoria4.txt(mayoría de 4 bits: salida 1 si ≥3 entradas son 1). - Documentación: README con tabla de ficheros de ejemplo y descripción; DOCUMENTACION.md con nueva sección "Ficheros de datos de ejemplo" y renumeración de secciones (6→Ejecución, 7→Tests, 8→Referencias).
Archivos nuevos: valoresPolinomio4.txt, valoresTrigComplejo.txt, valoresExpGauss.txt, valoresX2Ruido.txt, valoresMultivariadoComplejo.txt, clasificacionXOR.csv, clasificacionCirculo.csv, tablaVerdad4vars.txt, tablaVerdadMayoria4.txt. Modificados: README.md, doc/DOCUMENTACION.md, changelog.md.
2026-03-07 — Evolución del algoritmo genético: escalado lineal, mutación punto/contracción, selección por ranking
Resumen:
- Escalado lineal en regresión (DominioAritmetico): Parámetro
usarEscaladoLineal(por defectotrue). EncalcularFitnessse obtienen predicciones p_i del árbol; se ajustan a y b por mínimos cuadrados (a·p_i + b ≈ y_i); fitness = −RMSE(a·p + b, y) − α·nodos. Aplicado en rama univariada y multivariada. Sin cambiar la estructura del árbol se mejora el fitness al permitir escala y desplazamiento. - Nuevos operadores de mutación (AlgoritmoGenetico): Tres tipos con probabilidades configurables (
setProbabilidadesMutacion(subarbol, punto, contraccion)): (1) Subárbol (comportamiento actual: sustituir subárbol por uno aleatorio de profundidad 2). (2) Punto: si el nodo es terminal constante → perturbación (valor + delta en [-0.5, 0.5]); si otro terminal → sustituir por terminal aleatorio; si función → sustituir por otra función de la misma aridad manteniendo hijos. (3) Contracción: elegir nodo no terminal y sustituir su subárbol por un terminal aleatorio. Por defecto solo subárbol = 1.0 para compatibilidad. - Selección por ranking: Enum
TipoSeleccion { TORNEO, RANKING }. MétodoseleccionarPadres(): con TORNEO se mantiene la lógica actual; con RANKING se ordena la población por fitness, se asignan pesos por rango², se normalizan y se muestrean dos padres sin reemplazo. Por defecto TORNEO. Configuración:setTipoSeleccion(TipoSeleccion). - TerminalConstante: Añadido getter
getValor()para lectura del valor en mutación por punto.
Archivos modificados: DominioAritmetico.java, TerminalConstante.java, AlgoritmoGenetico.java, doc/DOCUMENTACION.md, changelog.md.
- DOCUMENTACION.md: Reescrito para reflejar el estado actual del código: DominioAritmetico (RMSE, todas las funciones, TSV/CSV, multivariado), DominioClasificacion, DominioBooleano; cruce con cualquier aridad; parámetros de parada y límite de nodos; ejecución (GUI, runners). Eliminadas frases genéricas ("Se irá ampliando...", "Este documento se ampliará...") y la nota obsoleta sobre paridad del tamaño de población.
- ROADMAP.md: Título e intro acortados; "Prioridades sugeridas" renombrado a "Prioridades". Sin cambios de contenido técnico.
Resumen:
- README: Reescrito con tono profesional y estándar. Incluye sección "Qué es la Programación Genética" explicando idea central, flujo (población, evaluación, selección, cruce, mutación, reemplazo), casos de uso (regresión simbólica, clasificación, síntesis lógica) y carácter estocástico. Sin referencias académicas ni a prácticas.
- Licencia: Añadido fichero
LICENSEcon MIT License. Copyright (c) Eduardo Díaz Sánchez. - Documentación: Eliminadas referencias a "práctica" o contexto universitario.
doc/EVOLUCION_PROYECTO.mdsustituido pordoc/ROADMAP.md(mismo contenido técnico, redacción neutra).doc/DOCUMENTACION.mdactualizado para enlazar aROADMAP.md. - Eliminados:
Diagrama de clases.pdf,doc/EVOLUCION_PROYECTO.md. - Changelog: Entrada "README profesional y académico" renombrada a "README profesional"; "buenas prácticas" reemplazado por "prácticas habituales" en otra entrada.
Archivos nuevos: LICENSE, doc/ROADMAP.md. Archivos modificados: README.md, doc/DOCUMENTACION.md, changelog.md. Archivos eliminados: Diagrama de clases.pdf, doc/EVOLUCION_PROYECTO.md.
Resumen:
- CRÍTICO — Cruce con funciones unarias (sin, cos, neg, abs, exp, log, sqrt, sqr): El método
cruce()enAlgoritmoGeneticoasumía que el padre del punto de cruce siempre tenía 2 hijos (aridad 2). Con funciones unarias,raiz.getDescendientes().get(1)lanzabaIndexOutOfBoundsException. Se reescribió el cruce usandoList.set()directo, que funciona con cualquier aridad sin asumir el número de hijos. - CRÍTICO — Bucle infinito en
crearNuevaPoblacion(): El bucle usabawhile (nuevaPoblacion.size() != tamanioPoblacion)y añadía 2 descendientes por iteración. Con poblaciones impares, el tamaño se pasaba y el!=nunca se cumplía → bucle infinito. Cambiado a<con guard de tamaño al añadir descendientes. - Imports duplicados eliminados:
IAlgoritmo.java(IIndividuo x2),AppGP.java(Stage x2),TesterDemoValores.java(DominioAritmetico x2). - copy() normalizado en 13 funciones:
FuncionDivision,FuncionSeno,FuncionCoseno,FuncionNegacion,FuncionValorAbsoluto,FuncionExp,FuncionLog,FuncionSqrt,FuncionCuadrado,FuncionAnd,FuncionOr,FuncionNot,FuncionXorllamabanincluirDescendiente(nodo.copy())peroNodo.incluirDescendiente()ya llamanodo.copy()internamente → doble copia innecesaria. Ahora todas usanincluirDescendiente(nodo), consistente con FuncionSuma/Resta/Multiplicacion. - TerminalBooleano.copy(): No preservaba el valor actual del terminal. Ahora copia el valor con
setValor(this.calcular()). - Warning unchecked en AppGP:
chartDatos.getData().addAll(s1, s2)varargs genérico → sustituido por dos llamadasadd(). - 5 tests nuevos: Cruce con funciones solo unarias (50 seeds), cruce con mezcla binarias/unarias (50 seeds), población tamaño impar (5 tamaños), ejecución completa con funciones unarias, ejecución solo con funciones unarias.
Tests: 35 tests, 0 fallos (antes 30).
Archivos modificados: AlgoritmoGenetico.java, IAlgoritmo.java, AppGP.java, FuncionDivision.java, FuncionSeno.java, FuncionCoseno.java, FuncionNegacion.java, FuncionValorAbsoluto.java, FuncionExp.java, FuncionLog.java, FuncionSqrt.java, FuncionCuadrado.java, FuncionAnd.java, FuncionOr.java, FuncionNot.java, FuncionXor.java, TerminalBooleano.java, CruceIntegracionTest.java, AlgoritmoGeneticoIntegracionTest.java, TesterDemoValores.java.
Resumen:
- Nuevas funciones matemáticas: exp (exponencial acotada), log (log(1+|x|)), sqrt (raíz de |x|), sqr (cuadrado). Registradas en DominioAritmetico y disponibles en la GUI como checkboxes.
- Carga de datos flexible: En DominioAritmetico y DominioClasificacion, definirValoresPrueba acepta TSV (tabulador) o CSV (coma). Si la primera línea no es numérica, se considera cabecera y se omite. Permite cargar cualquier archivo de valores deseado.
- Dominio de clasificación binaria: Nueva clase DominioClasificacion. Lee ficheros con N columnas numéricas + última columna clase (0.0/1.0). Fitness = precisión − ALPHA*nodos. Mismo algoritmo genético que para regresión. Fichero de ejemplo clasificacionEjemplo.csv (x1, x2, clase).
- Constantes aleatorias en GUI: Opción "Const. aleat. N" con spinners N, min, max. Se generan N constantes en [min,max] con la semilla indicada al inicio de la ejecución. Combinable con constantes fijas.
- AlgoritmoGenetico: setMaxNodosIndividuo(int): rechaza hijos que superen ese número de nodos (0 = sin límite). setGeneracionesSinMejoraParaParar(int): parada por convergencia (0 = desactivado). Ambos configurables desde la GUI.
- GUI: Botón "Examinar..." para elegir el fichero de datos con un diálogo. Combo "Tipo: Regresión | Clasificación". Spinners para semilla, max nodos y parar sin mejora. Checkboxes exp, log, sqrt, sqr. Opción "Exportar expr." para guardar la mejor expresión en un fichero de texto al finalizar.
Archivos nuevos: FuncionExp, FuncionLog, FuncionSqrt (raíz cuadrada), FuncionCuadrado (sqr), DominioClasificacion, clasificacionEjemplo.csv.
Archivos modificados: DominioAritmetico (exp/log/sqrt/sqr, carga CSV y cabecera), DominioClasificacion (definirConjuntoTerminalesConConstantes), AlgoritmoGenetico (maxNodos, generacionesSinMejora), AppGP (selector fichero, tipo problema, constantes aleatorias, nuevas funciones, exportar expresión).
Fases implementadas: 0.1, 0.2, 0.3, 1.1, 1.2, 1.3, 2.1, 2.2, 2.3, 3.1
Resumen:
- Fase 0.1 (Nodo.java):
numNodosestático reemplazado porAtomicInteger CONTADOR. Elimina condición de carrera entre el hilo del algoritmo y el Task de JavaFX. - Fase 0.2 (DominioAritmetico): Fitness cambiado de conteo binario a RMSE negado (
fitness = -RMSE - ALPHA*nodos).fitnessBuscado()devuelve 0.0. El algoritmo para cuando RMSE < ~0.05. Tests de dominio actualizados. - Fase 0.3:
TesterDemoValoresyAppGPusandefinirConjuntoTerminalesConConstantescon {-1.0, 0.0, 1.0, 2.0}. - Fase 1.1 (AlgoritmoGenetico): Inicialización ramped half-and-half: mitad con
full(profundidad exacta), mitad congrow(profundidad variable). Mayor diversidad inicial.crearIndividuoAleatorioGrowañadido aIndividuo. - Fase 1.2: Funciones unarias sin, cos, neg, abs (
FuncionSeno,FuncionCoseno,FuncionNegacion,FuncionValorAbsoluto).crearIndividuoAleatorioRecusa aridad dinámica (f.getNumArgu()).getNumArgu()añadido aFuncion. Nuevo ficherovaloresSeno.txt. - Fase 1.3 (DominioAritmetico): Soporte multivariado:
definirValoresPruebaMultiVar(fichero, "x", "y")carga N+1 columnas;calcularFitnessinyecta variables por nombre. Nuevo ficherovaloresMultiVar.txt(z = x²+y²). - Fase 2.1 (AppGP): Panel de configuración completo: spinners para población, generaciones, profundidad, torneo, cruce%, mutación%; checkboxes para cada función matemática; campo para constantes efímeras.
- Fase 2.2:
EvolucionLoggerse activa desde la GUI (checkbox + ruta CSV). - Fase 2.3: Canvas con árbol visual de la mejor expresión: BFS para asignar posiciones, elipses coloreadas (verde=hoja, azul=función), aristas grises. Se actualiza en cada generación.
- Fase 3.1: Nuevo DominioBooleano (
DominioBooleano.java), terminalTerminalBooleano, funcionesFuncionAnd/Or/Not/Xor. Lee tablas de verdad TSV. Nuevo ficherotablaVerdad.txt(función mayoría 3 bits). Tests:DominioBooleanoTest(6 tests).
Tests: 30 tests, 0 fallos.
Archivos nuevos main: FuncionSeno, FuncionCoseno, FuncionNegacion, FuncionValorAbsoluto, FuncionAnd, FuncionOr, FuncionNot, FuncionXor, TerminalBooleano, DominioBooleano.
Archivos modificados main: Nodo, Funcion, Individuo, AlgoritmoGenetico, DominioAritmetico, AppGP.
Archivos nuevos test: DominioBooleanoTest.
Archivos modificados test: DominioFitnessTest, TesterDemoValores.
Datos nuevos: valoresSeno.txt, valoresMultiVar.txt, tablaVerdad.txt.
Resumen:
- AppGP reescrita: ya no usa reflexión ni
calcularFitness(alg). Configura dominio (definirValoresPrueba, terminales, funciones con "+", "-", "*", "/"), algoritmo consetGeneracionListener; ejecutaalg.ejecutar(dominio)dentro de unTask<Void>. En cada generación el listener actualiza en el hilo JavaFX el gráfico de fitness y el área de la mejor expresión; al finalizar se dibujan en el otro gráfico los puntos degetValoresPrueba()y la curva del mejor individuo evaluada en 50 puntos. - DominioFitnessTest: el test
calcularFitness_asignaFitnessAlIndividuofallaba porque con parsimonia el fitness puede ser negativo (0 puntos − α·nodos). Se cambió la aserción aDouble.isFinite(ind.getFitness()) && ind.getFitness() <= 1.0. - README: descripción de la GUI, nuevos ficheros de datos (valoresLineal, valoresCubica), estructura actualizada (main/java, gui), funcionalidad actual (parsimonia, profundidad, división, constantes, logger, GUI) y tests (EvolucionLogger, constantes).
Archivos modificados: src/main/java/gui/AppGP.java, src/test/java/test/DominioFitnessTest.java, README.md.
Archivos nuevos:
valoresX2.txt: 7 puntos (x, x²) con x desde -3 a 3 (tab-separado). Sirve para comprobar si el GP encuentra una expresión como( * x x ).src/test/java/test/TesterDemoValores.java: runner que cargavaloresX2.txt, imprime un encabezado explicando el objetivo y ejecuta el algoritmo. Ejecutar desde la raíz del proyecto.
Archivos modificados: README.md (sección de ejecución y estructura: mención a valoresX2.txt y TesterDemoValores).
Motivo: Tener un caso de prueba con función conocida (parábola) para validar el comportamiento del algoritmo sin depender solo de valores.txt (polinomio más complejo).
Resumen:
- 1. Unificar cruce: TesterCruce usa ahora
IAlgoritmo.cruce()(AlgoritmoGenetico con terminales/funciones y semilla); eliminada la clase PruebaCruce (duplicaba la lógica de cruce). - 2. Datos y README: Añadida en README nota explícita: directorio de trabajo = raíz del proyecto para localizar valores.txt / valoresReducido.txt.
- 3. Configuración por argumentos: TesterAlgoritmoProgramacionGenetica acepta un argumento opcional: ruta del fichero de datos; por defecto "valores.txt". README actualizado con ejemplo de uso.
- 4. Parada temprana: En AlgoritmoGenetico.ejecutar(), al alcanzar el fitness objetivo se imprime "Objetivo de fitness alcanzado." antes del break.
- 5. Javadoc API: Mejorado Javadoc de clase en AlgoritmoGenetico, Individuo y DominioAritmetico; corregido typo en IIndividuo (funciones/terminales) y en IDominio (distinas → distintas); corregido param en Individuo.crearIndividuoAleatorioRec (funciones).
- 6. Tests de borde: CruceIntegracionTest: nuevo test cruce_unProgenitorUnNodo_completaConReintentos (un progenitor con un solo nodo, otro con varios; reintentos hasta éxito). DominioFitnessTest: nuevo test ficheroVacio_fitnessBuscadoCero_calcularFitnessDevuelveCero (fichero vacío, fitnessBuscado 0, calcularFitness devuelve 0).
Archivos modificados: TesterCruce.java, TesterAlgoritmoProgramacionGenetica.java, README.md, AlgoritmoGenetico.java, IIndividuo.java, IDominio.java, Individuo.java, DominioAritmetico.java, CruceIntegracionTest.java, DominioFitnessTest.java. Eliminado: PruebaCruce.java.
Resumen de la revisión:
- IndividuoYArbolTest: Correctos (creación aleatoria, número de nodos, crearSubarbolAleatorio, reemplazarNodo raíz/hijo, calcularExpresion). Coherentes con
Individuo. - MutacionTest: Correctos (mutar devuelve individuo válido, semilla, original inalterado).
- CruceIntegracionTest: Correctos (dos descendientes, progenitores no modificados, crearNuevaPoblacion con reintentos).
- AlgoritmoGeneticoIntegracionTest: Correctos (crearPoblacion, crearNuevaPoblacion con/sin mutación, ejecutar con fichero temporal).
- DominioFitnessTest: Correctos (terminales, funciones, excepción longitud, definirValoresPrueba, fitnessBuscado, calcularFitness y asignación al individuo; valor 2.0 para "x" con (0,0) y (1,1) coincide con la fórmula del dominio).
- TesterCruce: Reintento ante CruceNuloException ya añadido; flujo correcto.
- TesterIndividuos: Correcto (árbol manual, writeIndividuo, crearIndividuoAleatorio).
- TesterLecturaYFitness: Corregido
throws IOException, IOException→throws IOException. - TesterAlgoritmoProgramacionGenetica: Añadido
returntras capturarArgsDistintosFuncionesExceptionpara no ejecutar con estado indefinido. - PruebaCruce: Lógica de cruce por subárbol correcta (intercambio de referencias, sin doble uso de nodos).
Archivos modificados: TesterLecturaYFitness.java, TesterAlgoritmoProgramacionGenetica.java.
Archivos modificados: src/test/java/test/TesterCruce.java
Resumen: Cuando los dos puntos de cruce salen en la raíz (etiqueta 1), PruebaCruce.cruce lanza CruceNuloException (cruce considerado nulo). El main de TesterCruce ahora reintenta hasta 20 veces; solo si todos fallan se muestra el error. Así se evita que una ejecución aleatoria acabe en excepción por mala suerte.
Cambios:
- Código principal movido a
src/main/java/(paquetesalgoritmogenetico,excepciones). - Tests y runners movidos a
src/test/java/test/. pom.xml: eliminadossourceDirectory,testSourceDirectoryyexcludes; se usan los valores por defecto de Maven.
Archivos afectados: pom.xml, toda la estructura bajo src/.
Motivo: Con todo bajo src/ y src/test/, el IDE y algunos runners no resolvían bien el classpath (JUnit en scope test, separación main/test). La estructura estándar (src/main/java, src/test/java) hace que Maven y el IDE (Java Language Server / Red Hat Java) asignen correctamente dependencias de test y ejecuten JUnit y los Tester* sin errores de classpath.
Qué hacer en el IDE: Recargar el proyecto Maven (por ejemplo: "Java: Clean Java Language Server Workspace" y reabrir, o desde paleta "Maven: Update project") para que tome las nuevas carpetas de código.
Archivos nuevos:
README.md: presentación del proyecto (requisitos, construcción, estructura, funcionalidad, tests, documentación, historial). Pensado para ampliarse en cada iteración.
Archivos nuevos:
doc/DOCUMENTACION.md: documentación unificada (visión general, arquitectura, operadores, dominio, ejecución, tests). Pensada para ampliarse en cada iteración.pom.xml: Maven con JUnit 5 para compilar y ejecutar tests (mvn test).src/test/IndividuoYArbolTest.java: tests de Individuo y árbol (creación aleatoria, número de nodos, crearSubarbolAleatorio, reemplazarNodo, calcularExpresion).src/test/MutacionTest.java: tests del operador de mutación (individuo válido, semilla, original no modificado).src/test/CruceIntegracionTest.java: tests del cruce (dos descendientes, progenitores inalterados, crearNuevaPoblacion).src/test/AlgoritmoGeneticoIntegracionTest.java: tests de integración (crearPoblacion, crearNuevaPoblacion con/sin mutación, ejecutar una generación con fichero temporal; 80 % cruce para evitar bucle infinito).src/test/DominioFitnessTest.java: tests del dominio aritmético (terminales, funciones, definirValoresPrueba, calcularFitness).
Resumen:
- Documentación en
doc/DOCUMENTACION.mdcubre base y mutación; nota sobre paridad (tamanioPoblacion - referencia) para que crearNuevaPoblacion termine. - Tests comprueban lo implementado (individuo, mutación, cruce, algoritmo, dominio) y se pueden ampliar con cada nueva funcionalidad.
- En los tests de integración se usa probabilidad de cruce 80 % para evitar bucle infinito cuando los individuos a añadir son impares.
Motivo: Tener una base documental y de pruebas que crezca con el proyecto.
Archivos modificados:
src/algoritmogenetico/individuo/Individuo.javasrc/algoritmogenetico/IAlgoritmo.javasrc/algoritmogenetico/AlgoritmoGenetico.javasrc/test/TesterAlgoritmoProgramacionGenetica.java
Resumen:
- Mutación: Nuevo operador que elige un nodo al azar en el árbol y sustituye su subárbol por uno aleatorio de profundidad máxima 2 (constante
PROFUNDIDAD_SUBARBOL_MUTACION). Se aplica a cada descendiente tras el cruce con probabilidad configurable. - Individuo:
crearSubarbolAleatorio(profundidadMax, terminales, funciones, rng)reutiliza la lógica de creación de árboles;reemplazarNodo(etiqueta, nuevoSubarbol)sustituye el nodo por etiqueta (raíz o hijo). - IAlgoritmo: Método
IIndividuo mutar(IIndividuo individuo). - AlgoritmoGenetico: Campo
probabilidadMutacion(por defecto 0 en el constructor de 5 parámetros). Constructores de 6 y 7 parámetros para fijar probabilidad de mutación y semilla. Integración encrearNuevaPoblacion(): tras cada cruce, cada descendiente se muta con probabilidadprobabilidadMutacionantes de añadirse a la nueva población. - Tester: Usa
probabilidadMutacion = 0.15para ejercitar la mutación.
Motivo: Completar el esquema GP estándar (selección + cruce + mutación) y permitir exploración adicional de la búsqueda.
Archivos modificados:
src/algoritmogenetico/dominio/DominioAritmetico.javasrc/algoritmogenetico/AlgoritmoGenetico.javasrc/algoritmogenetico/individuo/Individuo.javasrc/algoritmogenetico/individuo/nodo/INodo.javasrc/algoritmogenetico/individuo/nodo/Nodo.javasrc/algoritmogenetico/individuo/nodo/terminales/TerminalAritmetico.javasrc/test/PruebaCruce.java
Resumen:
- Recursos:
definirValoresPruebausa try-with-resources para cerrarBufferedReaderautomáticamente. - Comparación de fitness: Uso de
Comparator.comparingDouble(IIndividuo::getFitness)en torneo y bestFitness para evitar overflow y seguir prácticas habituales. - CruceNuloException: Reintentos (hasta 50) en
crearNuevaPoblacion; si falla todo, se añaden copias de los ganadores del torneo para mantener el tamaño de la población. - Random: Un único
RandomenAlgoritmoGenetico(constructor conLong semillaopcional para reproducibilidad); se pasa a la creación de individuos. - Nomenclatura:
INodo.getRaiz()renombrado agetSimbolo();Individuo.getRaiz(INodo)renombrado agetPadre(INodo). - Nodo.copy(): Método declarado abstracto en
Nodopara forzar implementación en subclases concretas. - TerminalAritmetico: Constructor
TerminalAritmetico(String simbolo, double valor)y@Overrideencalcular().
Motivo: Preparar el proyecto para GitHub y futuras extensiones; mejorar robustez y claridad sin cambiar el comportamiento observable.