1

私は自分の名前と ID 番号を進化させるために遺伝的アルゴリズムを書かなければならない小さなプロジェクトをやっています。基本的に、ビット文字列をランダムに生成してから、ASCII 文字の文字列に生成し、生成がどれだけ近づくかを測定する必要があります。次に、ベスト 10 世代を変異させて、自分の名前と ID にできるだけ近づけようとします。

現在困っているのはアスキー世代です。最初のビット文字列に対しては正常に機能しますが、各ビット文字列が異なるにもかかわらず、残りのビット文字列に対して繰り返されます。誰でも問題を見ることができますか?どんな助けでも大歓迎です。

これまでのコード:

import java.util.Random ;

public class GeneticAlgorithm {

    public static void main(String[] args) throws Exception
    {
        int popSize = 0 ;
        int gen ;
        double repRate ;
        double crossRate ;
        double mutRate ;
        int seed = 9005970 ;
        String id = "John Connolly 00000000" ;
        int bits = 7 * id.length() ;
        String output ;
        int pop ;
        int bitGen ;

        Random rand = new Random(seed) ;
        ConvertToAscii convert = new ConvertToAscii() ;
        Fitness fit = new Fitness() ;

        try {
            popSize = Integer.parseInt(args[0]) ;
            if(popSize < 0 || popSize > 100000)
            {
                System.out.print("Invalid number! A positive number between 0 and 100000 must be used for the population rate!") ;
                System.exit(1) ; // Signifies system exit if error occurs
            }
            gen = Integer.parseInt(args[1]) ;
            if(gen < 0 || gen > 100000)
            {
                System.out.println("Invalid number! A positive number between 0 and 100000 must be used for the generation rate!") ;
                System.exit(1) ;
            }
            repRate = Double.parseDouble(args[2]) ;
            if(repRate < 0 || repRate > 1.0)
            {
                System.out.println("Invalid number! A positive decimal point number between 0 and 1.0 must be used for the reproduction rate!") ;
                System.exit(1) ;
            }
            crossRate = Double.parseDouble(args[3]) ;
            if(crossRate < 0 || crossRate > 1.0)
            {
                System.out.println("Invalid number! A positive decimal point number between 0 and 1.0 must be used for the crossover rate!") ;
                System.exit(1) ;
            }
            mutRate = Double.parseDouble(args[4]) ;
            if(mutRate < 0 || mutRate > 1.0)
            {
                System.out.println("Invalid number! A positive decimal point number between 0 and 1.0 must be used for the mutation rate!") ;
                System.exit(1) ;
            }
            if(repRate + crossRate + mutRate != 1.0)
            {
                System.out.println("The Reproduction Rate, Crossover Rate and Mutation Rate when sumed together must equal 1.0!") ;
                System.exit(1) ;
            }
            output = args[5] ;
            java.io.File file = new java.io.File(output);
            java.io.PrintWriter writeOut = new java.io.PrintWriter(file) ;
            StringBuffer bitString = new StringBuffer() ;
            int bestFit = 0, fitness = 0, totalFit = 0 ;
            String ascii = "" ;
            writeOut.println(popSize + " " + gen + " " + repRate + " " + crossRate + " " + mutRate + " " + output + " " + seed) ;
            for(pop = 0 ; pop < popSize ; pop++)
            {
                ascii = "" ;
                writeOut.print(pop + " ") ;
                for(int i = 0 ; i < bits ; i++)
                {
                    bitGen = rand.nextInt(2);
                    writeOut.print(bitGen) ;
                    bitString.append(bitGen) ;
                }
                ascii = convert.binaryToASCII(bitString) ;
                writeOut.print(" " + ascii) ;
                writeOut.println() ;
            }
            writeOut.close() ;
            System.exit(0) ;            

        } catch(ArrayIndexOutOfBoundsException e) {
            System.out.println("You have entered the incorrect number of arguments!") ;
            System.out.println("Please enter the required 6 arguments.") ;
            System.exit(1) ;
        } catch(NumberFormatException n) {
            System.out.println("Invalid argument type") ;
            System.exit(1) ;
        }
    }
}

変換コードは次のとおりです。

public class ConvertToAscii {

    public String binaryToASCII(StringBuffer bitString)
    {
        String ascii = "" ;
        String byteString ;
        int decimal ;
        int i = 0, n = 7 ;
        int baseNumber = 2 ;
        char asciiChar ;
        while(n <= 154)
        {
            byteString = bitString.substring(i, n) ;
            decimal = Integer.parseInt(byteString, baseNumber) ;
            System.out.print(" " + decimal) ;
            i += 7 ;
            n += 7 ;
            if(decimal < 33 || decimal > 136)
            {
                decimal = 32 ;
                asciiChar = (char) decimal ;
            } else {
                asciiChar = (char) decimal ;
            }
            ascii += asciiChar ;
        }
        return ascii ;
    }

}
4

2 に答える 2

2

同じ StringBuffer を何度も使用していて、決してクリアしていません。母集団の最初のメンバーを最初の 154 文字である StringBuffer に追加します。次に、2 番目のメンバーはスロット 155 ~ 308 にありますが、binaryToASCII() メソッドはスロット 154 を超えて検索することはありません。

毎回新しい StringBuffer を使用してみてください (そして、上でコメントしたように、スレッド化されていない環境ではより効率的であるため、StringBuilder を使用してみてください)。

于 2013-09-27T15:53:08.767 に答える
1

彼の回答で dcsohl が述べているように、反復ごとに同じ bitString を送信して評価しています。私はこの修正を行い、読みやすさ、コードの再利用、正しいデータ型のためにコードを少し最適化しました。

import java.util.Random ;

public class GeneticAlgorithm {
    public static void main(String[] args) throws Exception
    {
        int popSize = 0 ;
        int gen ;
        double repRate ;
        double crossRate ;
        double mutRate ;
        int seed = 9005970 ;
        String id = "John Connolly 00000000" ;
        int bits = 7 * id.length() ;
        String output ;
        int pop ;
        int bitGen ;

        Random rand = new Random(seed) ;
        ConvertToAscii convert = new ConvertToAscii() ;
        Fitness fit = new Fitness() ;

        try {
            popSize = validateIntArg(args[0], "population rate");
            gen = validateIntArg(args[1], "generation rate");

            repRate = validateDoubleArg(args[2], "reproduction rate");
            crossRate = validateDoubleArg(args[3], "crossover rate");
            mutRate = validateDoubleArg(args[4], "mutationRate") ;

            if(repRate + crossRate + mutRate != 1.0)
            {
                System.out.println("The Reproduction Rate, Crossover Rate and Mutation Rate when sumed together must equal 1.0!") ;
                System.exit(1) ;
            }
            output = args[5] ;
            java.io.File file = new java.io.File(output);
            java.io.PrintWriter writeOut = new java.io.PrintWriter(file) ;
            StringBuilder bitString = new StringBuilder() ;

            int bestFit = 0, fitness = 0, totalFit = 0 ;
            String ascii = "" ;
            writeOut.println(popSize + " " + gen + " " + repRate + " " + crossRate + " " + mutRate + " " + output + " " + seed) ;

            for(pop = 0 ; pop < popSize ; pop++)
            {
                bitString.setLength(0);
                writeOut.print(pop + " ");
                for(int i = 0 ; i < bits ; i++)
                {
                    bitGen = rand.nextInt(2);
                    writeOut.print(bitGen);
                    bitString.append(bitGen);
                }
                ascii = convert.binaryToASCII(bitString) ;
                writeOut.print(" " + ascii) ;
                writeOut.println();
            }
            writeOut.close() ;
            System.exit(0) ;            

        } catch(ArrayIndexOutOfBoundsException e) {
            System.out.println("You have entered the incorrect number of arguments!") ;
            System.out.println("Please enter the required 6 arguments.") ;
            System.exit(1) ;
         } catch(NumberFormatException n) {
            System.out.println("Invalid argument type") ;
            System.exit(1) ;
       }
    }

    private static int validateIntArg(String arg, String argName) {
        int n = Integer.parseInt(arg);
        if (n < 0 || n > 100000) {
            System.out.print("Invalid number! A positive number between 0 and 100000 must be used for the " + argName + "!") ;
            System.exit(1);
        }

        return n;
    }   

    private static int validateDoubleArg(String arg, String argName) {
        double n = Double.parseDouble(arg);
        if (n < 0 || n > 100000) {
            System.out.print("Invalid number! A positive decimal point number between 0 and 1.0 must be used for the " + argName + "!") ;
            System.exit(1);
        }

        return n;
    }   
}

クラス ConvertToAscii:

public class ConvertToAscii {

    public String binaryToASCII(StringBuilder bitString)
    {
        StringBuilder ascii = new StringBuilder();
        String byteString ;
        int decimal ;
        int i = 0, n = 7 ;
        int baseNumber = 2 ;
        char asciiChar ;
        while(n <= 154)
        {
            byteString = bitString.substring(i, n) ;
            decimal = Integer.parseInt(byteString, baseNumber) ;
            System.out.print(" " + decimal) ;
            i += 7 ;
            n += 7 ;
            if(decimal < 33 || decimal > 136)
            {
                decimal = 32 ;
            }
            asciiChar = (char) decimal ;
            ascii.append(asciiChar);
        }
        return ascii.toString();
    }

}
于 2013-09-27T16:17:04.500 に答える