二進位制蟻群演算法【原始碼實現】
阿新 • • 發佈:2021-05-30
蟻群演算法
之前講解了蟻群演算法,見連結。萬字長文帶你瞭解蟻群演算法及求解複雜約束問題【原始碼實現】
今天講解下二進位制的蟻群演算法。
直接上算例。
算例
愛小玉,愛學習。 假設一個數PD=210,它可以看成下列中的數,某幾個組合而成來的P_state=np.array([1700,2600,180,2200,1400,60,85,290,4100,3000,1590,200,1300,50,100,30,90]),即PD=sum(xiP_statei)其中的xi表示狀態,只能取0或1。
限制條件:【180,2200】,序號[2,3]不能共存;【60,85,300】,序號[5,6,7]不能共存;【50,100】 序號[13,14]不能共存;【25,90】序號[15,16]不能共存。
這題的意思假設某刻時刻。家用總負荷為210W
家用總負荷是由各個電器的功率疊加的。其中【180,2200】,序號[2,3]不能共存,表示【180,2200】對應的是同一個電器,這個電器的功率可以是180或者2200.當一個時刻只能是一個值。其它同理。
算例實現
python 版程式碼。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: yudengwu(餘登武)
# @Date : 2021/5/28
#@email:[email protected]
import numpy as np
from tqdm import tqdm#進度條設定
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib; matplotlib.use('TkAgg')
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定預設字型
mpl.rcParams['axes.unicode_minus'] = False # 解決儲存影象是負號'-'顯示為方塊的問題
import math
#以一個負荷為例講解優化演算法
P_state=np.array([1700,2600,180,2200,1400,60,85,290,4100,3000,1590,200,1300 ,50,100,30,90])#17個狀態
state_num=17 #狀態數
#【180,2200】,序號[2,3]不能共存
#【60,85,300】,序號[5,6,7]不能共存
#【50,100】 序號[13,14]不能共存
#【25,90】序號[15,16]不能共存
#總負荷
Pload=446.0 #這個值可以設定的
########適應度函式
def calc_f(xi):
"""
:param xi 為個體 即電器的工作狀態,01二二進位制,0表示當前狀態關,1表示開:
xi 為np.array(資料)
:return 返回 np.abs(XiP_state-pload) P_state為電器"額定功率":
"""
xi=np.array(xi)
xi=xi.reshape(state_num,)
return np.abs(np.sum(xi*P_state)-Pload)
#=================初始化引數================
m=20 #螞蟻個數
G_max=300 #最大迭代次數
Rho=0.9 #資訊素蒸發係數
P0=0.2 #轉移概率常數
Tau=np.zeros(shape=(m,)) #資訊素
P=np.zeros(shape=(G_max,m)) #狀態轉移矩陣
fitneess_value_list=[] #迭代記錄最優目標函式值
#########初始化群體
f=np.random.randint(0,2,(m,state_num)) #在[0,2)之前隨機取整數,取state_num(17)個 f.shape=(20, 17)
for j in tqdm(range(m)):
while f[j, 2] + f[j, 3] == 2:
f[j, 2] = np.random.randint(0, 2, 1)
f[j, 3] = np.random.randint(0, 2, 1)
# 【60,85,300】,序號[5,6,7]不能共存
while f[j, 5] + f[j, 6] + f[j, 7] == 2 or f[j, 5] + f[j, 6] + f[j, 7] == 3:
f[j, 5] = np.random.randint(0, 2, 1)
f[j, 6] = np.random.randint(0, 2, 1)
f[j, 7] = np.random.randint(0, 2, 1)
# 【50,100】 序號[13,14]不能共存
while f[j, 13] + f[j, 14] == 2:
f[j, 13] = np.random.randint(0, 2, 1)
f[j, 14] = np.random.randint(0, 2, 1)
# 【25,90】序號[15,16]不能共存
while f[j, 15] + f[j, 16] == 2:
f[j, 15] = np.random.randint(0, 2, 1)
f[j, 16] = np.random.randint(0, 2, 1)
for i in range(m):#遍歷每一個螞蟻
Tau[i] = calc_f(f[i])#資訊素
step=0.3; #區域性搜尋步長
for NC in range(G_max):#遍歷每一代
lamda=1/(NC+1)
BestIndex=np.argmin(Tau) #最優索引
Tau_best=Tau[BestIndex] #最優資訊素
#計算狀態轉移概率
for i in range(m):#遍歷每一個螞蟻
P[NC,i]=np.abs((Tau_best-Tau[i]))/np.abs(Tau_best)+0.01 #即例最優資訊素的距離.越近越好
# =======位置更新==========
for i in range(m): # 遍歷每一個螞蟻
#當前螞蟻
bf=f[i].copy()
# ===區域性搜尋===
if P[NC, i] < P0:
#每隻螞蟻 的元素隨機選擇 np.int(state_num*(step*lamda))個 取反
sizeaca=np.int(state_num*(step*lamda))#取反的個數
index=np.random.choice(np.arange(0,state_num,1),size=sizeaca,replace=False)#取反的序號
bf[index]=1-bf[index] #元素取反
# ===全域性搜尋===
else:
#選擇4分之一元素取反
index = np.random.choice(np.arange(0, state_num, 1), size=np.int(state_num/4), replace=False) # 取反的序號
bf[index] = 1 - bf[index] # 元素取反
# =====位置限制=====
# 【180,2200】,序號[2,3]不能共存
while bf[2] + bf[3] == 2:
bf[2] = np.random.randint(0, 2, 1)
bf[3]= np.random.randint(0, 2, 1)
# 【60,85,300】,序號[5,6,7]不能共存
while bf[5] + bf[6] + bf[7] == 2 or bf[5] + bf[6] + bf[7] == 3:
bf[5] = np.random.randint(0, 2, 1)
bf[6] = np.random.randint(0, 2, 1)
bf[7] = np.random.randint(0, 2, 1)
# 【50,100】 序號[13,14]不能共存
while bf[13] + bf[14] == 2:
bf[13] = np.random.randint(0, 2, 1)
bf[14] = np.random.randint(0, 2, 1)
# 【25,90】序號[15,16]不能共存
while bf[15] + bf[16] == 2:
bf[15] = np.random.randint(0, 2, 1)
bf[16] = np.random.randint(0, 2, 1)
##判斷螞蟻是否移動(選更優)
if calc_f(bf) < calc_f(f[i]):
f[i]=bf
# =====更新資訊素========
for i in range(m): # 遍歷每一個螞蟻
Tau[i] = (1 - Rho) * Tau[i] + calc_f(f[i]) # (1 - Rho) * Tau[i] 資訊蒸發後保留的
index = np.argmin(Tau) # 最小值索引
value = Tau[index] # 最小值
fitneess_value_list.append(calc_f(f[i])) # 記錄最優目標函式值
#列印結果
min_index=np.argmin(Tau)#最優值索引
minf=f[min_index] #最優變數 \最優螞蟻
minValue=calc_f(minf) #最優目標函式值
print('最優變數',minf)
print('最優變數對應的功率',minf*P_state)
print('最優誤差',minValue)
plt.plot(fitneess_value_list,label='迭代曲線')
plt.legend()
plt.show()
作者:電氣-餘登武。 一個電氣專業的計算機選手
原創不易,禁止轉載。