1

我目前正在做一个项目,试图创建一个简单的遗传算法。关于结构,我有一个基因,它是 char [],有四个数字和一个染色体,它是一个由 10 个基因对象组成的数组。

我正在尝试编写一个简单的交叉方法,从每个父染色体的一半创建一个孩子。我从下面的方法开始,但很快意识到我只是浅拷贝。在过去的几天里,我阅读了许多关于使用可克隆接口实现深度复制的文章,但所有尝试都没有成功。请有人帮我解决这个问题。任何提示和指示将不胜感激

public Chromosome createChild (Chromosome parentA, Chromosome parentB)
{
    Chromosome child=new Chromosome();
    for (int i=0;i<10; i++)
    {   
        if (i<5)
        {
            child.genes[i] = parentA.genes[i]; 
        }
        else
        {
            child.genes[i] = parentB.genes[i];
        }

    }   
    return child;       
}
4

2 回答 2

2

让我们首先考虑Gene该类:根据您的规范(我有一个 Gene 是 char [] 和四个数字),您需要一个char数组作为该类的属性。而且,这个类应该是可克隆的,那么你必须让这个类实现Cloneable接口:为此,你必须声明这个Gene类实现了Cloneable接口(简单地写implements Cloneable在类定义中)并且你必须实现clone这个类中的方法(在此方法中,您必须制作对象字段的深层副本并返回克隆的对象,请参阅下面的代码了解详细信息)。

import java.util.Arrays;

/*
 * Definition of the class that also includes the declaration
 * of the implementation of the Cloneable interface.
 */
public class Gene implements Cloneable {

    /*
     * The length of a gene.
     * It is defined as constant (final) in order to use the same value
     * in the whole class, where and when necessary.
     */
    private static final int GENE_LENGTH = 4;

    /*
     * In biology a gene it corresponds to a sequence of nucleic acids,
     * so I thought of naming m_sequence this field.
     */
    private char m_sequence[];

    /*
     * This constructor allows you to instantiate a new object from a char array.
     */
    public Gene(char sequence[]) {
        // The field m_sequence is initialized with a copy
        // of the array specified in the constructor.
        m_sequence = Arrays.copyOf(sequence, GENE_LENGTH);
    }

    /*
     * Simple getter method.
     * Since m_sequence is private, you need a method like this
     * in order to access elements of the array.
     */
    public char getUnit(int index) {
        return m_sequence[index];
    }

    /*
     * Simple setter method.
     * Since m_sequence is private, you need a method like this
     * in order to set the elements of the array.
     */
    public void setUnit(int index, char unit) {
        m_sequence[index] = unit;
    }

    /*
     * The Cloneable declaration requires that this class has clone method.
     * This method should return an Gene object within an Object.
     */
    protected Object clone() throws CloneNotSupportedException {
        // First, we invoke the clone method of the superclass
        Gene clone = (Gene)(super.clone());

        // Then, make the deep copy of the object.
        // In this case the only field present in the Gene object is an array,
        // then you must make a deep copy of this array: in order to make a deep
        // copy of the array, you should use the Arrays.copyOf method.
        clone.m_sequence = Arrays.copyOf(m_sequence, GENE_LENGTH);

        return clone;
    }

    /*
     * Get a representation of this object as a String.
     * Just a method for simple testing.
     */
    @Override
    public String toString() {
        return Arrays.toString(m_sequence);
    }
}

请注意,为了复制数组,我使用了类的方法copyOf(有关数组复制的更多详细信息,Arrays请阅读此处)。

一个简单的测试来检查Gene对象中深拷贝的功能:

public static void main(String args[]) throws CloneNotSupportedException {
    Gene g1 = new Gene(new char[]{'a', 'b', 'c', 'd'});
    Gene g2 = (Gene)(g1.clone());

    // now Let's modify g1
    g1.setUnit(0, 'e');
    g1.setUnit(1, 'f');
    g1.setUnit(2, 'g');
    g1.setUnit(3, 'h');

    System.out.println("g1: " + g1);
    System.out.println("g2: " + g2);   // g2 has not changed
}

所以,在你应该改变你的createChild方法如下。

public class Chromosome {
    private static final int CHROMOSOME_LENGTH = 10;

    /* Array of Gene object. */
    private Gene genes[];

    /* Default constructor. */
    public Chromosome() {
        // Simply allocates an array of 10 elements.
        genes = new Gene[CHROMOSOME_LENGTH];
    }

/*
     * Simple getter method.
     * Since m_Genes is private, you need a method like this
     * in order to access elements of the array.
     */
    public Gene getGene(int index) {
        return genes[index];
    }

/*
     * Simple setter method.
     * Since m_Genes is private, you need a method like this
     * in order to set the elements of the array.
     */
    public void setGene(int index, Gene gene) {
        genes[index] = gene;
    }

    /* The method which make the cross-over. */
    public Chromosome createChild(Chromosome parentA, Chromosome parentB) throws CloneNotSupportedException {
        Chromosome child = new Chromosome();

        // make the cross-over
        for (int i=0;i<10; i++)
        {   
            if (i<5)
            {
                // you need to call the clone() method
                child.genes[i] = (Gene)(parentA.genes[i].clone());
            }
            else
            {
                // you need to call the clone() method
                child.genes[i] = (Gene)(parentB.genes[i].clone());
            }
        }

        return child;
    }
}
于 2012-04-30T10:19:42.517 回答
0

我将以下代码用于我的调查项目的交叉。也许它可以帮助你。

 package geneticSource;

import java.util.*;
import java.util.Random;

public class Crossover { 
//                                          //Var for seeds
private Random rdn;            
private Random rdn2;
private Random rdn3;
private double PROB_CROSS=1;

public Crossover(double value,int seed){
    this.PROB_CROSS=value;  
    this.rdn= new Random(seed);
    this.rdn2= new Random(seed+1);
    this.rdn3= new Random(seed+2);
}



public Population Cross(Population p){
    int pointCross=0;        //Crossover point
    int n1=0;                
    int n2=0;
    double probCross=0;
    double probMut=0;
    Chromosome cr1=null;
    Chromosome cr2=null;
    List<Gen> mum1=new LinkedList<Gen>();
    List<Gen> dad1=new LinkedList<Gen>();
    List<Gen> mum2=new LinkedList<Gen>();
    List<Gen> dad2=new LinkedList<Gen>();
    ArrayList<Gen> geno1=new ArrayList<Gen>();
    ArrayList<Gen> geno2=new ArrayList<Gen>();
    Population pnew = new Population();
    //Integer[] cruce=new Integer [p.population.size()];
    ArrayList <Integer>cruceControl=new ArrayList<Integer>();
    for(int i=0;i<p.population.size();i++){
        cruceControl.add(i);
    }
    int aux=0;
    for(int i=0;i<p.population.size()/2;i++){

        n1=rdn.nextInt(cruceControl.size());
        aux=cruceControl.get(n1);
        cruceControl.remove(n1);    
        n1=aux;
        n2=rdn.nextInt(cruceControl.size());
        aux=cruceControl.get(n2);
        cruceControl.remove(n2);
        n2=aux;

        mum1=new LinkedList<Gen>();
        dad1=new LinkedList<Gen>();
        mum2=new LinkedList<Gen>();
        dad2=new LinkedList<Gen>();
        geno1=new ArrayList<Gen>();
        geno2=new ArrayList<Gen>();
        cr1=p.population.get(n1);
        cr2=p.population.get(n2);   

        probCross=this.rdn3.nextDouble();   
        probMut =this.rdn2.nextDouble();    
        if(probCross<=PROB_CROSS){               
            pointCross=rdn.nextInt(p.population.get(0).getChromosome().size());
            mum1=cr1.getChromosome().subList(0,pointCross );
            dad1=cr1.getChromosome().subList(pointCross,cr1.getChromosome().size() );
            mum2=cr2.getChromosome().subList(0,pointCross );
            dad2=cr2.getChromosome().subList(pointCross,cr2.getChromosome().size() );
            //cross;
            geno1.addAll(mum1);
            geno1.addAll(geno1.size(), dad2);
            geno2.addAll(mum2);
            geno2.addAll(geno2.size(), dad1);

            //Update the number for chromosome
            int Nva1=0;
            int Nva2=0;
            for(int j=0;j<geno1.size();j++){
                if(geno1.get(j).getValue()==1)Nva1++;
                if(geno2.get(j).getValue()==1)Nva2++;
            }
            p.population.set(n1, new Chromosome(geno1));
            p.population.get(n1).setNVariables(Nva1);
            p.population.set(n2, new Chromosome(geno2));
            p.population.get(n2).setNVariables(Nva2);
            if(Nva1<p.fminV) p.fminV=Nva1;
            if(Nva2<p.fminV) p.fminV=Nva2;
            if(Nva1>p.fmaxV) p.fmaxV=Nva1;
            if(Nva2>p.fmaxV) p.fmaxV=Nva2;

        }


    }
    int k=0;
    for(Chromosome c : p.getPopulation()){
        k=0;
        for(Gen g : c.getChromosome())
            if(g.getValue()==1)k++;
                    if(k!=c.getNVariables())System.out.println(".................................................................");
    }


    return p;
    }



  }

我使用了种子,并计算了染色体的数量,因为我将这个变量用于健身属性。

于 2014-12-17T19:37:40.847 回答