zoukankan      html  css  js  c++  java
  • [python] 简单遗传算法与粒子群算法

    遺伝的アルゴリズム

    問題の説明

    遺伝的アルゴリズムを使用し、下記の関数の最大化及び最小化を実現しなさい。
    ただし、x1、x2、x3の取り得る値は0~15とし、それぞれの遺伝子型は4ビットのビット列で表現すること。
    選択、交叉、突然変異のパラメータは各自の自由とする。
    群の個体数は100とし、100世代まで進化させた際の、1~100世代における最良解のy値をグラフで示しなさい。選択、交叉、突然変異のパラメータも記載すること。

    このプロジェクトでは、遺伝的アルゴリズムをいくつかの小さな部分に分割し、それらを個別に実装する予定です。
    実行シーケンスは、遺伝子の初期化 → ベストバリュー計算 → 100回の繰り返し。
    繰り返しは一点交叉 → 突然変異 → 適応度計算 → ベストバリュー計算 → 出力 → 選択で構成されます。

    y=2x12-3x<sub>2</sub>2-4x1+5x2+x3

    適応度は上記の式で表されます

    グローバル変数を宣言する

    num = 100         # 個体数
    iteration = 100   # 世代数
    Pc = 0.3          # 交叉確率
    Pm = 0.05         # 突然変異確率
    

    データ構造

    100 * 13リストを作成して、0〜11番目は3 * 4ビットの変数を格納し、12番目は適合度を格納します。

    [[0,1,0,0,0,1,1,1,0,1,0,0,133] ,
     [0,1,0,0,0,1,1,1,0,1,0,0,123] ,
            … 合計100個 … 
     [0,1,0,0,0,1,1,1,0,1,0,0,223] ,
     [0,1,0,0,0,1,1,1,0,1,0,0,233]]
    

    初期世代の構造関数はランダム関数を呼び出し、ランダムに各ビットの0/1を生成します。次に、適応度計算関数を呼び出し、リストの12番目の場所に入力します。

    ci = []
        for i in range(num):  # 初期世代の個体群を構造
            temp = []
            for j in range(12):
                temp.append(rand(0.5))
            temp.append(calculate(temp))
            ci.append(temp)
    

    関数の実装

    ランダム関数
    import random
    def rand(a):
        if random.random() < a:
            return 1
        else:
            return 0
    
    適応度計算関数
    def calculate(lb):
        x1 = lb[0]*8 + lb[1]*4 + lb[2]*2 + lb[3]
        x2 = lb[4]*8 + lb[5]*4 + lb[6]*2 + lb[7]
        x3 = lb[8]*8 + lb[9]*4 + lb[10]*2 + lb[11]
        return 2*x1*x1 - 3*x2*x2 - 4*x1 + 5*x2 + x3
    
    出力関数
    def show(lb, ni):
        sum_l = 0
        max_l = 0
        min_l = 0
        for i in range(num):
            sum_l = sum_l + lb[i][12]
            if lb[i][12] > lb[max_l][12]:
                max_l = i
            if lb[i][12] < lb[min_l][12]:
                min_l = i
        sum_l = sum_l / num
        print(ni, ":平均値", sum_l, ",最大値", lb[max_l], ",最小値", lb[min_l])
    
    ベストバリュー計算
    • 最大値計算

      def cal_max(lb):
          max_l = 0
          for i in range(num):
              if lb[i][12] > lb[max_l][12]:
                  max_l = i
          return lb[max_l][12]
      
    • 最小値計算

      def cal_min(lb):
          min_l = 0
          for i in range(num):
              if lb[i][12] < lb[min_l][12]:
                  min_l = i
          return lb[min_l][12]
      

    コア関数の実装

    一点交叉関数

    一点交叉関数は100の遺伝子をランダムに50ペアに一致させ、特定の確率(このプログラムでは0.3に設定)で一点交叉を実行し、クロスポイントはランダムです。

    def cross(lb):
        tmp = []  # 個体の利用フラグ
        for i in range(num):
            tmp.append(False)
        for i in range(int(num/2)):
            p1 = random.randint(0, num-1)  # 親p1を決定
            while tmp[p1]:
                p1 = random.randint(0, num-1)
            tmp[p1] = True
            p2 = random.randint(0, num-1)  # 親p2を決定
            while tmp[p2]:
                p2 = random.randint(0, num-1)
            tmp[p2] = True
            point = random.randint(0, 11)  # 交叉点を決定
            if rand(Pc) == 1:
                for j in range(point):
                    t = lb[p1][j]
                    lb[p1][j] = lb[p2][j]
                    lb[p2][j] = t
            return lb
    
    突然変異関数

    突然変異関数に奇妙なbugが含まれています。リストで各ヘリターを直接操作した場合、10回を超える反復の後、ある操作がすると、操作された遺伝子はすべての遺伝子に自分自身をコピーします。 bugの原因は見つかりませんでしたが、新しいリストを作成してbugを回避するために戻るだけで済みました。

    def accident(lb):
        temp = []  # 新しいリストを作成
        for i in range(num):
            a = []
            for j in range(0, 12):  # すべての遺伝子のすべてを通過する
                if rand(Pm) == 1:  # 0-1の間の変換は、特定の確率で発生します
                    a.append((1 + lb[i][j]) % 2)
                else:
                    a.append(lb[i][j])
            a.append(0)
            temp.append(a)
        return temp
    
    選択関数

    最初に、各遺伝子の適応度を計算して正規化し、対応する数の遺伝子をリストに入力しました。乱数0 ≤ n < sumである限り、対応するインデックスにアクセスと、対応する遺伝子を取得します。

    def select_max(lb):
        min_l = cal_min(lb)  # 最小値計算
        sum_l = 0
        temp_l = []
        ci_l = []
        for i in range(num):  # 正規化
            lb[i][12] = lb[i][12] + abs(min_l)
            sum_l = sum_l + lb[i][12]
            for j in range(lb[i][12]):
                temp_l.append(lb[i])
        if sum_l is 0:
            return lb
        for i in range(num):  # リストを生成する
            a = random.randint(0, sum_l-1)
            ci_l.append(temp_l[a])  # 対応するインデックスにアクセス
        return ci_l
    

    ただし、リストアイテムを大量に追加する必要があるため、このアプローチのリスト生成速度は遅すぎます。 そのため、この状況に合わせて最適化されました。代わりに、100項目のリストを使用して、各遺伝子サブの適応度+以前のすべての遺伝子サブの適応度の合計を記録し、リストを後でたどりました。 乱数より大きい数値が表示された場合、それは選択する必要があるインデックス番号です。

    def select_max(lb):
        min_l = cal_min(lb)  # 最小値計算
        sum_l = 0
        temp_l = []
        ci_l = []
        for i in range(num):  # 正規化
            lb[i][12] = lb[i][12] + abs(min_l)
            sum_l = sum_l + lb[i][12]
            temp_l.append(sum_l)
        for i in range(num):  # リストを生成する
            a = random.random() * sum_l
            for j in range(num):
                if a < temp_l[j]:
                    ci_l.append(lb[j])  # 対応するインデックスにアクセス
                    break
        return ci_l
    

    そのような最適化の後、操作速度は大幅に改善されます

    演算結果

    最大を見つける
    1 : 平均値 -86.14 , 最大値 15 1 13 , 最小値 2 15 4
    2 : 平均値 4.4 , 最大値 15 1 13 , 最小値 3 15 10
    3 : 平均値 24.49 , 最大値 15 0 6 , 最小値 3 14 9
    4 : 平均値 94.56 , 最大値 15 0 11 , 最小値 1 14 2
    5 : 平均値 125.34 , 最大値 15 0 14 , 最小値 9 15 0
    6 : 平均値 164.72 , 最大値 15 0 10 , 最小値 9 15 9
    7 : 平均値 197.09 , 最大値 15 0 14 , 最小値 4 12 10
    8 : 平均値 215.71 , 最大値 15 2 15 , 最小値 9 12 8
    9 : 平均値 253.02 , 最大値 15 0 13 , 最小値 1 5 9
    10 : 平均値 256.97 , 最大値 15 0 13 , 最小値 7 12 13
    11 : 平均値 272.89 , 最大値 15 0 15 , 最小値 14 14 11
    12 : 平均値 263.58 , 最大値 15 0 15 , 最小値 7 15 3
    13 : 平均値 255.41 , 最大値 15 1 15 , 最小値 15 15 11
    14 : 平均値 269.75 , 最大値 15 1 15 , 最小値 12 14 11
    15 : 平均値 266.94 , 最大値 15 0 15 , 最小値 7 12 12
    16 : 平均値 257.24 , 最大値 15 0 15 , 最小値 3 5 13
    17 : 平均値 291.26 , 最大値 15 1 13 , 最小値 7 6 14
    18 : 平均値 288.23 , 最大値 15 1 13 , 最小値 14 13 1
    19 : 平均値 270.99 , 最大値 15 1 13 , 最小値 13 14 11
    20 : 平均値 267.73 , 最大値 15 1 13 , 最小値 2 9 11
    21 : 平均値 262.81 , 最大値 15 0 13 , 最小値 9 12 0
    22 : 平均値 265.99 , 最大値 15 0 13 , 最小値 7 14 11
    23 : 平均値 263.43 , 最大値 15 1 14 , 最小値 6 13 1
    24 : 平均値 255.39 , 最大値 15 0 12 , 最小値 8 13 5
    25 : 平均値 271.49 , 最大値 15 1 14 , 最小値 14 13 8
    26 : 平均値 257.18 , 最大値 15 0 12 , 最小値 13 15 0
    27 : 平均値 243.53 , 最大値 15 0 12 , 最小値 5 12 8
    28 : 平均値 253.7 , 最大値 15 0 13 , 最小値 7 14 14
    29 : 平均値 246.05 , 最大値 15 1 6 , 最小値 15 15 0
    30 : 平均値 260.21 , 最大値 15 2 14 , 最小値 13 15 11
    31 : 平均値 249.38 , 最大値 15 2 14 , 最小値 3 14 12
    32 : 平均値 246.18 , 最大値 15 2 14 , 最小値 15 15 2
    33 : 平均値 260.36 , 最大値 15 2 14 , 最小値 13 14 11
    34 : 平均値 239.45 , 最大値 15 2 13 , 最小値 10 12 4
    35 : 平均値 237.81 , 最大値 15 2 13 , 最小値 11 13 7
    36 : 平均値 237.08 , 最大値 15 1 12 , 最小値 5 7 4
    37 : 平均値 265.21 , 最大値 15 2 15 , 最小値 14 14 5
    38 : 平均値 271.42 , 最大値 15 1 11 , 最小値 12 14 10
    39 : 平均値 288.8 , 最大値 15 1 13 , 最小値 7 7 14
    40 : 平均値 279.2 , 最大値 15 1 14 , 最小値 14 12 1
    41 : 平均値 290.35 , 最大値 15 1 14 , 最小値 7 10 9
    42 : 平均値 298.95 , 最大値 15 1 14 , 最小値 7 9 9
    43 : 平均値 273.21 , 最大値 15 1 15 , 最小値 11 14 12
    44 : 平均値 296.45 , 最大値 15 1 15 , 最小値 3 8 8
    45 : 平均値 283.2 , 最大値 15 1 15 , 最小値 14 14 7
    46 : 平均値 288.22 , 最大値 15 0 15 , 最小値 6 6 7
    47 : 平均値 293.06 , 最大値 15 1 15 , 最小値 7 6 15
    48 : 平均値 288.76 , 最大値 15 0 15 , 最小値 7 11 11
    49 : 平均値 298.55 , 最大値 15 1 14 , 最小値 14 14 5
    50 : 平均値 296.83 , 最大値 15 1 14 , 最小値 11 12 11
    51 : 平均値 267.88 , 最大値 15 1 13 , 最小値 12 14 6
    52 : 平均値 246.19 , 最大値 15 2 15 , 最小値 14 15 13
    53 : 平均値 257.11 , 最大値 15 0 14 , 最小値 14 15 10
    54 : 平均値 276.37 , 最大値 15 2 15 , 最小値 11 15 14
    55 : 平均値 240.25 , 最大値 15 1 14 , 最小値 1 6 1
    56 : 平均値 259.25 , 最大値 15 1 14 , 最小値 14 15 10
    57 : 平均値 260.02 , 最大値 15 1 14 , 最小値 6 13 1
    58 : 平均値 269.05 , 最大値 15 1 12 , 最小値 13 14 5
    59 : 平均値 271.16 , 最大値 15 1 12 , 最小値 15 15 8
    60 : 平均値 269.82 , 最大値 15 1 14 , 最小値 7 11 0
    61 : 平均値 273.94 , 最大値 15 1 14 , 最小値 6 11 12
    62 : 平均値 267.44 , 最大値 15 1 14 , 最小値 13 15 13
    63 : 平均値 292.45 , 最大値 15 1 14 , 最小値 7 4 2
    64 : 平均値 278.96 , 最大値 15 0 14 , 最小値 14 13 2
    65 : 平均値 260.95 , 最大値 15 1 12 , 最小値 6 11 3
    66 : 平均値 255.04 , 最大値 15 1 14 , 最小値 14 13 10
    67 : 平均値 264.48 , 最大値 15 1 14 , 最小値 6 14 3
    68 : 平均値 267.67 , 最大値 15 1 14 , 最小値 6 9 10
    69 : 平均値 281.47 , 最大値 15 1 14 , 最小値 15 15 12
    70 : 平均値 281.71 , 最大値 15 1 14 , 最小値 9 11 8
    71 : 平均値 264.98 , 最大値 15 1 12 , 最小値 14 15 6
    72 : 平均値 265.07 , 最大値 15 1 13 , 最小値 13 15 4
    73 : 平均値 267.13 , 最大値 15 1 12 , 最小値 9 12 13
    74 : 平均値 281.34 , 最大値 15 1 14 , 最小値 13 15 4
    75 : 平均値 273.73 , 最大値 15 1 14 , 最小値 9 10 9
    76 : 平均値 294.49 , 最大値 15 1 14 , 最小値 9 14 9
    77 : 平均値 293.32 , 最大値 15 1 14 , 最小値 8 15 8
    78 : 平均値 272.92 , 最大値 15 1 14 , 最小値 4 8 5
    79 : 平均値 286.8 , 最大値 15 1 14 , 最小値 7 10 0
    80 : 平均値 299.35 , 最大値 15 1 14 , 最小値 6 9 12
    81 : 平均値 285.55 , 最大値 15 1 14 , 最小値 15 15 3
    82 : 平均値 280.27 , 最大値 15 1 14 , 最小値 15 14 0
    83 : 平均値 267.84 , 最大値 15 1 15 , 最小値 11 11 15
    84 : 平均値 277.02 , 最大値 15 1 15 , 最小値 5 9 7
    85 : 平均値 267.05 , 最大値 15 1 15 , 最小値 7 11 11
    86 : 平均値 268.56 , 最大値 15 1 15 , 最小値 9 9 6
    87 : 平均値 269.93 , 最大値 15 1 15 , 最小値 7 13 14
    88 : 平均値 290.83 , 最大値 15 1 15 , 最小値 7 10 12
    89 : 平均値 287.12 , 最大値 15 1 15 , 最小値 11 11 6
    90 : 平均値 307.94 , 最大値 15 1 15 , 最小値 15 14 9
    91 : 平均値 291.02 , 最大値 15 1 15 , 最小値 11 12 8
    92 : 平均値 290.77 , 最大値 15 1 15 , 最小値 6 7 13
    93 : 平均値 276.55 , 最大値 15 1 15 , 最小値 9 9 15
    94 : 平均値 306.53 , 最大値 15 1 15 , 最小値 7 9 9
    95 : 平均値 301.99 , 最大値 15 1 15 , 最小値 7 11 4
    96 : 平均値 290.15 , 最大値 15 1 15 , 最小値 9 12 12
    97 : 平均値 289.04 , 最大値 15 1 15 , 最小値 1 10 12
    98 : 平均値 285.86 , 最大値 15 1 15 , 最小値 5 5 6
    99 : 平均値 276.47 , 最大値 15 1 15 , 最小値 11 14 1
    100 : 平均値 284.85 , 最大値 15 1 15 , 最小値 4 8 6
    最大値は: 407 です
    最小を見つける
    1 : 平均値 -77.74 , 最大値 14 1 8 , 最小値 3 15 6
    2 : 平均値 -187.7 , 最大値 11 2 12 , 最小値 1 15 11
    3 : 平均値 -257.01 , 最大値 11 4 7 , 最小値 1 15 11
    4 : 平均値 -321.24 , 最大値 13 9 15 , 最小値 1 15 3
    5 : 平均値 -351.15 , 最大値 8 2 2 , 最小値 2 15 1
    6 : 平均値 -389.09 , 最大値 14 6 5 , 最小値 2 15 1
    7 : 平均値 -411.3 , 最大値 11 8 9 , 最小値 1 15 1
    8 : 平均値 -400.56 , 最大値 6 4 4 , 最小値 2 15 1
    9 : 平均値 -391.36 , 最大値 11 5 14 , 最小値 1 15 3
    10 : 平均値 -371.05 , 最大値 11 3 11 , 最小値 1 15 1
    11 : 平均値 -401.58 , 最大値 15 12 14 , 最小値 1 15 7
    12 : 平均値 -425.69 , 最大値 3 7 11 , 最小値 2 15 5
    13 : 平均値 -420.51 , 最大値 5 0 1 , 最小値 1 15 6
    14 : 平均値 -444.87 , 最大値 7 7 12 , 最小値 2 15 2
    15 : 平均値 -428.34 , 最大値 10 7 2 , 最小値 1 15 0
    16 : 平均値 -435.0 , 最大値 14 9 2 , 最小値 1 15 1
    17 : 平均値 -428.14 , 最大値 8 7 12 , 最小値 1 15 1
    18 : 平均値 -480.21 , 最大値 3 6 2 , 最小値 1 15 1
    19 : 平均値 -432.8 , 最大値 15 7 6 , 最小値 1 15 1
    20 : 平均値 -415.34 , 最大値 15 7 7 , 最小値 1 15 2
    21 : 平均値 -441.3 , 最大値 11 7 0 , 最小値 1 15 2
    22 : 平均値 -419.79 , 最大値 9 1 10 , 最小値 1 15 2
    23 : 平均値 -437.17 , 最大値 10 6 10 , 最小値 1 15 2
    24 : 平均値 -462.87 , 最大値 15 11 11 , 最小値 1 15 1
    25 : 平均値 -440.88 , 最大値 10 7 9 , 最小値 0 15 0
    26 : 平均値 -405.39 , 最大値 14 5 11 , 最小値 1 15 1
    27 : 平均値 -434.42 , 最大値 14 7 8 , 最小値 1 15 0
    28 : 平均値 -442.73 , 最大値 13 7 11 , 最小値 1 15 0
    29 : 平均値 -429.37 , 最大値 6 3 3 , 最小値 1 15 2
    30 : 平均値 -423.1 , 最大値 12 6 8 , 最小値 1 15 2
    31 : 平均値 -432.83 , 最大値 9 7 15 , 最小値 1 15 0
    32 : 平均値 -449.45 , 最大値 5 2 0 , 最小値 1 15 0
    33 : 平均値 -438.95 , 最大値 7 6 3 , 最小値 1 15 0
    34 : 平均値 -453.62 , 最大値 10 7 14 , 最小値 1 15 0
    35 : 平均値 -461.67 , 最大値 12 9 7 , 最小値 1 15 0
    36 : 平均値 -456.97 , 最大値 13 7 15 , 最小値 1 15 0
    37 : 平均値 -489.36 , 最大値 5 6 2 , 最小値 1 15 0
    38 : 平均値 -459.12 , 最大値 1 3 0 , 最小値 1 15 0
    39 : 平均値 -491.9 , 最大値 9 7 13 , 最小値 1 15 0
    40 : 平均値 -481.82 , 最大値 9 6 8 , 最小値 1 15 0
    41 : 平均値 -475.63 , 最大値 13 7 0 , 最小値 1 15 0
    42 : 平均値 -479.99 , 最大値 11 5 8 , 最小値 1 15 0
    43 : 平均値 -474.5 , 最大値 0 3 2 , 最小値 1 15 0
    44 : 平均値 -460.77 , 最大値 13 7 11 , 最小値 1 15 0
    45 : 平均値 -476.18 , 最大値 6 6 0 , 最小値 1 15 0
    46 : 平均値 -497.66 , 最大値 5 7 11 , 最小値 1 15 0
    47 : 平均値 -495.33 , 最大値 1 3 0 , 最小値 1 15 0
    48 : 平均値 -493.76 , 最大値 7 3 9 , 最小値 1 15 0
    49 : 平均値 -473.62 , 最大値 12 7 0 , 最小値 1 15 0
    50 : 平均値 -457.96 , 最大値 2 4 9 , 最小値 1 15 0
    51 : 平均値 -475.4 , 最大値 5 6 13 , 最小値 1 15 0
    52 : 平均値 -457.61 , 最大値 4 3 7 , 最小値 1 15 0
    53 : 平均値 -450.48 , 最大値 9 7 1 , 最小値 1 15 0
    54 : 平均値 -463.83 , 最大値 6 5 9 , 最小値 1 15 0
    55 : 平均値 -478.52 , 最大値 9 7 1 , 最小値 1 15 0
    56 : 平均値 -489.0 , 最大値 6 7 9 , 最小値 1 15 0
    57 : 平均値 -471.68 , 最大値 11 7 6 , 最小値 1 15 0
    58 : 平均値 -456.63 , 最大値 10 7 5 , 最小値 1 15 0
    59 : 平均値 -455.26 , 最大値 10 7 13 , 最小値 1 15 0
    60 : 平均値 -466.83 , 最大値 11 6 12 , 最小値 1 15 0
    61 : 平均値 -482.53 , 最大値 5 7 7 , 最小値 1 15 0
    62 : 平均値 -474.0 , 最大値 9 5 15 , 最小値 1 15 0
    63 : 平均値 -478.58 , 最大値 7 6 12 , 最小値 1 15 0
    64 : 平均値 -493.78 , 最大値 3 2 8 , 最小値 1 15 2
    65 : 平均値 -481.1 , 最大値 9 5 4 , 最小値 1 15 2
    66 : 平均値 -463.97 , 最大値 14 11 5 , 最小値 0 15 0
    67 : 平均値 -470.84 , 最大値 2 5 14 , 最小値 2 15 3
    68 : 平均値 -451.24 , 最大値 12 7 1 , 最小値 1 15 1
    69 : 平均値 -489.47 , 最大値 0 1 8 , 最小値 1 15 0
    70 : 平均値 -513.98 , 最大値 9 5 15 , 最小値 1 15 0
    71 : 平均値 -491.74 , 最大値 2 3 3 , 最小値 1 15 0
    72 : 平均値 -475.63 , 最大値 2 3 10 , 最小値 1 15 0
    73 : 平均値 -464.65 , 最大値 5 3 0 , 最小値 1 15 0
    74 : 平均値 -487.96 , 最大値 10 7 9 , 最小値 1 15 0
    75 : 平均値 -484.62 , 最大値 1 6 8 , 最小値 1 15 0
    76 : 平均値 -464.15 , 最大値 14 11 12 , 最小値 1 15 0
    77 : 平均値 -428.86 , 最大値 15 11 2 , 最小値 1 15 1
    78 : 平均値 -478.03 , 最大値 9 4 12 , 最小値 1 15 1
    79 : 平均値 -482.3 , 最大値 0 5 14 , 最小値 1 15 1
    80 : 平均値 -458.75 , 最大値 9 5 12 , 最小値 1 15 0
    81 : 平均値 -445.12 , 最大値 13 4 11 , 最小値 1 15 0
    82 : 平均値 -421.97 , 最大値 14 3 14 , 最小値 1 15 0
    83 : 平均値 -408.07 , 最大値 9 7 0 , 最小値 1 15 0
    84 : 平均値 -445.73 , 最大値 13 10 11 , 最小値 1 15 0
    85 : 平均値 -417.5 , 最大値 13 7 12 , 最小値 1 15 0
    86 : 平均値 -437.89 , 最大値 14 7 2 , 最小値 1 15 0
    87 : 平均値 -412.38 , 最大値 13 5 7 , 最小値 1 15 0
    88 : 平均値 -435.58 , 最大値 8 7 1 , 最小値 0 15 0
    89 : 平均値 -432.28 , 最大値 11 6 1 , 最小値 2 15 0
    90 : 平均値 -445.06 , 最大値 4 3 1 , 最小値 1 15 1
    91 : 平均値 -440.91 , 最大値 9 7 0 , 最小値 1 15 1
    92 : 平均値 -456.21 , 最大値 1 2 13 , 最小値 1 15 1
    93 : 平均値 -446.63 , 最大値 9 7 4 , 最小値 1 15 1
    94 : 平均値 -444.54 , 最大値 13 7 8 , 最小値 2 15 2
    95 : 平均値 -425.98 , 最大値 4 4 12 , 最小値 0 15 1
    96 : 平均値 -450.8 , 最大値 8 7 8 , 最小値 1 15 1
    97 : 平均値 -467.01 , 最大値 14 10 12 , 最小値 0 15 2
    98 : 平均値 -461.93 , 最大値 6 6 4 , 最小値 2 15 2
    99 : 平均値 -465.24 , 最大値 6 2 0 , 最小値 0 15 2
    100 : 平均値 -442.72 , 最大値 13 6 9 , 最小値 0 15 2
    最小値は: -602 です
    
    Process finished with exit code 0
    

    粒子群最適化

    問題の説明

    上記の最適化問題を、粒子群最適化法を用いて解きなさい。
    各パラメータは各自の自由とする。
    粒子の数は100とし、100回目まで更新させた際の、1~100世代における最良解の値をグラフで示しなさい。

    このプロジェクトでは、最大値または最小値を探索するための機能を含む、全ての粒子のためのPSOクラスを作成します。
    主な機能には、我々は、粒子群として100個の粒子を作成し、各移動後の最善の解決策を見つけると、全ての粒子の運動機能を呼び出す必要があります。

    y=2x12-3x<sub>2</sub>2-4x1+5x2+x3

    適応度は上記の式で表されます

    クラス構造

    初期化中にすべてのプライベート変数を宣言する

    def __init__(self, c1=2, c2=2, w=1):
        self.w = w  # 慣性定数
        self.v0 = 0  # 探索個体の初速度
        self.v1 = 0
        self.v2 = 0
        self.x0 = random.randint(0, 15)  # 探索個体の位置
        self.x1 = random.randint(0, 15)
        self.x2 = random.randint(0, 15)
        self.y = calculate(self.x0, self.x1, self.x2)
        self.c1 = c1  # 学習係数
        self.c2 = c2
        self.p = [self.x0, self.x1, self.x2, self.y]  # 探索個体の最良位置
    

    関数宣言、gは最適解の位置です

    go(self, g)
    go_max(self, g)
    go_min(self, g)
    

    関数の実装

    適応度計算
    def calculate(x0, x1, x2):  # 適応度
        return 2 * x0 * x0 - 3 * x1 * x1 - 4 * x0 + 5 * x1 + x2
    
    探索関数
    1. 計算速度

      v = wv + c1r1(Gbest - x) + c2r2(Pbest - x)

    2. 計算場所

      x = x + v

    def go(self, g):  # 探索関数
        # 計算速度
        self.v0 = self.w * self.v0 + self.c1 * random.random() * (g[0] - self.x0) + self.c2 * random.random() * (
                    self.p[0] - self.x0)
        self.v1 = self.w * self.v1 + self.c1 * random.random() * (g[1] - self.x1) + self.c2 * random.random() * (
                    self.p[1] - self.x1)
        self.v2 = self.w * self.v2 + self.c1 * random.random() * (g[2] - self.x2) + self.c2 * random.random() * (
                    self.p[2] - self.x2)
        # 計算場所
        self.x0 = self.x0 + self.v0  # 限られた値の範囲
        if self.x0 > 15:
            self.x0 = 15
        elif self.x0 < 0:
            self.x0 = 0
        self.x1 = self.x1 + self.v1
        if self.x1 > 15:
            self.x1 = 15
        elif self.x1 < 0:
            self.x1 = 0
        self.x2 = self.x2 + self.v2
        if self.x2 > 15:
            self.x2 = 15
        elif self.x2 < 0:
            self.x2 = 0
        self.y = calculate(self.x0, self.x1, self.x2)  # 計算適応度
    
    探索個体の最良位置
    def go_max(self, g):
        self.go(g)
        if self.y > self.p[3]:
            self.p = [self.x0, self.x1, self.x2, self.y]  # 自分の最適な位置を更新する
    
    def go_min(self, g):
        self.go(g)
        if self.y < self.p[3]:
            self.p = [self.x0, self.x1, self.x2, self.y]  # 自分の最適な位置を更新する
    
    出力

    より良い解決策がない場合、それは出力されません

    for j in range(100):
        show = False
        for i in range(100):
            a[i].go_min(best)
            if a[i].y < best[3]:
                best = a[i].p
                show = True
        if show:
            print(best)
    

    演算結果

    c1 = 2
    c2 = 2
    w = 1

    最大を見つける
    [15, 0.374963944391387, 15, 406.4530258431763]
    [15, 0.8919276768891968, 15, 407.07303344204314]
    [15, 0.8348837178082772, 15, 407.0833261222573]
    [15, 0.8321133497489408, 15, 407.0833288682535]
    [15, 0.8330926190723068, 15, 407.08333315950324]
    [15, 0.8335237214448654, 15, 407.08333322459043]
    [15, 0.8334223377156362, 15, 407.083333309568]
    最大値は: 407.083333309568 です
    最小を見つける
    [0.8964719926138809, 15, 0, -601.9785639033732]
    [1.0132336239397892, 15, 0, -601.9996497423948]
    [0.9902767087255728, 15, 0, -601.9998109152135]
    [0.9925054520072736, 15, 0, -601.9998876635008]
    [1.0010034789381652, 15, 0.0, -601.9999979860601]
    [0.9996368213014294, 15, 0, -601.9999997362025]
    [0.9996987995938881, 15, 0, -601.9999998185566]
    最小値は: -601.9999998185566 です
    
    Process finished with exit code 0
    

    c1 = 2
    c2 = 2
    w = 2

    最大を見つける
    [15, 0.8623157788455933, 15, 407.08081338688976]
    [15.0, 0.8618974100967376, 15, 407.08088561388934]
    [15, 0.8459074975515879, 15, 407.082859004516]
    最大値は: 407.082859004516 です
    最小を見つける
    [0.8479086047155134, 15, 0, -601.9537364149609]
    [1.0394032279942933, 15, 0, -601.9968947712472]
    最小値は: -601.9968947712472 です
    

    遺伝的アルゴリズム.py

    import random
    
    num = 100         # 個体数
    iteration = 100   # 世代数
    Pc = 0.3          # 交叉確率
    Pm = 0.05         # 突然変異確率
    
    
    def rand(a):
        if random.random() < a:
            return 1
        else:
            return 0
    
    
    def calculate(lb):
        x1 = lb[0]*8 + lb[1]*4 + lb[2]*2 + lb[3]
        x2 = lb[4]*8 + lb[5]*4 + lb[6]*2 + lb[7]
        x3 = lb[8]*8 + lb[9]*4 + lb[10]*2 + lb[11]
        return 2*x1*x1 - 3*x2*x2 - 4*x1 + 5*x2 + x3
    
    
    def show(lb, ni):
        sum_l = 0  # 和
        max_l = 0  # 最大値
        min_l = 0  # 最小値
        for i in range(num):
            sum_l = sum_l + lb[i][12]
            if lb[i][12] > lb[max_l][12]:
                max_l = i
            if lb[i][12] < lb[min_l][12]:
                min_l = i
        sum_l = sum_l / num
        max_x1 = lb[max_l][0]*8 + lb[max_l][1]*4 + lb[max_l][2]*2 + lb[max_l][3]
        max_x2 = lb[max_l][4]*8 + lb[max_l][5]*4 + lb[max_l][6]*2 + lb[max_l][7]
        max_x3 = lb[max_l][8]*8 + lb[max_l][9]*4 + lb[max_l][10]*2 + lb[max_l][11]
        min_x1 = lb[min_l][0]*8 + lb[min_l][1]*4 + lb[min_l][2]*2 + lb[min_l][3]
        min_x2 = lb[min_l][4]*8 + lb[min_l][5]*4 + lb[min_l][6]*2 + lb[min_l][7]
        min_x3 = lb[min_l][8]*8 + lb[min_l][9]*4 + lb[min_l][10]*2 + lb[min_l][11]
        print(ni, ": 平均値", sum_l, ", 最大値", max_x1, max_x2, max_x3, ", 最小値", min_x1, min_x2, min_x3)
    
    
    def cal_max(lb):
        max_l = 0
        for i in range(num):
            if lb[i][12] > lb[max_l][12]:
                max_l = i
        return lb[max_l][12]
    
    
    def cal_min(lb):
        min_l = 0
        for i in range(num):
            if lb[i][12] < lb[min_l][12]:
                min_l = i
        return lb[min_l][12]
    
    
    def cross(lb):
        tmp = []  # 個体の利用フラグ
        for i in range(num):
            tmp.append(False)
        for i in range(int(num/2)):
            p1 = random.randint(0, num-1)  # 親p1を決定
            while tmp[p1]:
                p1 = random.randint(0, num-1)
            tmp[p1] = True
            p2 = random.randint(0, num-1)  # 親p2を決定
            while tmp[p2]:
                p2 = random.randint(0, num-1)
            tmp[p2] = True
            point = random.randint(0, 11)  # 交叉点を決定
            if rand(Pc) == 1:
                for j in range(point):
                    t = lb[p1][j]
                    lb[p1][j] = lb[p2][j]
                    lb[p2][j] = t
            return lb
    
    
    def accident(lb):
        temp = []  # 新しいリストを作成
        for i in range(num):
            a = []
            for j in range(0, 12):  # すべての遺伝子のすべてを通過する
                if rand(Pm) == 1:  # 0-1の間の変換は、特定の確率で発生します
                    a.append((1 + lb[i][j]) % 2)
                else:
                    a.append(lb[i][j])
            a.append(0)
            temp.append(a)
        return temp
    
    
    def select_max(lb):
        min_l = cal_min(lb)  # 最小値計算
        sum_l = 0
        temp_l = []
        ci_l = []
        for i in range(num):  # 正規化
            lb[i][12] = lb[i][12] + abs(min_l)
            sum_l = sum_l + lb[i][12]
            temp_l.append(sum_l)
        for i in range(num):  # リストを生成する
            a = random.random() * sum_l
            for j in range(num):
                if a < temp_l[j]:
                    ci_l.append(lb[j])  # 対応するインデックスにアクセス
                    break
        return ci_l
    
    
    def select_min(lb):
        max_l = cal_max(lb)  # 最大値計算
        sum_l = 0
        temp_l = []
        ci_l = []
        for i in range(num):  # 正規化
            lb[i][12] = abs(lb[i][12] - abs(max_l))
            sum_l = sum_l + lb[i][12]
            temp_l.append(sum_l)
        for i in range(num):  # リストを生成する
            a = random.random() * sum_l
            for j in range(num):
                if a < temp_l[j]:
                    ci_l.append(lb[j])  # 対応するインデックスにアクセス
                    break
        return ci_l
    
    
    def go_max():
        ci = []
        for i in range(num):  # 初期世代の個体群を構造
            temp = []
            for j in range(12):
                temp.append(rand(0.5))
            temp.append(calculate(temp))
            ci.append(temp)
        max_g = cal_max(ci)
        # 迭代100次
        g = 0
        while g < iteration:
            ci = cross(ci)
            ci = accident(ci)
            for j in range(num):  # 重新计算
                ci[j][12] = calculate(ci[j])
            now = cal_max(ci)
            if max_g < now:
                max_g = now
            g = g + 1
            show(ci, g)
            ci = select_max(ci)
        print("最大値は:", max_g, "です")
    
    
    def go_min():
        ci = []
        for i in range(num):   # 初期世代の個体群を構造
            temp = []
            for j in range(12):
                temp.append(rand(0.5))
            temp.append(calculate(temp))
            ci.append(temp)
        min_g = cal_min(ci)
        # 迭代100次
        g = 0
        while g < iteration:
            ci = cross(ci)
            ci = accident(ci)
            for j in range(num):  # 重新计算
                ci[j][12] = calculate(ci[j])
            now = cal_min(ci)
            if min_g > now:
                min_g = now
            g = g + 1
            show(ci, g)
            ci = select_min(ci)
        print("最小値は:", min_g, "です")
    
    
    print("最大を見つける")
    go_max()
    print("最小を見つける")
    go_min()
    

    粒子群最適化.py

    import random
    
    
    def calculate(x0, x1, x2):  # 適応度
        return 2 * x0 * x0 - 3 * x1 * x1 - 4 * x0 + 5 * x1 + x2
    
    
    class PSO:
        def __init__(self, c1=2, c2=2, w=2):
            self.w = w  # 慣性定数
            self.v0 = 0  # 探索個体の初速度
            self.v1 = 0
            self.v2 = 0
            self.x0 = random.randint(0, 15)  # 探索個体の位置
            self.x1 = random.randint(0, 15)
            self.x2 = random.randint(0, 15)
            self.y = calculate(self.x0, self.x1, self.x2)
            self.c1 = c1  # 学習係数
            self.c2 = c2
            self.p = [self.x0, self.x1, self.x2, self.y]  # 探索個体の最良位置
    
        def go(self, g):  # 探索関数
            # 計算速度
            self.v0 = self.w * self.v0 + self.c1 * random.random() * (g[0] - self.x0) + self.c2 * random.random() * (
                        self.p[0] - self.x0)
            self.v1 = self.w * self.v1 + self.c1 * random.random() * (g[1] - self.x1) + self.c2 * random.random() * (
                        self.p[1] - self.x1)
            self.v2 = self.w * self.v2 + self.c1 * random.random() * (g[2] - self.x2) + self.c2 * random.random() * (
                        self.p[2] - self.x2)
            # 計算場所
            self.x0 = self.x0 + self.v0  # 限られた値の範囲
            if self.x0 > 15:
                self.x0 = 15
            elif self.x0 < 0:
                self.x0 = 0
            self.x1 = self.x1 + self.v1
            if self.x1 > 15:
                self.x1 = 15
            elif self.x1 < 0:
                self.x1 = 0
            self.x2 = self.x2 + self.v2
            if self.x2 > 15:
                self.x2 = 15
            elif self.x2 < 0:
                self.x2 = 0
            self.y = calculate(self.x0, self.x1, self.x2)  # 計算適応度
    
        def go_max(self, g):
            self.go(g)
            if self.y > self.p[3]:
                self.p = [self.x0, self.x1, self.x2, self.y]  # 自分の最適な位置を更新する
    
        def go_min(self, g):
            self.go(g)
            if self.y < self.p[3]:
                self.p = [self.x0, self.x1, self.x2, self.y]  # 自分の最適な位置を更新する
    
    
    print("最大を見つける")
    a = []
    k = 0
    best = []
    
    for i in range(100):  # 初期粒子群を構造
        a.append(PSO())
        if a[k].y < a[i].y:
            k = i
    best = a[k].p  # 最良解の値
    for j in range(100):
        show = False
        for i in range(100):
            a[i].go_max(best)
            if a[i].y > best[3]:
                best = a[i].p
                show = True
        if show:
            print(best)
    print("最大値は:", best[3], "です")
    
    a = []
    k = 0
    best = []
    
    print("最小を見つける")
    for i in range(100):
        a.append(PSO())
        if a[k].y > a[i].y:
            k = i
    best = a[k].p
    for j in range(100):
        show = False
        for i in range(100):
            a[i].go_min(best)
            if a[i].y < best[3]:
                best = a[i].p
                show = True
        if show:
            print(best)
    print("最小値は:", best[3], "です")
    
  • 相关阅读:
    在一个类中写完多线程(sleep 方法和wait 方法的区别)
    final
    Oracle 远程访问配置
    在 Windows Forms 和 WPF 应用中使用 FontAwesome 图标
    C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素”
    C#[Win32&WinCE&WM]应用程序只能运行一个实例:MutexHelper
    『.NET Core CLI工具文档』(十四)dotnet-install 脚本参考
    『.NET Core CLI工具文档』(十三)dotnet-publish
    『.NET Core CLI工具文档』(十二)dotnet-pack
    『.NET Core CLI工具文档』(十一)dotnet-test
  • 原文地址:https://www.cnblogs.com/winng/p/inherit.html
Copyright © 2011-2022 走看看