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