
優(yōu)化算法—人工蜂群算法(ABC)
一、人工蜂群算法的介紹
人工蜂群算法(Artificial Bee Colony, ABC)是由Karaboga于2005年提出的一種新穎的基于群智能的全局優(yōu)化算法,其直觀背景來源于蜂群的采蜜行為,蜜蜂根據(jù)各自的分工進(jìn)行不同的活動(dòng),并實(shí)現(xiàn)蜂群信息的共享和交流,從而找到問題的最優(yōu)解。人工蜂群算法屬于群智能算法的一種。
二、人工蜂群算法的原理
1、原理
標(biāo)準(zhǔn)的ABC算法通過模擬實(shí)際蜜蜂的采蜜機(jī)制將人工蜂群分為3類: 采蜜蜂、觀察蜂和偵察蜂。整個(gè)蜂群的目標(biāo)是尋找花蜜量最大的蜜源。在標(biāo)準(zhǔn)的ABC算法中,采蜜蜂利用先前的蜜源信息尋找新的蜜源并與觀察蜂分享蜜源信息;觀察蜂在蜂房中等待并依據(jù)采蜜蜂分享的信息尋找新的蜜源;偵查蜂的任務(wù)是尋找一個(gè)新的有價(jià)值的蜜源,它們在蜂房附近隨機(jī)地尋找蜜源。
假設(shè)問題的解空間是維的,采蜜蜂與觀察蜂的個(gè)數(shù)都是,采蜜蜂的個(gè)數(shù)或觀察蜂的個(gè)數(shù)與蜜源的數(shù)量相等。則標(biāo)準(zhǔn)的ABC算法將優(yōu)化問題的求解過程看成是在維搜索空間中進(jìn)行搜索。每個(gè)蜜源的位置代表問題的一個(gè)可能解,蜜源的花蜜量對(duì)應(yīng)于相應(yīng)的解的適應(yīng)度。一個(gè)采蜜蜂與一個(gè)蜜源是相對(duì)應(yīng)的。與第個(gè)蜜源相對(duì)應(yīng)的采蜜蜂依據(jù)如下公式尋找新的蜜源:
其中是區(qū)間
上的隨機(jī)數(shù),
。標(biāo)準(zhǔn)的ABC算法將新生成的可能解
與原來的解
作比較,并采用貪婪選擇策略保留較好的解。每一個(gè)觀察蜂依據(jù)概率選擇一個(gè)蜜源,概率公式為
其中,是可能解
的適應(yīng)值。對(duì)于被選擇的蜜源,觀察蜂根據(jù)上面概率公式搜尋新的可能解。當(dāng)所有的采蜜蜂和觀察蜂都搜索完整個(gè)搜索空間時(shí),如果一個(gè)蜜源的適應(yīng)值在給定的步驟內(nèi)(定義為控制參數(shù)“l(fā)imit”) 沒有被提高, 則丟棄該蜜源,而與該蜜源相對(duì)應(yīng)的采蜜蜂變成偵查蜂,偵查蜂通過已下公式搜索新的可能解。
其中,r是區(qū)間上的隨機(jī)數(shù),是第d維的下界和上界。
2、流程
初始化;
重復(fù)以下過程:
將采蜜蜂與蜜源一一對(duì)應(yīng),根據(jù)上面第一個(gè)公式更新蜜源信息,同時(shí)確定蜜源的花蜜量;
觀察蜂根據(jù)采蜜蜂所提供的信息采用一定的選擇策略選擇蜜源,根據(jù)第一個(gè)公式更新蜜源信息,同時(shí)確定蜜源的花蜜量;
確定偵查蜂,并根據(jù)第三個(gè)公式尋找新的蜜源;數(shù)據(jù)分析師培訓(xùn)
記憶迄今為止最好的蜜源;
判斷終止條件是否成立;
三、人工蜂群算法用于求解函數(shù)優(yōu)化問題
對(duì)于函數(shù)
其中。
代碼:
[cpp] view plain copy 在CODE上查看代碼片派生到我的代碼片
#include<iostream>
#include<time.h>
#include<stdlib.h>
#include<cmath>
#include<fstream>
#include<iomanip>
using namespace std;
const int NP=40;//種群的規(guī)模,采蜜蜂+觀察蜂
const int FoodNumber=NP/2;//食物的數(shù)量,為采蜜蜂的數(shù)量
const int limit=20;//限度,超過這個(gè)限度沒有更新采蜜蜂變成偵查蜂
const int maxCycle=10000;//停止條件
/*****函數(shù)的特定參數(shù)*****/
const int D=2;//函數(shù)的參數(shù)個(gè)數(shù)
const double lb=-100;//函數(shù)的下界
const double ub=100;//函數(shù)的上界
double result[maxCycle]={0};
/*****種群的定義****/
struct BeeGroup
{
double code[D];//函數(shù)的維數(shù)
double trueFit;//記錄真實(shí)的最小值
double fitness;
double rfitness;//相對(duì)適應(yīng)值比例
int trail;//表示實(shí)驗(yàn)的次數(shù),用于與limit作比較
}Bee[FoodNumber];
BeeGroup NectarSource[FoodNumber];//蜜源,注意:一切的修改都是針對(duì)蜜源而言的
BeeGroup EmployedBee[FoodNumber];//采蜜蜂
BeeGroup OnLooker[FoodNumber];//觀察蜂
BeeGroup BestSource;//記錄最好蜜源
/*****函數(shù)的聲明*****/
double random(double, double);//產(chǎn)生區(qū)間上的隨機(jī)數(shù)
void initilize();//初始化參數(shù)
double calculationTruefit(BeeGroup);//計(jì)算真實(shí)的函數(shù)值
double calculationFitness(double);//計(jì)算適應(yīng)值
void CalculateProbabilities();//計(jì)算輪盤賭的概率
void evalueSource();//評(píng)價(jià)蜜源
void sendEmployedBees();
void sendOnlookerBees();
void sendScoutBees();
void MemorizeBestSource();
/*******主函數(shù)*******/
int main()
{
ofstream output;
output.open("dataABC.txt");
srand((unsigned)time(NULL));
initilize();//初始化
MemorizeBestSource();//保存最好的蜜源
//主要的循環(huán)
int gen=0;
while(gen<maxCycle)
{
sendEmployedBees();
CalculateProbabilities();
sendOnlookerBees();
MemorizeBestSource();
sendScoutBees();
MemorizeBestSource();
output<<setprecision(30)<<BestSource.trueFit<<endl;
gen++;
}
output.close();
cout<<"運(yùn)行結(jié)束!!"<<endl;
return 0;
}
/*****函數(shù)的實(shí)現(xiàn)****/
double random(double start, double end)//隨機(jī)產(chǎn)生區(qū)間內(nèi)的隨機(jī)數(shù)
{
return start+(end-start)*rand()/(RAND_MAX + 1.0);
}
void initilize()//初始化參數(shù)
{
int i,j;
for (i=0;i<FoodNumber;i++)
{
for (j=0;j<D;j++)
{
NectarSource[i].code[j]=random(lb,ub);
EmployedBee[i].code[j]=NectarSource[i].code[j];
OnLooker[i].code[j]=NectarSource[i].code[j];
BestSource.code[j]=NectarSource[0].code[j];
}
/****蜜源的初始化*****/
NectarSource[i].trueFit=calculationTruefit(NectarSource[i]);
NectarSource[i].fitness=calculationFitness(NectarSource[i].trueFit);
NectarSource[i].rfitness=0;
NectarSource[i].trail=0;
/****采蜜蜂的初始化*****/
EmployedBee[i].trueFit=NectarSource[i].trueFit;
EmployedBee[i].fitness=NectarSource[i].fitness;
EmployedBee[i].rfitness=NectarSource[i].rfitness;
EmployedBee[i].trail=NectarSource[i].trail;
/****觀察蜂的初始化****/
OnLooker[i].trueFit=NectarSource[i].trueFit;
OnLooker[i].fitness=NectarSource[i].fitness;
OnLooker[i].rfitness=NectarSource[i].rfitness;
OnLooker[i].trail=NectarSource[i].trail;
}
/*****最優(yōu)蜜源的初始化*****/
BestSource.trueFit=NectarSource[0].trueFit;
BestSource.fitness=NectarSource[0].fitness;
BestSource.rfitness=NectarSource[0].rfitness;
BestSource.trail=NectarSource[0].trail;
}
double calculationTruefit(BeeGroup bee)//計(jì)算真實(shí)的函數(shù)值
{
double truefit=0;
/******測試函數(shù)1******/
truefit=0.5+(sin(sqrt(bee.code[0]*bee.code[0]+bee.code[1]*bee.code[1]))*sin(sqrt(bee.code[0]*bee.code[0]+bee.code[1]*bee.code[1]))-0.5)
/((1+0.001*(bee.code[0]*bee.code[0]+bee.code[1]*bee.code[1]))*(1+0.001*(bee.code[0]*bee.code[0]+bee.code[1]*bee.code[1])));
return truefit;
}
double calculationFitness(double truefit)//計(jì)算適應(yīng)值
{
double fitnessResult=0;
if (truefit>=0)
{
fitnessResult=1/(truefit+1);
}else
{
fitnessResult=1+abs(truefit);
}
return fitnessResult;
}
void sendEmployedBees()//修改采蜜蜂的函數(shù)
{
int i,j,k;
int param2change;//需要改變的維數(shù)
double Rij;//[-1,1]之間的隨機(jī)數(shù)
for (i=0;i<FoodNumber;i++)
{
param2change=(int)random(0,D);//隨機(jī)選取需要改變的維數(shù)
/******選取不等于i的k********/
while (1)
{
k=(int)random(0,FoodNumber);
if (k!=i)
{
break;
}
}
for (j=0;j<D;j++)
{
EmployedBee[i].code[j]=NectarSource[i].code[j];
}
/*******采蜜蜂去更新信息*******/
Rij=random(-1,1);
EmployedBee[i].code[param2change]=NectarSource[i].code[param2change]+Rij*(NectarSource[i].code[param2change]-NectarSource[k].code[param2change]);
/*******判斷是否越界********/
if (EmployedBee[i].code[param2change]>ub)
{
EmployedBee[i].code[param2change]=ub;
}
if (EmployedBee[i].code[param2change]<lb)
{
EmployedBee[i].code[param2change]=lb;
}
EmployedBee[i].trueFit=calculationTruefit(EmployedBee[i]);
EmployedBee[i].fitness=calculationFitness(EmployedBee[i].trueFit);
/******貪婪選擇策略*******/
if (EmployedBee[i].trueFit<NectarSource[i].trueFit)
{
for (j=0;j<D;j++)
{
NectarSource[i].code[j]=EmployedBee[i].code[j];
}
NectarSource[i].trail=0;
NectarSource[i].trueFit=EmployedBee[i].trueFit;
NectarSource[i].fitness=EmployedBee[i].fitness;
}else
{
NectarSource[i].trail++;
}
}
}
void CalculateProbabilities()//計(jì)算輪盤賭的選擇概率
{
int i;
double maxfit;
maxfit=NectarSource[0].fitness;
for (i=1;i<FoodNumber;i++)
{
if (NectarSource[i].fitness>maxfit)
maxfit=NectarSource[i].fitness;
}
for (i=0;i<FoodNumber;i++)
{
NectarSource[i].rfitness=(0.9*(NectarSource[i].fitness/maxfit))+0.1;
}
}
void sendOnlookerBees()//采蜜蜂與觀察蜂交流信息,觀察蜂更改信息
{
int i,j,t,k;
double R_choosed;//被選中的概率
int param2change;//需要被改變的維數(shù)
double Rij;//[-1,1]之間的隨機(jī)數(shù)
i=0;
t=0;
while(t<FoodNumber)
{
R_choosed=random(0,1);
if(R_choosed<NectarSource[i].rfitness)//根據(jù)被選擇的概率選擇
{
t++;
param2change=(int)random(0,D);
/******選取不等于i的k********/
while (1)
{
k=(int)random(0,FoodNumber);
if (k!=i)
{
break;
}
}
for(j=0;j<D;j++)
{
OnLooker[i].code[j]=NectarSource[i].code[j];
}
/****更新******/
Rij=random(-1,1);
OnLooker[i].code[param2change]=NectarSource[i].code[param2change]+Rij*(NectarSource[i].code[param2change]-NectarSource[k].code[param2change]);
/*******判斷是否越界*******/
if (OnLooker[i].code[param2change]<lb)
{
OnLooker[i].code[param2change]=lb;
}
if (OnLooker[i].code[param2change]>ub)
{
OnLooker[i].code[param2change]=ub;
}
OnLooker[i].trueFit=calculationTruefit(OnLooker[i]);
OnLooker[i].fitness=calculationFitness(OnLooker[i].trueFit);
/****貪婪選擇策略******/
if (OnLooker[i].trueFit<NectarSource[i].trueFit)
{
for (j=0;j<D;j++)
{
NectarSource[i].code[j]=OnLooker[i].code[j];
}
NectarSource[i].trail=0;
NectarSource[i].trueFit=OnLooker[i].trueFit;
NectarSource[i].fitness=OnLooker[i].fitness;
}else
{
NectarSource[i].trail++;
}
}
i++;
if (i==FoodNumber)
{
i=0;
}
}
}
/*******只有一只偵查蜂**********/
void sendScoutBees()//判斷是否有偵查蜂的出現(xiàn),有則重新生成蜜源
{
int maxtrialindex,i,j;
double R;//[0,1]之間的隨機(jī)數(shù)
maxtrialindex=0;
for (i=1;i<FoodNumber;i++)
{
if (NectarSource[i].trail>NectarSource[maxtrialindex].trail)
{
maxtrialindex=i;
}
}
if(NectarSource[maxtrialindex].trail>=limit)
{
/*******重新初始化*********/
for (j=0;j<D;j++)
{
R=random(0,1);
NectarSource[maxtrialindex].code[j]=lb+R*(ub-lb);
}
NectarSource[maxtrialindex].trail=0;
NectarSource[maxtrialindex].trueFit=calculationTruefit(NectarSource[maxtrialindex]);
NectarSource[maxtrialindex].fitness=calculationFitness(NectarSource[maxtrialindex].trueFit);
}
}
void MemorizeBestSource()//保存最優(yōu)的蜜源
{
int i,j;
for (i=1;i<FoodNumber;i++)
{
if (NectarSource[i].trueFit<BestSource.trueFit)
{
for (j=0;j<D;j++)
{
BestSource.code[j]=NectarSource[i].code[j];
}
BestSource.trueFit=NectarSource[i].trueFit;
}
}
}
收斂曲線:
數(shù)據(jù)分析咨詢請(qǐng)掃描二維碼
若不方便掃碼,搜微信號(hào):CDAshujufenxi
訓(xùn)練與驗(yàn)證損失驟升:機(jī)器學(xué)習(xí)訓(xùn)練中的異常診斷與解決方案 在機(jī)器學(xué)習(xí)模型訓(xùn)練過程中,“損失曲線” 是反映模型學(xué)習(xí)狀態(tài)的核心指 ...
2025-09-19解析 DataHub 與 Kafka:數(shù)據(jù)生態(tài)中兩類核心工具的差異與協(xié)同 在數(shù)字化轉(zhuǎn)型加速的今天,企業(yè)對(duì)數(shù)據(jù)的需求已從 “存儲(chǔ)” 轉(zhuǎn)向 “ ...
2025-09-19CDA 數(shù)據(jù)分析師:讓統(tǒng)計(jì)基本概念成為業(yè)務(wù)決策的底層邏輯 統(tǒng)計(jì)基本概念是商業(yè)數(shù)據(jù)分析的 “基礎(chǔ)語言”—— 從描述數(shù)據(jù)分布的 “均 ...
2025-09-19CDA 數(shù)據(jù)分析師:表結(jié)構(gòu)數(shù)據(jù) “獲取 - 加工 - 使用” 全流程的賦能者 表結(jié)構(gòu)數(shù)據(jù)(如數(shù)據(jù)庫表、Excel 表、CSV 文件)是企業(yè)數(shù)字 ...
2025-09-19SQL Server 中 CONVERT 函數(shù)的日期轉(zhuǎn)換:從基礎(chǔ)用法到實(shí)戰(zhàn)優(yōu)化 在 SQL Server 的數(shù)據(jù)處理中,日期格式轉(zhuǎn)換是高頻需求 —— 無論 ...
2025-09-18MySQL 大表拆分與關(guān)聯(lián)查詢效率:打破 “拆分必慢” 的認(rèn)知誤區(qū) 在 MySQL 數(shù)據(jù)庫管理中,“大表” 始終是性能優(yōu)化繞不開的話題。 ...
2025-09-18DSGE 模型中的 Et:理性預(yù)期算子的內(nèi)涵、作用與應(yīng)用解析 動(dòng)態(tài)隨機(jī)一般均衡(Dynamic Stochastic General Equilibrium, DSGE)模 ...
2025-09-17Python 提取 TIF 中地名的完整指南 一、先明確:TIF 中的地名有哪兩種存在形式? 在開始提取前,需先判斷 TIF 文件的類型 —— ...
2025-09-17CDA 數(shù)據(jù)分析師:解鎖表結(jié)構(gòu)數(shù)據(jù)特征價(jià)值的專業(yè)核心 表結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 規(guī)范存儲(chǔ)的結(jié)構(gòu)化數(shù)據(jù),如數(shù)據(jù)庫表、Excel 表、 ...
2025-09-17Excel 導(dǎo)入數(shù)據(jù)含缺失值?詳解 dropna 函數(shù)的功能與實(shí)戰(zhàn)應(yīng)用 在用 Python(如 pandas 庫)處理 Excel 數(shù)據(jù)時(shí),“缺失值” 是高頻 ...
2025-09-16深入解析卡方檢驗(yàn)與 t 檢驗(yàn):差異、適用場景與實(shí)踐應(yīng)用 在數(shù)據(jù)分析與統(tǒng)計(jì)學(xué)領(lǐng)域,假設(shè)檢驗(yàn)是驗(yàn)證研究假設(shè)、判斷數(shù)據(jù)差異是否 “ ...
2025-09-16CDA 數(shù)據(jù)分析師:掌控表格結(jié)構(gòu)數(shù)據(jù)全功能周期的專業(yè)操盤手 表格結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 存儲(chǔ)的結(jié)構(gòu)化數(shù)據(jù),如 Excel 表、數(shù)據(jù) ...
2025-09-16MySQL 執(zhí)行計(jì)劃中 rows 數(shù)量的準(zhǔn)確性解析:原理、影響因素與優(yōu)化 在 MySQL SQL 調(diào)優(yōu)中,EXPLAIN執(zhí)行計(jì)劃是核心工具,而其中的row ...
2025-09-15解析 Python 中 Response 對(duì)象的 text 與 content:區(qū)別、場景與實(shí)踐指南 在 Python 進(jìn)行 HTTP 網(wǎng)絡(luò)請(qǐng)求開發(fā)時(shí)(如使用requests ...
2025-09-15CDA 數(shù)據(jù)分析師:激活表格結(jié)構(gòu)數(shù)據(jù)價(jià)值的核心操盤手 表格結(jié)構(gòu)數(shù)據(jù)(如 Excel 表格、數(shù)據(jù)庫表)是企業(yè)最基礎(chǔ)、最核心的數(shù)據(jù)形態(tài) ...
2025-09-15Python HTTP 請(qǐng)求工具對(duì)比:urllib.request 與 requests 的核心差異與選擇指南 在 Python 處理 HTTP 請(qǐng)求(如接口調(diào)用、數(shù)據(jù)爬取 ...
2025-09-12解決 pd.read_csv 讀取長浮點(diǎn)數(shù)據(jù)的科學(xué)計(jì)數(shù)法問題 為幫助 Python 數(shù)據(jù)從業(yè)者解決pd.read_csv讀取長浮點(diǎn)數(shù)據(jù)時(shí)的科學(xué)計(jì)數(shù)法問題 ...
2025-09-12CDA 數(shù)據(jù)分析師:業(yè)務(wù)數(shù)據(jù)分析步驟的落地者與價(jià)值優(yōu)化者 業(yè)務(wù)數(shù)據(jù)分析是企業(yè)解決日常運(yùn)營問題、提升執(zhí)行效率的核心手段,其價(jià)值 ...
2025-09-12用 SQL 驗(yàn)證業(yè)務(wù)邏輯:從規(guī)則拆解到數(shù)據(jù)把關(guān)的實(shí)戰(zhàn)指南 在業(yè)務(wù)系統(tǒng)落地過程中,“業(yè)務(wù)邏輯” 是連接 “需求設(shè)計(jì)” 與 “用戶體驗(yàn) ...
2025-09-11塔吉特百貨孕婦營銷案例:數(shù)據(jù)驅(qū)動(dòng)下的精準(zhǔn)零售革命與啟示 在零售行業(yè) “流量紅利見頂” 的當(dāng)下,精準(zhǔn)營銷成為企業(yè)突圍的核心方 ...
2025-09-11