2012-04-30 2 views
1

Я работаю над проектом на данный момент, чтобы попытаться создать простой генетический алгоритм. Что касается структуры, у меня есть Gene, который является char [] с четырьмя числами и хромосомой, которая представляет собой массив из 10 объектов гена.Глубокое копирование и генетический алгоритм

Я пытаюсь написать простой метод кроссовера, который создает дочерний элемент из половины каждой из родительских хромосом. Я начал с подхода ниже, но вскоре понял, что я просто мелкое копирование. Последние несколько дней я читал многочисленные сообщения об использовании клонированного интерфейса для реализации глубокого копирования, но я не увенчался успехом со всеми попытками. Пожалуйста, помогите мне с этим вопросом. Любые советы и указатели будут grately оценены

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

Являются ли «гены» изменчивыми? То есть существует ли какая-либо операция, которая может изменить их значение, не переназначая их? –

+0

Эй, Борис, у меня есть класс мутаторов, который повлияет на детскую хромосому. Вот почему мне нужны отдельные массивы для родительского и дочернего. –

+0

Да, и они уже являются отдельными массивами. Просто они имеют одни и те же объекты .gene. Я все еще не убежден, что это вызывает какие-либо проблемы. Потому что я не могу придумать операцию, которая изменит значение «гена». Можете ли вы поделиться типом этих объектов, и если он объявлен вами, включите их код в вопрос? –

ответ

2

Давайте сначала рассмотрим Gene класс: в соответствии с вашими требованиями (У меня есть ген, символ [] с четырьмя числами), вам нужен 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 класса (пожалуйста, прочитайте here для получения более подробной информации о копировании массива).

Простой тест для проверки функционирования глубокой копии в 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; 
    } 
} 
+0

Привет, enzom83, большое спасибо за ваш ответ. Я пытаюсь работать через ваше решение. С кодом child.setGene (i, parentA.getGene (i)) - метод setGene относится к методу setUnit в классе Gene? Как должны выглядеть эти методы setGene и getGene? Извиняюсь, я очень новичок в программировании (6 месяцев). Заранее спасибо –

+0

Извините, я забыл приложить весь класс Chromosome: теперь я добавил его. Вскоре я добавлю некоторые детали к своему ответу – enzom83

+0

Еще раз спасибо моему другу ..Я думаю, что теперь у меня это работает из-за вашего сообщения –

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



    } 

Я использовал семена и подсчитывал количество хромосом, потому что использовал эту переменную для атрибутов пригодности.

Смежные вопросы