Beispiel #1
0
                         QTDE_MAXIMA_GERACOES   = 3000;                     // qtde máxima de gerações
        /// <summary>
        /// Entry point do programa
        /// </summary>
        /// <param name="args">parâmetros da linha de comando</param>
        static void Main(string[] args)
        {
            bool flgHouveTroca = false,                                     // true indica que houve troca
                 flgRodeioIgual = false;                                    // true indica que seleção repetida (duplicidade)
            int   i, j, k, m, n, p;                                         // indices e contadores genéricos
            Int64 x, y, z,                                                  // variáveis do programa
                  nValorEquacao   = 0,                                      // valor da equação
                  nMelhorAvalicao = 0,                                      // indivíduo com a melhor avaliação no rodeio
                  nResultado      = 0;                                      // valor a ser obtido na solução da equação
            int nIndice           = QTDE_BITS_CADA_VARIAVEL - 2,            // indice inicial para conversão binário / decimal
                nPontoDeCorte     = 0,                                      // ponto de corte para cruzamento
                nBitMutacao       = 0,                                      // indice do bit a ser mutado
                nPrimeiroPai      = 0,                                      // indice do primeiro pai selecionado
                nSegundoPai       = 0;                                      // idem para o cruzamento

            // vetor par seleção dos individuos com método rodeio
            int[] nPartRodeio = new int[QTDE_INDIVIDUOS_RODEIO];
            // dimensionar a população
            populacao = new stINDIVIDUO[QTDE_INDIVIDUOS_POPULACAO];
            // dimensionar e calcular os pesos de 2 ^^ 30 até 2 ^^ 0
            pesos = new Int64[QTDE_BITS_CADA_VARIAVEL - 1];
            for (i = 0; i < QTDE_BITS_CADA_VARIAVEL - 1; i++, nIndice--)
            {
                pesos[i] = Convert.ToInt64(Math.Pow(2, nIndice));
            }
            // pedir o valor da equação
            do
            {
                try
                {
                    Console.Write("Resultado da equação: 3x + 2z - 2y = ");
                    nResultado = Convert.ToInt64(Console.ReadLine());
                    break;                                                  // cai fora do do...while
                }
                catch (Exception)
                {
                    Console.WriteLine("Digite algarismos válidos!");
                    //throw;
                }
            } while (true);
            //
            // inicializar os cromossomos dos indivíduos da população
            Random rndSorteio = new Random(SEMENTE_RANDOM);

            for (i = 0; i < QTDE_INDIVIDUOS_POPULACAO; i++)
            {
                // dimensionar o cromossomo de cada indivíduo
                populacao[i].cIndividuo = new char[QTDE_BITS_CADA_INDIVIDUO];
                // loop para sorteio de '0' e '1'
                for (j = 0; j < QTDE_BITS_CADA_INDIVIDUO; j++)
                {
                    if (rndSorteio.Next() % 2 == 0)                         // "bit zero"?
                    {
                        populacao[i].cIndividuo[j] = '0';                   // "bit zero"
                    }
                    else
                    {
                        populacao[i].cIndividuo[j] = '1';                   // "bit um"
                    }
                } // for j
                populacao[i].nAvaliacao = 0;                                // zero de avaliação para o indivíduo
            } // for i
            // loop para todas as geraões possíveis
            for (j = 0; j < QTDE_MAXIMA_GERACOES; j++)
            {
                // loop de avaliação de cada indivíduo da população
                for (i = 0; i < QTDE_INDIVIDUOS_POPULACAO; i++)
                {
                    // calcular x, y, z e aplicar na equação
                    x = CalcularVariavel(populacao[i].cIndividuo, INDICE_X);
                    y = CalcularVariavel(populacao[i].cIndividuo, INDICE_Y);
                    z = CalcularVariavel(populacao[i].cIndividuo, INDICE_Z);
                    // aplicar na equação
                    try
                    {
                        nValorEquacao           = (3 * x) + (2 * z) - (2 * y);
                        populacao[i].nAvaliacao =
                            Math.Abs(nResultado - nValorEquacao);           // aptidão
                    }
                    catch (Exception)
                    {
                        populacao[i].nAvaliacao = Int64.MaxValue;           // pior possível
                        //throw;
                    }
                    // verificar se a equação foi resolvida
                    if (populacao[i].nAvaliacao == 0)                        // chegou ao resultado
                    {
                        Console.WriteLine(
                            "Equação resolvida: x = {0} y = {1} z = {2}\nGeração: {3}",
                            x, y, z, (j + 1));
                        Console.WriteLine("Digite qualquer tecla para encerrar...");
                        Console.ReadKey();
                        return;
                    }
                } // for i - loop de avaliação
                // solução não foi encontrada]
                // 1. Classificar a população para isolar a elite (elitismo)
                // 2. Selecionar dois pais para a elite para o cruzamento
                //      Operador da seleção será o rodeio
                // 3. Fazer o cruzamento entre dois pais gerando 2 novos indivíduos
                //      da população
                // 4. Fazer a mutação em cada novo indivíduo
                //
                // Classificar com o Bubble Sort
                do
                {
                    flgHouveTroca = false;                                         // não houve troca ainda
                    for (i = 0; i < QTDE_INDIVIDUOS_POPULACAO - 1; i++)
                    {                                                              // loop de comparação de avaliação de dois a dois indivíduos
                        if (populacao[i].nAvaliacao > populacao[i + 1].nAvaliacao) // fora de ordem?
                        {                                                          // fazer a troca de posições entre elem[i] e elem[i + 1]
                            stTrabalho       = populacao[i];                       // salva o elem[i]
                            populacao[i]     = populacao[i + 1];                   // troca o elem[i + 1]
                            populacao[i + 1] = stTrabalho;                         // troca o elem[i]
                            flgHouveTroca    = true;
                        }
                    } // for i
                } while (flgHouveTroca);                                // loop enquanto houver troca
                // temos a elite
                // loop de cruzamentos e mutação
                for (i = 0, k = INDICE_PRIMEIRO_FILHO; i < QTDE_CRUZAMENTOS; i++)
                {
                    // seleção do primeiro pai
                    nMelhorAvalicao = Int64.MaxValue;       // começa com a pior
                    //loop d seleção do primeiro pai
                    for (m = 0; m < QTDE_INDIVIDUOS_RODEIO; m++)
                    {
                        nPartRodeio[m] = rndSorteio.Next(PERCENTUAL_ELITISMO);     // sortear de 0 a 19
                        // loop para verificar se já foi sorteado
                        for (n = 0, flgRodeioIgual = false; n < m; n++)
                        {
                            if (nPartRodeio[n] == nPartRodeio[m])                       // mesmo indivíduo?
                            {
                                n--;                                                    // repete o sorteio
                                flgRodeioIgual = true;                                  // indica que é repetido
                                break;                                                  // cai fora do for n
                            }
                        }                                                               // for n
                        if (!flgRodeioIgual)                                            // não é repetido?
                        {                                                               // este "indice do indivíduo não foi sorteado antes"
                            if (populacao[nPartRodeio[m]].nAvaliacao < nMelhorAvalicao) // melhor?
                            {                                                           // melhor avaliação até agora
                                nMelhorAvalicao =
                                    populacao[nPartRodeio[m]].nAvaliacao;               // salva a melhor até agora
                                nPrimeiroPai = nPartRodeio[m];                          // possível primeiro pai
                            }
                        }
                    } // for m - primeiro pai
                    // temos o primeiro pai
                    // O mesmo para encontrar o segundo pai que não pode ser igual ao primeiro
                    do
                    {
                        // seleção do segundo pai
                        nMelhorAvalicao = Int64.MaxValue;       // começa com a pior
                        //loop d seleção do primeiro pai
                        for (m = 0; m < QTDE_INDIVIDUOS_RODEIO; m++)
                        {
                            nPartRodeio[m] = rndSorteio.Next(PERCENTUAL_ELITISMO);     // sortear de 0 a 19
                            // loop para verificar se já foi sorteado
                            for (n = 0, flgRodeioIgual = false; n < m; n++)
                            {
                                if (nPartRodeio[n] == nPartRodeio[m])                       // mesmo indivíduo?
                                {
                                    n--;                                                    // repete o sorteio
                                    flgRodeioIgual = true;                                  // indica que é repetido
                                    break;                                                  // cai fora do for n
                                }
                            }                                                               // for n
                            if (!flgRodeioIgual)                                            // não é repetido?
                            {                                                               // este "indice do indivíduo não foi sorteado antes"
                                if (populacao[nPartRodeio[m]].nAvaliacao < nMelhorAvalicao) // melhor?
                                {                                                           // melhor avaliação até agora
                                    nMelhorAvalicao =
                                        populacao[nPartRodeio[m]].nAvaliacao;               // salva a melhor até agora
                                    nSegundoPai = nPartRodeio[m];                           // possível segundo pai
                                }
                            }
                        } // for m - segundo pai
                    } while (nPrimeiroPai == nSegundoPai);              // repete o loop se mesmo pai
                    // termos agora o primeiro e o segundo pai para o cruzamento
                    nPontoDeCorte = rndSorteio.Next(1, QTDE_BITS_CADA_INDIVIDUO);
                    // vamos cruzar o primeiro filho
                    for (m = n = 0; m < nPontoDeCorte; m++)
                    {   // copiar a primeira parte do primeiro pai
                        stTrabalho.cIndividuo[n++] =
                            populacao[nPrimeiroPai].cIndividuo[m];
                    }                                         // for m
                    for (; m < QTDE_BITS_CADA_INDIVIDUO; m++) // copiar até o fim
                    {                                         // copiar a segunda parte do segundo pai
                        stTrabalho.cIndividuo[n++] =
                            populacao[nSegundoPai].cIndividuo[m];
                    }   // for m
                    // temos o primeiro filho = fazer a mutação
                    for (m = 0; m < QTDE_MUTACAO; m++)
                    {
                        nBitMutacao = rndSorteio.Next(QTDE_BITS_CADA_INDIVIDUO); // sorteia o bit
                        if (stTrabalho.cIndividuo[nBitMutacao] == '0')           // "bit zero"?
                        {
                            stTrabalho.cIndividuo[nBitMutacao] = '1';            // muta para bit um
                        }
                        else
                        {
                            stTrabalho.cIndividuo[nBitMutacao] = '0';   // muta para zero
                        }
                    } // for m
                    // temos o primeiro filho
                    populacao[k++] = stTrabalho;                        // novo indivíduo da população
                    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                    // vamos cruzar o segundo filho
                    for (m = n = 0; m < nPontoDeCorte; m++)
                    {   // copiar a primeira parte do primeiro pai
                        stTrabalho.cIndividuo[n++] =
                            populacao[nSegundoPai].cIndividuo[m];
                    }                                         // for m
                    for (; m < QTDE_BITS_CADA_INDIVIDUO; m++) // copiar até o fim
                    {                                         // copiar a segunda parte do segundo pai
                        stTrabalho.cIndividuo[n++] =
                            populacao[nPrimeiroPai].cIndividuo[m];
                    }   // for m
                    // temos o primeiro filho = fazer a mutação
                    for (m = 0; m < QTDE_MUTACAO; m++)
                    {
                        nBitMutacao = rndSorteio.Next(QTDE_BITS_CADA_INDIVIDUO); // sorteia o bit
                        if (stTrabalho.cIndividuo[nBitMutacao] == '0')           // "bit zero"?
                        {
                            stTrabalho.cIndividuo[nBitMutacao] = '1';            // muta para bit um
                        }
                        else
                        {
                            stTrabalho.cIndividuo[nBitMutacao] = '0';   // muta para zero
                        }
                    } // for m
                    // temos o segundo filho
                    populacao[k++] = stTrabalho;                        // novo indivíduo da população
                } // for i - loop de cruzamentos
            } // for j - loop de todas as gerações
            // todas as gerações foram executadas e a solulção não foi encontrada
            // calcular o x, y, z do indivíduo com o índice zero (melhor aptidão)
            x             = CalcularVariavel(populacao[0].cIndividuo, INDICE_X);
            y             = CalcularVariavel(populacao[0].cIndividuo, INDICE_Y);
            z             = CalcularVariavel(populacao[0].cIndividuo, INDICE_Z);
            nValorEquacao = (3 * x) + (2 * z) - (2 * y);
            Console.WriteLine("Equação não resolvida: x={0} y={1} z={2}", x, y, z);
            Console.WriteLine("Valor da equação = {0}", nValorEquacao);
            Console.WriteLine("Diferença={0}", (nResultado = nValorEquacao));
            Console.WriteLine("Digite qualquer tecla para encerrar...!");
            Console.ReadKey();
        } // main
Beispiel #2
0
                  QTDE_MAXIMA_GERACOES   = 3000;                   // qtde máxima de gerações

        /// <summary>
        ///
        /// </summary>
        /// <param name="args">parâmetros da linha de comando</param>
        static void Main(string[] args)
        {
            bool  flgHouveTroca = false;                        // true - indica que houve troca de posição
            int   i, j, k, l, m, n, p;                          // índices genéricos
            Int64 x, y, z,                                      // variáveis da equação
                  nValorEquacao = 0,                            // para calcular o valor da equação
                  nResultado;                                   // resultado da equação a ser obtido
            int nIndice       = QTDE_BITS_CADA_VARIAVEL - 2,    // índice do bit mais significativo do valor
                nPontoDeCorte = 0,                              // ponto de corte para o cruzamento
                nBitMutacao   = 0,                              // índice do bit para mutação
                nPrimeiroPai  = 0,                              // índice do primeiro pai para o cruzamento
                nSegundoPai   = 0;                              // idem do segundo pai

            populacao = new
                        stINDIVIDUO[QTDE_INDIVIDUOS_POPULACAO]; // dimensiona a população
            // definir e calcular os pesos para a quantidade de bits especificado
            pesos = new Int64[nIndice + 1];                     // dimensiona o vetor de pesos
            // loop para o cálculo dos pesos
            for (i = 0; i < QTDE_BITS_CADA_VARIAVEL - 1; i++, nIndice--)
            {
                pesos[i] = Convert.ToInt64(Math.Pow(2, nIndice));
            }
            // pedir o valor da equação a ser resolvida
            do
            {
                try
                {
                    Console.Write("Valor da equação: 3x + 2z - 2y = ");
                    nResultado = Convert.ToInt64(Console.ReadLine());
                    break;                                      // cai fora do while
                }
                catch (Exception)
                {
                    Console.WriteLine("Redigite o resultado corretamente!");
                }
            } while (true);
            // vamos sortear os bits do cromossomo de cada indivíduo da população
            Random rndSorteio = new Random(SEMENTE_RANDOM);

            // loop para inicializar os cromossomos da população da geração inicial
            for (i = 0; i < QTDE_INDIVIDUOS_POPULACAO; i++)
            {
                // dimensionar o cromossomo de cada indivíduo da população inicial
                populacao[i].cIndividuo = new char[QTDE_BITS_CADA_INDIVIDUO];
                // loop para criar os bits '0' e '1' de cada cromossomo
                for (j = 0; j < QTDE_BITS_CADA_INDIVIDUO; j++)
                {
                    if (rndSorteio.Next() % 2 == 0)              // bit zero?
                    {
                        populacao[i].cIndividuo[j] = '0';
                    }
                    else
                    {
                        populacao[i].cIndividuo[j] = '1';
                    }
                } // for j
                populacao[i].nAvaliacao = 0;
            }     // for i - população
            //
            // loop para todas as gerações possíveis
            for (j = 0; j < QTDE_MAXIMA_GERACOES; j++)
            {
                // loop de avaliação de cada indivíduo da população
                for (i = 0; i < QTDE_INDIVIDUOS_POPULACAO; i++)
                {
                    // calcular x, y e z e aplicar na equação e obter a aptidão
                    x = CalcularVariavel(populacao[i].cIndividuo, INDICE_X);
                    y = CalcularVariavel(populacao[i].cIndividuo, INDICE_Y);
                    z = CalcularVariavel(populacao[i].cIndividuo, INDICE_Z);
                    // aplicar na equação
                    try
                    {
                        nValorEquacao           = (3 * x) + (2 * z) - (2 * y);
                        populacao[i].nAvaliacao =
                            Math.Abs(nResultado - nValorEquacao);   // aptidão deste indivíduo
                    }
                    catch (Exception)
                    {
                        populacao[i].nAvaliacao = Int64.MaxValue;   // aptidão absurda
                    }
                    // verificar se a equação foi resolvida
                    if (populacao[i].nAvaliacao == 0)                // chegou ao resultado?
                    {
                        Console.WriteLine(
                            "Equação foi resolvida: x = {0} y = {1} z = {2}\nNa geração: {3}\nDigite qualquer tecla para encerrar o programa.",
                            x, y, z, (j + 1));
                        Console.ReadKey();                          // pausa
                        return;                                     // volta ao sistema operacional
                    }
                } // for i - população
                  // a população foi avaliada e a solução não foi encontrada nesta geração
                  // gerar uma nova população de soluções através dos seguintes operadores genéticos:
                  // 1. Seleção de 2 pais através do seguinte:
                  // 1.1 - Elitismo para isolar os melhores
                  // 1.2 - Seleção através do rodeio de pais da elite
                  // 2. Cruzamento entre dois pais selecionados da elite gerando 2 filhos
                  // 3. Mutação nos dois filhos gerados pelo cruzamentos ou crossover

                // para fazer o elitismo precisamos classificar os indivíduos da população
                // em ordem crescente de avaliação.
                do
                {
                    flgHouveTroca = false;                                         // não houve troca ainda
                    for (i = 0; i < QTDE_INDIVIDUOS_POPULACAO - 1; i++)
                    {                                                              // loop para comparação dois a dois indivíduos
                        if (populacao[i].nAvaliacao > populacao[i + 1].nAvaliacao) // fora de ordem?
                        {                                                          // fazer a troca de posição entre eleme[i] e elem[i+1]
                            stTrabalho       = populacao[i];                       // salva o elem[i]
                            populacao[i]     = populacao[i + 1];                   // troca o elem[i+]
                            populacao[i + 1] = stTrabalho;                         // troca o elem[i]
                            flgHouveTroca    = true;
                        }
                    } // for i
                } while (flgHouveTroca);
            }         // for j - loop de gerações
        }             // main