Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }