Commit 03c5b5a4 authored by 刘乐's avatar 刘乐

1, 遗产算法更改

parent bde40d2e
......@@ -6,9 +6,10 @@
#include "OptScheduling.h"
#include "FirstOptScheduling.h"
GenAlg::GenAlg(GenType genType):mGenType(genType)
GenAlg::GenAlg(std::shared_ptr<OptScheduling> optScheduling)
:mOptScheduling(optScheduling)
{
mOptScheduling = std::make_unique<FirstOptScheduling>();
}
double GenAlg::random(int min , int max)
......@@ -47,18 +48,7 @@ void GenAlg::init(int popsize, double MutRate, double CrossRate, int GenLength,
// 把所有的基因编码初始化为函数区间内的随机数。
for (int j = 0; j < mChromoLength; j++)
{
switch (mGenType)
{
case RealValueCoding:
vecPop[i].vecGenome.push_back(random(0,MAX_RANDOM) * (mRightPoint - mLeftPoint) + mLeftPoint);
break;
case BinaryCoding:
vecPop[i].mBinaryGenVec.push_back((int)random() % 2);
break;
default:
break;
}
}
}
}
......@@ -87,70 +77,29 @@ void GenAlg::mutate(vector<double>& chromo)
}
}
void GenAlg::mutate(vector<char>& chromo)
{
// 遵循预定的突变概率,对基因进行突变
for (int i = 0; i < chromo.size(); ++i)
{
// 如果发生突变的话
if (random(0,1) < mMutationRate)
{
chromo[i] =( chromo[i]&0x01) ^ 0x01;
}
}
}
void GenAlg::select()
void GenAlg::select(vector<Genome>& genVec)
{
// 产生一个 0 到种群总适应性评分总和之间的随机数. mTotalFitness记录了整个种群的适应性分数总和
double slice = (random(0, 1)) * mTotalFitness;
}
void GenAlg::corssver()
{
// 染色体个数
int popSize = vecPop.size();
// 种群数组的索引
std::vector<int> randIndexVec;
for (int i = 0; i < popSize; i++)
randIndexVec.push_back(i);
// 这个基因将承载转盘所选出来的那个个体.
Genome theChosenOne;
// 随机排序,为了随机配对染色体
std::random_shuffle(randIndexVec.begin(), randIndexVec.end());
// 累计适应性分数的和.
double fitnessSoFar = 0;
int left = 0;
int right = popSize-1;
while (left < right)
// 遍历总种群里面的每一条染色体。
for (int i = 0; i < mPopSize; ++i)
{
int indexLeft = randIndexVec[left];
int indexRight = randIndexVec[right];
// 两个染色体互换
crossover(vecPop[indexLeft].mBinaryGenVec, vecPop[indexRight].mBinaryGenVec);
left++;
right--;
}
}
void GenAlg::crossover(vector<char>& chromo1, vector<char>& chromo2)
{
if (chromo1.size() != chromo2.size())
return;
int total = chromo1.size();
//累计适应性分数.
fitnessSoFar += vecPop[i].fitness;
// 基因交叉重组
for (int i = 0; i < total; i++)
{
// 满足交叉概率
if (random(0, 1) < mCrossoverRate)
{
int index = random(0, total);
for (int i = index; i < total; i++)
// 如果累计分数大于随机数,就选择此时的基因.
if (fitnessSoFar >= slice)
{
swap(chromo1[i], chromo2[i]);
}
theChosenOne = vecPop[i];
genVec.push_back(theChosenOne);
continue;
}
}
}
......@@ -229,7 +178,11 @@ void GenAlg::reset()
void GenAlg::epoch(vector<Genome>& vecNewPop)
{
// 计算当前种群适应度值
calculateBestWorstAvTot();
// 根据个体自适应度进行选择
select(vecNewPop);
}
Genome GenAlg::bestFitness()
......@@ -260,49 +213,76 @@ double GenAlg::fitnessfunction(float cost, map<string, double>& monitorValues)
return objVal;
}
void GenAlg::encoding(map<string, int>& phenotype, vector<char>& chromo)
void GenAlg::decoding(vector<map<string, float>>& genVals)
{
map<string, int>::iterator iter = phenotype.begin();
for (; iter != phenotype.end(); iter++)
size_t popSize = vecPop.size();
for (int i = 0; i < popSize; i++)
{
Genome genome = vecPop[i];
vector<double> genomeValsVec = genome.vecGenome;
size_t genSize = genomeValsVec.size();
map<string, float> genMap;
for (int j = 0; j < genSize; i++)
{
genMap.insert(pair<string,float>(mPumpVec[j], genomeValsVec[j]));
}
genVals.push_back(genMap);
}
}
void GenAlg::decoding(vector<map<string, int>>& phenotype)
void GenAlg::updateGenomeFitNess(int index, double fitNess)
{
size_t total = vecPop.size();
if (index < 0 || index >= vecPop.size())
return;
for (int i = 0; i < total; i++)
{
Genome genome = vecPop[i];
vector<char> genVec = genome.mBinaryGenVec;
for (int j = 0; j < genVec.size(); j++)
{
phenotype[i].insert(pair<string, char>(mPumpBits[j], genVec[j]));
}
}
vecPop[index].fitness = fitNess;
}
void GenAlg::decodingSingle(vector<char>& chromo, map<string, int>& phenotype)
void GenAlg::crossover(const vector<Genome>& parent, vector<Genome>& son)
{
for (int j = 0; j < chromo.size(); j++)
size_t pGenSize = parent.size();
// 种群数组的索引
std::vector<int> randIndexVec;
for (int i = 0; i < pGenSize; i++)
randIndexVec.push_back(i);
// 随机排序,为了随机配对染色体
std::random_shuffle(randIndexVec.begin(), randIndexVec.end());
int left = 0;
int right = pGenSize - 1;
while (left < right)
{
phenotype.insert(pair<string, char>(mPumpBits[j], chromo[j]));
int indexLeft = randIndexVec[left];
int indexRight = randIndexVec[right];
Genome genome = crossover(parent[indexLeft], parent[indexRight]);
son.push_back(genome);
left++;
right--;
}
}
void GenAlg::setMaxMonitorVals(const map<string, double>& maxMonitors)
Genome GenAlg::crossover(const Genome& gen1, const Genome& gen2)
{
mOptScheduling->setMaxMonitorVals(maxMonitors);
}
Genome geoMe;
void GenAlg::setMinMonitorsVals(const map<string, double>& minMonitors)
{
mOptScheduling->setMinMonitorsVals(minMonitors);
}
vector<double> genVec1 = gen1.vecGenome;
vector<double> genVec2 = gen2.vecGenome;
void GenAlg::setPumpBit(const vector<string>& pumpBit)
{
mPumpBits = pumpBit;
if (genVec1.size() != genVec2.size())
return geoMe;
size_t genSize = genVec1.size();
double a = 0.15;
for (int i = 0; i < genSize; i++)
{
double newGenVal = genVec1[i] + a * (genVec1[i] - genVec2[i]);
geoMe.vecGenome.push_back(newGenVal);
}
return geoMe;
}
\ No newline at end of file
......@@ -20,15 +20,8 @@ class OptScheduling;
class PANDAALGORITHM_API GenAlg
{
public:
// 基因编码类型
enum GenType
{
RealValueCoding,
BinaryCoding
};
//构造函数
explicit GenAlg(GenType genType);
explicit GenAlg(std::shared_ptr<OptScheduling>optScheduling);
//初始化变量
void reset();
......@@ -45,9 +38,6 @@ public:
// 基因变异函数(实值编码)
void mutate(vector<double>& chromo);
// 基因变异函数(二进制编码)
void mutate(vector<char>& chromo);
//这函数产生新一代基因
void epoch(vector<Genome>& vecNewPop);
......@@ -57,49 +47,46 @@ public:
// 获取平均适应度
double averageFitness();
// 所有基因重组
void corssver();
/**
* @brief 解码,将基因型解码成基础算法计算所需数据
* @param [genVals] 解析的数据集合
*/
void decoding(vector<map<string, float>> & genVals);
// 选择运算,前群体中适应度较高的个体按某种规则或模型遗传到下一代群体中
void select();
// 根据监测点计算值,计算个体自适应度
double fitnessfunction(float cost,map<string,double>& monitorValues);
void select(vector<Genome>& genVec);
/**
* @brief 编码, 将水泵开关状态编码成二进制状态:0表示管,1表示开
* @param
* @brief 交叉重组
* @param [parent] 父代个体
* @param [son] 产生子代
*/
void encoding(map<string, int>& phenotype, vector<char>& chromo);
void crossover(const vector<Genome>& parent, vector<Genome>& son );
/**
* @brief 解码, 将二进制状态吗解码成水泵对应的状态
* @param
* @brief 根据监测点计算值,计算个体自适应度
* @param [cost] 能耗
* @param [monitorValues] 监测点的值
* @return 适应度值
*/
void decoding(vector<map<string, int>>& phenotype);
void decodingSingle(vector<char>& chromo, map<string, int>& phenotype);
void setMaxMonitorVals(const map<string, double>& maxMonitors);
void setMinMonitorsVals(const map<string, double>& minMonitors);
void setPumpBit(const vector<string>& pumpBit);
double fitnessfunction(float cost, map<string,double>& monitorValues);
/**
* @brief 更新种群个体自适应度
* @param [index] 种群的个体
* @param [fitNess] 个体适应度
*/
void updateGenomeFitNess(int index, double fitNess);
private:
// 产生[a,b)之间的浮点数
double random(int a=0, int b= RAND_MAX);
// 两个染色体交叉运算
void crossover(vector<char>& chromo1, vector<char>& chromo2);
// 交叉重组,产生新的个体
Genome crossover(const Genome& gen1, const Genome& gen2);
private:
// 这个容器将储存每一个个体的染色体
vector <Genome> vecPop;
// 基因编码类型
GenType mGenType;
// 种群数量
int mPopSize;
......@@ -139,9 +126,9 @@ private:
// 右边界
double mRightPoint;
// 水泵状态位
vector<string> mPumpBits;
//
vector<string> mPumpVec;
// 优化调度函数
std::unique_ptr<OptScheduling> mOptScheduling;
std::shared_ptr<OptScheduling> mOptScheduling = nullptr;
};
......@@ -14,11 +14,8 @@ public:
Genome() :fitness(0) {}
Genome(std::vector <double> vec, double f) : vecGenome(vec), fitness(f) {} //类的带参数初始化参数。
Genome(std::vector <char> vec, double f) :mBinaryGenVec(vec), fitness(f) {}
private:
std::vector<double> vecGenome; // 装载基因的容器
std::vector<char> mBinaryGenVec; // 二进制编码
double fitness; // 适应度
};
......@@ -93,7 +93,5 @@ bool PANDANALYSIS_API optimalSchedulingSimulation(char* uri, char* condition, ch
jsonObj.parse(timeStr);
return true;
}
\ No newline at end of file
......@@ -65,7 +65,7 @@ extern "C" {
*@brief 优化调度模拟
*@param [in] uri:condition
*@param [in] condition:约束条件, 格式: json字符串 {"测压点1":[32,46],"测压点2":[28,33]}
*@param [in] timeInterval:时段,格式:{"start":'2020-10-27 00:00:00',"end":'2020-10-27 08:00:00' }
*@param [in] timeInterval:时段,格式:{"time":'1' }
*@param [out] result: 模拟的调度结果
*/
bool PANDANALYSIS_API optimalSchedulingSimulation(char* uri, char* condition, char* timeInterval, char* result);
......
......@@ -3,96 +3,68 @@
#include "GenAlg.h"
#include "FirstOptScheduling.h"
#include "CivPumpHelper.h"
#include "CivSchedulingCompute.h"
#include "Genome.h"
#include "CivReportReader.h"
#include "CivCommonUtils.h"
CivOptSchedEngine::CivOptSchedEngine(const string& uri):mUri(uri)
CivOptSchedEngine::CivOptSchedEngine(const string& uri)
:mUri(uri),mMutRate(0.45),mCrossRate(0.07), popsize(10)
{
mMutRate = 0.45;
mCrossRate = 0.07;
}
bool CivOptSchedEngine::optimalScheduling()
bool CivOptSchedEngine::optimalScheduling(int time)
{
// 转inp文件
CivInpConvertor convertor(mUri);
string inpFile = convertor.convertBaseInp();
// 获取水泵个数,根据水泵个数确定基因编码长度
CivPumpHelper pumpHelper(mUri);
mGenLength = pumpHelper.getPumpNumbers();
// 获取本点号和code的映射
map<string, string> snToCodeMap;
pumpHelper.getMap("本点号", "code", snToCodeMap);
// 获取本点号集合
vector<string> snVec;
pumpHelper.getPumpSn(snVec);
// 计算初始化
beginCompute();
// 开始遗传算法
GenAlg genAlg(GenAlg::BinaryCoding);
std::shared_ptr<OptScheduling> optScheduling(new FirstOptScheduling());
optScheduling->setMinMonitorsVals(mMinMonitorVals);
optScheduling->setMaxMonitorVals(mMaxMonitorVals);
// 设置水泵的编码位
genAlg.setPumpBit(snVec);
GenAlg genAlg(optScheduling);
// 种群初始化
popsize = 100;
genAlg.init(popsize, mMutRate, mCrossRate, mGenLength, 0, 0);
// 构造水力计算对象
CivSchedulingCompute schedulingCompute(CivSchedulingCompute::PumpScheduling);
vector<string> monitorVec;
for (auto iter = mMonitoring.begin(); iter != mMonitoring.end(); iter++)
{
monitorVec.push_back(iter->first);
}
schedulingCompute.setMonitors(monitorVec);
schedulingCompute.openFile(inpFile);
// 原始管网计算一次水力,保留调度前的水力计算结果
if (!schedulingCompute.calculate())
return false;
// 保存原始管网监测点的模拟值
schedulingCompute.getMonitorsValue(mBforeSchedulingResults);
popsize = 10;
genAlg.init(popsize, mMutRate, mCrossRate, mGenLength, 0, 1);
// 开始迭代计算
int index = 0;
while (index++ < popsize)
// 迭代次数
int generation = 20;
while (index++ < generation)
{
// 管网平差计算
vector<map<string, int>>monitorsMap;
vector<map<string, float>> monitorsMap;
genAlg.decoding(monitorsMap);
// 计算种群个体的每个
size_t mSize = monitorsMap.size();
for (int i = 0; i < mSize; i++)
{
schedulingCompute.updatePumpStatus(monitorsMap[i]);
if (!schedulingCompute.calculate())
mSchedulingCompute->updatePumpSpeed(monitorsMap[i]);
if (!mSchedulingCompute->calculate())
continue;
// 获取计算的监测点的值
vector<map<string, double>> monitorCalcMapValues;
schedulingCompute.getMonitorsValue(monitorCalcMapValues);
map<string, double> monitorCalcMapValues;
mSchedulingCompute->getMonitorsValue(mPeriod, monitorCalcMapValues);
// 获取消耗的能量值
float cost = schedulingCompute.totalEnergy(i);
float cost = mSchedulingCompute->totalEnergy(mPeriod);
// 计算个体自适度
genAlg.fitnessfunction(cost, monitorCalcMapValues[i]);
double fitness = genAlg.fitnessfunction(cost, monitorCalcMapValues);
// 更新个体的自适应度
genAlg.updateGenomeFitNess(i, fitness);
}
// 根据个体自适应度进行选择
genAlg.chromoRoulette();
// 自适应交叉变异
genAlg.corssver();
//
// genAlg.mutate()
// 产生下一代种群
std::vector<Genome> newGenmeVec;
genAlg.epoch(newGenmeVec);
......@@ -100,20 +72,18 @@ bool CivOptSchedEngine::optimalScheduling()
// 获取最好的
Genome genome = genAlg.bestFitness();
vector<char> genVec = genome.mBinaryGenVec;
vector<double> genVec = genome.vecGenome;
// 最优水泵组合
genAlg.decodingSingle(genVec, mPumpBestStatus);
map<string, float> genMap;
for (int i = 0; i < mMonitorsVec.size(); i++)
genMap.insert(pair<string, double>(mMonitorsVec[i], genVec[i]));
// 再做一次水力计算,计算调度后的值
schedulingCompute.updatePumpStatus(mPumpBestStatus);
schedulingCompute.calculate();
mSchedulingCompute->updatePumpSpeed(genMap);
mSchedulingCompute->calculate();
// 最有调度值
schedulingCompute.getMonitorsValue(mBforeSchedulingResults);
// 结束计算
schedulingCompute.close();
mSchedulingCompute->getMonitorsValue(mPeriod,mAfterSchedulingResults);
return true;
}
......@@ -165,22 +135,50 @@ void CivOptSchedEngine::schedulingResultToJson(string& json)
json.append("]}");
}
void CivOptSchedEngine::setMonitor(const map<string, vector<double>>& monitorMap)
void CivOptSchedEngine::updateMonitorsVals(const map<string, double>& monitorVals)
{
mMonitoring = monitorMap;
mCurrentMonitorVals = monitorVals;
}
void CivOptSchedEngine::setDecisionVariableStatusBit(const map<int,string>& statusMap)
bool CivOptSchedEngine::beginCompute()
{
mStatusBit = statusMap;
// 转inp文件
CivInpConvertor convertor(mUri);
string inpFile = convertor.convertBaseInp();
// 初始化计算
mSchedulingCompute = std::make_shared<CivSchedulingCompute>(CivSchedulingCompute::PumpScheduling);
// 构造水力计算对象
mSchedulingCompute->setMonitors(mMonitorsVec);
mSchedulingCompute->openFile(inpFile);
// 原始管网计算一次水力,保留调度前的水力计算结果
if (!mSchedulingCompute->calculate())
return false;
// 保存原始管网监测点的模拟值
mSchedulingCompute->getMonitorsValue(mPeriod,mBforeSchedulingResults);
// 获取水泵个数,根据水泵个数确定基因编码长度
CivPumpHelper pumpHelper(mUri);
mGenLength = pumpHelper.getPumpNumbers();
// 获取本点号和code的映射
map<string, string> snToCodeMap;
pumpHelper.getMap("本点号", "code", snToCodeMap);
// 获取本点号集合
vector<string> snVec;
pumpHelper.getPumpSn(snVec);
}
void CivOptSchedEngine::setStartTime(const string& time)
void CivOptSchedEngine::endCompute()
{
mStartTime = time;
mmSchedulingCompute->close();
}
void CivOptSchedEngine::setEndTime(const string& time)
void CivOptSchedEngine::setMonitors(const vector<string>& monitor)
{
mEndTime = time;
mMonitorsVec = monitor;
}
......@@ -2,9 +2,11 @@
#include <string>
#include <vector>
#include <map>
#include "CivSchedulingCompute.h"
using namespace std;
class CivSchedulingCompute;
/**
优化调度客户端
*/
......@@ -13,19 +15,22 @@ class CivOptSchedEngine
public:
explicit CivOptSchedEngine(const string& uri);
bool optimalScheduling();
bool optimalScheduling(int time);
// 设置监测点
void setMonitor(const map<string, vector<double>>& monitorMap);
void updateMonitorsVals(const map<string,double>& monitorVals);
// 设置决策变量状态位
void setDecisionVariableStatusBit(const map<int, string>& statusMap);
// 设置调度开始时段
void setStartTime(const string& time);
/**
*@brief 监测点的编号
* @param [monitor] 监测点的编号
*/
void setMonitors(const vector<string>& monitor);
// 设置调度结束时段
void setEndTime(const string& time);
/**
*@brief 设置需要调度的时段,范围为0-24
* @param [time] 调度的时段
*/
void setSchedulingPeriod(int time) { mPeriod = time; }
protected:
/**
......@@ -34,36 +39,57 @@ protected:
*/
void schedulingResultToJson(string& json);
/**
*@brief 调度之前的一些初始化操作
*/
bool beginCompute();
/**
*@brief 调度之后的一些收尾工作,清理
*/
void endCompute();
private:
// 编码与状态的映射
map<int, string> mStatusBit;
// 选出的最优组合
map<string, int> mPumpBestStatus;
map<string, double> mPumpBestSpeed;
// 监测点编码
vector<string>& mMonitorsVec;
// 实时计算的当前监测点的值
map<string,double> mCurrentMonitorVals;
// 监测点
map<string, vector<double>> mMonitoring;
vector<map<string, double>> mBforeSchedulingResults;
vector<map<string, double>> mAfterSchedulingResults;
// 监测点压力的界限值
map<string, double> mMaxMonitorVals;
map<string, double> mMinMonitorVals;
map<string, double> mBforeSchedulingResults;
map<string, double> mAfterSchedulingResults;
// 数据连接地址
string mUri;
// 调度开始时段
string mStartTime;
// 调度结束时段
string mEndTime;
// 调度的那个时段
int mPeriod;
// 初始中群大小
int popsize;
// 变异率
double mMutRate;
// 交叉率
double mCrossRate;
//基因编码长度
int mGenLength;
// 针对浮点数编码
double mLeftPoint;
double mRightPoint;
std::shared_ptr<CivSchedulingCompute> mSchedulingCompute;
};
......@@ -80,12 +80,12 @@ bool CivSchedulingCompute::calculate()
char id[128] = "";
ENgetlinkid(i, id);
auto iter = mPumpStatus.find(id);
if (iter == mPumpStatus.end())
map<string,float>::iterator iter = mPumpSpeed.find(id);
if (iter == mPumpSpeed.end())
continue;
iter->second;
ENsetlinkvalue(i, EN_STATUS, iter->second == '1' ? OPEN : CLOSED);
// 更新水泵的转速
ENsetlinkvalue(i, EN_STATUS, iter->second );
}
break;
case PBVScheduling& EN_PBV:
......@@ -126,15 +126,18 @@ void CivSchedulingCompute::close()
ENclose();
}
void CivSchedulingCompute::updatePumpStatus(const map<string, int>& pumpStatus)
void CivSchedulingCompute::updatePumpSpeed(const map<string, float>& pumpSpeed)
{
mPumpStatus.clear();
mPumpStatus = pumpStatus;
mPumpSpeed.clear();
mPumpSpeed = pumpSpeed;
}
void CivSchedulingCompute::getMonitorsValue(vector<map<string, double>>& monitorMap)
void CivSchedulingCompute::getMonitorsValue(int time, map<string, double>& monitorMap)
{
monitorMap = mMonitorsValue;
if (time<0 || time> mMonitorsValue.size() - 1)
return;
monitorMap = mMonitorsValue[time];
}
void CivSchedulingCompute::setMonitors(const vector<string>& monitor)
......
......@@ -32,11 +32,15 @@ public:
// 结束计算,关闭文件句柄
void close();
// 更新水泵开关状态
void updatePumpStatus(const map<string, int>& pumpStatus);
// 更新水泵的转速比
void updatePumpSpeed(const map<string, float>& pumpSpeed);
// 获取监测点计算出的值
void getMonitorsValue(vector<map<string, double>>& monitorMap);
/**
* @brief 获取某个具体时段的计算的监测点的模拟值
* @param [time] 时段
* @param [monitorMap] 具体某个时段的监测值
*/
void getMonitorsValue(int time, map<string, double>& monitorMap);
// 更改压力制动阀压力设置
void updatePBVSettings(const string& sn, double pressure);
......@@ -50,6 +54,7 @@ private:
// 获取计算的水泵的能耗
void getPumpEnergy(int time);
private:
std::string mRptFile;
std::string mBinFile;
......@@ -60,8 +65,8 @@ private:
// 错误吗
int mErrcode = 0;
// 更新水泵的状态
map<string, int> mPumpStatus;
// 更新水泵的转速比
map<string, float> mPumpSpeed;
// 水泵消耗的能量
vector<map<string, float>> mPumpEnergy;
......@@ -70,5 +75,4 @@ private:
vector<map<string, double>> mMonitorsValue;
SchdulingType mChdulingType;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment