【问题标题】:Evolving strings? How to find the cause of an infinite loop?不断发展的弦乐?如何找到死循环的原因?
【发布时间】:2016-08-19 10:34:31
【问题描述】:

我意识到这是一个初学者的问题,但我真的被我的代码难住了。我正在创建一个程序,该程序将采用随机字母并在一定数量的世代内将其演变成您的名字。我的所有逻辑都是正确的,但是当我运行程序时,我得到了不同字母的无限循环。我有 3 个类,基因组,其中包含变异和交叉,种群在每个繁殖周期中被调用并将基因组存储在一个列表中,以及一个主类,它调用 day() 方法,直到字符串的适应度为 0,我有没有发布这个。

我认为我的问题是对基因组进行排序,因为我的变异和交叉似乎工作正常。我使用归并排序对基因组进行排序,并尝试了 Collections.sort 与比较器,但它没有用。如果有人可以查看我的程序以找到错误,那就太好了!我被难住了,并且已经坚持了一段时间。这是一个任务,所以提示会很好。

这里是基因组:

      import java.util.ArrayList;
import java.util.Random;

public class Genome {
/**
 * Data element initialized to name.
 */
private String target = "TEST NAME";
private StringBuilder myCurrentStr;
private double myMutationRate;
private Random myRandom = new Random();
private int myFitness = 100000;
private boolean isFitness;
private final char[] myCharList = "ABCDEFGHIJKLMNOPQRSTUVWXYZ -'".toCharArray();

/**
 * Initializes a Genome with value'A', 
 * assigns internal mutation rate.
 * @param mutationRate
 */

public Genome(double mutationRate) { // mutationrate must be between 0 and 1
    this.myMutationRate = mutationRate;
    myCurrentStr = new StringBuilder("A");
    //myFitness = 0;
    isFitness = false;
}

/**
 * Copy constructor, initializes a Genome with
 * the same values as the input gene.
 * @param gene
 */
public Genome(Genome gene) {
//  myCurrentStr = gene.myCurrentStr;
    this.myCurrentStr = new StringBuilder(gene.myCurrentStr);
    this.myFitness = gene.myFitness;
    myMutationRate = gene.myMutationRate;
    this.target = gene.target;
    this.isFitness = gene.isFitness;

}
public void setTarget(String name) {
    this.target = name;
}

/**
 * Mutates string in this Genome.
 */
public void mutate() {
    if(myRandom.nextDouble() <= myMutationRate) {
        addChar();
    }
    if(myRandom.nextDouble() <= myMutationRate) {
        deleteChar();
    }
    for(int i = 0; i < myCurrentStr.length(); i++) {
        if(myRandom.nextDouble() <= myMutationRate) {
            replaceChar(i);
        }
    }

}
public int getFitness() {
    if(!isFitness){
        fitness();
    }

    return myFitness;
}
private void addChar() {
    myRandom = new Random();
    int charIndex = myRandom.nextInt(29);
    int place = myRandom.nextInt(myCurrentStr.length() + 1);
    char letter = myCharList[myRandom.nextInt(myCharList.length)];


    if(place < myCurrentStr.length()) {
         myCurrentStr.insert(place, letter);
    }
    else{
        myCurrentStr.append(myCharList[charIndex]);
    }
}
private void replaceChar(int replaceHere) {
    if(replaceHere >= myCurrentStr.length()) {
        return;

    }
    myRandom = new Random();
    char letter = myCharList[myRandom.nextInt(myCharList.length)];
    myCurrentStr.setCharAt(replaceHere, letter);

}
private void deleteChar() {
    if(myCurrentStr.length() == 1) {
        return;
    }
    myRandom = new Random();
    int place = myRandom.nextInt(myCurrentStr.length());
    myCurrentStr.deleteCharAt(place);

}
/**
 * Will update current Genome by crossing it over
 * with other.
 * @param other
 */
public void crossOver(Genome other) {       
    Random rand = new Random();

    for(int i = 0; i < myCurrentStr.length(); i++) {
        int coinFlip = rand.nextInt(2);

        if(coinFlip == 0) {
            continue;

        } else {
            if(i < other.getString().length()){
                myCurrentStr.setCharAt(i, other.getString().charAt(i));

            } else{
                myCurrentStr.delete(i, myCurrentStr.length());
                break;
            }
        }
    }

}
public StringBuilder getString() {
    return myCurrentStr;

}
/**
 * Returns the fitness of the Genome calculated.
 * @return
 */
public Integer fitness() {
    int n = myCurrentStr.length();
    int m = target.length();
    int l = n < m ? n : m;
    int f = Math.abs(m-n) *2 ;

    for(int i = 0; i < l; i++) {
        if(myCurrentStr.charAt(i) != target.charAt(i)) {
            f = f + 1;
        } 
    }   
    myFitness = f;
    isFitness = true;
    return f;

}
public String toString() {
    StringBuilder result = new StringBuilder();
    result.append("(\"");
    result.append(myCurrentStr);
    result.append("\",");
    result.append(fitness());
    result.append(')');

    return result.toString();


}

}

这里是人口:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

public class Population {
/**
 * A data element that is equal
 * to the most fit Genome.
 */
public Genome mostFit = null;
private Integer myNumGenomes;
private Double myMutationRate;
private ArrayList<Genome> myGenomeList;

/**
 * Initializes a population with a number of 
 * default genomes.
 * @param numGenomes is 100
 * @param mutationRate is .05
 */
public Population(Integer numGenomes, Double mutationRate) {
    this.myNumGenomes = numGenomes;
    this.myMutationRate = mutationRate;
    this.myGenomeList= new ArrayList<Genome>(numGenomes);
    if(myMutationRate < 0 || myMutationRate > 1) {
        System.out.println("Mutation rate must be between 0 & 1.");
    }
    for(int i = 0; i < numGenomes; i++) {
        myGenomeList.add(new Genome(mutationRate));
    }
}
/**
 * Called every breeding cycle.
 */
public void day() {
    mergeSort(myGenomeList, 0, myGenomeList.size() - 1); // using merge sort 
    mostFit = myGenomeList.get(0);

    int i = myNumGenomes / 2;
    int j = myNumGenomes/2;
    while(i++ < myNumGenomes -1 ) {
        Random rand = new Random();
        int coinFlip = rand.nextInt(2);
        Genome selectedG = myGenomeList.get(rand.nextInt(j));

        if(coinFlip == 0) {
            Genome g2 = new Genome(selectedG);
            g2.mutate();
            myGenomeList.add(g2);
        } 
        else{
            Genome g2 = new Genome(selectedG);
            Genome g3 = myGenomeList.get(rand.nextInt(j));

            g2.crossOver(g3);
            g2.mutate();
            myGenomeList.add(g2);

        }

    }

}

private  void merge(List<Genome> list, int start, int finish){
    int mid = (start+finish)/2;
    int i = start;
    int j = mid + 1;
    List<Genome> temp = new ArrayList<Genome>();
    while(i < mid + 1 && j < finish + 1) {

        temp.add(list.get(i).getFitness()<list.get(j).getFitness()?list.get(i++):list.get(j++));
    }
    while(i < mid +1){
        temp.add(list.get(i++));
    }
    while(j < finish) {
        temp.add(list.get(j++));
    }
    for(i = 0;i<temp.size();i++){
        list.set(start+i, temp.get(i));
    }
}

private void mergeSort(List<Genome> list, int start, int finish){
    if(start < finish){
        int mid = (start + finish)/2;
        mergeSort(list,start,mid);
        mergeSort(list,mid+1,finish);
        merge(list, start,finish);
    }
}

这是我的输出:

 ("G",29)
 ("V",29)
("-",29)
("J",29)
("H",29)
("A",29)
("H",29)
("V",29)
("A",29)
("A",29)
("L",29) this continues infinitely, should be evolving into TEST NAME, or      target in the genome class. 

注意
我意识到,如果我打印出存储人口类中所有基因组的列表,它会演变为目标名称,虽然不正确,但它仍然会这样做。

已解决
请参阅下面的答案,了解我是如何解决这个问题的。

【问题讨论】:

    标签: java string loops sorting random


    【解决方案1】:

    我发现了问题。这是一件非常奇怪的事情。在我的基因组课程中,我将健身方法更新为:

        public Integer fitness() {
        int n = myCurrentStr.length();
        int m = target.length();
        int l = n < m ? n : m;
        int f = Math.abs(n - m) * 2; // in my code it was m - n, 
        for (int i = 0; i < l; i++) {
            if (myCurrentStr.charAt(i) != target.charAt(i))
                f = f + 1;
        }
        this.myFitness = f;
        this.isFitness = true;
        return f;
    }
    

    修复了我的整个程序,现在运行良好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-09
      • 1970-01-01
      • 1970-01-01
      • 2018-05-04
      • 2011-12-16
      • 1970-01-01
      • 2018-05-06
      • 1970-01-01
      相关资源
      最近更新 更多