본문 바로가기

backup

유전자 알고리즘 프로그래밍 코드

유전자 알고리즘 프로그래밍 소스 코드를 원하시면..

제가 대충 쓸려고 만든거라, 최적화 등등이 제대로 되어 있지 않지만, 제가 만든거 보여드리겠습니다. 참조용으로 쓰세요.



---------------------------------------------------------------------------------------------------------------------------------------------------------------------------


/*
 * Gene.h
 *
 *  Created on: Mar 4, 2014
 *      Author: whitesun
 */

#ifndef GENE_H_
#define GENE_H_

namespace Genetic {

class Chromosome {
public:
    char gene[100];

// 본래 bit로 하는게 맞지만, 개발 편의를 위해서 char 썼습니다. 여기에 들어가는 값이 0과 1만 되도록 프로그래밍하실때 주의하세요
    int length;
    int score;

    Chromosome()
    :length(0), score(0)
    {
        for(int i = 0; i < 100; ++i){
            gene[0] = 0;
        }
    }
    virtual ~Chromosome();
};

} /* namespace Genetic */

#endif /* GENE_H_ */




-------------------------------------------------------------------------------------------------------


#ifndef NATURE_H_
#define NATURE_H_

#include <vector>
#include "Chromosome.h"
#include <time.h>
#include <stdlib.h>
#include <iostream>

namespace Genetic {

class GeneticAlgorithm {

public:

    std::vector<Chromosome*> species;
    int crossRatio;
    int mutantRatio;


    GeneticAlgorithm(){
        crossRatio = 70;
        mutantRatio = 10;

// crossRatio는 교차율로 1/100 값이고 mutantRatio 변이율이고 1/1000 값입니다.
    }
    virtual ~GeneticAlgorithm();

    void setSpecies(Chromosome *gene){
        species.push_back(gene);

    }

    void select(){
        int sumpoint = 0;
        int size = species.size();
        srand((unsigned int) time(NULL));

//srand는 rand()의 seed 값을 정해주는 부분입니다. 사실 rand() 가 정확한 난수 발생기는 아니죠. rand()가 정확한 난수가 아니라는 것은 이 프로그램의 단점 중 하나입니다.


        std::vector<Chromosome*> descendants;

        for(int i = 0; i < size ; ++i){
            sumpoint += ((Chromosome*)species[i])->score;
        }

        int count = 0;

        while(count < size){
            Chromosome *A = species[selectOne(sumpoint, size)];
            Chromosome *B = species[selectOne(sumpoint, size)];

//각각의 최적 점수에 기반해서 두개의 유전자를 선택하는 부분입니다.



            Chromosome *dA = new Chromosome;
            Chromosome *dB = new Chromosome;;

            dA->length = A->length;
            dB->length = B->length;



            //두 부모 유전자를 교차시켜서 자식 유전자에게 내려주는 부분입니다. 저는 구간을 교차시키는 것이 아니라 각 유전자 각각을 교차시키는 방식으로 했는데, 이 방식이 우월하다는 학술적 근거는 딱히 없습니다. 이 방식도 값 찾는데는 무난하네요.
            for(int i = 0; i < dA->length; ++i){               
                if(rand()% 100 >= crossRatio){
                    dA->gene[i] = A->gene[i];
                    dB->gene[i] = B->gene[i];
                }else{
                    dA->gene[i] = B->gene[i];
                    dB->gene[i] = A->gene[i];
                }

                //교배시키고 바로 변이를 시켜줍니다.
                if(getMutantRatio() <= mutantRatio){
                    dA->gene[i] = (dA->gene[i] == 0)?1:0;
                }

                if(getMutantRatio() <= mutantRatio){
                    dB->gene[i] = (dB->gene[i] == 0)?1:0;
                }

            }

            descendants.push_back(dA);
            descendants.push_back(dB);

            count += 2;
        }

        species.clear();


        for(int i = 0; i < size ; ++i){
            species.push_back(descendants[i]);
        }

    }

private:


    //각각 적합도 점수에 기반해서 하나를 선택하는 부분입니다.
    int selectOne(int sumpoint, int size) {

        int point = rand() % sumpoint + 1;
        int subSum = 0;
        int pos = 0;
        for (; pos < size; ++pos) {
            subSum += ((Chromosome*) (species[pos]))->score;
            if (subSum >= point)
                break;
        }
        return pos;
    }

    int getMutantRatio() {
        int point = rand() % 1000+1;
        return point;
    }

};

} /* namespace Genetic */

#endif /* NATURE_H_ */


-----------------------------------------------------------------------------------------------------------------------


그리고 이 부분은 위에서 만든 클래스를 실제 돌리는 부분입니다.



    for(int i = 0; i < mmCount; ++i){


        Genetic::Chromosome* chromosome = new Genetic::Chromosome;
        lm[i]->setToChromosome(chromosome);

         //lm[i]는 제가 백테스트를 진행한 거래로직입니다. 거래로직으로부터 입력변수를 이진코드로 만든 값을 받습니다.
        GA.setSpecies(chromosome);
    }

    BackTest::BackTester* test = new BackTest::BackTester;


    int count = 0;

    while(count < 200){
        test->RunBackTest();

         //백테스트를 실행합니다.

        ++count;

        for(int i = 0; i < mmCount; ++i){

            lm[i]->ToString();

            //이 부분은 실행결과 화면에 보기 위한 부분입니다.


            GA.species[i]->score = lm[i]->GetScore();

            //백테스트를 실행한 뒤의 적합도 점수를 기록합니다.
        }

        GA.select();

        //유전자를 교차시킵니다.

        for(int i = 0; i < mmCount; ++i){
            lm[i]->getFromChromosome(GA.species[i]);         

            //이진코드로부터 입력변수를 입력 받습니다.
        }

   }