[python] 简单遗传算法与粒子群算法
Posted winng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[python] 简单遗传算法与粒子群算法相关的知识,希望对你有一定的参考价值。
遺伝的アルゴリズム
問題の説明
遺伝的アルゴリズムを使用し、下記の関数の最大化及び最小化を実現しなさい。
ただし、x1、x2、x3の取り得る値は0~15とし、それぞれの遺伝子型は4ビットのビット列で表現すること。
選択、交叉、突然変異のパラメータは各自の自由とする。
群の個体数は100とし、100世代まで進化させた際の、1~100世代における最良解のy値をグラフで示しなさい。選択、交叉、突然変異のパラメータも記載すること。
このプロジェクトでは、遺伝的アルゴリズムをいくつかの小さな部分に分割し、それらを個別に実装する予定です。
実行シーケンスは、遺伝子の初期化 → ベストバリュー計算 → 100回の繰り返し。
繰り返しは一点交叉 → 突然変異 → 適応度計算 → ベストバリュー計算 → 出力 → 選択で構成されます。
y=2x1^2-3x2^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=2x1^2-3x2^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
探索関数
-
計算速度
v = wv + c1r1(Gbest - x) + c2r2(Pbest - x)
-
計算場所
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], "です")
以上是关于[python] 简单遗传算法与粒子群算法的主要内容,如果未能解决你的问题,请参考以下文章
优化求解基于matlab粒子群与遗传算法混合算法求解切削参数优化问题(以成本和碳排放量为目标函数)含Matlab源码 1619期