1. 程式人生 > >品鑒同事發來的遺傳算法

品鑒同事發來的遺傳算法

get str pri elf list true vol 遺傳算法 rand

<?php

class GA{
    public static $length ;
    public static $count;
    public static $population;

    /**
     * GA constructor.
     * @param $length
     * @param $count
     * 長度
     * 生成的數量
     */
    public function __construct($length,$count){
        self::$length = $length;
        self
::$count = $count; self::$population = self::gen_population($length,$count); } public static function gen_population($length, $count){ $population = []; for($i=0;$i<$count;$i++){ $population[] = self::gen_chromosome($length); } return $population
; } public static function gen_chromosome($length){ $str = 0; for($i=0;$i<$length;$i++){ $str |=(1<<$i)*mt_rand(0,1); } return $str; } /** * @param float $retain_rate * @param float $random_select_rate * @param float $mutation_rate * 進化
*/ public function evolve($retain_rate = 0.2,$random_select_rate = 0.5,$mutation_rate = 0.01){ $parents = self::selection($retain_rate,$random_select_rate); self::crossover($parents); self::mutation($mutation_rate); } /** * @param $retain_rate * @param $random_select_rate * @return array * 選擇 */ public static function selection($retain_rate, $random_select_rate){ $graded = []; foreach(self::$population as $v){ $graded[] = [self::fitness($v),$v]; } rsort($graded); $graded = array_column($graded,1); $retain_length = intval(count($graded)*$retain_rate); $parents = array_slice($graded,0,$retain_length); foreach(array_slice($graded,$retain_length,count($graded)-$retain_length) as $v){ //lcg_value()隨機生成0-1浮點數 if(lcg_value() < $random_select_rate){ $parents[] = $v; } } return $parents; } public static function fitness($chromosome){ $x = self::decode($chromosome); return $x + 10*sin(5*$x) + 7*cos(4*$x); } public static function decode($chromosome){ return $chromosome * 9.0 / (pow(2,self::$length)-1); } /** * @param $parents * 交叉 *染色體的交叉、繁殖,生成新一代的種群 */ public static function crossover($parents){ //新出生的孩子,最終會被加入存活下來的父母之中,形成新一代的種群。 $children = []; //需要繁殖的孩子的量 $target_count = count(self::$population)-count($parents); while(count($children) < $target_count){ $male = rand(0,count($parents)-1); $female = rand(0,count($parents)-1); if($male != $female){ $cross_pos = rand(0,self::$length); //生成掩碼,方便位操作 $mask = 0; for($i=0;$i<$cross_pos;$i++){ $mask |= (1<<$i); } $male = $parents[$male]; $female = $parents[$female]; $child = (($male & $mask) | ($female & ~$mask)) & ((1<<self::$length)-1); $children[] = $child; } } self::$population = array_merge($parents,$children); } /** * @param $rate * 變異 * 對種群中的所有個體,隨機改變某個個體中的某個基因 */ public static function mutation($rate){ foreach(self::$population as $k => $v){ if(lcg_value() < $rate){ $j = rand(0,self::$length-1); self::$population[$k] ^= 1 << $j; } } } public function result(){ foreach(self::$population as $v){ $graded[] = [self::fitness($v),$v]; } rsort($graded); $graded = array_column($graded,1); return self::decode($graded[0]); } public static function println($data){ echo "<br>".$data."<br>"; } } if(!function_exists("array_column")) { function array_column($array=array(),$value="",$key="",$key_prefix="") { //模擬實現PHP5.5的array_column $list=array();//初始化返回數組 $is_need_all=$value==="*";//是否需要獲取整個數組 $is_need_key=$key!=="";//是否需要key if($is_need_key) { //說明有key 直接取當前遍歷的 value 字段 或者當前遍歷元素 $key=$key_prefix.$key;//拼接前綴 foreach($array as $v) { $tmp= $is_need_all ? $v : (isset($v[$value])?$v[$value]:""); $list[$v[$key]]=$tmp; } } else { //說明沒有key直接把數組元素返回到數組中去 foreach($array as $v) { $tmp= $is_need_all ? $v : (isset($v[$value])?$v[$value]:""); $list[]=$tmp; } } return $list; } } $t1 = microtime(true); $ga = new GA(17,100); for($i=1;$i<=100;$i++){ $ga->evolve(); } //var_dump($ga::$population); echo $ga->result()."<br>"; $t = microtime(true)-$t1; echo "time:".$t;

品鑒同事發來的遺傳算法