public List <Cromosoma> Cruce(Cromosoma progenitor1, Cromosoma progenitor2, System.Random rnd) { String aux; // Lista de piezas de cada progenitor (no tendrán espacios y solo representan un orden entre las piezas de dicho progenitor) // Lista de operadores de cada progenitor (tendrá espacios en los que colocaremos las piezas) // Separar la parte de piezas de la parte de operadores para el progenitor1 List <String> progenitor1_listaPiezas, progenitor1_listaOperadores; SepararPiezasYOperadores(progenitor1, out progenitor1_listaPiezas, out progenitor1_listaOperadores); // Separar la parte de piezas de la parte de operadores para el progenitor2 List <String> progenitor2_listaPiezas, progenitor2_listaOperadores; SepararPiezasYOperadores(progenitor2, out progenitor2_listaPiezas, out progenitor2_listaOperadores); // Se crea un diccionario vacio cuyas claves son cadenas y los valores son listas de cadenas, // solo iterando la lista de piezas Dictionary <string, List <string> > mapping_relaciones = new Dictionary <string, List <string> >(); // Inicializar el diccionario con listas vacias en los valores de los keys foreach (string genPieza in progenitor1_listaPiezas) { mapping_relaciones.Add(genPieza.Substring(0, genPieza.Length - 1), new List <string>()); } // Ahora, escoger dos número que delimitarán el segmento aleatorio de la lista // de piezas que serán intercambiados entre los progenitores para formar un hijo // el segundo numero debe ser mayor al primero!! int primerCorte = rnd.Next(0, progenitor1_listaPiezas.Count - 2); int segundoCorte = rnd.Next(primerCorte, progenitor1_listaPiezas.Count - 1); // ----------------------------------------------------------------------------------- // Crossover para los operadores: Debe ser ordenado // ----------------------------------------------------------------------------------- // Determinar qué operadores del primer progenitor serán intercambiados con los operadores en el segundo List <bool> paraIntercambiar = new List <bool>(); int cantPiezas = 0; // Esto contará las piezas for (int i = 0; i < progenitor1_listaOperadores.Count; ++i) { if (progenitor1_listaOperadores[i] == "") { ++cantPiezas; } if (cantPiezas >= primerCorte && cantPiezas < segundoCorte && progenitor1_listaOperadores[i] != "") { paraIntercambiar.Add(true); } else { paraIntercambiar.Add(false); } } int cantOperadoresEncontrados; for (int i = 0; i < progenitor1_listaOperadores.Count; ++i) { if (paraIntercambiar[i]) { // Cuenta el número de operadores que tiene el gen hasta aquí (variable i) cantOperadoresEncontrados = 0; for (int j = 0; j <= i; ++j) { if (progenitor1_listaOperadores[j] != "") { ++cantOperadoresEncontrados; } } // Una vez contados, obtenemos el operador que será intercambiado en el segundo progenitor for (int j = 0; j < progenitor2_listaOperadores.Count; ++j) { // Primero, revisar si es un operador, si lo es, restamos 1 de la cantidad de operadores encontrados if (progenitor2_listaOperadores[j] != "") { --cantOperadoresEncontrados; } if (cantOperadoresEncontrados == 0) { // intercambiar aux = progenitor1_listaOperadores[i]; progenitor1_listaOperadores[i] = progenitor2_listaOperadores[j]; progenitor2_listaOperadores[j] = aux; break; } } } } // ----------------------------------------------------------------------------------- // Crossover para las piezas // ----------------------------------------------------------------------------------- // Intercambia un subgrupo entre los progenitores for (int i = primerCorte; i <= segundoCorte; ++i) { // Guardar la pieza del 1er progenitor antes de removerlo aux = progenitor1_listaPiezas[i]; progenitor1_listaPiezas.RemoveAt(i); // Insertar la pieza del 2do progenitor en la posición removida del 1er progenitor progenitor1_listaPiezas.Insert(i, progenitor2_listaPiezas[i]); // Remueve la pieza del 2do progenitor progenitor2_listaPiezas.RemoveAt(i); // Insertar la pieza del 1er progenitor en la posición removida del 2do progenitor progenitor2_listaPiezas.Insert(i, aux); } // Una vez intercambios, se deben corregir para evitar soluciones no validas // Determinar las relaciones de ambos progenitores usando el diccionario mapping_relaciones for (int i = primerCorte; i <= segundoCorte; ++i) { //mapping_relaciones[progenitor1_listaPiezas[i]].Add(progenitor2_listaPiezas[i]); //mapping_relaciones[progenitor2_listaPiezas[i]].Add(progenitor1_listaPiezas[i]); mapping_relaciones[progenitor1_listaPiezas[i].Substring(0, progenitor1_listaPiezas[i].Length - 1)].Add(progenitor2_listaPiezas[i]); mapping_relaciones[progenitor2_listaPiezas[i].Substring(0, progenitor2_listaPiezas[i].Length - 1)].Add(progenitor1_listaPiezas[i]); } Utilitarios.unfold_relationships(mapping_relaciones); // Las piezas desde [0; primerCorte-1] y del [segundoCorte+1; tamListaPiezas-1] van a cambiar* si están en el rango [primerCorte, segundoCorte], // con el fin de no tener piezas repetidas en un mismo cromosoma // * Serán cambiadas por un número (pieza) de su mapping_relaciones que no esté en toda la lista de genes de piezas // Segmento izquierdo CorregirPiezas(progenitor1_listaPiezas, progenitor2_listaPiezas, mapping_relaciones, primerCorte, segundoCorte, 0, primerCorte - 1); // Segmento derecho CorregirPiezas(progenitor1_listaPiezas, progenitor2_listaPiezas, mapping_relaciones, primerCorte, segundoCorte, segundoCorte + 1, progenitor1_listaPiezas.Count - 1); // ----------------------------------------------------------------------------------------- // Unir la lista de operadores con la lista de piezas para fomar los nuevos descendientes // ----------------------------------------------------------------------------------------- // Insertar la lista de piezas en los espacios de la lista de operadores del progenitor 1 Cromosoma descendiente1 = UnirOperadoresYPiezas(progenitor1_listaOperadores, progenitor1_listaPiezas); // Insertar la lista de piezas en los espacios de la lista de operadores del progenitor 2 Cromosoma descendiente2 = UnirOperadoresYPiezas(progenitor2_listaOperadores, progenitor2_listaPiezas); List <Cromosoma> descendientes = new List <Cromosoma>(); descendientes.Add(descendiente1); descendientes.Add(descendiente2); return(descendientes); }
public bool Mutacion(Cromosoma cromosoma, System.Random rnd) { List <String> listaGenes = cromosoma.ListaGenes; // Escoger 2 diferentes posiciones de genes aleatorios int posGen1 = rnd.Next(0, listaGenes.Count - 1); int posGen2 = rnd.Next(posGen1 + 1, listaGenes.Count); // Ahora, revisamos que son // Si ambos genes son piezas, podemos intercambiarlos sin problemas if (Utilitarios.EsPieza(listaGenes[posGen1]) && Utilitarios.EsPieza(listaGenes[posGen2])) { String aux = listaGenes[posGen1]; listaGenes[posGen1] = listaGenes[posGen2]; listaGenes[posGen2] = aux; } else if (!Utilitarios.EsPieza(listaGenes[posGen1])) { String aux = listaGenes[posGen1]; listaGenes[posGen1] = listaGenes[posGen2]; listaGenes[posGen2] = aux; } // Si el gen1 es pieza y el gen2 es un operador else if (Utilitarios.EsPieza(listaGenes[posGen1]) && !Utilitarios.EsPieza(listaGenes[posGen2])) { int cantOperadores = 0; int cantPiezas = 0; // Debemos verificar que cada posición entre los genes p1 y p2 verifica que No <= Np - 3 for (int i = 0; i < listaGenes.Count; ++i) { if (Utilitarios.EsPieza(listaGenes[i])) { ++cantPiezas; } else { ++cantOperadores; } if (i >= posGen1 && i <= posGen2) { if (!(cantOperadores <= cantPiezas - 3)) { return(false); } } } // Si se cumple la condición, entonces el intrecambio es posible String aux = listaGenes[posGen1]; listaGenes[posGen1] = listaGenes[posGen2]; listaGenes[posGen2] = aux; } listaGenes[posGen1] = Utilitarios.RotarPiezaAleatorio(listaGenes[posGen1], rnd); listaGenes[posGen2] = Utilitarios.RotarPiezaAleatorio(listaGenes[posGen2], rnd); cromosoma.ListaGenes = listaGenes; return(true); }
public void CorregirPiezas(List <String> progenitor1_listaPiezas, List <String> progenitor2_listaPiezas, Dictionary <string, List <string> > mapping_relaciones, int primerCorte, int segundoCorte, int posIni, int posFin) { String aux; for (int i = posIni; i <= posFin; ++i) // segmento { for (int j = primerCorte; j <= segundoCorte; ++j) // segmento interno { if (Utilitarios.CompararPiezas(progenitor1_listaPiezas[i], progenitor1_listaPiezas[j])) // significa que el elemento interno debe ser intercambiado por un elemento de su mapping_relaciones, que no está en la cadena { // Para cada elemento de la relación foreach (string el in mapping_relaciones[Utilitarios.ObtenerPieza(progenitor1_listaPiezas[j])]) { // Si el elemento no está en la lista de piezas, entonces intercambiar //Comparison<String> compPiezas = new Comparison<String>(Utilities.CompararPiezas); //if (!progenitor1_listaPiezas.Contains(el, StringComparer.OrdinalIgnoreCase)) //if (!progenitor1_listaPiezas.Contains(el)) bool contiene = progenitor1_listaPiezas.Any(x => Utilitarios.ObtenerPieza(x) == Utilitarios.ObtenerPieza(el)); if (!contiene) { // in "el" we have the element that can be swapped with the "repeated number in 1", we must find it in outter 2 to make the swap for (int k = 0; k < primerCorte; ++k) { if (Utilitarios.CompararPiezas(el, progenitor2_listaPiezas[k])) { // Save the element of 1 to aux aux = progenitor1_listaPiezas[i]; progenitor1_listaPiezas[i] = el; progenitor2_listaPiezas[k] = aux; } } // Revisar también el lado derecho de la selección for (int l = segundoCorte + 1; l < progenitor2_listaPiezas.Count; ++l) { if (Utilitarios.CompararPiezas(el, progenitor2_listaPiezas[l])) { // Save the element of 1 to aux aux = progenitor1_listaPiezas[i]; progenitor1_listaPiezas[i] = el; progenitor2_listaPiezas[l] = aux; } } } } } } } }