2016-04-25 3 views
-1

Ich weiß, dass dies eine Art Anfängerfrage ist, aber ich bin wirklich mit meinem Code ratlos. Im Erstellen eines Programms, das zufällige Buchstaben nimmt und es in einer bestimmten Anzahl von Generationen zu Ihrem Namen entwickelt. Ich habe die ganze Logik richtig, aber ich bekomme eine unendliche Schleife von verschiedenen Buchstaben, wenn ich das Programm starte. Ich habe 3 Klassen, Genome, das Mutate und Crossover enthält, Population, die jeden Brutzyklus genannt wird und die Genome in einer Liste speichert, und ein Main, das die day() -Methode aufruft, bis die Fitness der Zeichenkette 0 ist nicht gepostet.Entwickelnde Strings? Wie finde ich die Ursache einer Endlosschleife?

Ich denke, mein Problem ist das Sortieren der Genome, weil meine Mutate und Crossover scheinen gut zu funktionieren. Ich verwende merge sort, um die Genome zu sortieren, und habe Collections.sort mit einem Komparator ausprobiert, und es hat nicht funktioniert. Wenn jemand mein Programm ansehen könnte, um vielleicht den Fehler zu finden, wäre das großartig! Ich bin ratlos und habe eine Weile hier festgesteckt. Das ist eine Aufgabe, also wäre ein Hinweis nett. Hier

ist Genom:

 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(); 


} 

}

Hier Bevölkerung ist:

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); 
    } 
} 

hier meine Ausgabe lautet:

("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. 

HINWEIS
Ich erkannte, dass wenn ich die Liste ausdrucke, die alle Genome in der Populationsklasse speichert, es sich nicht korrekt zum Zielnamen entwickelt, aber es tut es immer noch.

GELÖST
Siehe meine Antwort unten, wie ich das Problem gelöst.

Antwort

0

Ich habe das Problem gefunden. Es war etwas sehr Seltsames. In meiner Genom Klasse aktualisiere ich die Fitness-Methode dazu:

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; 
} 

, die mein ganzes Programm festgelegt, und es läuft jetzt gut.

Verwandte Themen