天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 69|回复: 0

遗传算法解决多元函数优化问题(C++实现)

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <cstdlib>
using namespace std;

class GeneticAlgorithm {
public:
        struct parameters {
                int populationSize = 200;  //种群大小
                int maxGeneration = 200;    //最大迭代次数
                double mutationRate = 0.05; //变异概率
                double crossoverRate = 0.4; //交叉概率
                int tournamentSize = 50;   //选择种群大小
                float crossPercent = 0.2;   //交叉百分比
        } param;

        struct individual {
                double fitness;                     //适应度
                double culmulateProbability;        //累积概率
        vector<unsigned int> sourceVec;     //源数据
                vector<char> code;                  //编码值
        vector<double> indenpendentValVec; //自变量数组
        };

        vector<individual> group;       //种群
        vector<individual> crossGroup;  //交叉种群

        int resolution;                                        //分辨率:编码的位数
    vector<double> translationVec;  //转化系数数组
    unsigned int sourceMax;         //原码最大值
    bool ifMax;
    int indenpendentNum;            //自变量个数
    vector<vector<float>> Domain;   //自变量范围

        GeneticAlgorithm(vector<vector<float>> Domain, int resolution, bool ifMax) {
                this->resolution = resolution;                        //初始化参数
                this->sourceMax = (pow(2, resolution) - 1);
        this->ifMax = ifMax;
        this->indenpendentNum = Domain.size();
        this->Domain = Domain;
        for (size_t i = 0; i < this->indenpendentNum; i++)
            this->translationVec.push_back((Domain[i][1] - Domain[i][0])/sourceMax);

                init();     //初始化种群 产生编码范围内随机数 生成二进制编码

                for (size_t i = 0; i < param.maxGeneration + 1; i++)
                {
                        updateGroupFitness();   //更新种群适应度
                        calculatePropers();     //计算累积概率   用于轮盘赌
                        selectCrossGroup();     //选择交叉种群    轮盘赌
                        crossover();            //交叉  
                        mutation();             //变异
                        selectGroup();          //选择下一代种群
                        if (i % 20 == 0)
            cout << "第" << i << "代的适应度:" << getResult() << endl;
                }
                // showGroup();
        // showGroup();
        }


        void init() {   //初始化种群 随机初始路径
                srand(time(NULL));
                individual tmp;
                for (size_t i = 0; i < param.populationSize; i++)
                {
            tmp.sourceVec.clear();
            for (size_t j = 0; j < indenpendentNum; j++){
                tmp.sourceVec.emplace_back(rand() % sourceMax);
            }
            group.emplace_back(tmp);
                }
        source2code();  //将随机数转化为编码
        code2val();     //将编码解码为自变量
        }

    void source2code(){    //将随机数转化为编码
        for (size_t i = 0; i < group.size(); i++)
        {
            group[i].code.clear();
            for(size_t k = 0; k < indenpendentNum; k++){
                for (size_t j = 0; j < resolution; j++)
                    group[i].code.push_back((group[i].sourceVec[k] >> j) & 1);
            }
        }
    }

    void code2val(){//将编码解码为自变量
        for (size_t i = 0; i < group.size(); i++)
        {
            group[i].indenpendentValVec.clear();
            for (size_t j = 0; j < indenpendentNum; j++)
            {
                double tmp = 0;
                for (size_t k = 0; k < resolution; k++)
                    tmp += group[i].code[k + j*resolution] * pow(2, resolution - k - 1);
                group[i].indenpendentValVec.push_back(tmp * translationVec[j] + Domain[j][0]);
            }
        }
    }

    void code2val(individual &ind){//将编码解码为自变量
        ind.indenpendentValVec.clear();
        for (size_t i = 0; i < indenpendentNum; i++){
                double tmp = 0;
                for (size_t k = 0; k < resolution; k++)
                    tmp += ind.code[k+ i*resolution] * pow(2, resolution - k - 1);
                ind.indenpendentValVec.push_back(tmp * translationVec[i] + Domain[i][0]);
        }
        
    }

        void showGroup() {   //打印种群  用于测试
                int size = group.size();
        for (size_t i = 0; i < 10; i++)
        {
            cout << "第" << i << "个个体的编码:";
            int size = resolution * indenpendentNum;
            for (size_t j = 0; j < size; j++)
                cout << (int)group[i].code[j];
            cout << endl;

            cout << "第" << i << "个个体的自变量:";
            for (size_t j = 0; j < indenpendentNum; j++)
                cout << group[i].indenpendentValVec[j] << " ";
            cout << endl;

            cout << "第" << i << "个个体的适应度:" << group[i].fitness << endl;
            cout << "第" << i << "个个体的累积概率:" << group[i].culmulateProbability << endl;

            cout<<"------------------------------------------------------"<<endl;
        }
        
               
        }

        void updateGroupFitness() {  //更新整个种群的适应度
                for (size_t i = 0; i < param.populationSize; i++)
                        calculateFitness(group[i]);
        }

        void calculateFitness(individual &ind) {    //计算适应度
                double x = ind.indenpendentValVec[0];
        double y = ind.indenpendentValVec[1];
        ind.fitness = 6.452*(x+0.125*y)*pow(cos(x) - cos(2*y),2)/
        pow(0.8+pow((x-4.2),2)+2*pow((y-7),2),0.5) + 3.226*y;
        if (!ifMax)
                        ind.fitness = 1 / ind.fitness;
        }

        void calculatePropers() {  //计算累积概率
                group[0].culmulateProbability = group[0].fitness;
                for (size_t i = 1; i < param.populationSize; i++)
                        group[i].culmulateProbability = group[i - 1].culmulateProbability + group[i].fitness;
                for (size_t i = 0; i < param.populationSize; i++)
                        group[i].culmulateProbability /= group[param.populationSize - 1].culmulateProbability;
        }

        void selectCrossGroup() {  //选择交叉种群
                for (size_t i = 0; i < param.crossoverRate*param.populationSize; i++) {
                        double r = (double)rand() / RAND_MAX;
                        if (r < group[0].culmulateProbability) {
                                crossGroup.emplace_back(group[0]);
                                continue;
                        }
                        for (size_t j = 1; j < param.populationSize; j++) {
                                if (r >= group[j - 1].culmulateProbability && r < group[j].culmulateProbability) {
                                        crossGroup.emplace_back(group[j]);
                                        break;
                                }
                        }
                }
        }

    void crossover() {  //交叉   核心代码
        int gsize = crossGroup.size();
        for (size_t i = 0; i < gsize; i += 2) {
            int size = indenpendentNum*resolution * param.crossPercent;
            int r = rand() % (indenpendentNum*resolution-size);
            for (size_t j = r; j < r+size; j++){
                int tmp = crossGroup[i].code[j];
                crossGroup[i].code[j] = crossGroup[i + 1].code[j];
                crossGroup[i + 1].code[j] = tmp;
            }
        }
    }

    void mutation() {  //变异
        for (size_t i = 1; i < group.size(); i++) {
            if (rand() % 100 < param.mutationRate * 100) {
                int r = rand() % resolution*indenpendentNum;
                group[i].code[r] = !group[i].code[r];
            }
        }
    }

    void selectGroup() {  //选择种群
        int csize = crossGroup.size();
        for (size_t i = 0; i < csize; i++)
            {
                code2val(crossGroup[i]);
                calculateFitness(crossGroup[i]);
                group.emplace_back(crossGroup[i]);
            }
        sort(group.begin(), group.end(), compare);
        group.erase(group.begin() + param.populationSize, group.end());
        crossGroup.clear();
    }

    //比较函数 用于排序
    static bool compare(individual a, individual b) {
        return a.fitness > b.fitness;
    }

        double getResult() {  //获取结果
        if(ifMax)
            return group[0].fitness;
        else
            return 1 / group[0].fitness;
        }

};


int main() {
    //参数范围
    vector<vector<float>> Domain = { {0,10},{0,10} };
    int resolution = 16;    //编码长度
    bool ifMax = true;      //是否是最大值
        GeneticAlgorithm ga(Domain, resolution, ifMax);
}

 

 

 

 

遗传算法解决多元函数优化问题(C++实现)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 10:26 , Processed in 0.142890 second(s), 28 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表