【发布时间】: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