zoukankan      html  css  js  c++  java
  • 品鉴同事发来的遗传算法

    <?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;
  • 相关阅读:
    给vs2012轻松换肤
    几种软件常用授权方式总结
    Discuz X2多人斗地主[消耗论坛积分]小体积版本,仅25MB!
    关于Socket 设置 IPAddress.Any 情况下,出现服务器积极拒绝的问题
    以前看过一个压缩过的.exe,运行会播放长达半小时的动画,却只有60KB,个人认为其中的原理
    VisualSvn Server安装和使用
    socket短时间内重连需注意的问题
    PostgreSQL在何处处理 sql查询之十一
    PostgreSQL在何处处理 sql查询之十三
    PostgreSQL在何处处理 sql查询之十四
  • 原文地址:https://www.cnblogs.com/lizhaoyao/p/8602270.html
Copyright © 2011-2022 走看看