基因演算法 - 猜數字

by sj82516

JavaScript

/*
*  簡單的基因演算法實踐
*  參考內容:http://www.theprojectspot.com/tutorial-post/creating-a-genetic-algorithm-for-beginners/3
*  題目:隨機生成 0,1組成的數字列(預設長度為50),如果採用暴力解需 2的50次方 才能解決,故用基因演算法嘗試在特定時間內找出最佳解
*  		 可打開console看log
*  Warning:這需要大量運算,所以瀏覽器話卡住一段時間
*/

// 單體,也就是個別解
class Individual {
	constructor(size){
    	this.size = size
        // 隨機生成基因列,ex. [1,0,1,....]
        this._genes = Array(size).fill(0).map( _ => + (Math.random()>0.5))
        // 暫存適應度
        this._fitness = 0
    }
    
    getFitness(){
    	if (this._fitness == 0) {
            this._fitness = Fitness.calcFitness(this);
        }
        return this._fitness;
    }
    
    // 設定單個基因
    setGene(pos, val){
    	this._genes[pos] = val
    }
    // 取得定單個基因
    getGene(pos){
    	return this._genes[pos]
    }
    
    // 取得基因長度
    size(){
    	return this._genes.length
    }
}

// 管理全部的individual
class Population {
	// 定義靜態變數
	static get GENE_SIZE() {
    	return 50
    }
    
    // 判斷是否為初始化,如果是則需要隨機產生單體,反之則否
	constructor(size, init){
   		this._size = size
    	this._individualList = Array(size).fill(0).map( _ => init?new Individual(this.constructor.GENE_SIZE):{})
    }
    
    // 找出適應度最好的基因
    getFitnessIndividual(){
    	return this._individualList.reduce(function(a, b) {
      		return a.getFitness() > b.getFitness() ? a:b
        })
    }
    
    size(){
    	return this._size
    }
    
    getIndividual(pos){
    	return this._individualList[pos]
    }
    setIndividual(pos, id){
    	this._individualList[pos] = id
    }
}

// Fintness計算
class Fitness{
    static setSolution(solution){
    	this._solution = solution
    }
    
    static calcFitness(id){
    	let score = 0
        this._solution.forEach((ele, i) => {
        	if(id.getGene(i) == ele) score ++
        })
        return score
    }
}

class GA {
	/* 定義靜態變數 */
    // A/B母體的基因遺傳機率(選A還選B)
	static get UNIFORM_RATE(){
     	return 0.5
    }
    // 基因突變的機率
    static get MUTATION_RATE(){
    	return 0.015
    }
    // 篩選法中的子群體數
   ...