免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發新帖
查看: 35386 | 回復: 0
打印 上一主題 下一主題

求精簡和修改perl6寫的遺傳算法GA [復制鏈接]

論壇徽章:
0
跳轉到指定樓層
1 [收藏(0)] [報告]
發表于 2020-01-04 18:46 |只看該作者 |倒序瀏覽
本帖最后由 aef25u 于 2020-01-06 19:21 編輯

仿照python用perl6實現了最簡單的遺傳算法,但感覺臃腫,請大牛幫精簡或改寫地更perler一些,只改部分代碼均行。
其中:1、dot函數自已實現的只適用簡單情況,不知perl6有沒有現成的或哪個模塊能提供?
        2、np.random.choice(python版函數),我用自己想的方法進行模擬(位于select()函數內),求改寫地更簡潔或更好的版本
  1.     my @p=@fitness.map: {$_/sum(@fitness)};
  2.     my %h=(0..@p.elems-1).map: {$_=>($POP_SIZE* @p[$_]*10).round(1)+1};
  3.     my @sample;
  4.     for %h.kv -> $key, $value {
  5.         #say("$key=>$value");
  6.         push(@sample,$key) for (1..$value);      
  7.     }
  8.     my @samshuffle=@sample.sort: { rand };
  9.     my @idx = @samshuffle.roll($POP_SIZE);
復制代碼



  1. my $DNA_SIZE = 10;            # DNA 長度
  2. my $POP_SIZE = 100;           # 種群總數
  3. my $CROSS_RATE = 0.8;        # 交叉配對比率 (DNA crossover)
  4. my $MUTATION_RATE = 0.003;    # 變異率 mutation probability
  5. my $N_GENERATIONS = 200;      # 繁殖代數
  6. my @X_BOUND = (0, 5);         # x坐標范圍

  7. sub dot(@a,@b) {
  8.     fail "Vector @a length not equal to @b!" unless +@a == +@b;
  9.     my @c = @a <<*>> @b;
  10. }

  11. # 查找某函數在X_BOUND范圍內的最大值
  12. sub F(@x) {return @x.map:{sin(10*$_)*$_ + cos(2*$_)*$_}}

  13. #適應度函數(y值占所有y值合計的占比越大越有優勢)
  14. #如果函數會產生負值,將橫坐標軸下移,令所有y值均大于0,
  15. #因遺傳選擇時select(),@p=@fitness.map: {$_/sum(@fitness)};不能為負值且分母不能為0
  16. sub get_fitness(@pred) { return @pred.map: {$_ + 1e-3 - min(@pred)}}

  17. # DNA翻譯規則:即x,二進制表示的DNA轉為十進制,并將其歸一化至(0, 5)
  18. sub translateDNA(@pop){return @pop.map: { [+](dot($_,(0..^$DNA_SIZE).reverse.map: { 2** $_} )) / (2**$DNA_SIZE-1)*@X_BOUND[1]}}

  19. #遺傳選擇函數,適者生存,不適者淘汰
  20. #按編號返回優勢者個體列表;$p參數:表示選擇標準(此例中按照比例來選擇,適應度得分高的p有越大的概率被留下來)
  21. sub select(@pop, @fitness){
  22.     my @p=@fitness.map: {$_/sum(@fitness)};
  23.     my %h=(0..@p.elems-1).map: {$_=>($POP_SIZE* @p[$_]*10).round(1)+1};
  24.     my @sample;
  25.     for %h.kv -> $key, $value {
  26.         #say("$key=>$value");
  27.         push(@sample,$key) for (1..$value);      
  28.     }
  29.     my @samshuffle=@sample.sort: { rand };
  30.     my @idx = @samshuffle.roll($POP_SIZE);
  31.     return @pop[@idx];
  32. }

  33. #繁衍,優勢個體作為父親,按交叉配對比率CROSS_RATE在優勢種群中選擇母親,生成小孩
  34. sub crossover($parent, @pop) {
  35.     if (rand <  $CROSS_RATE) {
  36.         my $i=(0..^$POP_SIZE).roll(1);
  37.         say("PARENT<=>MOTHER:["~$parent~"]<=>["~ @pop[$i]~"]");
  38.         my @cross_points =Bool.roll($DNA_SIZE);
  39.         say(@cross_points);
  40.         @cross_points[$_] ?? ($parent[$_]=@pop[$i][$_]) !! $parent[$_] for (0..@cross_points.elems-1);
  41.         say("CHILD:["~$parent~"]");
  42.         }
  43.         return $parent;
  44. }


  45. #變異(在DNA_SIZE中的每一位(0/1)基因根據變異率MUTATION_RATE突變為(1/0))
  46. sub mutate($child) {
  47.      for 0..^$DNA_SIZE ->$point {
  48.           if rand < $MUTATION_RATE {
  49.                  ($child[$point] == 0) ?? ($child[$point] = 1) !! 0;
  50.           }
  51.     }
  52.     return $child;
  53. }

  54. sub Pop{
  55.      my @pop;
  56.      @pop[$_]= roll($DNA_SIZE, ^2).Array for ^$POP_SIZE;
  57.      return @pop;
  58. }

  59. ### 01INPUT:初始化種群DNA
  60. my @pop=Pop();
  61. #say(@pop);

  62. for (1..$N_GENERATIONS) {
  63.     #二進制DNA轉為十進制并輸入函數,得出y值
  64.     my @F_values = F(translateDNA(@pop));
  65.    
  66.     ### 02PROCESS:遺傳選擇過程
  67.     #計算適應度得分,評價個體的優劣
  68.     my @fitness = get_fitness(@F_values);

  69.     my $midx=@fitness.first: * == max(@fitness), :k;
  70.     my $MF_pop=@pop[$midx];
  71.     say("Most fitted DNA: ["~$MF_pop~"]"~translateDNA(Array($MF_pop)));
  72.     #say(@fitness[$midx] ~"="~max(@fitness));

  73.     #模擬自然環境的優勝劣汰,輸入種群與適應度得分,返回優勢種群
  74.     my @pop_sel = select(@pop, @fitness);
  75.     my @pop_copy=@pop_sel;
  76.     for @pop_sel -> $parent  is rw {
  77.          #在優勢種群中找到母親,并與父親進行繁衍
  78.          my $child = crossover($parent, @pop_copy);
  79.          ###03OUTPUT:產生更多優勢個體
  80.          #變異
  81.          $child = mutate($child);
  82.          #小孩列表更換為父親列表
  83.          $parent= $child;
  84.          say("Most fitted CHILD=>["~$parent~"]"~translateDNA(Array($parent)));
  85.     }
  86. }
復制代碼




您需要登錄后才可以回帖 登錄 | 注冊

本版積分規則 發表回復

  

北京盛拓優訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網監中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區
中國互聯網協會會員  聯系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP
   日韩综合区视频第一页导航,无码JK粉嫩小泬在线观看,午夜精品A片一区二区三区,日日躁夜夜躁狠狠躁麻豆,大胆国模,免费观看无遮挡www的网站