//Operador Genético de cruce de tipo one-point public void Cruce_unpunto(ref Cromosoma cromosoma2, out Cromosoma hijo1, out Cromosoma hijo2) { int punto = TheSeed.Next(1, Poblacion.numTrabajadores); hijo1 = new Cromosoma(); hijo2 = new Cromosoma(); CopiarInformacionCromosoma(hijo1); CopiarInformacionCromosoma(hijo2); int cont = 0; for (int i = 0; i < Poblacion.numTrabajadores; i++) { for (int j = 0; j < Poblacion.numPuestosDeTrabajo; j++) { if (i < punto) { hijo1.TheArray.Add(TheArray[cont]); hijo2.TheArray.Add(cromosoma2.TheArray[cont]); } else { hijo1.TheArray.Add(cromosoma2.TheArray[cont]); hijo2.TheArray.Add(TheArray[cont]); } cont++; } } }
//Se copia la información de un cromosoma a otro public void CopiarInformacionCromosoma(Cromosoma dest) { Cromosoma cromosoma = dest; cromosoma.Length = Length; cromosoma.TheMin = TheMin; cromosoma.TheMax = TheMax; }
//Se copia la información y contenido de un cromosoma a otro public void CopiarCromosoma(out Cromosoma dest) { dest = new Cromosoma(); dest.Length = Length; dest.TheMin = TheMin; dest.TheMax = TheMax; dest.FitnessActual = FitnessActual; for (int i = 0; i < Length; i++) { dest.TheArray.Add(TheArray[i]); } }
//Ordena los cromosomas de la generación actual y actualiza el fitness total de dicha generación private void RankPopulation() { totalFitness = 0.0; for (int i = 0; i < PoblacionActual; i++) { Cromosoma cromosoma = (Cromosoma)Cromosomas[i]; totalFitness += cromosoma.FitnessActual; } Cromosomas.Sort(new ComparadorCromosoma()); double fitness = 0.0; tablaFitness.Clear(); for (int j = 0; j < PoblacionActual; j++) { fitness += ((Cromosoma)Cromosomas[j]).FitnessActual; tablaFitness.Add(fitness); } }
//Este constructor, genera la población inicial public Poblacion(ArrayList trab, ArrayList proc, int td) { //Se inicializan las variables principales de Población numTrabajadores = trab.Count; numPuestosDeTrabajo = proc.Count; duracionTurno = td; procesos = proc; trabajadores = trab; for (int i = 0; i < poblacionInicial; i++) { //Aquí se generan los cromosomas de la poblacion inicial Cromosoma cromosoma = new Cromosoma(numPuestosDeTrabajo * numTrabajadores, kMin, kMax); cromosoma.CalcularFitness(); Cromosomas.Add(cromosoma); } //Se proceden a ordenar los cromosomas de menor a mayor fitness RankPopulation(); }
private static void Main(string[] args) { int duracionTurno = 0; //Indica la duracion total de un dia de trabajo en minutos ArrayList trabajadores = new ArrayList(); ArrayList procesos = new ArrayList(); //Se procede a leer la data inicial desde un archivo .csv leerDataEntrada(trabajadores, procesos, ref duracionTurno); StreamWriter reporte = new StreamWriter("reporte.txt"); var watch = System.Diagnostics.Stopwatch.StartNew(); //Se genera la población inicial int generacion = 1; //Indica el numero de la generacion Poblacion poblacion = new Poblacion(trabajadores, procesos, duracionTurno); //Se obtiene el mejor cromosoma de la poblacion inicial Cromosoma mejorCromosoma = poblacion.obtenerMejorCromosoma(); Cromosoma ultimoCromosoma = new Cromosoma(); reporte.WriteLine("Población inicial"); reporte.WriteLine("Mejor cromosoma"); mejorCromosoma.mostrarCromosoma(reporte); int repetido = 0, i = 0; // Condicion de parada del algoritmo genetico while ((i < MAX_ITERACIONES) && (repetido < MAX_REPETIDOS)) { reporte.WriteLine(); reporte.WriteLine("Generación " + generacion); // Generar la siguiente generacion poblacion.SiguienteGeneracion(); //Se obtiene el mejor cromosoma de la actual generacion Cromosoma nuevoCromosoma = poblacion.obtenerMejorCromosoma(); //Se compara si el mejor cromosoma de la generacion actual es mejor que el mejor cromosoma historico if (nuevoCromosoma.FitnessActual > mejorCromosoma.FitnessActual) { mejorCromosoma = nuevoCromosoma; } if (Math.Truncate(nuevoCromosoma.FitnessActual) == Math.Truncate(ultimoCromosoma.FitnessActual)) { //Si el mejor cromosoma de la generacion actual es igual al mejor cromosoma de la generacion anterior repetido++; } else { //Si el mejor cromosoma de la generacion actual no es igual al mejor cromosoma de la generacion anterior repetido = 0; } generacion++; i++; // Se guarda el mejor cromosoma actual para tenerlo en cuenta en la siguiente generacion ultimoCromosoma = nuevoCromosoma; reporte.WriteLine("Mejor cromosoma:"); nuevoCromosoma.mostrarCromosoma(reporte); } reporte.WriteLine(); reporte.WriteLine("RESULTADOS"); reporte.WriteLine("Mejor cromosoma global"); mejorCromosoma.mostrarCromosoma(reporte); reporte.Close(); // Se muestran las asignaciones correspondientes //Console.WriteLine("Asignaciones"); //mejorCromosoma.mostrarAsignaciones(); mejorCromosoma.exportarCSV(); watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Console.WriteLine("Tiempo del algoritmo {0} segundos.", elapsedMs / 1000.0); Console.WriteLine("Fitness del mejor cromosoma {0}.", mejorCromosoma.FitnessActual); Console.WriteLine("Presione ENTER para continuar"); Console.ReadLine(); }
//Esta función acciona el operador genético de cruce y de mutación public void Cruce(ArrayList cromosomas) { CromosomasResultantes.Clear(); ArrayList CromosomasMadre = new ArrayList(); ArrayList CromosomasPadre = new ArrayList(); //Se procede a repartir equitativamente los cromosomas para generar los cruces posteriores repartirCromosomas(cromosomas, CromosomasMadre, CromosomasPadre); //Se proceden a realizar los cruces entre padre y madre escogiendo estos por el método de la ruleta for (int j = 0; j < CromosomasPadre.Count; j++) { Cromosoma hijo1; Cromosoma hijo2; int ind1 = RouletteSelection(); //Indica el indice del cromosoma padre int ind2 = RouletteSelection(); //Indica el indice del cromosoma madre Cromosoma padre = (Cromosoma)CromosomasPadre[ind1]; Cromosoma madre = (Cromosoma)CromosomasMadre[ind2]; //Dependiendo de la frecuencia de cruce, puede que se haga cruce o no if (Cromosoma.TheSeed.NextDouble() < frecuenciaCruce) { //Se procede a accionar el operador genético de cruce de tipo uniforme padre.Cruce_uniforme(ref madre, out hijo1, out hijo2); //Se verifica que los cromosomas después del cruce sigan siendo validos en estructura if (!hijo1.esValido()) { padre.CopiarCromosoma(out hijo1); } if (!hijo2.esValido()) { madre.CopiarCromosoma(out hijo2); } } else { padre.CopiarCromosoma(out hijo1); madre.CopiarCromosoma(out hijo2); } // Dependiendo de la frecuencia de mutación, puede que se mute o no if (Cromosoma.TheSeed.NextDouble() < frecuenciaMutacion) { // Se procede a accionar el operador genético de mutación hijo1.Mutar_intercambio(); hijo2.Mutar_intercambio(); // Se verifica que los cromosomas después de la mutación sigan siendo validos en estructura if (!hijo1.esValido()) { padre.CopiarCromosoma(out hijo1); } if (!hijo2.esValido()) { madre.CopiarCromosoma(out hijo2); } } // Se agrupan los hijos para generar la siguiente generación CromosomasResultantes.Add(hijo1); CromosomasResultantes.Add(hijo2); } }
//Devuelve el mejor cromosoma de la generación actual public Cromosoma obtenerMejorCromosoma() { Cromosoma valor = (Cromosoma)Cromosomas[PoblacionActual - 1]; return(valor); }